good code red for groovy

under register key
This commit is contained in:
Anna.Kozlova
2019-01-23 19:09:11 +01:00
parent 6fa3ee99d9
commit e4ee82fd98
8 changed files with 196 additions and 35 deletions
@@ -46,5 +46,6 @@
<orderEntry type="library" name="protobuf" level="project" />
<orderEntry type="module" module-name="intellij.json" />
<orderEntry type="module" module-name="intellij.java.aetherDependencyResolver" />
<orderEntry type="module" module-name="intellij.groovy.psi" />
</component>
</module>
@@ -0,0 +1,9 @@
<idea-plugin>
<extensions defaultExtensionNs="DevKit.lang">
<goodCodeRedVisitor language="Groovy" implementationClass="org.jetbrains.idea.devkit.inspections.internal.GroovyGoodCodeRedVisitor"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<registryKey key="groovy.good.code.is.red" defaultValue="false"
description="When enabled, groovy code would be checked for resolving symbols, accessibility and type checks"/>
</extensions>
</idea-plugin>
@@ -12,6 +12,7 @@
<depends>com.intellij.properties</depends>
<depends>com.intellij.modules.json</depends>
<depends config-file="gradle-devkit.xml" optional="true">org.jetbrains.plugins.gradle</depends>
<depends config-file="groovy-devkit.xml" optional="true">org.intellij.groovy</depends>
<resource-bundle>org.jetbrains.idea.devkit.DevKitBundle</resource-bundle>
@@ -163,7 +164,7 @@
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UsePrimitiveTypesInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="HighlightVisitorInternal"
<localInspection groupPath="Java" shortName="HighlightVisitorInternal"
displayName="Good code is red"
groupKey="inspections.group.name"
enabledByDefault="false" isInternal="true"
@@ -277,6 +278,18 @@
<ProviderFactory implementation="org.jetbrains.idea.devkit.themes.ThemeJsonSchemaProviderFactory"/>
</extensions>
<extensions defaultExtensionNs="DevKit.lang">
<goodCodeRedVisitor language="JAVA" implementationClass="org.jetbrains.idea.devkit.inspections.internal.JavaGoodCodeRedVisitor"/>
</extensions>
<extensionPoints >
<extensionPoint name="lang.goodCodeRedVisitor"
beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="org.jetbrains.idea.devkit.inspections.internal.GoodCodeRedVisitor"/>
</extensionPoint>
</extensionPoints>
<project-components>
<component>
<implementation-class>org.jetbrains.idea.devkit.testAssistant.TestDataHighlightingPassFactory</implementation-class>
@@ -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);
}
@@ -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<HighlightInfo> 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());
}
}
});
}
}
@@ -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);
}
}
@@ -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;
}
});
}
};
}
}
@@ -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<GoodCodeRedVisitor> {
public static final LanguageGoodCodeRedVisitors INSTANCE = new LanguageGoodCodeRedVisitors();
private LanguageGoodCodeRedVisitors() {
super("DevKit.lang.goodCodeRedVisitor");
}
}