Skip to content

Extend Jython auto-completion to instantiated classes#51

Merged
acardona merged 39 commits into
scijava:masterfrom
tferr:autocompletion-vars
Feb 12, 2022
Merged

Extend Jython auto-completion to instantiated classes#51
acardona merged 39 commits into
scijava:masterfrom
tferr:autocompletion-vars

Conversation

@tferr

@tferr tferr commented Dec 4, 2020

Copy link
Copy Markdown
Collaborator

@acardona , @haesleinhuepf , This implements the following changes by extending Albert's recent work:

  • Adds auto-completion to non-static methods
  • Auto-completion does not 'crash' if import statements are wrong (with typos, etc.)
  • Improves the description of suggestions by including type of parameters and return values

tferr added 3 commits December 3, 2020 21:44
Currently, if there is e.g., a typo in an import declaration completion will fail
with a ClassNotFoundException. This commit adds placeholders to the completion
list to warn user about such cases,
@imagesc-bot

Copy link
Copy Markdown

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/auto-code-completion-for-python-and-groovy-in-imagej-fiji/20515/22

@tferr

tferr commented Dec 4, 2020

Copy link
Copy Markdown
Collaborator Author

@acardona , there are still two things that are missing in this PR:

  1. Import with parenthesis are not recognized. E.g. in from ij import (ImagePlus, ImageProcessor), neither ImagePlus nor ImageProcessor get recognized as being imported
  2. the description of the auto-completion is missing the URL for the class's Javadoc. This would be straightforward to include the a tag here. I think ClassUtil, has already all that information cached?
  3. Another issue: currently completion works only with instantiated classes. It does not work with instances retrieved from static calls. I.e.: this works well:
from ij import ImagePlus
imp = ImagePlus()

But no completions are retrieved if you use:

from ij import IJ
imp = IJ.getImage()

The latter would be the most important issue. I will wait for your feedback on this.

@imagesc-bot

Copy link
Copy Markdown

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/auto-code-completion-for-python-and-groovy-in-imagej-fiji/20515/25

@acardona

acardona commented Dec 4, 2020

Copy link
Copy Markdown
Collaborator

Thanks a lot @tferr, this is great.

On from ij import (ImagePlus, ImageProcessor): are these even valid? If so, I had no idea. In python, one can use multi-imports like:

from ij import ImagePlus, ImageProcessor

or even:

from ij import ImagePlus,\
                 ImageProcessor

@acardona

acardona commented Dec 4, 2020

Copy link
Copy Markdown
Collaborator

On this use case:

from ij import IJ
imp = IJ.getImage()

If it's from a static method, the object class can be retrieved from the return type of the static method.

If it's from a function, like:

from ij import IJ
def getImage():
  return IJ.getImage()

imp = getImage()

... then no cookie: it's the perennial problem in non-strongly typed languages. Python is fixing this with annotations, which seem to be a part of the language in 3.8. There is currently an effort to bring jython to python 3+, but it's very understaffed (one very part-time developer).

(not just those which start with it)
// System.out.println("Hit: line #" + i + ": " + line);
// System.out.println("Matcher g1: " + matcher.group(1));
// System.out.println("Matcher g2: " + matcher.group(2));
if (variable.equals(matcher.group(1))) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is dangerous in that it doesn't consider the scope of the variable. I would do it differently, by parsing the code like jython's interpreter with a ParserFacade, see e.g. https://github.com/acardona/scripts/blob/master/python/imagej/jython/parse_code.py

@tferr tferr Dec 4, 2020

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Are you able to work on this? To me the priority would be to support he return type of the static method so I'd prefer to work on that instead (unless you say otherwise)

@acardona acardona Dec 4, 2020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, proper jython code parsing is something I've been working on but haven't committed yet. Will lead to:

  1. autocompletion for variable names within scope, in addition to possible java class imports;
  2. autocompletion and auto-import for python modules included in the jython jar or discoverable from its PYTHONPATH-equivalent;
  3. type resolution for variables within scope, in order to autocomplete their methods. Won't always work (e.g. when an object derives from a call on a function argument), but it will work in many cases.

For the latter case, the AutoCompletionListener interface will allow e.g. @haesleinhuepf's update site to add variable name-based imports (e.g. for imp, ip, fp, etc.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acardona, Great! On a second thought I will hold for now, as you are likely to revamp a bunch of things. But do let me know if there is something you want me too look into. I won't work on this until I hear from you (so feel free to merge), but do let me know if you want me to look into something. I will post below a summary of what this (snowballed) PR now has.

static private final Pattern importPattern = Pattern.compile("^(from[ \\t]+([a-zA-Z_][a-zA-Z0-9._]*)[ \\t]+|)import[ \\t]+([a-zA-Z_][a-zA-Z0-9_]*[ \\ta-zA-Z0-9_,]*)[ \\t]*([\\\\]*|)[ \\t]*(#.*|)$"),
tripleQuotePattern = Pattern.compile("\"\"\"");
tripleQuotePattern = Pattern.compile("\"\"\""),
variableDeclarationPattern = Pattern.compile("([a-zA-Z_][a-zA-Z0-9._]*)\\s*=\\s*([A-Z_][a-zA-Z0-9._]*)(?:\\()"); // E.g., in 'imp=ImagePlus()' grou1: imp; group2: ImagePlus

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all kinds of whitespace are valid, for example a line break isn't valid if the line doesn't end with a backslash. That's why I used [ \t] instead of \s.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. will fix.

String packageName = m2.group(3),
className = m2.group(4); // incomplete or empty, or multiple separated by commas with the last one incomplete or empty
final String packageName = m2.group(3); // incomplete or empty, or multiple separated by commas with the last one incomplete or empty
String className = m2.group(4);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this code was changed here? Seems like you have an opinionated code formatter. Now the comment is in the wrong place.

@tferr tferr Dec 4, 2020

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. My Eclipse has a will of its own. I hate it when it does that. Will fix.


// a call to an instantiated class
final String[] varAndSeed = getVariableAnSeedAtCaretLocation();
if (varAndSeed == null) return Collections.emptyList();;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double semicolon.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

haesleinhuepf and others added 13 commits December 4, 2020 20:29
…ontain_term

auto-complete words that contain a term
Import as statement (Adds support for lower case aliases)
- Include parameters type in replacement text (`imp.draw(int, int, int, int)`  vs `imp.draw(`
- Improve summary
- Display type of fields
- Include javadoc link in description
- Fix dup. text
...This facilitates access to other future providers (Groovy, etc.)
(also fixes missing .html suffix in URL)
At least for now. Somehow breaks variable completion 
This reverts commit 9a584df.
@tferr

tferr commented Dec 5, 2020

Copy link
Copy Markdown
Collaborator Author

For clarity, here is what this PR implements:

  • Adds preliminary support for non-static methods. This is fragile and will be revamped by @acardona's ParserFacade approach)
  • Shows an error in the popup list if import is not found (rather than exception)
  • Does approximate string matching (exact matches are still displayed on top of list)
  • Revamps auto-completion descriptions:
    • provides functional URLs to the class's JavaDoc
    • lists type of parameters, fields and return values and includes them in the replacement String
  • Includes' @acardona revisions and comments
  • Moves some common code to ClassUtil, so that it can be reused by future Completion providers

Here are some snapshots:

Field:
image

Fuzzy string search (methods):
image

Invalid import:
image

I have to say, I find it quite functional even at this stage.
NB:

  • I haven't implemented the retrieval of class from the return type of the static method, as I expect @acardona work will move things around
  • Scijava #@ parameters type of imports are not yet supported
  • Hyperlinks could likely be improved by attaching the anchor for the field/method to the html address of the class
  • @haesleinhuepf , i had to revert your commit 9a584df. Not so sure why, but it broke some of the downstream auto-completion. This means lower case aliases in import statements are still not supported.
    (all these are probably things that can be addressed later on)

@acardona

Copy link
Copy Markdown
Collaborator

Hi @tferr, the code may have changed significantly. Would appreciate if you could revise your commits and see which can be applied. The branch I pushed forward is "fix-autocompletion-listener".

And @haesleinhuepf: notice I've had to change the AutoCompletionListener interface significantly. Please have a look, should be straightforward to adapt for CLIJ to insert expansions for commonly used variable names.

tferr and others added 14 commits January 5, 2021 01:24
Currently, if there is e.g., a typo in an import declaration completion will fail
with a ClassNotFoundException. This commit adds placeholders to the completion
list to warn user about such cases,
(not just those which start with it)
- Include parameters type in replacement text (`imp.draw(int, int, int, int)`  vs `imp.draw(`
- Improve summary
- Display type of fields
- Include javadoc link in description
- Fix dup. text
...This facilitates access to other future providers (Groovy, etc.)
(also fixes missing .html suffix in URL)
At least for now. Somehow breaks variable completion 
This reverts commit 9a584df.
@tferr

tferr commented Jan 5, 2021

Copy link
Copy Markdown
Collaborator Author

@acardona, to include JavaDoc URLs and list types in the completions, I would have to modify DotAutoCompletions#get() to return both the completion String and the completion description (also a String). Are you OK with it?

@acardona

acardona commented Jan 5, 2021

Copy link
Copy Markdown
Collaborator

Hi @tferr, sounds good, should then return a new object that has both as fields rather than just a String.

@acardona

Copy link
Copy Markdown
Collaborator

By the way @tferr, when done, after review/test, I'd appreciate very much if you could release it all: the jython-autocompletion and the script-editor, so that it all appears in the Fiji updater.

@tferr

tferr commented Jan 24, 2021

Copy link
Copy Markdown
Collaborator Author

@acardona, sincere apologies for the delay. 'Real work' got in the way. I think I have it working, but still need to test it more seriously. Hyperlinks seem to be working, and the completion lists the type for both fields and methods. If there are no major issues I will push and release tonight.

There are still some (minor) issues like the .acess$000 entry below, but we can always tackle this at a later time point), otherwise it will never be ready
image

@acardona

Copy link
Copy Markdown
Collaborator

Sounds great! On the subclasses: a one-liner filtering for dollar signs '$', indicative of subclasses, would do, at the level of the returned stream or list of autocompletions.

@tferr

tferr commented Jan 25, 2021

Copy link
Copy Markdown
Collaborator Author

@acardona, I don't seem to have write access to this repository. Could you please merge this AND release version 5.0.10 of the script editor? Otherwise, give me write permissions and I will do so. Thanks!

@acardona acardona merged commit 6c48389 into scijava:master Feb 12, 2022
imagejan added a commit that referenced this pull request Feb 14, 2022
This file was accidentally added when merging #51 with commit 6c48389.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants