Skip to content

Commit

Permalink
Adding an intent to add the option to disable validation on individua…
Browse files Browse the repository at this point in the history
…l code blocks (#830)
  • Loading branch information
ahus1 committed Nov 14, 2024
1 parent 77ee8dd commit 9d6fba5
Show file tree
Hide file tree
Showing 23 changed files with 356 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This document provides a high-level view of the changes introduced by release.
=== 0.43.4

- Fix text color of non-icon admonitions in dark preview
- Adding an intent to add the option to disable validation on individual code blocks (#830)

=== 0.43.3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ System.out.println("Hello, world!");
----
-----

Add the `opts=novalidate` using an intent in the editor by pressing [.windows.linux]#kbd:[Alt+Enter]# [.macos]#kbd:[⌥ ↩]# and choosing *Hide errors in source blocks for this block*.

NOTE: This is available since plugin version 0.43.3. The intent is available from 0.43.4.

== How to edit files as a project

The user selects the menu item menu:File[Open...], then selects the folder and opens it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@

import java.util.List;

public class AsciiDocCodeFenceErrorHighlightingIntention implements IntentionAction {
public class AsciiDocCodeFenceErrorHighlightingIntentionAllLanguages implements IntentionAction {
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getText() {
return AsciiDocBundle.message("asciidoc.hide.errors.intention.text");
return AsciiDocBundle.message("asciidoc.hide.errors.allLanguages.intention.text");
}

@Nls(capitalization = Nls.Capitalization.Sentence)
Expand All @@ -56,6 +56,16 @@ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file
if (elementWithLanguage == null) {
return false;
}
if (!elementWithLanguage.validateContent()) {
return false;
}
String language = elementWithLanguage.getFenceLanguage();
if (language != null) {
if (AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getDisabledInjectionsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))
|| AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getHiddenErrorsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))) {
return false;
}
}
List<Pair<PsiElement, TextRange>> injectedPsiFiles = InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(elementWithLanguage);
return injectedPsiFiles != null && injectedPsiFiles.size() > 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.asciidoc.intellij.injection;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.asciidoc.intellij.AsciiDocBundle;
import org.asciidoc.intellij.file.AsciiDocFileType;
import org.asciidoc.intellij.psi.AsciiDocAttributeInBrackets;
import org.asciidoc.intellij.psi.AsciiDocBlockAttributes;
import org.asciidoc.intellij.psi.AsciiDocElementWithLanguage;
import org.asciidoc.intellij.psi.AsciiDocFile;
import org.asciidoc.intellij.psi.AsciiDocUtil;
import org.asciidoc.intellij.settings.AsciiDocApplicationSettings;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class AsciiDocCodeFenceErrorHighlightingIntentionThisBlock implements IntentionAction {
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getText() {
return AsciiDocBundle.message("asciidoc.hide.errors.thisBlock.intention.text");
}

@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getFamilyName() {
return getText();
}

/**
* {@inheritDoc}
* This action is only available if there is an active code injection at the active element.
*/
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (file.getFileType() != AsciiDocFileType.INSTANCE || AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().isHideErrorsInSourceBlocks()) {
return false;
}
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element == null) {
return false;
}
AsciiDocElementWithLanguage elementWithLanguage = PsiTreeUtil.getParentOfType(element, AsciiDocElementWithLanguage.class);
if (elementWithLanguage == null) {
return false;
}
if (!elementWithLanguage.validateContent()) {
return false;
}
String language = elementWithLanguage.getFenceLanguage();
if (language != null) {
if (AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getDisabledInjectionsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))
|| AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getHiddenErrorsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))) {
return false;
}
}
List<Pair<PsiElement, TextRange>> injectedPsiFiles = InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(elementWithLanguage);
return injectedPsiFiles != null && injectedPsiFiles.size() > 0;
}

@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element == null) {
return;
}
AsciiDocElementWithLanguage elementWithLanguage = PsiTreeUtil.getParentOfType(element, AsciiDocElementWithLanguage.class);

AsciiDocBlockAttributes blockAttributes = PsiTreeUtil.findChildOfType(elementWithLanguage, AsciiDocBlockAttributes.class);

if (blockAttributes == null) {
return;

}
PsiElement child = blockAttributes.getFirstChild();
boolean found = false;
while (child != null) {
if (child instanceof AsciiDocAttributeInBrackets a) {
if (a.getAttrName().equals("opts")) {
String value = a.getAttrValueUnresolved();
if (value == null || value.isEmpty()) {
value = "novalidate";
} else {
value = value + ",novalidate";
}
PsiElement newBlock = createAttributeBlock(project, value);
found = true;
child.replace(newBlock);
break;
}
}
child = child.getNextSibling();
}

if (!found) {
PsiElement newBlock = createAttributeBlock(project, "novalidate");
blockAttributes.addBefore(newBlock.getPrevSibling(), blockAttributes.getLastChild());
blockAttributes.addBefore(newBlock, blockAttributes.getLastChild());
}
}

private AsciiDocAttributeInBrackets createAttributeBlock(@NotNull Project project, String text) {
if (text.contains(",")) {
text = '"' + text + '"';
}
AsciiDocFile fileFromText = AsciiDocUtil.createFileFromText(project, "[,opts=" + text + "]\n----\n----\n");
return PsiTreeUtil.findChildOfType(fileFromText, AsciiDocAttributeInBrackets.class);
}

@Override
public boolean startInWriteAction() {
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.asciidoc.intellij.injection;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationAction;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.asciidoc.intellij.AsciiDocBundle;
import org.asciidoc.intellij.file.AsciiDocFileType;
import org.asciidoc.intellij.psi.AsciiDocElementWithLanguage;
import org.asciidoc.intellij.settings.AsciiDocApplicationSettings;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class AsciiDocCodeFenceErrorHighlightingIntentionThisLanguage implements IntentionAction {
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getText() {
return AsciiDocBundle.message("asciidoc.hide.errors.thisLanguage.intention.text");
}

@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getFamilyName() {
return getText();
}

/**
* {@inheritDoc}
* This action is only available if there is an active code injection at the active element.
*/
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (file.getFileType() != AsciiDocFileType.INSTANCE || AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().isHideErrorsInSourceBlocks()) {
return false;
}
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element == null) {
return false;
}
AsciiDocElementWithLanguage elementWithLanguage = PsiTreeUtil.getParentOfType(element, AsciiDocElementWithLanguage.class);
if (elementWithLanguage == null) {
return false;
}
if (!elementWithLanguage.validateContent()) {
return false;
}
String language = elementWithLanguage.getFenceLanguage();
if (language != null) {
if (AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getDisabledInjectionsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))
|| AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getHiddenErrorsByLanguageAsList().contains(language.substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length()))) {
return false;
}
}
List<Pair<PsiElement, TextRange>> injectedPsiFiles = InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(elementWithLanguage);
return injectedPsiFiles != null && injectedPsiFiles.size() > 0;
}

@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element == null) {
return;
}
AsciiDocElementWithLanguage elementWithLanguage = PsiTreeUtil.getParentOfType(element, AsciiDocElementWithLanguage.class);
if (elementWithLanguage == null) {
return;
}
if (!elementWithLanguage.validateContent()) {
return;
}
String language = elementWithLanguage.getFenceLanguage().substring(CodeFenceHighlightInfoFilter.SOURCE_PREFIX.length());
setHideErrors(true, language);

Notification notification = new Notification("asciidoctor", AsciiDocBundle.message("asciidoc.hide.errors.notification.title"),
AsciiDocBundle.message("asciidoc.hide.errors.notification.content"), NotificationType.INFORMATION);
notification.addAction(new NotificationAction(AsciiDocBundle.message("asciidoc.hide.errors.notification.rollback.action.text")) {
@Override
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
setHideErrors(false, language);
notification.expire();
}
});

notification.notify(project);
}

private void setHideErrors(boolean hideErrors, String language) {
List<String> languages = AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().getHiddenErrorsByLanguageAsList();
if (hideErrors && !languages.contains(language)) {
languages.add(language);
} else {
languages.remove(language);
}

AsciiDocApplicationSettings.getInstance().getAsciiDocPreviewSettings().setHideErrorsByLanguage(String.join(";", languages));

ApplicationManager.getApplication().getMessageBus()
.syncPublisher(AsciiDocApplicationSettings.SettingsChangedListener.TOPIC)
.onSettingsChange(AsciiDocApplicationSettings.getInstance());
}

@Override
public boolean startInWriteAction() {
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.asciidoc.intellij.lexer.AsciiDocTokenTypes;
import org.asciidoc.intellij.namesValidator.AsciiDocRenameInputValidator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -115,18 +116,25 @@ public String getAttrName() {
}

public String getAttrValue() {
TextRange bodyRange = getRangeOfBody(this);
if (bodyRange.isEmpty()) {
String value = getAttrValueUnresolved();
if (value == null) {
return null;
}
String value = bodyRange.substring(this.getText());
String resolvedValue = AsciiDocUtil.resolveAttributes(this, value);
if (resolvedValue != null) {
value = resolvedValue;
}
return value;
}

public @Nullable String getAttrValueUnresolved() {
TextRange bodyRange = getRangeOfBody(this);
if (bodyRange.isEmpty()) {
return null;
}
return bodyRange.substring(this.getText());
}

public static class Manipulator extends AbstractElementManipulator<AsciiDocAttributeInBrackets> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,8 @@ public void setHideErrorsByLanguage(String hideErrorsByLanguage) {
public List<String> getHiddenErrorsByLanguageAsList() {
List<String> list = new ArrayList<>();
if (myHideErrorsByLanguage != null) {
Arrays.asList(myHideErrorsByLanguage.split(";")).forEach(
entry -> list.add(entry.trim().toLowerCase(Locale.US))
Arrays.stream(myHideErrorsByLanguage.split(";")).map(String::trim).filter(s -> !s.isEmpty()).forEach(
list::add
);
}
return list;
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/AsciiDocBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,9 @@ asciidoc.add.block.id.to.section.name=Add Block ID to section
asciidoc.admonition.to.block.intention.family.name=Refactor to block admonition
asciidoc.admonition.to.block.intention.name=Refactor to block admonition

asciidoc.hide.errors.intention.text=Hide errors in source blocks for all languages
asciidoc.hide.errors.allLanguages.intention.text=Hide errors in source blocks for all languages
asciidoc.hide.errors.thisLanguage.intention.text=Hide errors in source blocks for this language
asciidoc.hide.errors.thisBlock.intention.text=Hide errors in source blocks for this block
asciidoc.settings.hide.errors.languages=Hide errors for:
asciidoc.settings.hide.errors=Hide errors in source blocks for all languages
asciidoc.hide.errors.notification.title=Source block errors
Expand Down
14 changes: 13 additions & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,19 @@
<language>AsciiDoc</language>
<bundleName>AsciiDocBundle</bundleName>
<categoryKey>asciidoc.intention.category</categoryKey>
<className>org.asciidoc.intellij.injection.AsciiDocCodeFenceErrorHighlightingIntention</className>
<className>org.asciidoc.intellij.injection.AsciiDocCodeFenceErrorHighlightingIntentionAllLanguages</className>
</intentionAction>
<intentionAction>
<language>AsciiDoc</language>
<bundleName>AsciiDocBundle</bundleName>
<categoryKey>asciidoc.intention.category</categoryKey>
<className>org.asciidoc.intellij.injection.AsciiDocCodeFenceErrorHighlightingIntentionThisLanguage</className>
</intentionAction>
<intentionAction>
<language>AsciiDoc</language>
<bundleName>AsciiDocBundle</bundleName>
<categoryKey>asciidoc.intention.category</categoryKey>
<className>org.asciidoc.intellij.injection.AsciiDocCodeFenceErrorHighlightingIntentionThisBlock</className>
</intentionAction>
<intentionAction>
<language>AsciiDoc</language>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<html>
<body>
This intention allows to disable errors highlighting in AsciiDoc source blocks.
This intention allows disabling errors highlighting in AsciiDoc source blocks for all languages.
<!-- tooltip end -->
<p>You can set/reset this setting in the language settings of the AsciiDoc plugin.</p>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Errors highlighting is disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Errors are highlighted in code fences
Loading

0 comments on commit 9d6fba5

Please sign in to comment.