diff --git a/plugins/devkit/devkit-core/intellij.devkit.iml b/plugins/devkit/devkit-core/intellij.devkit.iml
index 52fdb63d51d8..161940c14884 100644
--- a/plugins/devkit/devkit-core/intellij.devkit.iml
+++ b/plugins/devkit/devkit-core/intellij.devkit.iml
@@ -46,5 +46,6 @@
+
\ No newline at end of file
diff --git a/plugins/devkit/devkit-core/resources/META-INF/groovy-devkit.xml b/plugins/devkit/devkit-core/resources/META-INF/groovy-devkit.xml
new file mode 100644
index 000000000000..5dbd0a906534
--- /dev/null
+++ b/plugins/devkit/devkit-core/resources/META-INF/groovy-devkit.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
index b5d375e81e0d..3644a8ca4c94 100644
--- a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
+++ b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
@@ -12,6 +12,7 @@
com.intellij.properties
com.intellij.modules.json
org.jetbrains.plugins.gradle
+ org.intellij.groovy
org.jetbrains.idea.devkit.DevKitBundle
@@ -163,7 +164,7 @@
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UsePrimitiveTypesInspection"/>
-
+
+
+
+
+
+
+
+
+
+
+
org.jetbrains.idea.devkit.testAssistant.TestDataHighlightingPassFactory
diff --git a/plugins/devkit/devkit-core/src/inspections/internal/GoodCodeRedVisitor.java b/plugins/devkit/devkit-core/src/inspections/internal/GoodCodeRedVisitor.java
new file mode 100644
index 000000000000..c0ed42f8a915
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/internal/GoodCodeRedVisitor.java
@@ -0,0 +1,12 @@
+// Copyright 2000-2019 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.inspections.internal;
+
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.psi.PsiElementVisitor;
+import org.jetbrains.annotations.NotNull;
+
+public interface GoodCodeRedVisitor {
+
+ @NotNull
+ PsiElementVisitor createVisitor(ProblemsHolder holder);
+}
diff --git a/plugins/devkit/devkit-core/src/inspections/internal/GroovyGoodCodeRedVisitor.java b/plugins/devkit/devkit-core/src/inspections/internal/GroovyGoodCodeRedVisitor.java
new file mode 100644
index 000000000000..b3ddfc15e9d9
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/internal/GroovyGoodCodeRedVisitor.java
@@ -0,0 +1,95 @@
+// Copyright 2000-2019 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.inspections.internal;
+
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.codeInspection.bugs.GrAccessibilityChecker;
+import org.jetbrains.plugins.groovy.codeInspection.type.GroovyStaticTypeCheckVisitor;
+import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessChecker;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+
+import java.util.List;
+
+public class GroovyGoodCodeRedVisitor implements GoodCodeRedVisitor {
+
+ @NotNull
+ @Override
+ public PsiElementVisitor createVisitor(ProblemsHolder holder) {
+ if (!Registry.is("groovy.good.code.is.red", false)) {
+ return PsiElementVisitor.EMPTY_VISITOR;
+ }
+ GroovyFileBase file = (GroovyFileBase)holder.getFile();
+ Project project = holder.getProject();
+ GrUnresolvedAccessChecker unresolvedAccessChecker = new GrUnresolvedAccessChecker(file, project);
+ GrAccessibilityChecker accessibilityChecker = new GrAccessibilityChecker(file, project);
+ GroovyStaticTypeCheckVisitor typeCheckVisitor = new GroovyStaticTypeCheckVisitor() {
+ @Override
+ protected void registerError(@NotNull PsiElement location,
+ @NotNull String description,
+ @Nullable LocalQuickFix[] fixes,
+ ProblemHighlightType highlightType) {
+ if (highlightType == ProblemHighlightType.GENERIC_ERROR) {
+ holder.registerProblem(location, description);
+ }
+ }
+ };
+
+ return new GroovyPsiElementVisitor(new GroovyElementVisitor() {
+ @Override
+ public void visitElement(@NotNull GroovyPsiElement element) {
+ super.visitElement(element);
+ element.accept(typeCheckVisitor);
+ }
+
+ @Override
+ public void visitReferenceExpression(@NotNull GrReferenceExpression referenceExpression) {
+ super.visitReferenceExpression(referenceExpression);
+ List infos = unresolvedAccessChecker.checkReferenceExpression(referenceExpression);
+ if (infos != null) {
+ infos.forEach(info -> registerProblem(holder, info, referenceExpression));
+ }
+ else {
+ HighlightInfo info = accessibilityChecker.checkReferenceExpression(referenceExpression);
+ if (info != null) {
+ registerProblem(holder, info, referenceExpression);
+ }
+ }
+ }
+
+ @Override
+ public void visitCodeReferenceElement(@NotNull GrCodeReferenceElement refElement) {
+ super.visitCodeReferenceElement(refElement);
+ HighlightInfo info = unresolvedAccessChecker.checkCodeReferenceElement(refElement);
+ if (info != null) {
+ registerProblem(holder, info, refElement);
+ }
+ else {
+ info = accessibilityChecker.checkCodeReferenceElement(refElement);
+ if (info != null) {
+ registerProblem(holder, info, refElement);
+ }
+ }
+ }
+
+ private void registerProblem(ProblemsHolder holder, HighlightInfo info, PsiElement e) {
+ if (info.getSeverity() == HighlightSeverity.ERROR) {
+ holder.registerProblem(e, info.getDescription());
+ }
+ }
+ });
+ }
+}
diff --git a/plugins/devkit/devkit-core/src/inspections/internal/HighlightVisitorInternalInspection.java b/plugins/devkit/devkit-core/src/inspections/internal/HighlightVisitorInternalInspection.java
index b8df2e19aad2..3397750cf387 100644
--- a/plugins/devkit/devkit-core/src/inspections/internal/HighlightVisitorInternalInspection.java
+++ b/plugins/devkit/devkit-core/src/inspections/internal/HighlightVisitorInternalInspection.java
@@ -2,25 +2,17 @@
package org.jetbrains.idea.devkit.inspections.internal;
import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.compiler.CompilerConfiguration;
-import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilCore;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
public class HighlightVisitorInternalInspection extends AbstractBaseJavaLocalInspectionTool {
public static final Logger LOG = Logger.getInstance(HighlightVisitorInternalInspection.class);
@@ -45,35 +37,15 @@ public class HighlightVisitorInternalInspection extends AbstractBaseJavaLocalIns
}
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
if (virtualFile == null ||
- virtualFile.getFileType() != StdFileTypes.JAVA ||
CompilerConfiguration.getInstance(holder.getProject()).isExcludedFromCompilation(virtualFile)) {
return PsiElementVisitor.EMPTY_VISITOR;
}
- return new HighlightVisitorImpl(JavaPsiFacade.getInstance(holder.getProject()).getResolveHelper()) {
- {
- prepareToRunAsInspection(new HighlightInfoHolder(file) {
- @Override
- public boolean add(@Nullable HighlightInfo info) {
- if (super.add(info)) {
- if (info != null && info.getSeverity() == HighlightSeverity.ERROR) {
- final int startOffset = info.getStartOffset();
- final PsiElement element = file.findElementAt(startOffset);
- if (element != null) {
- holder.registerProblem(element, info.getDescription());
- }
- }
- return true;
- }
- return false;
- }
- @Override
- public boolean hasErrorResults() {
- //accept multiple errors per file
- return false;
- }
- });
- }
- };
+ GoodCodeRedVisitor visitor = LanguageGoodCodeRedVisitors.INSTANCE.forLanguage(file.getLanguage());
+ if (visitor == null) {
+ return PsiElementVisitor.EMPTY_VISITOR;
+ }
+
+ return visitor.createVisitor(holder);
}
}
diff --git a/plugins/devkit/devkit-core/src/inspections/internal/JavaGoodCodeRedVisitor.java b/plugins/devkit/devkit-core/src/inspections/internal/JavaGoodCodeRedVisitor.java
new file mode 100644
index 000000000000..c1093f8d29ff
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/internal/JavaGoodCodeRedVisitor.java
@@ -0,0 +1,46 @@
+// Copyright 2000-2019 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.inspections.internal;
+
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class JavaGoodCodeRedVisitor implements GoodCodeRedVisitor {
+ @NotNull
+ @Override
+ public PsiElementVisitor createVisitor(ProblemsHolder holder) {
+ return new HighlightVisitorImpl(JavaPsiFacade.getInstance(holder.getProject()).getResolveHelper()) {
+ {
+ prepareToRunAsInspection(new HighlightInfoHolder(holder.getFile()) {
+ @Override
+ public boolean add(@Nullable HighlightInfo info) {
+ if (super.add(info)) {
+ if (info != null && info.getSeverity() == HighlightSeverity.ERROR) {
+ final int startOffset = info.getStartOffset();
+ final PsiElement element = holder.getFile().findElementAt(startOffset);
+ if (element != null) {
+ holder.registerProblem(element, info.getDescription());
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasErrorResults() {
+ //accept multiple errors per file
+ return false;
+ }
+ });
+ }
+ };
+ }
+}
diff --git a/plugins/devkit/devkit-core/src/inspections/internal/LanguageGoodCodeRedVisitors.java b/plugins/devkit/devkit-core/src/inspections/internal/LanguageGoodCodeRedVisitors.java
new file mode 100644
index 000000000000..8c3d9efeabeb
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/internal/LanguageGoodCodeRedVisitors.java
@@ -0,0 +1,13 @@
+// Copyright 2000-2019 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.inspections.internal;
+
+import com.intellij.lang.LanguageExtension;
+
+public class LanguageGoodCodeRedVisitors extends LanguageExtension {
+ public static final LanguageGoodCodeRedVisitors INSTANCE = new LanguageGoodCodeRedVisitors();
+
+ private LanguageGoodCodeRedVisitors() {
+ super("DevKit.lang.goodCodeRedVisitor");
+ }
+
+}
\ No newline at end of file