Hooking up the PsiParser?

I'm trying to get my (partially implemented and totally broken) parser hooked in so I can start playing around with it.  Do I need to register the parser explicitly?

I ended up registering the sytnax highlighter explicitly (following some code from the javascript plugin):


public class FooSupport implements ApplicationComponent {

  public LangSupport() {
  }

  public void initComponent() {
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      public void run() {
        FileTypeManager.getInstance().registerFileType(new FooFileType( FooLanguage.getInstance() ), "gs");
        SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(FooLanguage.getInstance(), new FooHighlighterFactory());
      }
    });
  }

  public void disposeComponent() {
  }

  @NotNull
  public String getComponentName() {
    return "FooSupport";
  }

  public static FooSupport getInstance() {
    return ApplicationManager.getApplication().getComponent(FooSupport.class);
  }

}


I could add this as well:

        LanguageParserDefinitions.INSTANCE.addExplicitExtension(FooLanguage.getInstance(), new FooParserDefinition());


Unfortunately, just putting these entries in plugin.xml didn't seem to have much effect:

  <extensions defaultExtensionNs="com.guidewire.intellij">
    <lang.parserDefinition language="Foo" implementationClass="foo.FooParserDefinition"/>  
    <syntaxHighlighter key="Foo" factoryClass="foo.FooSyntaxHighlighterFactory"/>
  </extensions>


I feel like I'm definitely doing it wrong, so any pointers would be appreciated.

Cheers,
Carson

5 comments
Comment actions Permalink

Hello Carson,

Unfortunately, just putting these entries in plugin.xml didn't seem to
have much effect:

<extensions defaultExtensionNs="com.guidewire.intellij">


The namespace must be "com.intellij" here. This is the namespace in which
the extension point names are defined, not the namespace of your classes.

--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Thanks Dmitry, I'll fix that.  Ive managed to get myself to a state where my application plugin isn't getting loaded up (yay) so I'll report back once I get this straightened out.

You know, this would go a lot faster if you'd just come to my desk in San Mateo, CA and pair with me.  <smile/>

Cheers,
Carson

0
Comment actions Permalink

OK, I've got things loading in the orthodox manner from plugin.xml:

  <extensions defaultExtensionNs="com.intellij">
    <fileTypeFactory implementation="foo.FooFileTypeFactory"/>
    <lang.parserDefinition language="Foo" implementationClass="foo.FooParserDefinition"/>
    <syntaxHighlighter key="Foo" factoryClass="foo.FooSyntaxHighlighterFactory"/>
  </extensions>


To get syntax highlighting to work, I still had to explicitly register the highlighter in the language definition (like the javascript plugin does):

    SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
      @NotNull
      protected SyntaxHighlighter createHighlighter() {
        return new FooHighlighter();
      }
    });


I know my parser definition is being loaded because the constructor is called, but createParser() and createLexer() are never called on it when I open up a file.  Something is obviously not hooked up correctly.  I've got the fileTypeFactory producing a LanguageFileType.  Does "getName()" on that need to match up with the language name?  (I tried that and it didn't seem to work.)

Anywhere I can set a breakpoint to see why the editor isn't loading up my plugin?

Thanks,
Carson

0
Comment actions Permalink

OK, I've stumbled a bit further.  I wasn't returning a PsiFile correctly in my ParserDefinition.  I've now got a very simple one that looks like this:

public class PsiFooFile extends PsiFileBase implements PsiFile {

  public PsiFooFile(FileViewProvider viewProvider) {
    super(viewProvider, FooLanguage.getInstance());
  }

  @NotNull
  public FileType getFileType() {
    return FooFileTypeFactory.GSCRIPT_FILE_TYPE;
  }
}


Unfortunately, I get a stack exception in the super constructor:

com.intellij.psi.impl.PsiManagerImpl cannot be cast to com.intellij.psi.impl.PsiManagerEx
java.lang.ClassCastException: com.intellij.psi.impl.PsiManagerImpl cannot be cast to com.intellij.psi.impl.PsiManagerEx
    at com.intellij.psi.impl.source.PsiFileImpl.<init>(PsiFileImpl.java:348)
    at com.intellij.extapi.psi.PsiFileBase.<init>(PsiFileBase.java:5)
    at foo.PsiFooFile.<init>(PsiFooFile.java:12)
    at foo.FooParserDefinition.createFile(FooParserDefinition.java:56)
    at com.intellij.psi.SingleRootFileViewProvider.createFile(SingleRootFileViewProvider.java:180)
    at com.intellij.psi.SingleRootFileViewProvider.creatFile(SingleRootFileViewProvider.java:79)
    at com.intellij.psi.SingleRootFileViewProvider.c(SingleRootFileViewProvider.java:175)
    at com.intellij.psi.SingleRootFileViewProvider.getPsiInner(SingleRootFileViewProvider.java:115)
    at com.intellij.psi.SingleRootFileViewProvider.getPsi(SingleRootFileViewProvider.java:23)
    at com.intellij.psi.impl.file.impl.FileManagerImpl.findFile(FileManagerImpl.java:56)


In order to make all this work, I've had to add idea.jar to the project and move it ahead of the default plugin project dependency on IDEA.  Looking at the javascript plugin, it looks like they had to have done this as well.

The only way around this class cast exception I can guess at without the source code is to override the getManager() method on PsiFooFile.  Is that the correct direction to go?  Or am I still doing it wrong?

Thanks,
Carson

0
Comment actions Permalink

Heh.  Nevermind.  RTFM (http://www.jetbrains.com/idea/plugins/developing_custom_language_plugins.html):

The base classes for the PSI implementation (PsiFileBase, the base implementation of PsiFile, and ASTWrapperPsiElement, the base implementation of PsiElement) are provided by IDEA. However, these classes are coupled to the internal implementation of IDEA and are located in idea.jar. Because of this, every custom language plugin needs to include idea.jar in its classpath. (If the plugin is built as a DevKit project, idea.jar must be added to the list of JARs in the classpath of the IDEA SDK, and not added as a separate module or project library. Otherwise, the plugin will not work correctly.)


On to parsing.

Cheers,
Carson

0

Please sign in to leave a comment.