Extract binding variable declarations/types/values from separate Groovy script

Answered

Hi,

Is it possible to extract the final assigned values, or at least types, of binding variables defined in a simple Groovy script? I have scripts that run in an environment where there is a "source(String)" method available to evaluate additional scripts, loaded from a configurable location. I would like a script that source()s another file to be aware of binding variables set in the other file.

For example, I have a script "test1.groovy":

testVar1 = 42        // create binding variable 'testVar1' as an Integer
testVar1 = { String x, int y -> return "X: $y" } // redefine 'testVar1' as a Closure
int testVar1 = 42 // this a _scope_ variable so it should be ignored
testVar1 = 43 // still modifying the scope variable, not binding variable, so should be ignored

And another script, which my plugin will process, called "test2.mygroovy":

source("test1.groovy") // the plugin 
testVar2 = testVar1(42)

In "test2.mygroovy", I'd like the IDE to be aware of four things (in order of importance):

  1. That `testVar1` exists at all
  2. That `testVar1` is declared in test1.groovy
  3. That the inferred type of `testVar1` is a closure
  4. That the correct arguments for `testVar1` are a String and an int.

(I also want it to be able to find test1.groovy, based on paths configured in the plugin settings, which I believe I can easily accomplish with a `com.intellij.psi.referenceContributor` extension.)

 

I think this is very loosely similar to how in Java, the IDE is smart enough to determine the runtime values and raise warnings in simple code like this:

int testFun() {
int x = 42;
x = 43;
Object y = null;
if(x == 42) { // This will raise a constant condition warning
y = 0;
} else {
y = 0.0;
}

if(y instanceof Integer) { // This will also raise a constant condition warning
return 0;
} else {
return 1;
}
}

 

Of course there are vastly more complex potential cases — e.g. calling `source()` twice with two different scripts that define the same variables, or calling source() twice where the second script conditionally sets variables based on values defined in the first, or scripts that inadvertently source each other recursively — but to start I would be happy to accurately get references to the top-level assignments from the source()'d scripts.

 

I am trying to work out the extensions I need to implement. Beyond the `com.intellij.psi.referenceContributor` extension to detect the `source()` call and contribute a reference for its argument, I am not sure of the best approach.

My sense is that I need a visitor — not sure which extension point to use — that looks at the ".mygroovy" files for these `source()` calls and adds their declarations to the file's resolve scope. Will I also need a a visitor to determine the declarations from the file (#1-3 above, I think) and/or to retrieve information about the values (e.g. the closure and its arguments)? If I implement such a visitor, would you expect that I'd be able to handle some of the more complex cases described above?

I already have an `org.intellij.groovy.membersContributor` extension (NonCodeMembersContributor) to handle a few default binding variables, and an `org.intellij.groovy.importContributor` extension (GrImportContributor) to include some default imports, but they don't seem like the right fit for the rest of the work.

 

Does it sound like I'm on the right track? Is this generally feasible?

 

Thanks for your help!

1 comment
Comment actions Permalink

Sorry this got lost. Is this still actual?

0

Please sign in to leave a comment.