mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
PY-61639 Extracted PyHighlightingAnnotator
GitOrigin-RevId: 432bcb87b77fa55f1ccb26000d91ae021cebcc6b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d396a19918
commit
4602d09655
@@ -62,4 +62,9 @@ public interface PyAstFile extends PyAstElement, PsiFile, PyAstDocStringOwner, A
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
default boolean isAcceptedFor(@NotNull Class<?> visitorClass) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
<projectService serviceImplementation="com.jetbrains.python.findUsages.PyFindUsagesOptions"/>
|
||||
|
||||
<highlightRangeExtension implementation="com.jetbrains.python.validation.PyHighlightingAnnotator"/>
|
||||
<!-- We run it before FilePathCompletionContributor (id="filePath") to get help text about full path results in the extended completion -->
|
||||
<psi.referenceContributor implementation="com.jetbrains.python.codeInsight.PySoftFileReferenceContributor" language="Python"
|
||||
order="before filePath"/>
|
||||
|
||||
@@ -131,7 +131,6 @@ ANN.assignment.expressions.within.a.comprehension.cannot.be.used.in.a.class.body
|
||||
ANN.assignment.expression.as.a.target=Assignment expression cannot be used as a target here
|
||||
ANN.assignment.expression.in.an.iterable=Assignment expression cannot be used in a comprehension iterable
|
||||
ANN.ignore.errors.like.this=Ignore errors like this
|
||||
ANN.function.cannot.be.async=function \"{0}\" cannot be async
|
||||
ANN.python.does.not.support.yield.from.inside.async.functions=Python does not support 'yield from' inside async functions
|
||||
ANN.yield.outside.of.function='yield' outside of function
|
||||
ANN.non.empty.return.inside.asynchronous.generator=non-empty 'return' inside asynchronous generator
|
||||
@@ -965,9 +964,6 @@ INSP.dataclasses.method.should.be.called.on.dataclass.instances=''{0}'' method s
|
||||
INSP.dataclasses.method.should.be.called.on.attrs.instances=''{0}'' method should be called on attrs instances
|
||||
INSP.dataclasses.method.should.be.called.on.attrs.types=''{0}'' method should be called on attrs types
|
||||
|
||||
# PyHighlightingAnnotator
|
||||
INSP.python.trailing.suffix.not.support=Python does not support a trailing ''{0}''
|
||||
|
||||
# PyDeprecationInspection
|
||||
INSP.NAME.deprecated.function.class.or.module=Deprecated function, class, or module
|
||||
INSP.deprecation.abc.decorator.deprecated.use.alternative=''{0}'' is deprecated since Python 3.3. Use ''{1}'' with ''{2}'' instead
|
||||
|
||||
@@ -289,6 +289,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
// return element != null ? element : super.getNavigationElement();
|
||||
//}
|
||||
|
||||
@Override
|
||||
public boolean isAcceptedFor(@NotNull Class visitorClass) {
|
||||
for (Language lang : getViewProvider().getLanguages()) {
|
||||
final List<PythonVisitorFilter> filters = PythonVisitorFilter.INSTANCE.allForLanguage(lang);
|
||||
|
||||
@@ -15,21 +15,22 @@
|
||||
*/
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.intellij.codeInspection.util.InspectionMessage;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public abstract class PyAnnotator extends PyElementVisitor {
|
||||
public abstract class PyAnnotator extends PyElementVisitor implements PyAnnotatorBase {
|
||||
private final boolean myTestMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
private AnnotationHolder _holder;
|
||||
|
||||
@Override
|
||||
public boolean isTestMode() {
|
||||
return myTestMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationHolder getHolder() {
|
||||
return _holder;
|
||||
}
|
||||
@@ -38,6 +39,7 @@ public abstract class PyAnnotator extends PyElementVisitor {
|
||||
_holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void annotateElement(final PsiElement psiElement, final AnnotationHolder holder) {
|
||||
setHolder(holder);
|
||||
try {
|
||||
@@ -47,27 +49,4 @@ public abstract class PyAnnotator extends PyElementVisitor {
|
||||
setHolder(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void markError(@NotNull PsiElement element, @NotNull @InspectionMessage String message) {
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, message).range(element).create();
|
||||
}
|
||||
|
||||
protected void addHighlightingAnnotation(@NotNull PsiElement target, @NotNull TextAttributesKey key) {
|
||||
addHighlightingAnnotation(target, key, HighlightSeverity.INFORMATION);
|
||||
}
|
||||
|
||||
protected void addHighlightingAnnotation(@NotNull PsiElement target,
|
||||
@NotNull TextAttributesKey key,
|
||||
@NotNull HighlightSeverity severity) {
|
||||
final String message = myTestMode ? key.getExternalName() : null;
|
||||
// CodeInsightTestFixture#testHighlighting doesn't consider annotations with severity level < INFO
|
||||
final HighlightSeverity actualSeverity =
|
||||
myTestMode && severity.myVal < HighlightSeverity.INFORMATION.myVal ? HighlightSeverity.INFORMATION : severity;
|
||||
(message == null ? getHolder().newSilentAnnotation(actualSeverity) : getHolder().newAnnotation(actualSeverity, message))
|
||||
.range(target).textAttributes(key).create();
|
||||
}
|
||||
|
||||
protected void addHighlightingAnnotation(@NotNull ASTNode target, @NotNull TextAttributesKey key) {
|
||||
addHighlightingAnnotation(target.getPsi(), key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,5 +21,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.core.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis.impl" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -13,5 +13,7 @@
|
||||
<preFormatProcessor implementation="com.jetbrains.python.formatter.PyPreFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyTrailingBlankLinesPostFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyFromImportPostFormatProcessor"/>
|
||||
|
||||
<highlightRangeExtension implementation="com.jetbrains.python.validation.PyHighlightingAnnotator"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,4 +1,10 @@
|
||||
### Annotators ###
|
||||
ANN.function.cannot.be.async=function \"{0}\" cannot be async
|
||||
|
||||
### Formatter
|
||||
formatter.panel.dict.alignment.do.not.align=Do not align
|
||||
formatter.panel.dict.alignment.align.on.colon=Align on colon
|
||||
formatter.panel.dict.alignment.align.on.value=Align on value
|
||||
formatter.panel.dict.alignment.align.on.value=Align on value
|
||||
|
||||
# PyHighlightingAnnotator
|
||||
INSP.python.trailing.suffix.not.support=Python does not support a trailing ''{0}''
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.intellij.codeInspection.util.InspectionMessage;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.ast.PyAstFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public interface PyAnnotatorBase {
|
||||
@ApiStatus.Internal
|
||||
static void runAnnotators(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder, PyAnnotatorBase[] annotators) {
|
||||
PsiFile file = holder.getCurrentAnnotationSession().getFile();
|
||||
for (PyAnnotatorBase annotator : annotators) {
|
||||
if (file instanceof PyAstFile && !((PyAstFile)file).isAcceptedFor(annotator.getClass())) continue;
|
||||
annotator.annotateElement(psiElement, holder);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
boolean isTestMode();
|
||||
|
||||
AnnotationHolder getHolder();
|
||||
|
||||
void annotateElement(final PsiElement psiElement, final AnnotationHolder holder);
|
||||
|
||||
@ApiStatus.Internal
|
||||
default void markError(@NotNull PsiElement element, @NotNull @InspectionMessage String message) {
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, message).range(element).create();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
default void addHighlightingAnnotation(@NotNull PsiElement target, @NotNull TextAttributesKey key) {
|
||||
addHighlightingAnnotation(target, key, HighlightSeverity.INFORMATION);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
default void addHighlightingAnnotation(@NotNull PsiElement target,
|
||||
@NotNull TextAttributesKey key,
|
||||
@NotNull HighlightSeverity severity) {
|
||||
final String message = isTestMode() ? key.getExternalName() : null;
|
||||
// CodeInsightTestFixture#testHighlighting doesn't consider annotations with severity level < INFO
|
||||
final HighlightSeverity actualSeverity =
|
||||
isTestMode() && severity.myVal < HighlightSeverity.INFORMATION.myVal ? HighlightSeverity.INFORMATION : severity;
|
||||
(message == null ? getHolder().newSilentAnnotation(actualSeverity) : getHolder().newAnnotation(actualSeverity, message))
|
||||
.range(target).textAttributes(key).create();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
default void addHighlightingAnnotation(@NotNull ASTNode target, @NotNull TextAttributesKey key) {
|
||||
addHighlightingAnnotation(target.getPsi(), key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.ast.PyAstElementVisitor;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public class PyFrontendAnnotator extends PyAstElementVisitor implements PyAnnotatorBase {
|
||||
private final boolean myTestMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
private AnnotationHolder _holder;
|
||||
|
||||
@Override
|
||||
public boolean isTestMode() {
|
||||
return myTestMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationHolder getHolder() {
|
||||
return _holder;
|
||||
}
|
||||
|
||||
public void setHolder(AnnotationHolder holder) {
|
||||
_holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void annotateElement(final PsiElement psiElement, final AnnotationHolder holder) {
|
||||
setHolder(holder);
|
||||
try {
|
||||
psiElement.accept(this);
|
||||
}
|
||||
finally {
|
||||
setHolder(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,10 @@ import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PySyntaxCoreBundle;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.highlighting.PyHighlighter;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -31,10 +32,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class PyHighlightingAnnotator extends PyAnnotator implements HighlightRangeExtension {
|
||||
public final class PyHighlightingAnnotator extends PyFrontendAnnotator implements HighlightRangeExtension {
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(@NotNull PyFunction node) {
|
||||
public void visitPyFunction(@NotNull PyAstFunction node) {
|
||||
if (node.isAsyncAllowed()) {
|
||||
highlightKeyword(node, PyTokenTypes.ASYNC_KEYWORD);
|
||||
}
|
||||
@@ -43,57 +44,57 @@ public final class PyHighlightingAnnotator extends PyAnnotator implements Highli
|
||||
.ofNullable(node.getNode())
|
||||
.map(astNode -> astNode.findChildByType(PyTokenTypes.ASYNC_KEYWORD))
|
||||
.ifPresent(asyncNode -> getHolder().newAnnotation(HighlightSeverity.ERROR,
|
||||
PyPsiBundle.message("ANN.function.cannot.be.async", node.getName())).range(asyncNode).create());
|
||||
PySyntaxCoreBundle.message("ANN.function.cannot.be.async", node.getName())).range(asyncNode).create());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyNumericLiteralExpression(@NotNull PyNumericLiteralExpression node) {
|
||||
public void visitPyNumericLiteralExpression(@NotNull PyAstNumericLiteralExpression node) {
|
||||
String suffix = node.getIntegerLiteralSuffix();
|
||||
if (suffix == null || "l".equalsIgnoreCase(suffix)) return;
|
||||
if (node.getContainingFile().getLanguage() != PythonLanguage.getInstance()) return;
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("INSP.python.trailing.suffix.not.support", suffix))
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, PySyntaxCoreBundle.message("INSP.python.trailing.suffix.not.support", suffix))
|
||||
.range(node).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyForStatement(@NotNull PyForStatement node) {
|
||||
public void visitPyForStatement(@NotNull PyAstForStatement node) {
|
||||
highlightKeyword(node, PyTokenTypes.ASYNC_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyWithStatement(@NotNull PyWithStatement node) {
|
||||
public void visitPyWithStatement(@NotNull PyAstWithStatement node) {
|
||||
highlightKeyword(node, PyTokenTypes.ASYNC_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyPrefixExpression(@NotNull PyPrefixExpression node) {
|
||||
public void visitPyPrefixExpression(@NotNull PyAstPrefixExpression node) {
|
||||
highlightKeyword(node, PyTokenTypes.AWAIT_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyComprehensionElement(@NotNull PyComprehensionElement node) {
|
||||
public void visitPyComprehensionElement(@NotNull PyAstComprehensionElement node) {
|
||||
highlightKeywords(node, PyTokenTypes.ASYNC_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyMatchStatement(@NotNull PyMatchStatement node) {
|
||||
public void visitPyMatchStatement(@NotNull PyAstMatchStatement node) {
|
||||
highlightKeyword(node, PyTokenTypes.MATCH_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyCaseClause(@NotNull PyCaseClause node) {
|
||||
public void visitPyCaseClause(@NotNull PyAstCaseClause node) {
|
||||
highlightKeyword(node, PyTokenTypes.CASE_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTypeAliasStatement(@NotNull PyTypeAliasStatement node) {
|
||||
public void visitPyTypeAliasStatement(@NotNull PyAstTypeAliasStatement node) {
|
||||
highlightKeyword(node, PyTokenTypes.TYPE_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceHighlightParents(@NotNull PsiFile file) {
|
||||
return file instanceof PyFile;
|
||||
return file instanceof PyAstFile;
|
||||
}
|
||||
|
||||
private void highlightKeyword(@NotNull PsiElement node, @NotNull PyElementType elementType) {
|
||||
@@ -15,5 +15,12 @@
|
||||
<typedHandler implementation="com.jetbrains.python.codeInsight.PyKeywordTypedHandler" id="pyCommaAfterKwd"/>
|
||||
<typedHandler implementation="com.jetbrains.python.editor.PythonSpaceHandler"/>
|
||||
<backspaceHandlerDelegate implementation="com.jetbrains.python.codeInsight.editorActions.PyTripleQuoteBackspaceDelegate"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyCompositeAnnotator"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="Pythonid">
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.PyHighlightingAnnotator"/>
|
||||
</extensions>
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Pythonid.pyAnnotator" interface="com.jetbrains.python.validation.PyAnnotatorBase" dynamic="true"/>
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
@@ -7,11 +7,10 @@ import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public final class PyCompositeAnnotator implements Annotator {
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
PyAnnotator[] annotators = ExtensionPointName.<PyAnnotator>create("Pythonid.pyAnnotator").getExtensions();
|
||||
PyAnnotatingVisitor.runAnnotators(element, holder, annotators);
|
||||
PyAnnotatorBase[] annotators = ExtensionPointName.<PyAnnotatorBase>create("Pythonid.pyAnnotator").getExtensions();
|
||||
PyAnnotatorBase.runAnnotators(element, holder, annotators);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.psi.impl.PyFileImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -51,14 +49,6 @@ public final class PyAnnotatingVisitor implements Annotator, DumbAware {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
|
||||
runAnnotators(psiElement, holder, myAnnotators);
|
||||
}
|
||||
|
||||
static void runAnnotators(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder, PyAnnotator[] annotators) {
|
||||
PsiFile file = holder.getCurrentAnnotationSession().getFile();
|
||||
for (PyAnnotator annotator : annotators) {
|
||||
if (file instanceof PyFileImpl && !((PyFileImpl)file).isAcceptedFor(annotator.getClass())) continue;
|
||||
annotator.annotateElement(psiElement, holder);
|
||||
}
|
||||
PyAnnotatorBase.runAnnotators(psiElement, holder, myAnnotators);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
order="before pythonDocumentationProvider"/>
|
||||
<lang.emacs language="Python" implementationClass="com.jetbrains.python.editor.PyEmacsHandler"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyAnnotatingVisitor"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyCompositeAnnotator"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.inspections.PyCompatibilityInspectionAdvertiser"/>
|
||||
|
||||
<enterBetweenBracesDelegate language="Python"
|
||||
@@ -600,7 +599,6 @@
|
||||
<extensionPoint qualifiedName="Pythonid.unresolvedReferenceQuickFixProvider"
|
||||
interface="com.jetbrains.python.inspections.PyUnresolvedReferenceQuickFixProvider"
|
||||
dynamic="true"/>
|
||||
<extensionPoint qualifiedName="Pythonid.pyAnnotator" interface="com.jetbrains.python.validation.PyAnnotator" dynamic="true"/>
|
||||
<extensionPoint qualifiedName="Pythonid.documentationLinkProvider"
|
||||
interface="com.jetbrains.python.documentation.PythonDocumentationLinkProvider"
|
||||
dynamic="true"/>
|
||||
@@ -702,7 +700,6 @@
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.StarAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.StringLiteralQuotesAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.FStringsAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.PyHighlightingAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.PyPatternAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.PyTryExceptAnnotator"/>
|
||||
<pyAnnotator implementation="com.jetbrains.python.validation.PyLocalVariableAnnotator"/>
|
||||
|
||||
Reference in New Issue
Block a user