Report clashing signatures in the IDE

Expose extra diagnostics about platform signature clashes from light class data

 #KT-1 In Progress
This commit is contained in:
Andrey Breslav
2014-05-25 13:22:30 +02:00
parent 9b3f9fb70d
commit d25b2459d4
15 changed files with 210 additions and 24 deletions
+1
View File
@@ -277,6 +277,7 @@
<highlightRangeExtension implementation="org.jetbrains.jet.plugin.highlighter.JetPsiChecker"/>
<annotator language="jet" implementationClass="org.jetbrains.jet.plugin.highlighter.DebugInfoAnnotator"/>
<annotator language="jet" implementationClass="org.jetbrains.jet.plugin.highlighter.DuplicateJvmSignatureAnnotator"/>
<problemHighlightFilter implementation="org.jetbrains.jet.plugin.highlighter.KotlinProblemHighlightFilter"/>
<extendWordSelectionHandler implementation="org.jetbrains.jet.plugin.editor.wordSelection.JetStatementGroupSelectioner"/>
@@ -0,0 +1,72 @@
/*
* Copyright 2010-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.
*/
package org.jetbrains.jet.plugin.highlighter;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.asJava.KotlinLightClassForExplicitDeclaration;
import org.jetbrains.jet.asJava.KotlinLightClassForPackage;
import org.jetbrains.jet.lang.psi.JetClassBody;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.Diagnostics;
import org.jetbrains.jet.plugin.project.TargetPlatform;
import org.jetbrains.jet.plugin.project.TargetPlatformDetector;
public class DuplicateJvmSignatureAnnotator implements Annotator {
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
Diagnostics diagnostics;
PsiElement parent = element.getParent();
if (parent instanceof JetFile) {
if (TargetPlatformDetector.getPlatform((JetFile) parent) != TargetPlatform.JVM) return;
diagnostics = getDiagnosticsForPackage((JetFile) parent);
}
else if (parent instanceof JetClassBody) {
PsiElement parentsParent = parent.getParent();
if (!(parentsParent instanceof JetClassOrObject)) return;
if (TargetPlatformDetector.getPlatform(((JetClassBody) parent).getContainingJetFile()) != TargetPlatform.JVM) return;
diagnostics = getDiagnosticsForNonLocalClass((JetClassOrObject) parentsParent);
}
else {
return;
}
JetPsiChecker.annotateElement(element, holder, diagnostics);
}
@NotNull
private static Diagnostics getDiagnosticsForPackage(JetFile file) {
Project project = file.getProject();
return KotlinLightClassForPackage.FileStubCache.getInstance(project).get(
file.getPackageFqName(),
GlobalSearchScope.allScope(project)
).getValue().getExtraDiagnostics();
}
@NotNull
private static Diagnostics getDiagnosticsForNonLocalClass(JetClassOrObject jetClassOrObject) {
return KotlinLightClassForExplicitDeclaration.getLightClassData(jetClassOrObject).getExtraDiagnostics();
}
}
@@ -41,13 +41,12 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
import org.jetbrains.jet.lang.psi.JetCodeFragment;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.Diagnostics;
import org.jetbrains.jet.plugin.JetPluginUtil;
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionsFactory;
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
@@ -117,12 +116,7 @@ public class JetPsiChecker implements Annotator, HighlightRangeExtension {
element.accept(visitor);
}
if (JetPluginUtil.isInSource(element, /* includeLibrarySources = */ false) || file instanceof JetCodeFragment) {
ElementAnnotator elementAnnotator = new ElementAnnotator(element, holder);
for (Diagnostic diagnostic : bindingContext.getDiagnostics().forElement(element)) {
elementAnnotator.registerDiagnosticAnnotations(diagnostic);
}
}
annotateElement(element, holder, bindingContext.getDiagnostics());
if (element instanceof JetFile) {
//noinspection StaticMethodReferencedViaSubclass
@@ -130,6 +124,15 @@ public class JetPsiChecker implements Annotator, HighlightRangeExtension {
}
}
public static void annotateElement(PsiElement element, AnnotationHolder holder, Diagnostics diagnostics) {
if (JetPluginUtil.isInSource(element, /* includeLibrarySources = */ false) || element.getContainingFile() instanceof JetCodeFragment) {
ElementAnnotator elementAnnotator = new ElementAnnotator(element, holder);
for (Diagnostic diagnostic : diagnostics.forElement(element)) {
elementAnnotator.registerDiagnosticAnnotations(diagnostic);
}
}
}
@Override
public boolean isForceHighlightParents(@NotNull PsiFile file) {
return file instanceof JetFile;
@@ -283,4 +286,5 @@ public class JetPsiChecker implements Annotator, HighlightRangeExtension {
return message;
}
}
}
@@ -0,0 +1,4 @@
class C {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
@@ -0,0 +1,6 @@
class C {
class object {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
}
@@ -0,0 +1,6 @@
fun foo() {
class C {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
}
@@ -0,0 +1,6 @@
class B {
class C {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
}
@@ -0,0 +1,4 @@
object C {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
@@ -0,0 +1,5 @@
fun foo() =
object {
<error>val x = 1</error>
<error>fun getX() = 1</error>
}
@@ -0,0 +1,2 @@
<error>val x = 1</error>
<error>fun getX() = 1</error>
@@ -30,7 +30,7 @@ import org.jetbrains.jet.checkers.AbstractJetPsiCheckerTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@InnerTestClasses({JetPsiCheckerTestGenerated.Checker.class, JetPsiCheckerTestGenerated.Regression.class, JetPsiCheckerTestGenerated.Rendering.class, JetPsiCheckerTestGenerated.Infos.class})
@InnerTestClasses({JetPsiCheckerTestGenerated.Checker.class, JetPsiCheckerTestGenerated.Regression.class, JetPsiCheckerTestGenerated.Rendering.class, JetPsiCheckerTestGenerated.DuplicateJvmSignature.class, JetPsiCheckerTestGenerated.Infos.class})
public class JetPsiCheckerTestGenerated extends AbstractJetPsiCheckerTest {
@TestMetadata("idea/testData/checker")
public static class Checker extends AbstractJetPsiCheckerTest {
@@ -421,6 +421,64 @@ public class JetPsiCheckerTestGenerated extends AbstractJetPsiCheckerTest {
}
@TestMetadata("idea/testData/checker/duplicateJvmSignature")
@InnerTestClasses({DuplicateJvmSignature.FunctionAndProperty.class})
public static class DuplicateJvmSignature extends AbstractJetPsiCheckerTest {
public void testAllFilesPresentInDuplicateJvmSignature() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/checker/duplicateJvmSignature"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("idea/testData/checker/duplicateJvmSignature/functionAndProperty")
public static class FunctionAndProperty extends AbstractJetPsiCheckerTest {
public void testAllFilesPresentInFunctionAndProperty() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/checker/duplicateJvmSignature/functionAndProperty"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("class.kt")
public void testClass() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/class.kt");
}
@TestMetadata("classObject.kt")
public void testClassObject() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/classObject.kt");
}
@TestMetadata("localClass.kt")
public void testLocalClass() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/localClass.kt");
}
@TestMetadata("nestedClass.kt")
public void testNestedClass() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/nestedClass.kt");
}
@TestMetadata("object.kt")
public void testObject() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/object.kt");
}
@TestMetadata("objectExpression.kt")
public void testObjectExpression() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/objectExpression.kt");
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
doTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/topLevel.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("DuplicateJvmSignature");
suite.addTestSuite(DuplicateJvmSignature.class);
suite.addTestSuite(FunctionAndProperty.class);
return suite;
}
}
@TestMetadata("idea/testData/checker/infos")
public static class Infos extends AbstractJetPsiCheckerTest {
public void testAllFilesPresentInInfos() throws Exception {
@@ -464,6 +522,7 @@ public class JetPsiCheckerTestGenerated extends AbstractJetPsiCheckerTest {
suite.addTestSuite(Checker.class);
suite.addTestSuite(Regression.class);
suite.addTestSuite(Rendering.class);
suite.addTest(DuplicateJvmSignature.innerSuite());
suite.addTestSuite(Infos.class);
return suite;
}