Community
Participate
Working Groups
Hi guys, I have been playing around with groovy the last days and so far I really like it (imho, it's underestimated!). Anyways, So far it works great with the groovy eclipse plugin, even debugging almost works. What doesn't work is the expressions view. It can handle Java code, but not groovy code, like the safe-navigator/elvis operator `foo?.test?.value`. Also the Debug/display view doesn't support groovy, I've already file a bug at the plugins github issues: https://github.com/groovy/groovy-eclipse/issues/569 But I was told, that this is an issue with Eclipse JDT and to file a bug here :-) In case there is no good and fast-forward way to implement this feature for a new language, it would be nice to implement such an API in eclipse. If this does already exist somewhere, please guide me to the right place, so I can try to implement this myself Thanks for your help. Best regards, Matthias
(In reply to Matthias Fuchs from comment #0) > I've already file a bug at the plugins github issues: > https://github.com/groovy/groovy-eclipse/issues/569 > > But I was told, that this is an issue with Eclipse JDT and to file a bug > here :-) From original bug Groovy-eclipse wants this: "an extension mechanism to provide support to use any JVM language for expression evaluation". I doubt the JDT debug maintainers have time/interest to work on this, but this does not mean it is not a valid request. Someone who needs that must identify places that need to be extended and provide a plan how to fix that and a Gerrit patch following https://wiki.eclipse.org/Platform/How_to_Contribute
One step in the right direction would be to find all the places in JDT that create a CompilationUnit from source using ASTParser. There are several instances of this where the unit name is not set. making it difficult to determine within the parser if it is Java source being parsed or another JVM language. I have had to fall back on regex matching against the source text to see if I can determine it is Groovy source. One such example is in RunToLineAdapter: ASTParser parser = ASTParser.newParser(AST.JLS9); parser.setSource(document.get().toCharArray()); // missing: parser.setUnitName(typeRoot.getElementName()); or maybe document has the comp unit name CompilationUnit compilationUnit= (CompilationUnit)parser.createAST(null);
One clarification, the need for setUnitName(String) is only when using setSource(char[]).
Specifically for the Expressions evaluation to support other languages, 4 changes are required: 1) In org.eclipse.jdt.internal.debug.eval.ast.engine.EvaluationSourceGenerator#createEvaluationSourceFromSource, parser.setUnitName() must be called (near parser.setSource(...);). parser.setUnitName(type.getCompilationUnit().getPath().toString()); works for source units. I did not have a chance to try binary units. 2) In org.eclipse.jdt.internal.debug.eval.ast.engine.EvaluationSourceGenerator#createEvaluationSourceFromSource or org.eclipse.jdt.internal.debug.eval.ast.engine.SourceBasedSourceGenerator#buildCompilationUnit, the unit name "Eval" needs the same file extension as the unit name that was parsed for context. 3) In org.eclipse.jdt.internal.debug.eval.ast.engine.SourceBasedSourceGenerator#buildRunMethod, the method return type "void " needs to be replaced with "Object " to avoid compilation error "Cannot use return statement with an expression on a method that returns void". 4) In org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine#createExpressionFromAST, some change is required to get the instructions for the generated method from the GroovyCompilationUnit. If this change is not made, this method is returning "[no op]" and so all debug evaluations display "null".
For (4) in previous comment, I have a hook in GroovyCompilationUnit that requires implementation: public class GroovyCompilationUnit extends CompilationUnit { /** * sneaky... required because we cannot get in the jdt.debug code and change it. Here the plan is that if the debug * MethodSearchVisitor is being used we don't find the method. If it was found the body would be empty and the debug code would * think the method has not changed across builds - when it may have. It is empty because we don't parse below the method level * for groovy. * */ @Override protected void accept0(ASTVisitor visitor) { switch (visitor.getClass().getName()) { case "org.eclipse.jdt.internal.debug.core.hcr.MethodSearchVisitor": return; case "org.eclipse.jdt.internal.debug.eval.ast.engine.ASTInstructionCompiler": // TODO } super.accept0(visitor); } Note: Special handling is required because Groovy Development Tools (GDT) only create enough JDT model data for joint compilation. This is similar to creating Java stubs during groovyc (or what APT might do for Java). Methods are defined with empty bodies and so there are no debug instructions available naturally for the eval engine to harvest and execute.
Here are some additional uses of parser.setSource(char[]) that lack a call to setUnitName(...) org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.createParser(int) org.eclipse.jdt.ui.wizards.NewTypeWizardPage.constructCUContent(ICompilationUnit, String, String) org.eclipse.jdt.internal.core.CreateTypeMemberOperation.generateElementAST(ASTRewrite, ICompilationUnit) org.eclipse.jdt.internal.core.CreateTypeMemberOperation.generateSyntaxIncorrectAST() org.eclipse.jdt.internal.core.SortElementsOperation.processElement(ICompilationUnit, char[])