Autocompletion with custom language error

I'm creating a new language but i'm trying to reuse some components from the XML and HTML languages. So i have a simple FileType that extends XmlLikeFileType and that in the constructor creates the instance of my Language. My language class now looks like this:

public class MyTemplateLanguage extends XMLLanguage {
public MyTemplateLanguage() {
super("MyTemplateLanguage", "text/html");
}

@NotNull
public SyntaxHighlighter getSyntaxHighlighter(Project project, VirtualFile virtualFile) {
return new HtmlFileHighlighter();
}

public XmlPsiPolicy getPsiPolicy() {
return ENCODE_EACH_SYMBOL_POLICY;
}

public ParserDefinition getParserDefinition() {
return new HTMLParserDefinition();
}

@Nullable
public Annotator getAnnotator() {
return null;
}
}

Everything seems to work acording to plan except auto-completion. If i try to auto-complete any html attribute i get an exception:

java.lang.NullPointerException
at com.intellij.psi.impl.source.PsiFileImpl.clone(PsiFileImpl.java:7)
at com.intellij.psi.impl.source.PsiFileImpl.clone(PsiFileImpl.java:134)
at com.intellij.psi.impl.source.TreeWrapperPsiElement.copy(TreeWrapperPsiElement.java:14)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase.createFileCopy(CodeCompletionHandlerBase.java:78)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase.a(CodeCompletionHandlerBase.java:121)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase.access$100(CodeCompletionHandlerBase.java:82)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase$2.compute(CodeCompletionHandlerBase.java:1)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase$2.compute(CodeCompletionHandlerBase.java:2)
at com.intellij.openapi.application.impl.ApplicationImpl$10.run(ApplicationImpl.java:1)
at com.intellij.openapi.application.impl.ApplicationImpl$9.compute(ApplicationImpl.java:1)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.postponeFormattingInside(PostprocessReformattingAspect.java:167)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:71)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:295)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase.getLookupData(CodeCompletionHandlerBase.java:162)
at com.intellij.codeInsight.completion.CodeCompletionHandlerBase.invoke(CodeCompletionHandlerBase.java:144)
at com.intellij.codeInsight.actions.CodeInsightAction$1$1.run(CodeInsightAction.java:41)
at com.intellij.openapi.application.impl.ApplicationImpl$9.compute(ApplicationImpl.java:1)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.postponeFormattingInside(PostprocessReformattingAspect.java:167)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:71)
at com.intellij.codeInsight.actions.CodeInsightAction$1.run(CodeInsightAction.java:45)
at com.intellij.openapi.command.impl.CommandProcessorImpl.executeCommand(CommandProcessorImpl.java:111)
at com.intellij.openapi.command.impl.CommandProcessorImpl.executeCommand(CommandProcessorImpl.java:2)
at com.intellij.codeInsight.actions.CodeInsightAction.actionPerformedImpl(CodeInsightAction.java:36)
at com.intellij.codeInsight.completion.actions.CodeCompletionAction.actionPerformedImpl(CodeCompletionAction.java:4)
at com.intellij.codeInsight.actions.CodeInsightAction.actionPerformed(CodeInsightAction.java:25)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.a(IdeKeyEventDispatcher.java:211)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.b(IdeKeyEventDispatcher.java:55)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:67)
at com.intellij.ide.IdeEventQueue.a(IdeEventQueue.java:37)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:83)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)


Any ideas ?

0
44 comments

Forgot to say i'm still on 6.0.6

0

This actually happens with the simplest of FileTypes, i don't even need to have a Language. If i just register this file type:

public class MyFileType implements FileType {
public static final String DEFAULT_EXTENSION = "tml";

public boolean isBinary() {
return false;
}

public boolean isReadOnly() {
return false;
}

@Nullable
@NonNls
public String getCharset(@NotNull VirtualFile file) {
return "UTF-8";
}

@Nullable
public SyntaxHighlighter getHighlighter(@Nullable Project project, final VirtualFile virtualFile) {
return null;
}

@Nullable
public StructureViewBuilder getStructureViewBuilder(@NotNull VirtualFile file, @NotNull Project project) {
return null;
}

@NotNull
@NonNls
public String getName() {
return "MyFileType";
}

@NotNull
public String getDescription() {
return "MyDescription";
}

@NotNull
@NonNls
public String getDefaultExtension() {
return DEFAULT_EXTENSION;
}

@Nullable
public Icon getIcon() {
return null;
}
}

i start getting the exception when i press CTRL+SPACE on the file. I must be missing something really basic here but i can't figure out what.

Any help please ?

0
Avatar
Permanently deleted user

Seems that file.getViewProvider().clone().getPsi(file.getLanguage()) ==
null. This may happen if
FileTypeManager.getInstance().getFileTypeByFile(file.getViewProvider().getVirtualFile())
returns something unexpected (probably UnknownFileType), if you, for
example, didn't register your default extension with FileTypeManager
explicitly. So you should check this stuff first.

0

file.getViewProvider().clone().getPsi(file.getLanguage()) does return null.

But FileTypeManager.getInstance().getFileTypeByFile(file.getViewProvider().getVirtualFile()) does return the correct FileType. Plus i am registering the extension using FileTypeManager.getInstance().associateExtension.

Any idea on other conditions that can cause file.getViewProvider().clone().getPsi(file.getLanguage()) returning null ?

Thanks..

0
Avatar
Permanently deleted user

Does file.getViewProvider().getBaseLanguage() return your language?
Is file.getViewProvider() instanceof SingleRootFileViewProvider?

0

The answer is yes to both questions...

0
Avatar
Permanently deleted user

The answer is yes to both questions...


getRealFileType() instanceof LanguageFileType ? (if no, please make it,
this may help)

0

I can't find any getRealFileType() method...

In what class is that method defined ?

0
Avatar
Permanently deleted user

I can't find any getRealFileType() method...

In what class is that method defined ?


Oops, it's private. It will be equal to
viewProvider.clone().getVirtualFile().getFileType(). What's its value?

0

It returns my language, as it should i think.........

0
Avatar
Permanently deleted user

It returns my language, as it should i think.........

You mean your LanguageFileType?

OK then. Let's debug your copied viewProvider. First, invoke
provider.getPsi(provider.getBaseLanguage()). Then
provider.getKnownTreeRoots() (it's not in openapi, but you should be
able to invoke it from debugger) and describe what you see.

0

Yes, the LanguageFileType.

Ok, here what i get:

provider.getPsi(provider.getBaseLanguage()):

I get an instance of a PsiPlainTextFileImpl. The language of this element is TEXT.


provider.getKnownTreeRoots()

I get a one element array. The only value in it is an instance of PlainTextFileElement

0
Avatar
Permanently deleted user

Yes, the LanguageFileType.

Ok, here what i get:

provider.getPsi(provider.getBaseLanguage()):

I get an instance of a PsiPlainTextFileImpl. The language of this element is TEXT.


provider.getKnownTreeRoots()

I get a one element array. The only value in it is an instance of PlainTextFileElement


Is your ParserDefinition.createFile(viewProvider) called and return
non-null PsiFile? Isn't your file VERY large?

0
Avatar
Permanently deleted user

Yes, the LanguageFileType.

Ok, here what i get:

provider.getPsi(provider.getBaseLanguage()):

I get an instance of a PsiPlainTextFileImpl. The language of this element is TEXT.


provider.getKnownTreeRoots()

I get a one element array. The only value in it is an instance of PlainTextFileElement

Hugo,

If that's part of an opensource project (Tapestry plug-in?), why don't just point the entire
source code(subversion project) where this happens so that Jetbrains can try the entire thing?

just an idea...

Ahmed.

0

I was actually now trying out without a getParserDefinition() in my language. So the parser is null. But if i define this in my language:

public ParserDefinition getParserDefinition() {
return new HTMLParserDefinition();
}

I get the exact same error. Only the answer to your last question changes. provider.getPsi(provider.getBaseLanguage()) now returns an instance of HtmlFileImpl and provider.getKnownTreeRoots() return a 1 element array with a HtmlFileElement instance.

The file i'm using using is very small. It's two lines long.
Can i send you the project so you can test it ? It's only 3 files really....

0

This is for the Tapestry plugin but the plugin is no longer open-source.

Althought the code that replicates my problem is really simple and i now have a small plugin module with 3 files that replicates this.

0
Avatar
Permanently deleted user

I was actually now trying out without a getParserDefinition() in my language. So the parser is null. But if i define this in my language:

public ParserDefinition getParserDefinition() {
return new HTMLParserDefinition();
}

I get the exact same error. Only the answer to your last question changes. provider.getPsi(provider.getBaseLanguage()) now returns an instance of HtmlFileImpl and provider.getKnownTreeRoots() return a 1 element array with a HtmlFileElement instance.

The file i'm using using is very small. It's two lines long.
Can i send you the project so you can test it ? It's only 3 files really....


No need anymore. Without ParserDefinition you will get PsiPlainTextFile.
So you should have one, implement createFile() there create your own
PsiFile. But seems to me that this isn't necessary. Why do you need your
own custom file type at all (if I understand correctly, this is just HTML)?

0

It's not quite HTML. I want to use the HTML parser and highlighter and everything else but i don't want to use the XMLExternalAnnotator because it annotates errors that aren't errors in Tapestry templates.

So my solution would be to implement a custom language, that gets all those components from the HtmlLanguage and then implements it's own ExternalAnnotator.
If there's any other way to do this i'd really appreciate some ideas...

0
Avatar
Permanently deleted user

What exactly you want to change?

Hugo Palma wrote:

It's not quite HTML. I want to use the HTML parser and highlighter and everything else but i don't want to use the XMLExternalAnnotator because it annotates errors that aren't errors in Tapestry templates.

So my solution would be to implement a custom language, that gets all those components from the HtmlLanguage and then implements it's own ExternalAnnotator.
If there's any other way to do this i'd really appreciate some ideas...



--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

I can see that your annotator ultimately validates the document by calling ExternalDocumentValidator.doValidation.

In the implementation of that method you have code there that does exactly what i'd like it to do for Tapestry, only you've done it for JSF and for ANT. You're not validating against the DTD if you indicate the ANT or JSF namespace in the root element. I would also like that behaviour when i specify the Tapestry namespace in the root element.

I'm guessing you won't change that code to support Tapestry, at least not in the 6.x branch so i'm looking for a way around it.

0
Avatar
Permanently deleted user

AFAIK External validator works only for XML / XHTML / Jspx

Hugo Palma wrote:

I can see that your annotator ultimately validates the document by calling ExternalDocumentValidator.doValidation.

In the implementation of that method you have code there that does exactly what i'd like it to do for Tapestry, only you've done it for JSF and for ANT. You're not validating against the DTD if you indicate the ANT or JSF namespace in the root element. I would also like that behaviour when i specify the Tapestry namespace in the root element.

I'm guessing you won't change that code to support Tapestry, at least not in the 6.x branch so i'm looking for a way around it.



--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

That's right.

That's why i need to provide a different annotator.
So i guess the question is how can i either change the annotator the the HtmlLanguage is using or create a new language all together that is exactly the same as the Html one but has a different extension and a different annotator ?

0
Avatar
Permanently deleted user

To put previous message another way, external annotator is not used for
html and if you want to change this behavior you can write an inspection
for that.

Hugo Palma wrote:

That's right.

That's why i need to provide a different annotator.
So i guess the question is how can i either change the annotator the the HtmlLanguage is using or create a new language all together that is exactly the same as the Html one but has a different extension and a different annotator ?



--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

I'm sorry but i think it is. HtmlLanguage extends XmlLanguage and the HtmlLanguage doesn't define it's own external annotator, so i think this means that it's using the external annotator from the XmlLanguage. Which in turn uses ExternalDocumentValidator.

An inspection only annotates documents further, it doesn't allow me to remove errors from the document right ?

0
Avatar
Permanently deleted user

External Annotator uses Xerces to validate the document. Xerces do not
accept anything but Xml / XHtml

Hugo Palma wrote:

I'm sorry but i think it is. HtmlLanguage extends XmlLanguage and the HtmlLanguage doesn't define it's own external annotator, so i think this means that it's using the external annotator from the XmlLanguage. Which in turn uses ExternalDocumentValidator.

An inspection only annotates documents further, it doesn't allow me to remove errors from the document right ?


--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

Can you then please tell me what external annotator the HtmlLanguage is using ?

0
Avatar
Permanently deleted user

It inherits external annotator from xml language but the annotator does
not process with Html file actually.

Hugo Palma wrote:

Can you then please tell me what external annotator the HtmlLanguage is using ?


--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

Who is validating that my HTML document is conforming to the provided namespaces then ? There must be an annotator because i'm getting the errors on normal HTML files, not XML or XHTML.

0
Avatar
Permanently deleted user

Ah, now I understand your intent better, IDEA uses internal annotator
for any xml file and it is not possible to switch it off (except using
Hector). But it is possible to plug in own schema for the xml.
You need to add own binding context -> XmlNSDescriptor to MetaRegistry
or/and specify XmlFileNSInfoProvider (see XmlUtil.getDefaultNamespaces)

Hugo Palma wrote:

Who is validating that my HTML document is conforming to the provided namespaces then ? There must be an annotator because i'm getting the errors on normal HTML files, not XML or XHTML.


--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0
Avatar
Permanently deleted user

Alternatively, it is possible to configure additional html tags /
attributes (in corresponding inspection properties)

Maxim Mossienko (JetBrains) wrote:

Ah, now I understand your intent better, IDEA uses internal annotator
for any xml file and it is not possible to switch it off (except using
Hector). But it is possible to plug in own schema for the xml.
You need to add own binding context -> XmlNSDescriptor to MetaRegistry
or/and specify XmlFileNSInfoProvider (see XmlUtil.getDefaultNamespaces)

Hugo Palma wrote:

>> Who is validating that my HTML document is conforming to the provided
>> namespaces then ? There must be an annotator because i'm getting the
>> errors on normal HTML files, not XML or XHTML.




--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"

0

Please sign in to leave a comment.