Refine highlighting of '@'
- Do not highlight '@' as separate token. - Highlight '@' the same way as element where it's located: annotation, label or modifier. - Extend text range when positioning unresolved reference in annotation with '@'. Note that currently '@' is collapsed with modifiers tokens
This commit is contained in:
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.JetNodeTypes
|
|||||||
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getCalleeHighlightingRange
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import kotlin.platform.platformStatic
|
import kotlin.platform.platformStatic
|
||||||
@@ -226,7 +227,7 @@ public object PositioningStrategies {
|
|||||||
return ranges
|
return ranges
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listOf(element.getTextRange())
|
return listOf(element.getCalleeHighlightingRange())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
package org.jetbrains.kotlin.psi;
|
package org.jetbrains.kotlin.psi;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.JetNodeTypes;
|
import org.jetbrains.kotlin.JetNodeTypes;
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationEntryStub;
|
import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationEntryStub;
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
||||||
|
|
||||||
@@ -101,4 +103,8 @@ public class JetAnnotationEntry extends JetElementImplStub<KotlinAnnotationEntry
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PsiElement getAtSymbol() {
|
||||||
|
return findChildByType(JetTokens.AT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -570,3 +570,15 @@ private fun JetAnnotationsContainer.collectAnnotationEntriesFromPsi() =
|
|||||||
else -> emptyList<JetAnnotationEntry>()
|
else -> emptyList<JetAnnotationEntry>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun JetElement.getCalleeHighlightingRange(): TextRange {
|
||||||
|
val annotationEntry: JetAnnotationEntry =
|
||||||
|
PsiTreeUtil.getParentOfType<JetAnnotationEntry>(
|
||||||
|
this, javaClass<JetAnnotationEntry>(), /* strict = */false, javaClass<JetValueArgumentList>()
|
||||||
|
) ?: return getTextRange()
|
||||||
|
|
||||||
|
val startOffset = annotationEntry.getAtSymbol()?.getTextRange()?.getStartOffset()
|
||||||
|
?: annotationEntry.getCalleeExpression().getTextRange().getStartOffset()
|
||||||
|
|
||||||
|
return TextRange(startOffset, annotationEntry.getCalleeExpression().getTextRange().getEndOffset())
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<!UNRESOLVED_REFERENCE!>@Ann<!> class A
|
||||||
|
<!UNRESOLVED_REFERENCE!>Ann<!> class B
|
||||||
|
<!UNRESOLVED_REFERENCE!>@Ann<!>(1) class C
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -801,6 +801,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("WrongAnnotationArgsOnObject.kt")
|
||||||
public void testWrongAnnotationArgsOnObject() throws Exception {
|
public void testWrongAnnotationArgsOnObject() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/WrongAnnotationArgsOnObject.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/WrongAnnotationArgsOnObject.kt");
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ public class JetHighlighter extends SyntaxHighlighterBase {
|
|||||||
fillMap(keys1, JetTokens.KEYWORDS, JetHighlightingColors.KEYWORD);
|
fillMap(keys1, JetTokens.KEYWORDS, JetHighlightingColors.KEYWORD);
|
||||||
|
|
||||||
keys1.put(JetTokens.AS_SAFE, 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.INTEGER_LITERAL, JetHighlightingColors.NUMBER);
|
||||||
keys1.put(JetTokens.FLOAT_LITERAL, JetHighlightingColors.NUMBER);
|
keys1.put(JetTokens.FLOAT_LITERAL, JetHighlightingColors.NUMBER);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.application.ApplicationManager
|
|||||||
import com.intellij.openapi.editor.colors.CodeInsightColors
|
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.MultiRangeReference
|
import com.intellij.psi.MultiRangeReference
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
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(
|
private fun getBeforeAnalysisVisitors(holder: AnnotationHolder) = array(
|
||||||
SoftKeywordsHighlightingVisitor(holder),
|
SoftKeywordsHighlightingVisitor(holder),
|
||||||
LabelsHighlightingVisitor(holder),
|
LabelsHighlightingVisitor(holder),
|
||||||
|
|||||||
+14
-1
@@ -18,11 +18,13 @@ package org.jetbrains.kotlin.idea.highlighter;
|
|||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
import com.intellij.lang.annotation.AnnotationHolder;
|
||||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||||
|
import com.intellij.openapi.util.TextRange;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiReference;
|
import com.intellij.psi.PsiReference;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
|
||||||
class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
|
class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
|
||||||
@@ -41,7 +43,13 @@ class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (referenceTarget instanceof ClassDescriptor) {
|
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) {
|
else if (referenceTarget instanceof TypeParameterDescriptor) {
|
||||||
highlightName(expression, JetHighlightingColors.TYPE_PARAMETER);
|
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
|
@Override
|
||||||
public void visitObjectDeclarationName(@NotNull JetObjectDeclarationName declaration) {
|
public void visitObjectDeclarationName(@NotNull JetObjectDeclarationName declaration) {
|
||||||
PsiElement nameIdentifier = declaration.getNameIdentifier();
|
PsiElement nameIdentifier = declaration.getNameIdentifier();
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<info descr="null">annotation</info> class <info descr="null">Ann</info>
|
||||||
|
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_ANNOTATION">Ann</info> class <info descr="null">A1</info>
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_ANNOTATION">@Ann</info> class <info descr="null">A2</info>
|
||||||
|
|
||||||
|
fun <info descr="null">bar</info>(<info descr="null">block</info>: () -> <info descr="null">Int</info>) = <info descr="null"><info descr="null">block</info></info>()
|
||||||
|
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">@private</info>
|
||||||
|
fun <info descr="null">foo</info>() {
|
||||||
|
1 + [<info descr="null" textAttributesKey="KOTLIN_ANNOTATION">Ann</info>] 2
|
||||||
|
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_ANNOTATION">@Ann</info> 3 + 4
|
||||||
|
|
||||||
|
<info descr="null"><info descr="null">bar</info></info> <info descr="null" textAttributesKey="KOTLIN_ANNOTATION">@Ann</info> { 1 }
|
||||||
|
|
||||||
|
<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: Err" textAttributesKey="WRONG_REFERENCES_ATTRIBUTES">@Err</error>
|
||||||
|
<warning descr="[UNUSED_EXPRESSION] The expression is unused" textAttributesKey="WARNING_ATTRIBUTES">5</warning>
|
||||||
|
}
|
||||||
|
|
||||||
|
<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: Err" textAttributesKey="WRONG_REFERENCES_ATTRIBUTES">@Err</error> class <info descr="null" textAttributesKey="KOTLIN_CLASS">Err1</info>
|
||||||
|
|
||||||
|
class <info descr="null">NotAnn</info>
|
||||||
|
<error descr="[NOT_AN_ANNOTATION_CLASS] 'NotAnn' is not an annotation class" textAttributesKey="ERRORS_ATTRIBUTES">@NotAnn</error>
|
||||||
|
class <info descr="null">C</info>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun <info descr="null">bar</info>(<info descr="null">block</info>: () -> <info descr="null">Int</info>) = <info descr="null"><info descr="null">block</info></info>()
|
||||||
|
|
||||||
|
fun <info descr="null">foo</info>(): <info descr="null">Int</info> {
|
||||||
|
<info descr="null"><info descr="null">bar</info></info> <info descr="null" textAttributesKey="KOTLIN_LABEL">label@</info> {
|
||||||
|
return<info descr="null" textAttributesKey="KOTLIN_LABEL">@label</info> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_LABEL">loop@</info> for (<info descr="null">i</info> in 1..100) {
|
||||||
|
break<info descr="null" textAttributesKey="KOTLIN_LABEL">@loop</info>
|
||||||
|
}
|
||||||
|
|
||||||
|
<info descr="null" textAttributesKey="KOTLIN_LABEL">loop2@</info> for (<info descr="null">i</info> in 1..100) {
|
||||||
|
break<error descr="There should be no space or comments before '@' in label reference"> </error><info descr="null" textAttributesKey="KOTLIN_LABEL">@loop2</info>
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
@@ -35,6 +35,12 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/highlighter"), Pattern.compile("^(.+)\\.kt$"), true);
|
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")
|
@TestMetadata("Dynamic.kt")
|
||||||
public void testDynamic() throws Exception {
|
public void testDynamic() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Dynamic.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Dynamic.kt");
|
||||||
@@ -65,6 +71,12 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Labels.kt")
|
||||||
|
public void testLabels() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Labels.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Object.kt")
|
@TestMetadata("Object.kt")
|
||||||
public void testObject() throws Exception {
|
public void testObject() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Object.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Object.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user