diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index f73e2628e51..c4e1b27c805 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.JetNodeTypes import org.jetbrains.kotlin.lexer.JetKeywordToken import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getCalleeHighlightingRange import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.utils.sure import kotlin.platform.platformStatic @@ -226,7 +227,7 @@ public object PositioningStrategies { return ranges } } - return listOf(element.getTextRange()) + return listOf(element.getCalleeHighlightingRange()) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationEntry.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationEntry.java index 060373ca793..5b7a1d031b0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationEntry.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationEntry.java @@ -17,9 +17,11 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.JetNodeTypes; +import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationEntryStub; import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes; @@ -101,4 +103,8 @@ public class JetAnnotationEntry extends JetElementImplStub emptyList() } } + +public fun JetElement.getCalleeHighlightingRange(): TextRange { + val annotationEntry: JetAnnotationEntry = + PsiTreeUtil.getParentOfType( + this, javaClass(), /* strict = */false, javaClass() + ) ?: return getTextRange() + + val startOffset = annotationEntry.getAtSymbol()?.getTextRange()?.getStartOffset() + ?: annotationEntry.getCalleeExpression().getTextRange().getStartOffset() + + return TextRange(startOffset, annotationEntry.getCalleeExpression().getTextRange().getEndOffset()) +} diff --git a/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.kt b/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.kt new file mode 100644 index 00000000000..04d2055cc99 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.kt @@ -0,0 +1,3 @@ +@Ann class A +Ann class B +@Ann(1) class C diff --git a/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.txt b/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.txt new file mode 100644 index 00000000000..c4d8e79958a --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.txt @@ -0,0 +1,22 @@ +package + +[ERROR : Ann]() internal final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +[ERROR : Ann]() internal final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +[ERROR : Ann]() internal final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 95ec5592f75..e548b33cfd4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -801,6 +801,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("unresolvedReferenceRange.kt") + public void testUnresolvedReferenceRange() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/unresolvedReferenceRange.kt"); + doTest(fileName); + } + @TestMetadata("WrongAnnotationArgsOnObject.kt") public void testWrongAnnotationArgsOnObject() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/WrongAnnotationArgsOnObject.kt"); diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetHighlighter.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetHighlighter.java index 3e6d2d1ece9..1af8042c365 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetHighlighter.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetHighlighter.java @@ -52,7 +52,6 @@ public class JetHighlighter extends SyntaxHighlighterBase { fillMap(keys1, JetTokens.KEYWORDS, JetHighlightingColors.KEYWORD); keys1.put(JetTokens.AS_SAFE, JetHighlightingColors.KEYWORD); - keys1.put(JetTokens.AT, JetHighlightingColors.LABEL); keys1.put(JetTokens.INTEGER_LITERAL, JetHighlightingColors.NUMBER); keys1.put(JetTokens.FLOAT_LITERAL, JetHighlightingColors.NUMBER); diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetPsiChecker.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetPsiChecker.kt index 97bfc2850e0..144bc88c7a5 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetPsiChecker.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/JetPsiChecker.kt @@ -26,6 +26,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.colors.CodeInsightColors import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.openapi.progress.ProcessCanceledException +import com.intellij.openapi.util.TextRange import com.intellij.psi.MultiRangeReference import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -236,6 +237,12 @@ public open class JetPsiChecker : Annotator, HighlightRangeExtension { } } + platformStatic fun highlightName(holder: AnnotationHolder, textRange: TextRange, attributesKey: TextAttributesKey) { + if (namesHighlightingEnabled) { + holder.createInfoAnnotation(textRange, null).setTextAttributes(attributesKey) + } + } + private fun getBeforeAnalysisVisitors(holder: AnnotationHolder) = array( SoftKeywordsHighlightingVisitor(holder), LabelsHighlightingVisitor(holder), diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/TypeKindHighlightingVisitor.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/TypeKindHighlightingVisitor.java index a20e6cb0b9a..db9b1001696 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/TypeKindHighlightingVisitor.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/TypeKindHighlightingVisitor.java @@ -18,11 +18,13 @@ package org.jetbrains.kotlin.idea.highlighter; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.BindingContext; class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor { @@ -41,7 +43,13 @@ class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor { } if (referenceTarget instanceof ClassDescriptor) { - highlightName(expression, textAttributesKeyForClass((ClassDescriptor) referenceTarget)); + TextAttributesKey textAttributesKey = textAttributesKeyForClass((ClassDescriptor) referenceTarget); + if (textAttributesKey == JetHighlightingColors.ANNOTATION) { + highlightAnnotation(expression); + } + else { + highlightName(expression, textAttributesKey); + } } else if (referenceTarget instanceof TypeParameterDescriptor) { highlightName(expression, JetHighlightingColors.TYPE_PARAMETER); @@ -49,6 +57,11 @@ class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor { } } + private void highlightAnnotation(@NotNull JetSimpleNameExpression expression) { + TextRange toHighlight = PsiUtilPackage.getCalleeHighlightingRange(expression); + JetPsiChecker.highlightName(holder, toHighlight, JetHighlightingColors.ANNOTATION); + } + @Override public void visitObjectDeclarationName(@NotNull JetObjectDeclarationName declaration) { PsiElement nameIdentifier = declaration.getNameIdentifier(); diff --git a/idea/testData/highlighter/Annotations.kt b/idea/testData/highlighter/Annotations.kt new file mode 100644 index 00000000000..9289218bde9 --- /dev/null +++ b/idea/testData/highlighter/Annotations.kt @@ -0,0 +1,24 @@ +annotation class Ann + +Ann class A1 +@Ann class A2 + +fun bar(block: () -> Int) = block() + +@private +fun foo() { + 1 + [Ann] 2 + + @Ann 3 + 4 + + bar @Ann { 1 } + + @Err + 5 +} + +@Err class Err1 + +class NotAnn +@NotAnn +class C diff --git a/idea/testData/highlighter/Labels.kt b/idea/testData/highlighter/Labels.kt new file mode 100644 index 00000000000..e32e016de38 --- /dev/null +++ b/idea/testData/highlighter/Labels.kt @@ -0,0 +1,17 @@ +fun bar(block: () -> Int) = block() + +fun foo(): Int { + bar label@ { + return@label 2 + } + + loop@ for (i in 1..100) { + break@loop + } + + loop2@ for (i in 1..100) { + break @loop2 + } + + return 1 +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/HighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/HighlightingTestGenerated.java index feecb5673dd..ee8796c0159 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/HighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/HighlightingTestGenerated.java @@ -35,6 +35,12 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/highlighter"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("Annotations.kt") + public void testAnnotations() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Annotations.kt"); + doTest(fileName); + } + @TestMetadata("Dynamic.kt") public void testDynamic() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Dynamic.kt"); @@ -65,6 +71,12 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest { doTest(fileName); } + @TestMetadata("Labels.kt") + public void testLabels() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Labels.kt"); + doTest(fileName); + } + @TestMetadata("Object.kt") public void testObject() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Object.kt");