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 ?
Please sign in to leave a comment.
Forgot to say i'm still on 6.0.6
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 ?
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.
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..
Does file.getViewProvider().getBaseLanguage() return your language?
Is file.getViewProvider() instanceof SingleRootFileViewProvider?
The answer is yes to both questions...
getRealFileType() instanceof LanguageFileType ? (if no, please make it,
this may help)
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?
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.
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?
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.
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....
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.
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)?
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...
What exactly you want to change?
Hugo Palma wrote:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
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.
AFAIK External validator works only for XML / XHTML / Jspx
Hugo Palma wrote:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
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 ?
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:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
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 ?
External Annotator uses Xerces to validate the document. Xerces do not
accept anything but Xml / XHtml
Hugo Palma wrote:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
Can you then please tell me what external annotator the HtmlLanguage is using ?
It inherits external annotator from xml language but the annotator does
not process with Html file actually.
Hugo Palma wrote:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
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.
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:
--
Best regards,
Maxim Mossienko
IntelliJ Labs / JetBrains Inc.
http://www.intellij.com
"Develop with pleasure!"
Alternatively, it is possible to configure additional html tags /
attributes (in corresponding inspection properties)
Maxim Mossienko (JetBrains) 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!"