Repository navigation
Conversation
Complete code in appose-python scripts in two layers: * tree-sitter, in process: names in scope, script parameters, task, builtins and keywords, instantly and without any Python. * Jedi, in a small tooling environment of its own (built in the background on first use), analyzing scripts against their own environment's interpreter: members, module contents, signatures and documentation. Answers come without blocking typing, as updates; documentation is fetched on demand. Completion never builds a script's environment or disturbs its worker: environments built earlier (in any session) are found read-only. Dependencies a script declares but its environment lacks are installed for completion only, into a separate overlay directory, once they stop changing. Signature help comes from Jedi. Also extract the engine's environment resolution into ScriptEnvironment, shared with completion, and add ResidentWorkerService#find, a lookup that never replaces a running worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parameter preamble becomes ApposePythonDialect, and where the script runs (its environment's Python, its overlay) an EnvironmentContext. The preamble now lists imports first and task last. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Jedi tasks (JediClient, jedi_complete.py) give way to jedi-language-server, run from the tooling environment via code-lsp's LspClient; PythonLspClient reads its Python signatures. Tree-sitter's completions, dependency overlays and script environments stay as they were: the overlay and the environment's Python become the server's extra path and environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApposePythonLspServerPlugin offers it via code-lsp's LspService, for this completer and others (e.g. Jython's); PythonLspClient moved to code-lsp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tooling environment gets NumPy: script parameters typed as NumPy arrays (e.g. images) were unknown to the server until the script's own environment was built, so 'image.' offered nothing from it. jedi-language-server is started via a launcher that exits once this JVM is gone: the server does not notice by itself, and on Windows then loops, failing to write to the closed pipe, flooding its log (which now starts anew beyond 5 MB). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completion now comes from two lsp4j language servers, which code-lsp's LanguageServerService merges: PythonSyntaxServerPlugin (tree-sitter: instant names, parameters, builtins and keywords) and JediServerPlugin (jedi-language-server, against the script's environment plus overlays, seeing the script as plain Python). ApposePythonEnvironments holds what the completer knew about environments; ApposePythonCodeCompleter, and its merge and time budget, are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its remaining types (ScriptDocument, ScriptDialect, ClassIndex, Signatures, Environment) come from scijava-code-lsp, and script parameters from the LanguageServerService. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A script's environment can become available without the script changing: when a script run builds it, or when packages it declares are installed for completion. ResidentWorkerService now notifies listeners of finished builds, and DependencyOverlays of ready overlays; the jedi plugin passes both on to LanguageServerService.environmentsChanged(), so open scripts move to the servers of where they run now. Tests ask through script sessions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PythonCompletionServer (with DelegatingLanguageServer) completes Java members on objects jedi cannot see into. It is specific to Python, so it lives here now, with the one plugin using it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ScriptSession.setFile(File) is gone from code-lsp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp's merged completions now come once all servers have answered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp no longer merges several plugins' servers, nor moves scripts between them. ApposePythonServerPlugin now offers one server, ApposePythonLanguageServer: jedi's completions first, then the syntax server's for other names; jedi's signatures, hover and problems, else the syntax server's. It moves each script to a jedi of where it runs as that changes (as its metadata is edited, or its environment is built). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both are ordered places imports are resolved from; each server reads them as its language does. Nothing read the classpath. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jedi and the syntax-only server now read the text the session makes in ApposePythonDialect. The syntax server no longer reads #@ lines: it finds the parameters and task among the names declared, with the types they are annotated with. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
E.g. a package imported only to declare a parameter's type is no longer offered (see ScriptDialect#imported). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp now runs server processes from ServerProcessPlugins, replacing its launch package. JediLanguageServerSpec becomes JediServerProcessPlugin, a plugin that starts jedi-language-server in the tooling environment; ApposePythonLspServerPlugin, which offered the spec, is gone, and ApposePythonEnvironments gives just the tooling Python. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The language server plugin, its server, the environments it analyzes scripts against, jedi-language-server's plugin and the syntax-only server join the rest of the completion code (and their tests, the rest of its tests). The python package keeps what runs scripts. ScriptEnvironment, which both resolve scripts' environments with, is public now; so is what completion uses of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The syntax-only server was its analysis's only user, so the two are one class now: the analysis (analyze, Context, Kind) is package-private, for the tests. The dialect is the plugin's, so ApposePythonServerPlugin keeps it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PythonCompletionServer was the only server built on it, so it passes on what it does not change itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The syntax-only server (tree-sitter) answered only when jedi had failed, or with names jedi had not completed: completions waited for jedi anyway. Gone with it are the merging of the two servers' answers, the fallbacks from jedi to it, and the tree-sitter dependencies. Without jedi, the plugin no longer serves Appose Python at all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApposePythonEnvironments now gives the environment of each script as code-lsp asks, before each request, so the script moves to another jedi process once its environment is built or its overlay is ready. This replaces the router that relocated scripts between servers, and the listeners that told it to; PythonCompletionServer becomes ApposePythonLanguageServer in its place. Empty answers are no longer reused, as Jedi may know more once asked again (e.g. after a new dependency's overlay is ready). Everything but the two plugins is now package-private. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jedi-language-server is now offered by scijava-code-lsp-jedi (a runtime dependency), so JediServerProcessPlugin goes; the tooling environment here only installs dependency overlays. code-lsp's servers now analyze scripts in one environment each. Since a script's environment is in its text, and changes as it is edited, the new RoutingLanguageServer keeps a Python server per environment and moves each script to the one where it runs now, as asked before each request (and closes servers left without scripts). Also follow code-lsp's API: plugins say which LSP language they serve (appose-python), and ask whether python is served rather than catching its absence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp's sessions ask for the LSP language named as the script's language, in lower case, so the plugin no longer declares the script language it serves separately. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApposePythonDialect is now a ScriptDialect plugin: it shows scripts as plain Python and says which built Appose environment each runs in. The tuned server, the overlays and the routing moved to code-lsp-jedi and code-lsp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The completion integration test keeps script environments, image parameters and problems after #@ lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parameter types are never null, so stop checking for null. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialect writes its imports, its parameters' declarations and the task's in one header line, and names what it imports only for them, to hide from completion. Its tests now test each of its methods. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialect names its server only by language id: applications choose their servers, as scripting-groovy now has them do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overlays of packages a script declares, but its environment lacks, move here from scijava-code-lsp-jedi, whose servers now analyze scripts in exactly the environment they are given: ApposePythonDialect includes them in the environment it reports. They are installed with Appose's uv. Also follows scijava-code-lsp: sessions are made with the service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completion now builds the environment a script declares, in the background, once its configuration has stayed the same for a while (ApposePythonEnvironments): waiting for a script running in it first, and replacing its worker, as the script's next run would. Completion then analyzes the script there, conda packages and environment files included; and the next run need not build it. So the dependency overlays are gone. Also, an environment is no longer rebuilt in place while a worker of its earlier configuration may still be running: ResidentWorker.release() says when its process has ended, which LazyEnvironment waits for; and files of an environment being built are not used. Workers are made in one place (ScriptEnvironment.worker). FIXME: unsaved scripts are named differently by completion and by runs from the script editor, so a run builds another environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a
org.scijava.code.lsp.ScriptDialectthat describes how to convert a SciJava Appose Python script to plain python code. There's likely a lot of cleanup to be done here - claude had a big hand in making this code and may have touched some unnecessary files.See scijava/scijava#294 for discussion