From 8a4911fdd4193f6327924a8703249a029605f6a1 Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Sun, 23 Oct 2022 20:35:32 +0200 Subject: [PATCH] Prevent NPE when analyzing natural language text in IntelliJ 2022.3 (#1204) --- CHANGELOG.adoc | 4 +++ .../intellij/actions/asciidoc/MakeLink.java | 12 ++++----- .../AsciiDocAddBlockIdToSection.java | 2 +- .../AsciiDocAdmonitionToBlockIntention.java | 6 ++--- .../AsciiDocCompletionContributor.java | 12 ++++----- .../editor/ExtendWordSelectionHandler.java | 8 +++--- .../AsciiDocFindUsagesProvider.java | 2 +- .../AsciiDocReferenceContributor.java | 8 +++--- .../folding/AsciiDocFoldingBuilder.java | 4 +-- .../grazie/AsciiDocGrazieTextExtractor.java | 12 ++++----- .../grazie/AsciiDocLanguageSupport.java | 18 ++++++------- .../LanguageListCompletionContributor.java | 2 +- ...ciiDocAttributeContinuationInspection.java | 4 +-- .../AsciiDocHorizontalRuleInspection.java | 4 +-- .../AsciiDocListingStyleInspection.java | 3 +++ .../AsciiDocPageBreakInspection.java | 4 +-- .../AsciiDocPassthroughInspection.java | 4 +-- .../asciidoc/intellij/psi/AsciiDocBlock.java | 5 +++- .../intellij/psi/AsciiDocBlockMacro.java | 16 ++++++------ .../intellij/psi/AsciiDocHeading.java | 8 ++---- .../psi/AsciiDocIncludeTagInDocument.java | 5 ++-- .../intellij/psi/AsciiDocInlineMacro.java | 8 +++--- .../asciidoc/intellij/psi/AsciiDocLink.java | 26 +++---------------- .../intellij/psi/AsciiDocListing.java | 4 +-- .../asciidoc/intellij/psi/AsciiDocRef.java | 8 +++--- .../intellij/psi/PageAttributeProcessor.java | 10 +++---- .../AsciiDocAddAdocExtensionToXref.java | 2 +- 27 files changed, 94 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 55dd29a58..3342732b1 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -9,6 +9,10 @@ This document provides a high-level view of the changes introduced by release. === 0.37.53 +- Prevent NPE when analyzing natural language text (#1204) + +=== 0.37.53 + - Allow ID attribute on all macros, for example on images - Resolve `+++file:///+++` URIs to local files when auto-completing in the editor. diff --git a/src/main/java/org/asciidoc/intellij/actions/asciidoc/MakeLink.java b/src/main/java/org/asciidoc/intellij/actions/asciidoc/MakeLink.java index 4ad73ba53..13dcff325 100644 --- a/src/main/java/org/asciidoc/intellij/actions/asciidoc/MakeLink.java +++ b/src/main/java/org/asciidoc/intellij/actions/asciidoc/MakeLink.java @@ -79,7 +79,7 @@ protected void selectText(Editor editor) { PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument()); if (psiFile != null) { PsiElement statementAtCaret = AsciiDocUtil.getStatementAtCaret(editor, psiFile); - if (statementAtCaret != null && (statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK + if (statementAtCaret != null && statementAtCaret.getNode() != null && (statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK || statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_EMAIL)) { int start = statementAtCaret.getTextOffset(); int end = statementAtCaret.getTextOffset() + statementAtCaret.getTextLength(); @@ -124,7 +124,7 @@ private boolean isLink(Editor editor) { PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument()); if (psiFile != null) { PsiElement statementAtCaret = psiFile.findElementAt(editor.getSelectionModel().getSelectionStart()); - return statementAtCaret != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK; + return statementAtCaret != null && statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK; } } return false; @@ -135,7 +135,7 @@ private boolean isEmail(Editor editor) { PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument()); if (psiFile != null) { PsiElement statementAtCaret = psiFile.findElementAt(editor.getSelectionModel().getSelectionStart()); - return statementAtCaret != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_EMAIL; + return statementAtCaret != null && statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_EMAIL; } } return false; @@ -147,9 +147,9 @@ private void removeUrlStartEnd(Editor editor) { PsiDocumentManager.getInstance(editor.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument()); if (psiFile != null) { PsiElement statementAtCaret = psiFile.findElementAt(editor.getSelectionModel().getSelectionStart()); - if (statementAtCaret != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK) { - if (statementAtCaret.getPrevSibling() != null && statementAtCaret.getPrevSibling().getNode().getElementType() == AsciiDocTokenTypes.URL_START - && statementAtCaret.getNextSibling() != null && statementAtCaret.getNextSibling().getNode().getElementType() == AsciiDocTokenTypes.URL_END) { + if (statementAtCaret != null && statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK) { + if (statementAtCaret.getPrevSibling() != null && statementAtCaret.getPrevSibling().getNode() != null && statementAtCaret.getPrevSibling().getNode().getElementType() == AsciiDocTokenTypes.URL_START + && statementAtCaret.getNextSibling() != null && statementAtCaret.getNextSibling().getNode() != null && statementAtCaret.getNextSibling().getNode().getElementType() == AsciiDocTokenTypes.URL_END) { statementAtCaret.getPrevSibling().delete(); statementAtCaret.getNextSibling().delete(); PsiDocumentManager.getInstance(editor.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument()); diff --git a/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAddBlockIdToSection.java b/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAddBlockIdToSection.java index 2cf7e168c..044304a29 100644 --- a/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAddBlockIdToSection.java +++ b/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAddBlockIdToSection.java @@ -47,7 +47,7 @@ public static AsciiDocSection getSectionWithoutBlockIdAtCursor(PsiFile file, Edi return null; } } - if (statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.HEADING_TOKEN) { + if (statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() == AsciiDocTokenTypes.HEADING_TOKEN) { statementAtCaret = statementAtCaret.getParent(); } if (!(statementAtCaret instanceof AsciiDocSection)) { diff --git a/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAdmonitionToBlockIntention.java b/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAdmonitionToBlockIntention.java index 0986a1598..7956b4f8d 100644 --- a/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAdmonitionToBlockIntention.java +++ b/src/main/java/org/asciidoc/intellij/actions/intentions/AsciiDocAdmonitionToBlockIntention.java @@ -28,7 +28,7 @@ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file if (statementAtCaret == null) { return false; } - if (statementAtCaret.getNode().getElementType() != AsciiDocTokenTypes.ADMONITION) { + if (statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() != AsciiDocTokenTypes.ADMONITION) { return false; } return true; @@ -40,7 +40,7 @@ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws if (statementAtCaret == null) { return; } - if (statementAtCaret.getNode().getElementType() != AsciiDocTokenTypes.ADMONITION) { + if (statementAtCaret.getNode() != null && statementAtCaret.getNode().getElementType() != AsciiDocTokenTypes.ADMONITION) { return; } PsiElement loop = statementAtCaret.getNextSibling(); @@ -66,7 +66,7 @@ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws } else { onNewLine = false; } - if (loop instanceof AsciiDocBlock || loop.getNode().getElementType() == AsciiDocTokenTypes.CONTINUATION) { + if (loop instanceof AsciiDocBlock || (loop.getNode() != null && loop.getNode().getElementType() == AsciiDocTokenTypes.CONTINUATION)) { break; } buffer.append(loop.getText()); diff --git a/src/main/java/org/asciidoc/intellij/completion/AsciiDocCompletionContributor.java b/src/main/java/org/asciidoc/intellij/completion/AsciiDocCompletionContributor.java index 72b0569cf..e52ac3640 100644 --- a/src/main/java/org/asciidoc/intellij/completion/AsciiDocCompletionContributor.java +++ b/src/main/java/org/asciidoc/intellij/completion/AsciiDocCompletionContributor.java @@ -35,7 +35,7 @@ public void beforeCompletion(@NotNull CompletionInitializationContext context) { int offset = context.getStartOffset(); PsiElement element = context.getFile().findElementAt(offset); - if (element != null) { + if (element != null && element.getNode() != null) { if (element.getNode().getElementType() == AsciiDocTokenTypes.ATTRIBUTE_NAME) { // the identifier end offset needs to be set as otherwise an id containing a "-" will not be replaced context.getOffsetMap().addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getTextOffset() + element.getTextLength()); @@ -47,8 +47,8 @@ public void beforeCompletion(@NotNull CompletionInitializationContext context) { if (element.getNode().getElementType() == AsciiDocTokenTypes.ATTRIBUTE_REF) { PsiElement parent = element.getParent().getParent(); // help the autocomplete in AsciiDocFileReference to replace the full reference if it contains a nested attribute - if (parent.getNode().getElementType() == AsciiDocElementTypes.BLOCK_MACRO || parent.getNode().getElementType() == AsciiDocElementTypes.INLINE_MACRO - || parent.getNode().getElementType() == AsciiDocElementTypes.ATTRIBUTE_IN_BRACKETS) { + if (parent.getNode() != null && (parent.getNode().getElementType() == AsciiDocElementTypes.BLOCK_MACRO || parent.getNode().getElementType() == AsciiDocElementTypes.INLINE_MACRO + || parent.getNode().getElementType() == AsciiDocElementTypes.ATTRIBUTE_IN_BRACKETS)) { for (PsiReference reference : parent.getReferences()) { if (reference.getRangeInElement().shiftRight(parent.getTextOffset()).contains(element.getTextRange())) { context.getOffsetMap().addOffset(IDENTIFIER_FILE_REFERENCE, parent.getTextOffset() + reference.getRangeInElement().getEndOffset()); @@ -61,7 +61,7 @@ public void beforeCompletion(@NotNull CompletionInitializationContext context) { public AsciiDocCompletionContributor() { extend(CompletionType.BASIC, PlatformPatterns.psiElement().withElementType(AsciiDocTokenTypes.ATTRIBUTE_NAME).withLanguage(AsciiDocLanguage.INSTANCE), - new CompletionProvider() { + new CompletionProvider<>() { @Override public void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext processingContext, @NotNull CompletionResultSet resultSet) { @@ -75,7 +75,7 @@ public void addCompletions(@NotNull CompletionParameters parameters, @NotNull Pr int offset = insertionContext.getStartOffset(); PsiElement element = insertionContext.getFile().findElementAt(offset); if (element != null) { - if (element.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_NAME) { + if (element.getNode() != null && element.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_NAME) { // the finalizing : hasn't been entered yet, autocomplete it here offset += attribute.length(); insertionContext.getDocument().insertString(offset, ":"); @@ -94,7 +94,7 @@ public void addCompletions(@NotNull CompletionParameters parameters, @NotNull Pr } }); extend(CompletionType.BASIC, PlatformPatterns.psiElement().withElementType(AsciiDocTokenTypes.ATTR_VALUE).withLanguage(AsciiDocLanguage.INSTANCE), - new CompletionProvider() { + new CompletionProvider<>() { @Override public void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext processingContext, @NotNull CompletionResultSet resultSet) { diff --git a/src/main/java/org/asciidoc/intellij/editor/ExtendWordSelectionHandler.java b/src/main/java/org/asciidoc/intellij/editor/ExtendWordSelectionHandler.java index ddd1a39e8..8956b38b2 100644 --- a/src/main/java/org/asciidoc/intellij/editor/ExtendWordSelectionHandler.java +++ b/src/main/java/org/asciidoc/intellij/editor/ExtendWordSelectionHandler.java @@ -47,7 +47,7 @@ /** * Suggest word selections to the editor. - * See {@link com.intellij.codeInsight.editorActions.wordSelection.NaturalLanguageTextSelectioner} + * See com.intellij.codeInsight.editorActions.wordSelection.NaturalLanguageTextSelectioner * for more ideas. */ public class ExtendWordSelectionHandler extends ExtendWordSelectionHandlerBase { @@ -100,7 +100,7 @@ public List select(@NotNull PsiElement e, @NotNull CharSequence edito // expand start/endFormatting within paragraph while (startFormatting != null && endFormatting != null) { - while (startFormatting != null && + while (startFormatting != null && startFormatting.getNode() != null && !SYMMETRIC_FORMATTING.containsKey(startFormatting.getNode().getElementType()) && !startFormatting.getText().contains("\n")) { startFormatting = startFormatting.getPrevSibling(); @@ -108,7 +108,7 @@ public List select(@NotNull PsiElement e, @NotNull CharSequence edito if (startFormatting == null) { break; } - while (endFormatting != null && + while (endFormatting != null && startFormatting.getNode() != null && SYMMETRIC_FORMATTING.get(startFormatting.getNode().getElementType()) != endFormatting.getNode().getElementType() && !endFormatting.getText().contains("\n")) { endFormatting = endFormatting.getNextSibling(); @@ -124,7 +124,7 @@ public List select(@NotNull PsiElement e, @NotNull CharSequence edito if (endFormatting instanceof PsiWhiteSpace && endFormatting.getText().contains("\n")) { endOffset = -endFormatting.getTextLength() + endFormatting.getText().indexOf("\n"); } - if (SYMMETRIC_FORMATTING.get(startFormatting.getNode().getElementType()) == endFormatting.getNode().getElementType()) { + if (startFormatting.getNode() != null && SYMMETRIC_FORMATTING.get(startFormatting.getNode().getElementType()) == endFormatting.getNode().getElementType()) { // we might be looking at the identical token (for example a double quote) for start and end, // prevent to report this with its end first and start second, which would lead to an inverse and icorrect range if (startFormatting.getTextRange().getEndOffset() < endFormatting.getTextRange().getStartOffset()) { diff --git a/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocFindUsagesProvider.java b/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocFindUsagesProvider.java index 5b3fb1059..e3cd9e2f8 100644 --- a/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocFindUsagesProvider.java +++ b/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocFindUsagesProvider.java @@ -47,7 +47,7 @@ public String getDescriptiveName(@NotNull PsiElement element) { name = "???"; } } else { - name = "??? " + element.getNode().getElementType(); + name = "??? " + (element.getNode() != null ? element.getNode().getElementType() : element.getClass().getName()); } return name; } diff --git a/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocReferenceContributor.java b/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocReferenceContributor.java index 6a9ca3ffc..3caa4a5de 100644 --- a/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocReferenceContributor.java +++ b/src/main/java/org/asciidoc/intellij/findUsages/AsciiDocReferenceContributor.java @@ -46,7 +46,7 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) context) { int start = 0; PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_REF) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_REF) { start += child.getTextLength(); child = child.getNextSibling(); } @@ -130,7 +130,7 @@ private List findFilesInProject(AsciiDocTextQuoted element) { } private List findFileReferences(PsiElement element) { - if (element.getNode().findChildByType(AsciiDocTokenTypes.URL_LINK) != null) { + if (element.getNode() != null && element.getNode().findChildByType(AsciiDocTokenTypes.URL_LINK) != null) { return Collections.emptyList(); } if (element.getChildren().length > 0 && element.getChildren()[0] instanceof AsciiDocAttributeReference) { @@ -217,7 +217,7 @@ private List findFileReferences(PsiElement element) { private List findUrlReferencesInLinks(PsiElement element) { PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.URL_LINK) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.URL_LINK) { child = child.getNextSibling(); } if (child != null) { @@ -250,7 +250,7 @@ private List findTagInDocument(AsciiDocIncludeTagInDocument elemen private List findUrlReferencesInAttributeDefinition(PsiElement element) { PsiElement child = element.getFirstChild(); List result = new ArrayList<>(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_VAL) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRIBUTE_VAL) { child = child.getNextSibling(); } if (child != null) { diff --git a/src/main/java/org/asciidoc/intellij/folding/AsciiDocFoldingBuilder.java b/src/main/java/org/asciidoc/intellij/folding/AsciiDocFoldingBuilder.java index d729f1294..38c1ec419 100644 --- a/src/main/java/org/asciidoc/intellij/folding/AsciiDocFoldingBuilder.java +++ b/src/main/java/org/asciidoc/intellij/folding/AsciiDocFoldingBuilder.java @@ -100,7 +100,7 @@ public void visitElement(@NotNull PsiElement element) { } } else if (element instanceof AsciiDocHtmlEntity) { addDescriptors(element); - } else if (COLLAPSABLE_TYPES.containsKey(element.getNode().getElementType())) { + } else if (element.getNode() != null && COLLAPSABLE_TYPES.containsKey(element.getNode().getElementType())) { addDescriptors(element); } super.visitElement(element); @@ -147,7 +147,7 @@ private static void addDescriptors(@NotNull PsiElement element, descriptors.add(new FoldingDescriptor(element, range)); } else if (element instanceof AsciiDocHtmlEntity) { descriptors.add(new FoldingDescriptor(element, range)); - } else if (COLLAPSABLE_TYPES.containsKey(element.getNode().getElementType())) { + } else if (element.getNode() != null && COLLAPSABLE_TYPES.containsKey(element.getNode().getElementType())) { descriptors.add(new FoldingDescriptor(element, range)); } } diff --git a/src/main/java/org/asciidoc/intellij/grazie/AsciiDocGrazieTextExtractor.java b/src/main/java/org/asciidoc/intellij/grazie/AsciiDocGrazieTextExtractor.java index 8586a8cea..c240fce47 100644 --- a/src/main/java/org/asciidoc/intellij/grazie/AsciiDocGrazieTextExtractor.java +++ b/src/main/java/org/asciidoc/intellij/grazie/AsciiDocGrazieTextExtractor.java @@ -91,7 +91,7 @@ public void visitElement(@NotNull PsiElement element) { super.visitElement(element); if (languageSupport.getElementBehavior(root, element) == AsciiDocLanguageSupport.Behavior.TEXT) { int pos = element.getTextOffset(); - if (element.getNode().getElementType() == AsciiDocTokenTypes.TYPOGRAPHIC_SINGLE_QUOTE_START + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.TYPOGRAPHIC_SINGLE_QUOTE_START && element.getTextLength() == 2) { // ` at the end of '` ranges.add(new TextRange(pos + 1, pos + 2)); @@ -100,22 +100,22 @@ public void visitElement(@NotNull PsiElement element) { // AsciiDoc will eat extra spaces when rendering. Let's do the same here. ranges.add(new TextRange(pos + 1, pos + element.getTextLength())); } - if ((element.getNode().getElementType() == AsciiDocTokenTypes.ATTRIBUTE_CONTINUATION + if (element.getNode() != null && (element.getNode().getElementType() == AsciiDocTokenTypes.ATTRIBUTE_CONTINUATION || element.getNode().getElementType() == AsciiDocTokenTypes.ATTRIBUTE_CONTINUATION_LEGACY) && element.getTextLength() == 3) { // this will strip out the '+' or '\' and the newline from the continuation before forwarding it to the grammar check ranges.add(new TextRange(pos + 1, pos + 3)); } - if ((element.getNode().getElementType() == AsciiDocTokenTypes.DESCRIPTION_END)) { + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.DESCRIPTION_END) { // this will strip the duplicated characters ranges.add(new TextRange(pos, pos + element.getTextLength() - 1)); } - if (element.getNode().getElementType() == AsciiDocTokenTypes.TYPOGRAPHIC_SINGLE_QUOTE_END + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.TYPOGRAPHIC_SINGLE_QUOTE_END && element.getTextLength() == 2) { // ` at the beginning of `' ranges.add(new TextRange(pos, pos + 1)); } - if (element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_OLDSTYLE && element.getTextLength() >= 1) { + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_OLDSTYLE && element.getTextLength() >= 1) { // ignore second line of heading String heading = element.getText(); int i = heading.indexOf('\n'); @@ -123,7 +123,7 @@ public void visitElement(@NotNull PsiElement element) { ranges.add(new TextRange(pos + i, pos + heading.length())); } } - if (element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_TOKEN && element.getTextLength() >= 1 + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_TOKEN && element.getTextLength() >= 1 && element.getPrevSibling() == null) { // ignore "##" or "==" at start of heading String heading = element.getText(); diff --git a/src/main/java/org/asciidoc/intellij/grazie/AsciiDocLanguageSupport.java b/src/main/java/org/asciidoc/intellij/grazie/AsciiDocLanguageSupport.java index 9dd6d17d8..1bd24dfeb 100644 --- a/src/main/java/org/asciidoc/intellij/grazie/AsciiDocLanguageSupport.java +++ b/src/main/java/org/asciidoc/intellij/grazie/AsciiDocLanguageSupport.java @@ -157,7 +157,7 @@ public enum Behavior { AsciiDocTokenTypes.ATTRIBUTE_REF_END); public Behavior getElementBehavior(@NotNull PsiElement root, @NotNull PsiElement child) { - if (root != child && NODES_TO_CHECK.contains(child.getNode().getElementType())) { + if (root != child && child.getNode() != null && NODES_TO_CHECK.contains(child.getNode().getElementType())) { return Behavior.ABSORB; } else if (root == child && child instanceof AsciiDocAttributeDeclarationImpl) { if (((AsciiDocAttributeDeclarationImpl) child).hasSpellCheckableContent()) { @@ -171,7 +171,7 @@ public Behavior getElementBehavior(@NotNull PsiElement root, @NotNull PsiElement return Behavior.UNKNOWN; } else if (child instanceof AsciiDocTextQuoted && ((AsciiDocTextQuoted) child).isMono()) { return Behavior.UNKNOWN; - } else if (SEPARATOR_TOKENS.contains(child.getNode().getElementType())) { + } else if (child.getNode() != null && SEPARATOR_TOKENS.contains(child.getNode().getElementType())) { return Behavior.SEPARATE; } else if (root != child && child instanceof AsciiDocInlineMacro && ((AsciiDocInlineMacro) child).getMacroName().equals("footnote")) { return Behavior.ABSORB; @@ -179,8 +179,8 @@ public Behavior getElementBehavior(@NotNull PsiElement root, @NotNull PsiElement // A link or URL can contain either a macro text or no text. // AsciiDoc will display the macro text, or the link/email address if no such text is provided. // Pass on the content that would be displayed by AsciiDoc to the grammar check. - (child.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK || child.getNode().getElementType() == AsciiDocTokenTypes.URL_EMAIL) && - isChildOfLinkOrUrl(child)) { + (child.getNode() != null && (child.getNode().getElementType() == AsciiDocTokenTypes.URL_LINK || child.getNode().getElementType() == AsciiDocTokenTypes.URL_EMAIL) && + isChildOfLinkOrUrl(child))) { boolean macroTextPresent = false; ASTNode node = child.getNode(); while (node != null) { @@ -210,9 +210,9 @@ public Behavior getElementBehavior(@NotNull PsiElement root, @NotNull PsiElement } else { return Behavior.UNKNOWN; } - } else if (TEXT_TOKENS.contains(child.getNode().getElementType())) { + } else if (child.getNode() != null && TEXT_TOKENS.contains(child.getNode().getElementType())) { return Behavior.TEXT; - } else if (UNKNOWN_TOKENS.contains(child.getNode().getElementType())) { + } else if (child.getNode() != null && UNKNOWN_TOKENS.contains(child.getNode().getElementType())) { return Behavior.UNKNOWN; } else { return Behavior.STEALTH; @@ -234,7 +234,7 @@ public boolean hasFound() { @Override public void visitElement(@NotNull PsiElement element) { super.visitElement(element); - if (element.getNode().getElementType() == AsciiDocTokenTypes.MACROTEXT || element.getNode().getElementType() == AsciiDocTokenTypes.REFTEXT) { + if (element.getNode() != null && (element.getNode().getElementType() == AsciiDocTokenTypes.MACROTEXT || element.getNode().getElementType() == AsciiDocTokenTypes.REFTEXT)) { found = true; return; } @@ -247,7 +247,7 @@ public void visitElement(@NotNull PsiElement element) { } public static boolean containsOnlySpaces(PsiElement child) { - return child.getNode().getChars().chars().noneMatch(c -> c != ' '); + return child.getNode() != null && child.getNode().getChars().chars().noneMatch(c -> c != ' '); } private static final Key> KEY_ASCIIDOC_CONTEXT_ROOT = new Key<>("asciidoc-contextroot"); @@ -263,7 +263,7 @@ public boolean isMyContextRoot(@NotNull PsiElement psiElement) { ((AsciiDocInlineMacro) psiElement).getMacroName().equals("footnote")) { result = true; } else { - result = NODES_TO_CHECK.contains(psiElement.getNode().getElementType()) + result = (psiElement.getNode() != null && NODES_TO_CHECK.contains(psiElement.getNode().getElementType())) || psiElement instanceof PsiComment; } // as the calculated value depends only on the PSI node and its subtree, try to be more specific than the PsiElement diff --git a/src/main/java/org/asciidoc/intellij/injection/LanguageListCompletionContributor.java b/src/main/java/org/asciidoc/intellij/injection/LanguageListCompletionContributor.java index fcc0a17c4..ab189a38d 100644 --- a/src/main/java/org/asciidoc/intellij/injection/LanguageListCompletionContributor.java +++ b/src/main/java/org/asciidoc/intellij/injection/LanguageListCompletionContributor.java @@ -36,7 +36,7 @@ public void fillCompletionVariants(@NotNull CompletionParameters parameters, @No element = element.getPrevSibling(); continue; } - if (element.getNode().getElementType() == AsciiDocTokenTypes.SEPARATOR) { + if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.SEPARATOR) { element = element.getPrevSibling(); continue; } diff --git a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocAttributeContinuationInspection.java b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocAttributeContinuationInspection.java index 866c8cde8..a25d2179f 100644 --- a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocAttributeContinuationInspection.java +++ b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocAttributeContinuationInspection.java @@ -20,8 +20,8 @@ public class AsciiDocAttributeContinuationInspection extends AsciiDocInspectionB protected AsciiDocVisitor buildAsciiDocVisitor(@NotNull ProblemsHolder holder, @NotNull LocalInspectionToolSession session) { return new AsciiDocVisitor() { @Override - public void visitElement(PsiElement o) { - if (o != null && o.getNode().getElementType() == ATTRIBUTE_CONTINUATION_LEGACY) { + public void visitElement(@NotNull PsiElement o) { + if (o.getNode() != null && o.getNode().getElementType() == ATTRIBUTE_CONTINUATION_LEGACY) { LocalQuickFix[] fixes = new LocalQuickFix[]{ATTRIBUTE_CONTINUATION_LEGACY_QUICKFIX}; holder.registerProblem(o, TEXT_HINT_LEGACY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes); } diff --git a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocHorizontalRuleInspection.java b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocHorizontalRuleInspection.java index 09c413744..517f5117b 100644 --- a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocHorizontalRuleInspection.java +++ b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocHorizontalRuleInspection.java @@ -19,8 +19,8 @@ public class AsciiDocHorizontalRuleInspection extends AsciiDocInspectionBase { protected AsciiDocVisitor buildAsciiDocVisitor(@NotNull ProblemsHolder holder, @NotNull LocalInspectionToolSession session) { return new AsciiDocVisitor() { @Override - public void visitElement(PsiElement o) { - if (o != null && o.getNode().getElementType() == HORIZONTALRULE) { + public void visitElement(@NotNull PsiElement o) { + if (o.getNode() != null && o.getNode().getElementType() == HORIZONTALRULE) { if (o.getNode().getText().startsWith("-") || o.getNode().getText().startsWith("*") || o.getNode().getText().startsWith("_")) { LocalQuickFix[] fixes = new LocalQuickFix[]{MARKDOWN_HORIZONTAL_RULE_QUICKFIX}; holder.registerProblem(o, TEXT_HINT_MARKDOWN, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes); diff --git a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocListingStyleInspection.java b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocListingStyleInspection.java index ee1769192..2f3e615f3 100644 --- a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocListingStyleInspection.java +++ b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocListingStyleInspection.java @@ -39,6 +39,9 @@ private boolean isMarkdownListingBlock(AsciiDocBlock block) { if (block.getType() != AsciiDocBlock.Type.LISTING) { return false; } + if (block.getNode() == null) { + return false; + } ASTNode node = block.getNode().getFirstChildNode(); while (node != null && node.getElementType() != AsciiDocTokenTypes.LISTING_BLOCK_DELIMITER) { node = node.getTreeNext(); diff --git a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPageBreakInspection.java b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPageBreakInspection.java index ac9de80b8..b1aa9ed15 100644 --- a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPageBreakInspection.java +++ b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPageBreakInspection.java @@ -22,8 +22,8 @@ public class AsciiDocPageBreakInspection extends AsciiDocInspectionBase { protected AsciiDocVisitor buildAsciiDocVisitor(@NotNull ProblemsHolder holder, @NotNull LocalInspectionToolSession session) { return new AsciiDocVisitor() { @Override - public void visitElement(PsiElement o) { - if (o != null && o.getNode().getElementType() == PAGEBREAK) { + public void visitElement(@NotNull PsiElement o) { + if (o.getNode() != null && o.getNode().getElementType() == PAGEBREAK) { if (o.getNode().getText().trim().length() > 3) { LocalQuickFix[] fixes = new LocalQuickFix[]{PAGEBREAK_SHORTEN_QUICKFIX}; holder.registerProblem(o, TEXT_HINT_PAGEBREAK, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes); diff --git a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPassthroughInspection.java b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPassthroughInspection.java index 336dd9b77..5dd620b31 100644 --- a/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPassthroughInspection.java +++ b/src/main/java/org/asciidoc/intellij/inspections/AsciiDocPassthroughInspection.java @@ -46,12 +46,12 @@ public static boolean isQuotedTextWithObsoletePassthrough(@NotNull PsiElement e) } public static boolean isObsoletePassthroughStart(PsiElement e) { - return e.getNode().getElementType() == AsciiDocTokenTypes.PASSTRHOUGH_INLINE_START + return e.getNode() != null && e.getNode().getElementType() == AsciiDocTokenTypes.PASSTRHOUGH_INLINE_START && e.getNode().getText().equals(OBSOLETE_PASSTRHOUGH); } public static boolean isObsoletePassthroughEnd(PsiElement e) { - return e.getNode().getElementType() == AsciiDocTokenTypes.PASSTRHOUGH_INLINE_END + return e.getNode() != null && e.getNode().getElementType() == AsciiDocTokenTypes.PASSTRHOUGH_INLINE_END && e.getNode().getText().equals(OBSOLETE_PASSTRHOUGH); } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlock.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlock.java index e893fcd15..0ea6cf49b 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlock.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlock.java @@ -35,6 +35,9 @@ default Type getType() { @Nullable default String getTitle() { + if (getNode() == null) { + return null; + } ASTNode titleNode = getNode().findChildByType(AsciiDocElementTypes.TITLE); if (titleNode == null) { return null; @@ -61,7 +64,7 @@ default String getTitle() { @Nullable default PsiElement getFirstSignificantChildForFolding() { PsiElement child = getFirstChild(); - while (child != null && + while (child != null && child.getNode() != null && INSIGNIFICANT_TOKENS_FOR_FOLDING.contains(child.getNode().getElementType()) && child.getNextSibling() != null) { child = child.getNextSibling(); diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlockMacro.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlockMacro.java index aa4ac031a..8e78c88f4 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlockMacro.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocBlockMacro.java @@ -243,11 +243,11 @@ public TextRange getRangeInElement(@NotNull AsciiDocBlockMacro element) { private static TextRange getRangeOfBody(AsciiDocBlockMacro element) { PsiElement child = element.getFirstChild(); // skip over pre-block until macro ID starts - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.BLOCK_MACRO_ID) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.BLOCK_MACRO_ID) { child = child.getNextSibling(); } // skip over macro ID - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.BLOCK_MACRO_ID) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.BLOCK_MACRO_ID) { child = child.getNextSibling(); } if (child == null) { @@ -255,7 +255,7 @@ private static TextRange getRangeOfBody(AsciiDocBlockMacro element) { } int start = child.getStartOffsetInParent(); int end = start; - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_START) { end = child.getStartOffsetInParent() + child.getTextLength(); child = child.getNextSibling(); } @@ -276,24 +276,24 @@ public boolean hasAttributes() { public TextRange getAttributeRange() { PsiElement child = this.getFirstChild(); // skip over pre-block until macro ID starts - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.BLOCK_MACRO_ID) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.BLOCK_MACRO_ID) { child = child.getNextSibling(); } - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_START) { child = child.getNextSibling(); } - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.ATTRS_START) { child = child.getNextSibling(); } if (child == null) { return TextRange.EMPTY_RANGE; } int start = child.getStartOffsetInParent(); - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.ATTRS_START) { child = child.getNextSibling(); } int end = start; - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_END) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTRS_END) { end = child.getStartOffsetInParent() + child.getTextLength(); child = child.getNextSibling(); } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocHeading.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocHeading.java index f087be660..cd33d1978 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocHeading.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocHeading.java @@ -4,7 +4,6 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.ModificationTracker; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; @@ -35,10 +34,6 @@ public AsciiDocHeading(@NotNull ASTNode node) { return ReferenceProvidersRegistry.getReferencesFromProviders(this); } - public static TextRange getBodyRange(AsciiDocHeading element) { - return element.getTextRange(); - } - private static String trimHeading(String text) { if (text.charAt(0) == '=') { // new style heading @@ -63,7 +58,7 @@ public String getHeadingText(boolean substitution) { PsiElement child = getFirstChild(); boolean hasAttribute = false; while (child != null) { - if (HEADINGS.contains(child.getNode().getElementType())) { + if (child.getNode() != null && HEADINGS.contains(child.getNode().getElementType())) { sb.append(child.getText()); } else if (child instanceof AsciiDocAttributeReference) { hasAttribute = true; @@ -108,6 +103,7 @@ public AsciiDocBlockId getBlockId() { // only if the block ID is the last element in the heading it is the block ID of the section if (blockId != null && blockId.getNextSibling() != null && + blockId.getNextSibling().getNode() != null && blockId.getNextSibling().getNode().getElementType() == AsciiDocTokenTypes.INLINEIDEND && blockId.getNextSibling().getNextSibling() == null) { return blockId; diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocIncludeTagInDocument.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocIncludeTagInDocument.java index 671af2a3b..ecb48527c 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocIncludeTagInDocument.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocIncludeTagInDocument.java @@ -22,9 +22,8 @@ public AsciiDocIncludeTagInDocument(@NotNull ASTNode node) { super(node); } - @NotNull @Override - public PsiReference[] getReferences() { + public PsiReference @NotNull [] getReferences() { return ReferenceProvidersRegistry.getReferencesFromProviders(this); } @@ -35,7 +34,7 @@ public AsciiDocIncludeTagInDocument handleContentChange(@NotNull AsciiDocInclude @NotNull TextRange range, String newContent) throws IncorrectOperationException { PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTR_VALUE) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.ATTR_VALUE) { range = range.shiftRight(-child.getTextLength()); child = child.getNextSibling(); } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocInlineMacro.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocInlineMacro.java index 7ee599285..dc0a0f51f 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocInlineMacro.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocInlineMacro.java @@ -127,7 +127,7 @@ public AsciiDocInlineMacro handleContentChange(@NotNull AsciiDocInlineMacro elem @NotNull TextRange range, String newContent) throws IncorrectOperationException { PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_MACRO_BODY) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_MACRO_BODY) { range = range.shiftRight(-child.getTextLength()); child = child.getNextSibling(); } @@ -155,11 +155,11 @@ public TextRange getRangeInElement(@NotNull AsciiDocInlineMacro element) { private static TextRange getRangeOfBody(AsciiDocInlineMacro element) { PsiElement child = element.getFirstChild(); // skip over pre-block until macro ID starts - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_MACRO_ID) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_MACRO_ID) { child = child.getNextSibling(); } // skip over macro ID - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.INLINE_MACRO_ID) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.INLINE_MACRO_ID) { child = child.getNextSibling(); } if (child == null) { @@ -167,7 +167,7 @@ private static TextRange getRangeOfBody(AsciiDocInlineMacro element) { } int start = child.getStartOffsetInParent(); int end = start; - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_ATTRS_START) { end = child.getStartOffsetInParent() + child.getTextLength(); child = child.getNextSibling(); } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocLink.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocLink.java index 5c05a61d7..7724e6973 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocLink.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocLink.java @@ -20,9 +20,8 @@ public AsciiDocLink(@NotNull ASTNode node) { super(node); } - @NotNull @Override - public PsiReference[] getReferences() { + public PsiReference @NotNull [] getReferences() { return ReferenceProvidersRegistry.getReferencesFromProviders(this); } @@ -72,7 +71,7 @@ public TextRange getRangeInElement(@NotNull AsciiDocLink element) { public void setAnchor(String anchor) { PsiElement child = this.getFirstChild(); while (child != null) { - if (child.getNode().getElementType() == AsciiDocTokenTypes.LINKANCHOR) { + if (child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.LINKANCHOR) { if (child instanceof LeafElement) { ((LeafElement) child).replaceWithText(anchor); } @@ -97,7 +96,7 @@ public String getResolvedBody() { public static TextRange getBodyRange(AsciiDocLink element) { PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.LINKSTART) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.LINKSTART) { child = child.getNextSibling(); } if (child == null) { @@ -105,24 +104,7 @@ public static TextRange getBodyRange(AsciiDocLink element) { } int start = child.getStartOffsetInParent(); int end = start; - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_ATTRS_START) { - end = child.getStartOffsetInParent() + child.getTextLength(); - child = child.getNextSibling(); - } - return TextRange.create(start, end); - } - - public static TextRange getFileRange(AsciiDocLink element) { - PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.LINKSTART) { - child = child.getNextSibling(); - } - if (child == null) { - return TextRange.EMPTY_RANGE; - } - int start = child.getStartOffsetInParent(); - int end = start; - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_ATTRS_START) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.INLINE_ATTRS_START) { end = child.getStartOffsetInParent() + child.getTextLength(); child = child.getNextSibling(); } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocListing.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocListing.java index 180b65f44..cb8bd0e07 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocListing.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocListing.java @@ -99,10 +99,10 @@ public String getFenceLanguage() { // check for markdown style listing PsiElement child = this.getFirstChild(); - if (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.LISTING_BLOCK_DELIMITER && + if (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.LISTING_BLOCK_DELIMITER && child.getText().startsWith("`")) { child = child.getNextSibling(); - if (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.LISTING_TEXT) { + if (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.LISTING_TEXT) { return "source-" + child.getText(); } } diff --git a/src/main/java/org/asciidoc/intellij/psi/AsciiDocRef.java b/src/main/java/org/asciidoc/intellij/psi/AsciiDocRef.java index f5581b674..23d092d94 100644 --- a/src/main/java/org/asciidoc/intellij/psi/AsciiDocRef.java +++ b/src/main/java/org/asciidoc/intellij/psi/AsciiDocRef.java @@ -17,9 +17,8 @@ public AsciiDocRef(@NotNull ASTNode node) { super(node); } - @NotNull @Override - public PsiReference[] getReferences() { + public PsiReference @NotNull [] getReferences() { TextRange range = getRangeOfBody(this); if (!range.isEmpty()) { String file = this.getText().substring(range.getStartOffset(), range.getEndOffset()); @@ -53,7 +52,7 @@ public PsiReference[] getReferences() { private static TextRange getRangeOfBody(AsciiDocRef element) { PsiElement child = element.getFirstChild(); // skip over start ID - while (child != null && child.getNode().getElementType() == AsciiDocTokenTypes.REFSTART) { + while (child != null && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.REFSTART) { child = child.getNextSibling(); } if (child == null) { @@ -62,6 +61,7 @@ private static TextRange getRangeOfBody(AsciiDocRef element) { int start = child.getStartOffsetInParent(); int end = start; while (child != null + && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.SEPARATOR && child.getNode().getElementType() != AsciiDocTokenTypes.REFEND) { end = child.getStartOffsetInParent() + child.getTextLength(); @@ -77,7 +77,7 @@ public AsciiDocRef handleContentChange(@NotNull AsciiDocRef element, @NotNull TextRange range, String newContent) throws IncorrectOperationException { PsiElement child = element.getFirstChild(); - while (child != null && child.getNode().getElementType() != AsciiDocTokenTypes.REF) { + while (child != null && child.getNode() != null && child.getNode().getElementType() != AsciiDocTokenTypes.REF) { range = range.shiftRight(-child.getTextLength()); child = child.getNextSibling(); } diff --git a/src/main/java/org/asciidoc/intellij/psi/PageAttributeProcessor.java b/src/main/java/org/asciidoc/intellij/psi/PageAttributeProcessor.java index a95c1ec82..08e7b84ba 100644 --- a/src/main/java/org/asciidoc/intellij/psi/PageAttributeProcessor.java +++ b/src/main/java/org/asciidoc/intellij/psi/PageAttributeProcessor.java @@ -76,15 +76,15 @@ public boolean execute(@NotNull PsiElement element) { titleSeen = true; return true; } - } else if (titleSeen && element.getNode().getElementType() == AsciiDocTokenTypes.EMPTY_LINE) { + } else if (titleSeen && element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.EMPTY_LINE) { return false; - } else if (element.getNode().getElementType() == AsciiDocTokenTypes.HEADER) { + } else if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.HEADER) { return true; - } else if (element.getNode().getElementType() == AsciiDocTokenTypes.BLOCKIDSTART) { + } else if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.BLOCKIDSTART) { return true; - } else if (element.getNode().getElementType() == AsciiDocTokenTypes.BLOCKIDEND) { + } else if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.BLOCKIDEND) { return true; - } else if (element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_OLDSTYLE) { + } else if (element.getNode() != null && element.getNode().getElementType() == AsciiDocTokenTypes.HEADING_OLDSTYLE) { return true; } else if (element instanceof PsiWhiteSpace) { return true; diff --git a/src/main/java/org/asciidoc/intellij/quickfix/AsciiDocAddAdocExtensionToXref.java b/src/main/java/org/asciidoc/intellij/quickfix/AsciiDocAddAdocExtensionToXref.java index b5633620c..55a0ca530 100644 --- a/src/main/java/org/asciidoc/intellij/quickfix/AsciiDocAddAdocExtensionToXref.java +++ b/src/main/java/org/asciidoc/intellij/quickfix/AsciiDocAddAdocExtensionToXref.java @@ -60,7 +60,7 @@ private LeafPsiElement getChild(AsciiDocLink link) { child = child.getNextSibling(); } if (child instanceof LeafPsiElement && range.getEndOffset() <= child.getTextLength() - && child.getNode().getElementType() == AsciiDocTokenTypes.LINKFILE) { + && child.getNode() != null && child.getNode().getElementType() == AsciiDocTokenTypes.LINKFILE) { return (LeafPsiElement) child; } }