From 0c19a4c6958d9858ff9470bc82df02659c6c54f6 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 29 Sep 2017 13:46:37 +0300 Subject: [PATCH] inspection view: allow specify container element for every inspection for given language (IDEA-179773) --- .../AbstractBaseJavaLocalInspectionTool.java | 25 +------------- .../reference/RefJavaManagerImpl.java | 27 +++++++-------- .../codeInspection/LocalInspectionTool.java | 25 ++++++-------- .../lang/RefManagerExtension.java | 30 ++++++++-------- .../codeInspection/reference/RefManager.java | 22 ++++-------- .../reference/RefManagerImpl.java | 30 ++++++++-------- .../ex/LocalDescriptorsUtil.java | 31 ++++++++--------- .../OfflineDescriptorResolveResult.java | 34 ++++++------------- 8 files changed, 86 insertions(+), 138 deletions(-) diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java b/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java index a2c46384e0df..8c314fdd351d 100644 --- a/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java +++ b/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java @@ -1,29 +1,11 @@ -/* - * Copyright 2000-2013 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Conditions; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectionTool { - private static final Condition PROBLEM_ELEMENT_CONDITION = Conditions.and(Conditions.instanceOf(PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class), Conditions.notInstanceOf(PsiTypeParameter.class)); /** * Override this to report problems at method level. @@ -97,9 +79,4 @@ public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectio } }; } - - @Override - public PsiNamedElement getProblemElement(final PsiElement psiElement) { - return (PsiNamedElement)PsiTreeUtil.findFirstParent(psiElement, PROBLEM_ELEMENT_CONDITION); - } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java index e027610a47ab..42d49b0d5da5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.reference; import com.intellij.codeInsight.ExternalAnnotationsManager; @@ -26,6 +12,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -50,6 +38,9 @@ import java.util.Map; * Date: 20-Dec-2007 */ public class RefJavaManagerImpl extends RefJavaManager { + private static final Condition PROBLEM_ELEMENT_CONDITION = Conditions + .and(Conditions.instanceOf(PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class), Conditions.notInstanceOf(PsiTypeParameter.class)); + private static final Logger LOG = Logger.getInstance(RefJavaManagerImpl.class); private final PsiMethod myAppMainPattern; private final PsiMethod myAppPremainPattern; @@ -277,6 +268,12 @@ public class RefJavaManagerImpl extends RefJavaManager { return null; } + @Nullable + @Override + public PsiNamedElement getElementContainer(@NotNull PsiElement psiElement) { + return (PsiNamedElement)PsiTreeUtil.findFirstParent(psiElement, PROBLEM_ELEMENT_CONDITION); + } + @Override @Nullable public RefEntity getReference(final String type, final String fqName) { diff --git a/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java index df7e5bd693d1..441a712e3d17 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection; import com.intellij.lang.injection.InjectedLanguageManager; @@ -167,6 +153,15 @@ public abstract class LocalInspectionTool extends InspectionProfileEntry { }; } + /** + * The method finds problem container (ex: method, class, file) that used to be shown as inspection view tree node. + * + * Consider {@link com.intellij.codeInspection.lang.RefManagerExtension#getElementContainer(PsiElement)} + * to override container element for any inspection for given language. + * + * @param psiElement: problem element + * @return problem container element + */ @Nullable public PsiNamedElement getProblemElement(PsiElement psiElement) { while (psiElement!=null && !(psiElement instanceof PsiFile)) { diff --git a/platform/analysis-api/src/com/intellij/codeInspection/lang/RefManagerExtension.java b/platform/analysis-api/src/com/intellij/codeInspection/lang/RefManagerExtension.java index 6f66bc552c15..e0b5a02a010c 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/lang/RefManagerExtension.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/lang/RefManagerExtension.java @@ -1,27 +1,15 @@ -/* - * Copyright 2000-2015 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.lang; +import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.reference.RefVisitor; import com.intellij.lang.Language; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,6 +30,18 @@ public interface RefManagerExtension { @Nullable RefElement createRefElement(PsiElement psiElement); + /** + * The method finds problem container (ex: method, class, file) that used to be shown as inspection view tree node. + * If method returns not null value then {@link LocalInspectionTool#getProblemElement(PsiElement)} will be ignored. + * + * @param psiElement + * @return container element for given psiElement + */ + @Nullable + default PsiNamedElement getElementContainer(@NotNull PsiElement psiElement) { + return null; + } + @Nullable RefEntity getReference(final String type, final String fqName); diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java index 90b863c7bd9f..e6b159717853 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2009 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.reference; import com.intellij.analysis.AnalysisScope; @@ -22,6 +8,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiNamedElement; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -129,4 +116,9 @@ public abstract class RefManager { public boolean isInGraph(VirtualFile file) { return true; } + + @Nullable + public PsiNamedElement getContainerElement(@NotNull PsiElement element) { + return null; + } } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index b84585b7f556..f7e1fc89d0eb 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.reference; @@ -407,6 +393,20 @@ public class RefManagerImpl extends RefManager { return !myUnprocessedFiles.get(((VirtualFileWithId)file).getId()); } + @Nullable + @Override + public PsiNamedElement getContainerElement(@NotNull PsiElement element) { + Language language = element.getLanguage(); + return myExtensions + .values() + .stream() + .filter(extension -> extension.getLanguage().equals(language)) + .map(extension -> extension.getElementContainer(element)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + private synchronized void registerUnprocessed(VirtualFileWithId virtualFile) { myUnprocessedFiles.set(virtualFile.getId()); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalDescriptorsUtil.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalDescriptorsUtil.java index 64982028650f..414bf0b843fb 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalDescriptorsUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalDescriptorsUtil.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.ex; import com.intellij.codeInspection.*; @@ -20,6 +6,7 @@ import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefManagerImpl; import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNamedElement; import com.intellij.util.TripleFunction; import org.jetbrains.annotations.NotNull; @@ -33,7 +20,7 @@ import java.util.Map; public class LocalDescriptorsUtil { private static final TripleFunction CONVERT = (tool, element, context) -> { - final PsiNamedElement problemElement = tool.getProblemElement(element); + final PsiNamedElement problemElement = getContainerElement(element, tool, context); RefElement refElement = context.getRefManager().getReference(problemElement); if (refElement == null && problemElement != null) { // no need to lose collected results @@ -94,4 +81,16 @@ public class LocalDescriptorsUtil { @NotNull LocalInspectionTool tool) { addProblemDescriptors(descriptors, filterSuppressed, inspectionContext, tool, CONVERT, dpi); } + + public static PsiNamedElement getContainerElement(@Nullable PsiElement element, + @NotNull LocalInspectionTool tool, + @NotNull GlobalInspectionContext context) { + if (element == null) return null; + PsiNamedElement containerFromTool = tool.getProblemElement(element); + if (containerFromTool != null && !(containerFromTool instanceof PsiFile)) { + return containerFromTool; + } + PsiNamedElement container = context.getRefManager().getContainerElement(element); + return container != null ? container : containerFromTool; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java index 2d006754d693..1ab5c58e3b64 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 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 com.intellij.codeInspection.offlineViewer; import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; @@ -21,10 +7,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.*; import com.intellij.codeInspection.actions.RunInspectionAction; -import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper; -import com.intellij.codeInspection.ex.InspectionToolWrapper; -import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; -import com.intellij.codeInspection.ex.QuickFixWrapper; +import com.intellij.codeInspection.ex.*; import com.intellij.codeInspection.offline.OfflineProblemDescriptor; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; @@ -115,7 +98,11 @@ class OfflineDescriptorResolveResult { final PsiElement psiElement = ((RefElement)element).getElement(); if (psiElement != null) { ProblemDescriptor descriptor = ProgressManager.getInstance().runProcess( - () -> runLocalTool(psiElement, inspectionManager, offlineProblemDescriptor, (LocalInspectionToolWrapper)toolWrapper), new DaemonProgressIndicator()); + () -> runLocalTool(psiElement, + offlineProblemDescriptor, + (LocalInspectionToolWrapper)toolWrapper, + inspectionManager, + presentation.getContext()), new DaemonProgressIndicator()); if (descriptor != null) return descriptor; } return null; @@ -131,9 +118,10 @@ class OfflineDescriptorResolveResult { } private static ProblemDescriptor runLocalTool(@NotNull PsiElement psiElement, - @NotNull InspectionManager inspectionManager, @NotNull OfflineProblemDescriptor offlineProblemDescriptor, - @NotNull LocalInspectionToolWrapper toolWrapper) { + @NotNull LocalInspectionToolWrapper toolWrapper, + @NotNull InspectionManager inspectionManager, + @NotNull GlobalInspectionContextImpl context) { PsiFile containingFile = psiElement.getContainingFile(); final ProblemsHolder holder = new ProblemsHolder(inspectionManager, containingFile, false); final LocalInspectionTool localTool = toolWrapper.getTool(); @@ -159,7 +147,7 @@ class OfflineDescriptorResolveResult { final int idx = offlineProblemDescriptor.getProblemIndex(); int curIdx = 0; for (ProblemDescriptor descriptor : list) { - final PsiNamedElement member = localTool.getProblemElement(descriptor.getPsiElement()); + final PsiNamedElement member = LocalDescriptorsUtil.getContainerElement(descriptor.getPsiElement(), localTool, context); if (psiElement instanceof PsiFile || member != null && member.equals(psiElement)) { if (curIdx == idx) { return descriptor;