IDEA-337197 Throwable: the expensive method should not be called inside the highlighting pass in JSP

check unresolved references in a dedicated XmlUnresolvedReferenceInspection

GitOrigin-RevId: d54b7a0b933c33c8656726c84a9611c97c1268ff
This commit is contained in:
Dmitry Avdeev
2023-12-13 16:44:59 +01:00
committed by intellij-monorepo-bot
parent 63045881e6
commit 6ba55541ee
29 changed files with 246 additions and 126 deletions

View File

@@ -420,6 +420,10 @@
bundle="messages.XmlBundle" key="xml.inspections.path.resolve"
groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name"
implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection"/>
<localInspection language="XML" enabledByDefault="true" level="ERROR"
bundle="messages.XmlBundle" key="xml.inspections.unresolved"
groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name"
implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection"/>
<localInspection language="XML" enabledByDefault="true" level="WARNING"
bundle="messages.XmlBundle" key="xml.inspections.default.attribute.value"
groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name"

View File

@@ -4,6 +4,7 @@ package com.intellij.lang.ant;
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.lang.ant.dom.AntResolveInspection;
import com.intellij.lang.ant.validation.AntDuplicateTargetsInspection;
@@ -89,7 +90,8 @@ public class AntHighlightingTest extends DaemonAnalyzerTestCase {
return new LocalInspectionTool[]{
new AntDuplicateTargetsInspection(),
new AntResolveInspection(),
new XmlPathReferenceInspection()
new XmlPathReferenceInspection(),
new XmlUnresolvedReferenceInspection()
};
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.devkit.codeInsight;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
public class LiveTemplatesXmlTest extends LightJavaCodeInsightFixtureTestCase {
@@ -10,6 +11,7 @@ public class LiveTemplatesXmlTest extends LightJavaCodeInsightFixtureTestCase {
super.setUp();
myFixture.addClass("package com.intellij.ui.components; public class JBList {}");
myFixture.addFileToProject("MyBundle.properties", "key1=value1");
myFixture.enableInspections(new XmlUnresolvedReferenceInspection());
}

View File

@@ -5,6 +5,7 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInsight.hints.declarative.InlayHintsProviderExtensionBean;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.lookup.LookupElement;
@@ -70,7 +71,7 @@ public class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase {
myTempDirFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
myTempDirFixture.setUp();
myInspection = new PluginXmlDomInspection();
myFixture.enableInspections(myInspection);
myFixture.enableInspections(myInspection, new XmlUnresolvedReferenceInspection());
RecursionManager.assertOnRecursionPrevention(getTestRootDisposable());
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionActionBean;
import com.intellij.codeInspection.LocalInspectionEP;
@@ -38,7 +39,7 @@ public class PluginXmlExtensionRegistrationInspectionTest extends JavaCodeInsigh
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(PluginXmlExtensionRegistrationInspection.class);
myFixture.enableInspections(PluginXmlExtensionRegistrationInspection.class, XmlUnresolvedReferenceInspection.class);
}
public void testStatusBarWidgetFactoryEP() {

View File

@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="intellij.xml.dom.impl" exported="" />
<orderEntry type="module" module-name="intellij.java.compiler" exported="" />
<orderEntry type="module" module-name="intellij.jvm.analysis" exported="" />
<orderEntry type="module" module-name="intellij.xml.analysis.impl" scope="TEST" />
</component>
<component name="TestModuleProperties" production-module="intellij.devkit.core" />
</module>

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
public abstract class PluginXmlDomInspectionTestBase extends LightJavaCodeInsightFixtureTestCase {
@@ -12,6 +13,6 @@ public abstract class PluginXmlDomInspectionTestBase extends LightJavaCodeInsigh
myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}");
myFixture.addClass("package com.intellij.openapi.actionSystem; public abstract class ActionGroup extends AnAction {}");
myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent {}");
myFixture.enableInspections(new PluginXmlDomInspection());
myFixture.enableInspections(new PluginXmlDomInspection(), new XmlUnresolvedReferenceInspection());
}
}

View File

@@ -6,6 +6,7 @@ import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
import com.intellij.codeInsight.daemon.impl.analysis.HtmlUnknownAnchorTargetInspection;
import com.intellij.codeInsight.daemon.impl.analysis.HtmlUnknownTargetInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnboundNsPrefixInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.CachedIntentions;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -87,7 +88,8 @@ public class HtmlHighlightingTest extends BasePlatformTestCase {
new XmlUnboundNsPrefixInspection(),
new HtmlPresentationalElementInspection(),
new HtmlUnknownTargetInspection(),
new HtmlUnknownAnchorTargetInspection()
new HtmlUnknownAnchorTargetInspection(),
new XmlUnresolvedReferenceInspection()
};
}

View File

@@ -17,6 +17,7 @@ package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.openapi.application.PluginPathManager;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +28,7 @@ public class JavaFXImportTest extends DaemonAnalyzerTestCase {
protected void setUpModule() {
super.setUpModule();
AbstractJavaFXTestCase.addJavaFxJarAsLibrary(getModule());
enableInspectionTool(new XmlUnresolvedReferenceInspection());
}
public void testSimpleImport() throws Exception {

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.codeInsight.daemon.impl.analysis.PsiReferenceWithUnresolvedQuickFixes;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
@@ -15,7 +16,7 @@ import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.ArrayList;
import java.util.List;
public final class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeValue> {
public final class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeValue> implements PsiReferenceWithUnresolvedQuickFixes {
final PsiMethod myEventHandler;
final PsiClass myController;

View File

@@ -4,7 +4,7 @@
<AnchorPane xmlns:fx="http://javafx.com/fxml">
<children>
<AnchorPane AnchorPane.leftAnchor="0.0" <error descr="Attribute AnchorPane.leftAnchor1 is not allowed here">AnchorPane.leftAnchor1</error>="0.0">
<AnchorPane AnchorPane.leftAnchor="0.0" <error descr="Attribute AnchorPane.leftAnchor1 is not allowed here">AnchorPane.<error descr="Cannot resolve symbol 'leftAnchor1'">leftAnchor1</error></error>="0.0">
<AnchorPane.bottomAnchor>200</AnchorPane.bottomAnchor>
<<error descr="Element AnchorPane1.bottomAnchor is not allowed here">AnchorPane1.bottomAnchor</error>>200</<error descr="Element AnchorPane1.bottomAnchor is not allowed here">AnchorPane1.bottomAnchor</error>>
<GridPane.rowIndex>0</GridPane.rowIndex>

View File

@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -57,6 +58,7 @@ public abstract class AbstractJavaFXTestCase extends LightJavaCodeInsightFixture
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new XmlUnresolvedReferenceInspection());
enableInspections();
}
}

View File

@@ -3,6 +3,7 @@ package com.intellij.maven.testFramework
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.TargetElementUtil
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection
import com.intellij.codeInsight.documentation.DocumentationManager
import com.intellij.codeInsight.highlighting.HighlightUsagesHandler
import com.intellij.codeInsight.intention.IntentionAction
@@ -66,7 +67,7 @@ abstract class MavenDomTestCase : MavenMultiVersionImportingTestCase() {
// org.jetbrains.idea.maven.utils.MavenRehighlighter
(myFixture!! as CodeInsightTestFixtureImpl).canChangeDocumentDuringHighlighting(true)
myFixture!!.enableInspections(MavenModelInspection::class.java)
myFixture!!.enableInspections(MavenModelInspection::class.java, XmlUnresolvedReferenceInspection::class.java)
myOriginalAutoCompletion = CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION
CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = false

View File

@@ -2,6 +2,7 @@
package com.theoryinpractice.testng.referenceContributor;
import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.util.ui.UIUtil;
@@ -50,7 +51,7 @@ public class TestNGSuiteTest extends LightJavaCodeInsightFixtureTestCase {
"<classes></classes>" +
"</test>" +
"</suite>");
myFixture.enableInspections(new XmlPathReferenceInspection());
myFixture.enableInspections(new XmlPathReferenceInspection(), new XmlUnresolvedReferenceInspection());
myFixture.testHighlighting("testng.xml");
}
catch (Exception e) {

View File

@@ -16,6 +16,7 @@
package org.intellij.lang.xpath.xslt.impl;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.project.Project;
import com.intellij.pom.Navigatable;
@@ -43,13 +44,14 @@ import javax.xml.namespace.QName;
public class XsltStuffProvider implements UsageGroupingRuleProvider {
@SuppressWarnings({"unchecked"})
public static final Class<? extends LocalInspectionTool>[] INSPECTION_CLASSES = new Class[]{
UnusedElementInspection.class,
TemplateInvocationInspection.class,
XsltDeclarationInspection.class,
VariableShadowingInspection.class
};
@SuppressWarnings({"unchecked"})
public static final Class<? extends LocalInspectionTool>[] INSPECTION_CLASSES = new Class[]{
UnusedElementInspection.class,
TemplateInvocationInspection.class,
XsltDeclarationInspection.class,
VariableShadowingInspection.class,
XmlUnresolvedReferenceInspection.class
};
private final UsageGroupingRule[] myUsageGroupingRules;

View File

@@ -78,6 +78,7 @@ xml.inspections.duplicate.id=Duplicate 'id' attribute
xml.inspections.invalid.id=Unresolved 'id' reference
xml.inspections.unused.schema=Unused schema declaration
xml.inspections.path.resolve=Unresolved file reference
xml.inspections.unresolved=Unresolved references
xml.inspections.default.attribute.value=Redundant attribute with default value
xml.inspections.deprecated=Deprecated symbol
xml.inspections.required.attributes.display.name=Missing required attribute

View File

@@ -17,6 +17,7 @@ package org.intellij.plugins.relaxNG;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
import com.intellij.javaee.ExternalResourceManagerEx;
@@ -214,7 +215,7 @@ public abstract class HighlightingTestBase extends UsefulTestCase implements Ide
@Override
public Class<? extends LocalInspectionTool> @NotNull [] getInspectionClasses() {
//noinspection unchecked
return new Class[]{RngDomInspection.class, RequiredAttributesInspection.class};
return new Class[]{RngDomInspection.class, RequiredAttributesInspection.class, XmlUnresolvedReferenceInspection.class};
}
}
}

View File

@@ -5,10 +5,7 @@ import com.intellij.application.options.XmlSettings;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlDefaultAttributeValueInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnboundNsPrefixInspection;
import com.intellij.codeInsight.daemon.impl.analysis.*;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.htmlInspections.*;
@@ -166,6 +163,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
// TODO: external validator should not be launched due to error detected after general highlighting pass!
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testEntityRefWithEmptyDtd() throws Exception { doTest(); }
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testEmptyNSRef() throws Exception { doTest(); }
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
@@ -421,6 +419,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
);
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testSchemaReferencesValidation() throws Exception {
doTest(getFullRelativeTestName(".xsd"), false, false);
}
@@ -1138,6 +1137,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
checkResultByFile(s + "_after.xml");
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testSpecifyXsiSchemaLocationQuickFix() throws Exception {
configureByFile(BASE_PATH + "web-app_2_4.xsd");
final String testName = getTestName(false);
@@ -1766,6 +1766,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
checkResultByFile(BASE_PATH + testName + "_after.xml");
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testUnqualifiedAttributePsi() {
doTestWithLocations(null, "xml");
final List<XmlAttribute> attrs = new ArrayList<>(2);
@@ -1882,6 +1883,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
);
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testUnresolvedSymbolForForAttribute() throws Exception {
doTest();
}
@@ -2029,16 +2031,19 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
doDoTest(true, false);
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testEnumeratedBoolean() {
configureByFiles(null, BASE_PATH + "EnumeratedBoolean.xml", BASE_PATH + "EnumeratedBoolean.xsd");
doDoTest(true, false);
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testEnumeratedList() {
configureByFiles(null, BASE_PATH + "servers.xml", BASE_PATH + "servers.xsd");
doDoTest(true, false);
}
@HighlightingFlags(HighlightingFlag.SkipExternalValidation)
public void testEnumeratedExtension() {
configureByFiles(null, BASE_PATH + "enumerations.xml", BASE_PATH + "enumerations.xsd");
doDoTest(true, false);
@@ -2200,7 +2205,8 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase {
new XmlInvalidIdInspection(),
new CheckDtdReferencesInspection(),
new XmlUnboundNsPrefixInspection(),
new XmlPathReferenceInspection()
new XmlPathReferenceInspection(),
new XmlUnresolvedReferenceInspection()
};
}

View File

@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
@@ -37,4 +38,10 @@ public class IgnoreExternalResourcesFixTest extends LightQuickFixParameterizedTe
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/";
}
@Override
protected void setUp() throws Exception {
super.setUp();
enableInspectionTool(new XmlUnresolvedReferenceInspection());
}
}

View File

@@ -2,6 +2,7 @@
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.javaee.ExternalResourceManager;
@@ -120,6 +121,7 @@ public class RealFetchTest extends BasePlatformTestCase {
VirtualFile virtualFile = myFixture.getTempDirFixture().createFile("images.dtd", "");
ExternalResourceManagerExImpl.registerResourceTemporarily(url, virtualFile.getPath(), getTestRootDisposable());
myFixture.enableInspections(new XmlUnresolvedReferenceInspection());
myFixture.configureByText(XmlFileType.INSTANCE, """
<!DOCTYPE preferences SYSTEM "<error descr="Resource registered by this uri is not recognized (Settings | Languages & Frameworks | Schemas and DTDs)">http://java.sun.com/dtd/prefe<caret>rences.dtd</error>"><preferences>
<root type="system"><map/></root>

View File

@@ -26,6 +26,7 @@ public class XmlInspectionToolProvider implements InspectionToolProvider {
XmlUnusedNamespaceInspection.class,
XmlHighlightVisitorBasedInspection.class,
XmlPathReferenceInspection.class,
XmlUnresolvedReferenceInspection.class,
HtmlUnknownTargetInspection.class,
HtmlUnknownAnchorTargetInspection.class
};

View File

@@ -16,6 +16,7 @@
package com.intellij.xml;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnresolvedReferenceInspection;
import com.intellij.javaee.ExternalResourceManagerEx;
import com.intellij.javaee.XMLCatalogConfigurable;
import com.intellij.javaee.XMLCatalogManager;
@@ -115,4 +116,10 @@ public class XMLCatalogManagerTest extends BasePlatformTestCase {
protected boolean isCommunity() {
return true;
}
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new XmlUnresolvedReferenceInspection());
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Reports an unresolved references in XML.
</body>
</html>

View File

@@ -33,6 +33,6 @@ public class HtmlUnknownAnchorTargetInspection extends XmlPathReferenceInspectio
@Override
protected boolean needToCheckRef(PsiReference reference) {
return reference instanceof AnchorReference && HtmlUnknownTargetInspection.notRemoteBase(reference);
return super.needToCheckRef(reference) && reference instanceof AnchorReference && HtmlUnknownTargetInspection.notRemoteBase(reference);
}
}

View File

@@ -36,7 +36,7 @@ public class HtmlUnknownTargetInspection extends XmlPathReferenceInspection {
@Override
protected boolean needToCheckRef(PsiReference reference) {
return !(reference instanceof AnchorReference) && notRemoteBase(reference);
return super.needToCheckRef(reference) && !(reference instanceof AnchorReference) && notRemoteBase(reference);
}
static boolean notRemoteBase(PsiReference reference) {

View File

@@ -27,8 +27,8 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.html.HtmlTag;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceOwner;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.*;
import com.intellij.psi.impl.source.xml.TagNameReference;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
@@ -440,7 +440,7 @@ public class XmlHighlightVisitor extends XmlElementVisitor implements HighlightV
for (int i = start; i < references.length; ++i) {
PsiReference reference = references[i];
ProgressManager.checkCanceled();
if (isUrlReference(reference)) continue;
if (!shouldCheckResolve(reference)) continue;
if (!hasBadResolve(reference, false)) {
continue;
}
@@ -484,6 +484,14 @@ public class XmlHighlightVisitor extends XmlElementVisitor implements HighlightV
}
}
static boolean shouldCheckResolve(PsiReference reference) {
return reference instanceof TypeOrElementOrAttributeReference ||
reference instanceof DependentNSReference ||
reference instanceof URLReference ||
reference instanceof TagNameReference ||
reference instanceof PsiReferenceWithUnresolvedQuickFixes;
}
static boolean isUrlReference(PsiReference reference) {
return reference instanceof FileReferenceOwner || reference instanceof AnchorReference || reference instanceof PsiFileReference;
}

View File

@@ -1,111 +1,15 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.XmlSuppressableInspectionTool;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlDoctype;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author Dmitry Avdeev
*/
public class XmlPathReferenceInspection extends XmlSuppressableInspectionTool {
@NotNull
public class XmlPathReferenceInspection extends XmlReferenceInspectionBase {
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new XmlElementVisitor() {
@Override
public void visitXmlAttributeValue(@NotNull XmlAttributeValue value) {
checkRefs(value, holder);
}
@Override
public void visitXmlDoctype(@NotNull XmlDoctype xmlDoctype) {
checkRefs(xmlDoctype, holder);
}
@Override
public void visitXmlTag(@NotNull XmlTag tag) {
checkRefs(tag, holder);
}
};
}
private void checkRefs(@NotNull XmlElement element, @NotNull ProblemsHolder holder) {
PsiReference[] references = element.getReferences();
if (references.length == 0) {
return;
}
if (XmlHighlightVisitor.isInjectedWithoutValidation(element)) {
return;
}
boolean isHtml = HtmlUtil.isHtmlTagContainingFile(element);
if (isHtml ^ isForHtml()) {
return;
}
if (!isHtml && XmlHighlightVisitor.skipValidation(element)) {
return;
}
Collection<PsiReference> unresolved = getUnresolvedReferencesToAnnotate(references);
for (PsiReference reference : unresolved) {
holder.registerProblem(reference, ProblemsHolder.unresolvedReferenceMessage(reference),
isHtml ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
@NotNull
private Collection<PsiReference> getUnresolvedReferencesToAnnotate(PsiReference[] references) {
Map<TextRange, PsiReference> unresolvedReferences = new HashMap<>();
for (PsiReference reference : references) {
if (!XmlHighlightVisitor.isUrlReference(reference) || !needToCheckRef(reference)) {
continue;
}
TextRange elementRange = reference.getElement().getTextRange();
if (elementRange == null || elementRange.isEmpty()) {
continue;
}
TextRange rangeInElement = reference.getRangeInElement();
if (unresolvedReferences.containsKey(rangeInElement) && unresolvedReferences.get(rangeInElement) == null) {
continue;
}
if (XmlHighlightVisitor.hasBadResolve(reference, true)) {
if (!reference.isSoft()) {
unresolvedReferences.putIfAbsent(rangeInElement, reference);
}
}
else {
// the specific range has at least one resolved reference
// no need to check any other references from that range
unresolvedReferences.put(rangeInElement, null);
}
}
return ContainerUtil.skipNulls(unresolvedReferences.values());
}
protected boolean needToCheckRef(PsiReference reference) {
return true;
}
protected boolean isForHtml() {
return false;
return XmlHighlightVisitor.isUrlReference(reference);
}
}

View File

@@ -0,0 +1,134 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.XmlSuppressableInspectionTool;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.xml.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public abstract class XmlReferenceInspectionBase extends XmlSuppressableInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new XmlElementVisitor() {
@Override
public void visitXmlAttributeValue(@NotNull XmlAttributeValue value) {
checkRefs(value, holder, 0);
}
@Override
public void visitXmlAttribute(@NotNull XmlAttribute attribute) {
int startIndex = !attribute.getNamespacePrefix().isEmpty() ? 2 : 1;
checkRefs(attribute, holder, startIndex);
}
@Override
public void visitXmlDoctype(@NotNull XmlDoctype xmlDoctype) {
checkRefs(xmlDoctype, holder, 0);
}
@Override
public void visitXmlTag(@NotNull XmlTag tag) {
checkRefs(tag, holder, 0);
}
@Override
public void visitXmlProcessingInstruction(@NotNull XmlProcessingInstruction processingInstruction) {
checkRefs(processingInstruction, holder, 0);
}
};
}
private void checkRefs(@NotNull XmlElement element, @NotNull ProblemsHolder holder, int startIndex) {
PsiReference[] references = element.getReferences();
if (references.length <= startIndex) {
return;
}
if (XmlHighlightVisitor.isInjectedWithoutValidation(element)) {
return;
}
boolean isHtml = HtmlUtil.isHtmlTagContainingFile(element);
if (!checkHtml(element, isHtml)) {
return;
}
Collection<PsiReference> unresolved = getUnresolvedReferencesToAnnotate(Arrays.copyOfRange(references, startIndex, references.length));
for (PsiReference reference : unresolved) {
holder.registerProblem(reference, ProblemsHolder.unresolvedReferenceMessage(reference),
isHtml ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
protected boolean checkHtml(@NotNull XmlElement element, boolean isHtml) {
if (isHtml ^ isForHtml()) {
return false;
}
if (!isHtml && XmlHighlightVisitor.skipValidation(element)) {
return false;
}
return true;
}
@NotNull
private Collection<PsiReference> getUnresolvedReferencesToAnnotate(PsiReference[] references) {
Map<TextRange, PsiReference> unresolvedReferences = new HashMap<>();
for (PsiReference reference : references) {
if (!needToCheckRef(reference)) {
continue;
}
if (!checkRanges()) {
if (XmlHighlightVisitor.hasBadResolve(reference, false)) {
unresolvedReferences.put(reference.getRangeInElement(), reference);
}
continue;
}
TextRange elementRange = reference.getElement().getTextRange();
if (elementRange == null || elementRange.isEmpty()) {
continue;
}
TextRange rangeInElement = reference.getRangeInElement();
if (unresolvedReferences.containsKey(rangeInElement) && unresolvedReferences.get(rangeInElement) == null) {
continue;
}
if (XmlHighlightVisitor.hasBadResolve(reference, true)) {
if (!reference.isSoft()) {
unresolvedReferences.putIfAbsent(rangeInElement, reference);
}
}
else {
// the specific range has at least one resolved reference
// no need to check any other references from that range
unresolvedReferences.put(rangeInElement, null);
}
}
return ContainerUtil.skipNulls(unresolvedReferences.values());
}
protected boolean checkRanges() {
return true;
}
protected abstract boolean needToCheckRef(PsiReference reference);
protected boolean isForHtml() {
return false;
}
}

View File

@@ -0,0 +1,21 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.analysis
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider
import com.intellij.psi.PsiReference
import com.intellij.psi.xml.XmlElement
class XmlUnresolvedReferenceInspection: XmlReferenceInspectionBase() {
override fun needToCheckRef(reference: PsiReference?) = !XmlHighlightVisitor.shouldCheckResolve(reference) &&
!XmlHighlightVisitor.isUrlReference(reference)
override fun checkRanges() = false
override fun checkHtml(element: XmlElement, isHtml: Boolean) = true
}
/**
* Marker interface for references associated with [UnresolvedReferenceQuickFixProvider],
* which should be checked by [XmlHighlightVisitor]
*/
interface PsiReferenceWithUnresolvedQuickFixes: PsiReference