mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-08-18 07:15:51 +07:00
507 lines
21 KiB
Java
507 lines
21 KiB
Java
/*
|
|
* Copyright 2000-2016 JetBrains s.r.o.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.intellij.codeInsight.daemon;
|
|
|
|
import com.intellij.ToolExtensionPoints;
|
|
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
|
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
|
import com.intellij.codeInspection.LocalInspectionTool;
|
|
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstance;
|
|
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
|
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
|
|
import com.intellij.codeInspection.deprecation.DeprecationInspection;
|
|
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
|
|
import com.intellij.codeInspection.reference.EntryPoint;
|
|
import com.intellij.codeInspection.reference.RefElement;
|
|
import com.intellij.codeInspection.sillyAssignment.SillyAssignmentInspection;
|
|
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
|
|
import com.intellij.codeInspection.unneededThrows.RedundantThrowsDeclaration;
|
|
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
|
|
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
|
|
import com.intellij.lang.Language;
|
|
import com.intellij.lang.LanguageAnnotators;
|
|
import com.intellij.lang.annotation.Annotation;
|
|
import com.intellij.lang.annotation.AnnotationHolder;
|
|
import com.intellij.lang.annotation.Annotator;
|
|
import com.intellij.lang.annotation.HighlightSeverity;
|
|
import com.intellij.openapi.application.ApplicationManager;
|
|
import com.intellij.openapi.command.WriteCommandAction;
|
|
import com.intellij.openapi.editor.Editor;
|
|
import com.intellij.openapi.editor.ex.EditorEx;
|
|
import com.intellij.openapi.extensions.ExtensionPoint;
|
|
import com.intellij.openapi.extensions.Extensions;
|
|
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
|
import com.intellij.openapi.fileTypes.StdFileTypes;
|
|
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
|
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
|
import com.intellij.openapi.vfs.VfsUtil;
|
|
import com.intellij.openapi.vfs.VirtualFile;
|
|
import com.intellij.pom.java.LanguageLevel;
|
|
import com.intellij.psi.*;
|
|
import com.intellij.psi.xml.XmlAttribute;
|
|
import com.intellij.psi.xml.XmlTag;
|
|
import com.intellij.psi.xml.XmlToken;
|
|
import com.intellij.psi.xml.XmlTokenType;
|
|
import com.intellij.testFramework.IdeaTestUtil;
|
|
import com.intellij.testFramework.VfsTestUtil;
|
|
import com.intellij.util.ui.UIUtil;
|
|
import org.jdom.Element;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import java.awt.*;
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* This class is for "lightweight" tests only, i.e. those which can run inside default light project set up
|
|
* For "heavyweight" tests use AdvHighlightingTest
|
|
*/
|
|
public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase {
|
|
static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advHighlighting";
|
|
|
|
private UnusedDeclarationInspectionBase myUnusedDeclarationInspection;
|
|
|
|
private void doTest(boolean checkWarnings) {
|
|
doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
|
|
}
|
|
|
|
@Override
|
|
protected void setUp() throws Exception {
|
|
super.setUp();
|
|
myUnusedDeclarationInspection = new UnusedDeclarationInspection(isUnusedInspectionRequired());
|
|
enableInspectionTool(myUnusedDeclarationInspection);
|
|
setLanguageLevel(LanguageLevel.JDK_1_4);
|
|
}
|
|
|
|
private boolean isUnusedInspectionRequired() {
|
|
return getTestName(false).contains("UnusedInspection");
|
|
}
|
|
|
|
@NotNull
|
|
@Override
|
|
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
|
return new LocalInspectionTool[]{
|
|
new SillyAssignmentInspection(),
|
|
new AccessStaticViaInstance(),
|
|
new DeprecationInspection(),
|
|
new RedundantThrowsDeclaration(),
|
|
new UnusedImportLocalInspection(),
|
|
new UncheckedWarningLocalInspection()
|
|
};
|
|
}
|
|
|
|
public void testCanHaveBody() { doTest(false); }
|
|
public void testInheritFinal() { doTest(false); }
|
|
public void testBreakOutside() { doTest(false); }
|
|
public void testLoop() { doTest(false); }
|
|
public void testIllegalModifiersCombination() { doTest(false); }
|
|
public void testModifierAllowed() { doTest(false); }
|
|
public void testAbstractMethods() { doTest(false); }
|
|
public void testInstantiateAbstract() { doTest(false); }
|
|
public void testDuplicateClassMethod() { doTest(false); }
|
|
public void testStringLiterals() { doTest(false); }
|
|
public void testStaticInInner() { doTest(false); }
|
|
public void testInvalidExpressions() { doTest(false); }
|
|
public void testIllegalVoidType() { doTest(false); }
|
|
public void testIllegalType() { doTest(false); }
|
|
public void testOperatorApplicability() { doTest(false); }
|
|
public void testIncompatibleTypes() { doTest(false); }
|
|
public void testCtrCallIsFirst() { doTest(false); }
|
|
public void testAccessLevelClash() { doTest(false); }
|
|
public void testCasts() { doTest(false); }
|
|
public void testOverrideConflicts() { doTest(false); }
|
|
public void testOverriddenMethodIsFinal() { doTest(false); }
|
|
public void testMissingReturn() { doTest(false); }
|
|
public void testUnreachable() { doTest(false); }
|
|
public void testFinalFieldInit() { doTest(false); }
|
|
public void testLocalVariableInitialization() { doTest(false); }
|
|
public void testVarDoubleInitialization() { doTest(false); }
|
|
public void testFieldDoubleInitialization() { doTest(false); }
|
|
public void testAssignToFinal() { doTest(false); }
|
|
public void testUnhandledExceptionsInSuperclass() { doTest(false); }
|
|
public void testNoUnhandledExceptionsMultipleInheritance() { doTest(false); }
|
|
public void testIgnoreSuperMethodsInMultipleOverridingCheck() { doTest(false); }
|
|
public void testFalseExceptionsMultipleInheritance() { doTest(true); }
|
|
public void testAssignmentCompatible () { setLanguageLevel(LanguageLevel.JDK_1_5); doTest(false); }
|
|
public void testMustBeBoolean() { doTest(false); }
|
|
|
|
public void testNumericLiterals() { doTest(false); }
|
|
public void testInitializerCompletion() { doTest(false); }
|
|
|
|
public void testUndefinedLabel() { doTest(false); }
|
|
public void testDuplicateSwitchLabels() { doTest(false); }
|
|
public void testStringSwitchLabels() { doTest(false); }
|
|
public void testIllegalForwardReference() { doTest(false); }
|
|
public void testStaticOverride() { doTest(false); }
|
|
public void testCyclicInheritance() { doTest(false); }
|
|
public void testReferenceMemberBeforeCtrCalled() { doTest(false); }
|
|
public void testLabels() { doTest(false); }
|
|
public void testUnclosedBlockComment() { doTest(false); }
|
|
public void testUnclosedComment() { doTest(false); }
|
|
public void testUnclosedDecl() { doTest(false); }
|
|
public void testSillyAssignment() {
|
|
LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
|
|
doTest(true);
|
|
}
|
|
public void testTernary() { doTest(false); }
|
|
public void testDuplicateClass() { doTest(false); }
|
|
public void testCatchType() { doTest(false); }
|
|
public void testMustBeThrowable() { doTest(false); }
|
|
public void testUnhandledMessingWithFinally() { doTest(false); }
|
|
public void testSerializableStuff() { doTest(true); }
|
|
public void testDeprecated() { doTest(true); }
|
|
public void testJavadoc() { enableInspectionTool(new JavaDocLocalInspection()); doTest(true); }
|
|
public void testExpressionsInSwitch () { doTest(false); }
|
|
public void testAccessInner() throws IOException {
|
|
Editor e = createSaveAndOpenFile("x/BeanContextServicesSupport.java",
|
|
"" +
|
|
"package x;\n" +
|
|
"public class BeanContextServicesSupport {" +
|
|
" protected class BCSSChild {" +
|
|
" class BCSSCServiceClassRef {" +
|
|
" void addRequestor(Object requestor) {" +
|
|
" }" +
|
|
" }" +
|
|
" }" +
|
|
"}");
|
|
Editor e2 = createSaveAndOpenFile("x/Component.java",
|
|
"" +
|
|
"package x;\n" +
|
|
"public class Component {" +
|
|
" protected class FlipBufferStrategy {" +
|
|
" protected int numBuffers;" +
|
|
" protected void createBuffers(int numBuffers){}" +
|
|
" }" +
|
|
"}");
|
|
try {
|
|
UIUtil.dispatchAllInvocationEvents();
|
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
|
doTest(false);
|
|
}
|
|
finally {
|
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
|
VirtualFile file = FileDocumentManager.getInstance().getFile(e.getDocument());
|
|
FileEditorManager.getInstance(getProject()).closeFile(file);
|
|
VfsTestUtil.deleteFile(file);
|
|
VirtualFile file2 = FileDocumentManager.getInstance().getFile(e2.getDocument());
|
|
FileEditorManager.getInstance(getProject()).closeFile(file2);
|
|
VfsTestUtil.deleteFile(file2);
|
|
}
|
|
}
|
|
|
|
public void testExceptionNeverThrown() { doTest(true); }
|
|
public void testExceptionNeverThrownInTry() { doTest(false); }
|
|
|
|
public void testSwitchStatement() { doTest(false); }
|
|
public void testAssertExpression() { doTest(false); }
|
|
|
|
public void testSynchronizedExpression() { doTest(false); }
|
|
public void testExtendMultipleClasses() { doTest(false); }
|
|
public void testRecursiveConstructorInvocation() { doTest(false); }
|
|
public void testMethodCalls() { doTest(false); }
|
|
public void testSingleTypeImportConflicts() throws IOException {
|
|
createSaveAndOpenFile("sql/Date.java", "package sql; public class Date{}");
|
|
UIUtil.dispatchAllInvocationEvents();
|
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
|
doTest(false);
|
|
}
|
|
public void testMultipleSingleTypeImports() { doTest(true); } //duplicate imports
|
|
public void testNotAllowedInInterface() { doTest(false); }
|
|
public void testQualifiedNew() { doTest(false); }
|
|
public void testEnclosingInstance() { doTest(false); }
|
|
|
|
public void testStaticViaInstance() { doTest(true); } // static via instance
|
|
public void testQualifiedThisSuper() { doTest(true); } //illegal qualified this or super
|
|
|
|
public void testAmbiguousMethodCall() { doTest(false); }
|
|
|
|
public void testImplicitConstructor() { doTest(false); }
|
|
public void testDotBeforeDecl() { doTest(false); }
|
|
public void testComputeConstant() { doTest(false); }
|
|
|
|
public void testAnonInAnon() { doTest(false); }
|
|
public void testAnonBaseRef() { doTest(false); }
|
|
public void testReturn() { doTest(false); }
|
|
public void testInterface() { doTest(false); }
|
|
public void testExtendsClause() { doTest(false); }
|
|
public void testMustBeFinal() { doTest(false); }
|
|
|
|
public void testXXX() { doTest(false); }
|
|
public void testUnused() { doTest(true); }
|
|
public void testQualifierBeforeClassName() { doTest(false); }
|
|
public void testQualifiedSuper() {
|
|
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_6, getModule(), getTestRootDisposable());
|
|
doTest(false);
|
|
}
|
|
|
|
public void testIgnoreImplicitThisReferenceBeforeSuperSinceJdk7() { doTest(false); }
|
|
|
|
public void testCastFromVoid() { doTest(false); }
|
|
public void testCatchUnknownMethod() { doTest(false); }
|
|
public void testIDEADEV8822() { doTest(false); }
|
|
public void testIDEADEV9201() { doTest(false); }
|
|
public void testIDEADEV25784() { doTest(false); }
|
|
public void testIDEADEV13249() { doTest(false); }
|
|
public void testIDEADEV11919() { doTest(false); }
|
|
public void testIDEA67829() { doTest(false); }
|
|
public void testMethodCannotBeApplied() { doTest(false); }
|
|
public void testDefaultPackageClassInStaticImport() { doTest(false); }
|
|
|
|
public void testUnusedParamsOfPublicMethod() { doTest(true); }
|
|
public void testInnerClassesShadowing() { doTest(false); }
|
|
|
|
public void testUnusedParamsOfPublicMethodDisabled() {
|
|
UnusedSymbolLocalInspectionBase tool = myUnusedDeclarationInspection.getSharedLocalInspectionTool();
|
|
assertNotNull(tool);
|
|
String oldVal = tool.getParameterVisibility();
|
|
try {
|
|
tool.setParameterVisibility(PsiModifier.PRIVATE);
|
|
doTest(true);
|
|
}
|
|
finally {
|
|
tool.setParameterVisibility(oldVal);
|
|
}
|
|
}
|
|
|
|
public void testUnusedInspectionNonPrivateMembers() {
|
|
doTest(true);
|
|
}
|
|
|
|
public void testUnusedNonPrivateMembers2() {
|
|
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.DEAD_CODE_TOOL);
|
|
EntryPoint extension = new EntryPoint() {
|
|
@NotNull
|
|
@Override
|
|
public String getDisplayName() {
|
|
return "duh";
|
|
}
|
|
|
|
@Override
|
|
public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEntryPoint(@NotNull PsiElement psiElement) {
|
|
return psiElement instanceof PsiMethod && ((PsiMethod)psiElement).getName().equals("myTestMethod");
|
|
}
|
|
|
|
@Override
|
|
public boolean isSelected() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void setSelected(boolean selected) { }
|
|
|
|
@Override
|
|
public void readExternal(Element element) { }
|
|
|
|
@Override
|
|
public void writeExternal(Element element) { }
|
|
};
|
|
|
|
point.registerExtension(extension);
|
|
|
|
try {
|
|
myUnusedDeclarationInspection = new UnusedDeclarationInspectionBase(true);
|
|
doTest(true);
|
|
}
|
|
finally {
|
|
point.unregisterExtension(extension);
|
|
myUnusedDeclarationInspection = new UnusedDeclarationInspectionBase();
|
|
}
|
|
}
|
|
|
|
public void testUnusedInspectionNonPrivateMembersReferencedFromText() {
|
|
doTest(true);
|
|
WriteCommandAction.runWriteCommandAction(null, () -> {
|
|
PsiDirectory directory = myFile.getParent();
|
|
assertNotNull(myFile.toString(), directory);
|
|
PsiFile txt = directory.createFile("x.txt");
|
|
VirtualFile vFile = txt.getVirtualFile();
|
|
assertNotNull(txt.toString(), vFile);
|
|
try {
|
|
VfsUtil.saveText(vFile, "XXX");
|
|
}
|
|
catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
});
|
|
|
|
List<HighlightInfo> infos = doHighlighting(HighlightSeverity.WARNING);
|
|
assertEmpty(infos);
|
|
}
|
|
|
|
public void testNamesHighlighting() {
|
|
LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(LanguageLevel.JDK_1_5);
|
|
doTestFile(BASE_PATH + "/" + getTestName(false) + ".java").checkSymbolNames().test();
|
|
}
|
|
|
|
public void testMultiFieldDeclNames() {
|
|
doTestFile(BASE_PATH + "/" + getTestName(false) + ".java").checkSymbolNames().test();
|
|
}
|
|
|
|
public void testInjectedAnnotator() {
|
|
Annotator annotator = new MyAnnotator();
|
|
Language xml = StdFileTypes.XML.getLanguage();
|
|
LanguageAnnotators.INSTANCE.addExplicitExtension(xml, annotator);
|
|
try {
|
|
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(xml);
|
|
assertTrue(list.toString(), list.contains(annotator));
|
|
doTest(BASE_PATH + "/" + getTestName(false) + ".xml",true,false);
|
|
}
|
|
finally {
|
|
LanguageAnnotators.INSTANCE.removeExplicitExtension(xml, annotator);
|
|
}
|
|
|
|
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(xml);
|
|
assertFalse(list.toString(), list.contains(annotator));
|
|
}
|
|
|
|
public void testSOEForTypeOfHugeBinaryExpression() throws IOException {
|
|
configureFromFileText("a.java", "class A { String s = \"\"; }");
|
|
assertEmpty(highlightErrors());
|
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
|
|
|
final StringBuilder sb = new StringBuilder("\"-\"");
|
|
for (int i = 0; i < 10000; i++) sb.append("+\"b\"");
|
|
final String hugeExpr = sb.toString();
|
|
final int pos = getEditor().getDocument().getText().indexOf("\"\"");
|
|
|
|
ApplicationManager.getApplication().runWriteAction(() -> {
|
|
getEditor().getDocument().replaceString(pos, pos + 2, hugeExpr);
|
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
|
});
|
|
|
|
final PsiField field = ((PsiJavaFile)getFile()).getClasses()[0].getFields()[0];
|
|
final PsiExpression expression = field.getInitializer();
|
|
assert expression != null;
|
|
final PsiType type = expression.getType();
|
|
assert type != null;
|
|
assertEquals("PsiType:String", type.toString());
|
|
}
|
|
|
|
public void testSOEForCyclicInheritance() throws IOException {
|
|
configureFromFileText("a.java", "class A extends B { String s = \"\"; void f() {}} class B extends A { void f() {} } ");
|
|
doHighlighting();
|
|
}
|
|
|
|
public void testClassicRethrow() { doTest(false); }
|
|
public void testRegexp() { doTest(false); }
|
|
public void testUnsupportedFeatures() { doTest(false); }
|
|
public void testThisBeforeSuper() { doTest(false); }
|
|
public void testExplicitConstructorInvocation() { doTest(false); }
|
|
public void testThisInInterface() { doTest(false); }
|
|
public void testInnerClassConstantReference() { doTest(false); }
|
|
public void testIDEA60875() { doTest(false); }
|
|
public void testIDEA71645() { doTest(false); }
|
|
public void testIDEA18343() { doTest(false); }
|
|
public void testNewExpressionClass() { doTest(false); }
|
|
public void testInnerClassObjectLiteralFromSuperExpression() { doTest(false); }
|
|
public void testPrivateFieldInSuperClass() { doTest(false); }
|
|
public void testNoEnclosingInstanceWhenStaticNestedInheritsFromContainingClass() { doTest(false); }
|
|
public void testIDEA168768() { doTest(false); }
|
|
|
|
public void testStaticMethodCalls() {
|
|
doTestFile(BASE_PATH + "/" + getTestName(false) + ".java").checkSymbolNames().test();
|
|
}
|
|
|
|
public void testNestedLocalClasses() throws Exception {
|
|
doTest(false);
|
|
}
|
|
|
|
public void testAmbiguousConstants() throws Exception {
|
|
doTest(false);
|
|
}
|
|
|
|
public void testInsane() throws IOException {
|
|
configureFromFileText("x.java", "class X { \nx_x_x_x\n }");
|
|
List<HighlightInfo> infos = highlightErrors();
|
|
assertTrue(!infos.isEmpty());
|
|
}
|
|
|
|
public void testAnnotatorWorksWithFileLevel() {
|
|
Annotator annotator = new MyTopFileAnnotator();
|
|
Language java = StdFileTypes.JAVA.getLanguage();
|
|
LanguageAnnotators.INSTANCE.addExplicitExtension(java, annotator);
|
|
try {
|
|
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(java);
|
|
assertTrue(list.toString(), list.contains(annotator));
|
|
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
|
((EditorEx)getEditor()).getScrollPane().getViewport().setSize(new Dimension(1000,1000)); // whole file fit onscreen
|
|
doHighlighting();
|
|
List<HighlightInfo> fileLevel =
|
|
((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(ourProject)).getFileLevelHighlights(getProject(), getFile());
|
|
HighlightInfo info = assertOneElement(fileLevel);
|
|
assertEquals("top level", info.getDescription());
|
|
|
|
type("\n\n");
|
|
doHighlighting();
|
|
fileLevel =
|
|
((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(ourProject)).getFileLevelHighlights(getProject(), getFile());
|
|
info = assertOneElement(fileLevel);
|
|
assertEquals("top level", info.getDescription());
|
|
|
|
type("//xxx"); //disable top level annotation
|
|
List<HighlightInfo> warnings = doHighlighting(HighlightSeverity.WARNING);
|
|
assertEmpty(warnings);
|
|
fileLevel = ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(ourProject)).getFileLevelHighlights(getProject(), getFile());
|
|
assertEmpty(fileLevel);
|
|
}
|
|
finally {
|
|
LanguageAnnotators.INSTANCE.removeExplicitExtension(java, annotator);
|
|
}
|
|
|
|
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(java);
|
|
assertFalse(list.toString(), list.contains(annotator));
|
|
}
|
|
|
|
public void testIllegalWhitespaces() { doTest(false); }
|
|
|
|
// must stay public for PicoContainer to work
|
|
public static class MyAnnotator implements Annotator {
|
|
@Override
|
|
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
|
|
psiElement.accept(new XmlElementVisitor() {
|
|
@Override public void visitXmlTag(XmlTag tag) {
|
|
XmlAttribute attribute = tag.getAttribute("aaa", "");
|
|
if (attribute != null) {
|
|
holder.createWarningAnnotation(attribute, "MyAnnotator");
|
|
}
|
|
}
|
|
|
|
@Override public void visitXmlToken(XmlToken token) {
|
|
if (token.getTokenType() == XmlTokenType.XML_ENTITY_REF_TOKEN) {
|
|
holder.createWarningAnnotation(token, "ENTITY");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// must stay public for PicoContainer to work
|
|
public static class MyTopFileAnnotator implements Annotator {
|
|
@Override
|
|
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
|
|
if (psiElement instanceof PsiFile && !psiElement.getText().contains("xxx")) {
|
|
Annotation annotation = holder.createWarningAnnotation(psiElement, "top level");
|
|
annotation.setFileLevelAnnotation(true);
|
|
}
|
|
}
|
|
}
|
|
} |