Injecting hidden synthetic imports for code completion


I am hoping to use Idea's code editor and the Scala plugin as the basis for a Scala Worksheet-like interactive exploratory environment I'm building.

For my project I'd like to define a standard prologue of import statements that should be executed before the user's script contents. To avoid noise / clutter, this prolog shouldn't be visible in the user's script.  But I'd like to somehow have these imports processed so that code completion works properly in the editor.

I've managed to get a basic setup with a custom plugin that has the Scala plugin as a dependency.

My rough thinking was that I would just prepend the relevant "import X.Y.Z" statement to the editor contents.  But that seems like a bit of a non-starter now that I've examined the implementation of the Scala plugin a bit more, since the interactions of text editing, lexing, parsing and semantic processing seem tightly integrated.  A slightly more plausible approach seems to be constructing an ASTNode for the import statements I want to have processed and try to persuade the parser in the Scala plugin to process that.  Or just directly manipulate the symbol tables that are updated when processing import statement.  But I've thus far been unable to determine if either is feasible or what actual code to write.

I've studied the Scala plugin and the implementation of Scala PSI files and the (rather involved) ScalaCompletionContributor a bit. It appears that import statement processing happens in scala/lang/psi/impl/toplevel/imports/ScImportStmt.scala in the processDeclarations method, but it's not clear to me what state is being updated by that method, how or when it's called, or how the ScalaCompletionContributor interacts with that state.

Any pointers / suggestions on how to go about this would be much appreciated.


   -Antony Courtney

Comment actions Permalink

Hi, Antony,

There are two ways to do what you want. ScalaFileImpl contains two methods:

protected def implicitlyImportedPackages: Seq[String] = Seq.empty

protected def implicitlyImportedObjects: Seq[String] = Seq.empty

You can override them in your inheritor of ScalaFileImpl (like SbtFile for example)
Only problem is that it's wildcard imports and additionally it will have lower priority than explicit imports (when two classes with same name will be imported, so IDEA will highlight as green, compiler will fail).

If this approach is not ok for you, just say, we will try to find something better.

Best regards,
Alexander Podkhalyuzin.

Comment actions Permalink

Apologies for long-delayed reply. This suggestion worked perfectly, thank you!


Please sign in to leave a comment.