@@ -7,7 +7,9 @@ import com.intellij.lang.annotation.HighlightSeverity
77import com.intellij.psi.PsiElement
88import com.intellij.psi.util.PsiTreeUtil
99import org.elm.ide.color.ElmColor
10+ import org.elm.lang.core.psi.ancestors
1011import org.elm.lang.core.psi.elements.*
12+ import org.elm.lang.core.psi.isTopLevel
1113
1214
1315class ElmSyntaxHighlightAnnotator : Annotator {
@@ -18,6 +20,12 @@ class ElmSyntaxHighlightAnnotator : Annotator {
1820
1921 private fun AnnotationHolder.highlight (element : PsiElement ) {
2022 when (element) {
23+ is ElmTypeDeclaration -> typeDecl(element)
24+ is ElmTypeAliasDeclaration -> typeAliasDecl(element)
25+ is ElmImportClause -> importClause(element)
26+ is ElmPortAnnotation -> portAnnotation(element)
27+ is ElmRecordBaseIdentifier -> recordUpdate(element)
28+ is ElmLowerPattern -> functionArgument(element)
2129 is ElmValueDeclaration -> valueDeclaration(element)
2230 is ElmTypeAnnotation -> typeAnnotation(element)
2331 is ElmUpperCaseQID -> upperCaseQID(element)
@@ -28,6 +36,142 @@ class ElmSyntaxHighlightAnnotator : Annotator {
2836 is ElmUnionVariant -> unionVariant(element.upperCaseIdentifier)
2937 is ElmTypeVariable -> typeExpr(element)
3038 is ElmLowerTypeName -> typeExpr(element)
39+ is ElmValueExpr -> valueExpr(element)
40+ }
41+ }
42+
43+ private fun AnnotationHolder.typeDecl (element : ElmTypeDeclaration ) {
44+ applyColor(element.nameIdentifier, ElmColor .TYPE_DECLARATION )
45+ }
46+
47+ private fun AnnotationHolder.typeAliasDecl (element : ElmTypeAliasDeclaration ) {
48+ applyColor(element.nameIdentifier, ElmColor .TYPE_DECLARATION )
49+ }
50+
51+ private fun AnnotationHolder.importClause (element : ElmImportClause ) {
52+ applyColor(element.moduleQID, ElmColor .EXTERNAL_MODULE )
53+ element.exposingList?.exposedTypeList?.forEach { applyColor(it, ElmColor .TYPE_EXPR ) }
54+ element.exposingList?.exposedValueList?.forEach { applyColor(it, ElmColor .EXTERNAL_FUNCTION_CALL ) }
55+ }
56+
57+ private fun AnnotationHolder.portAnnotation (element : ElmPortAnnotation ) {
58+ applyColor(element.lowerCaseIdentifier, ElmColor .PORT )
59+ }
60+
61+ private fun AnnotationHolder.recordUpdate (element : ElmRecordBaseIdentifier ) {
62+ annotateArgument(element)
63+ }
64+
65+ private fun AnnotationHolder.annotateArgument (element : PsiElement ): Boolean {
66+ val parentFunction = element.ancestors
67+ .filterIsInstance<ElmValueDeclaration >()
68+ .firstOrNull {
69+ it.functionDeclarationLeft?.namedParameters?.any { p -> p.nameIdentifier.text == element.text } ? : false
70+ }
71+ if (parentFunction != null ) {
72+ if (parentFunction.isTopLevel) {
73+ applyColor(element, ElmColor .FUNCTION_ARGUMENT )
74+ } else {
75+ applyColor(element, ElmColor .LOCAL_FUNCTION_ARGUMENT )
76+ }
77+ return true
78+ }
79+
80+ val isInlineFunctionArgument = element.ancestors
81+ .filterIsInstance<ElmAnonymousFunctionExpr >()
82+ .firstOrNull {
83+ it.namedParameters.any { p -> p.nameIdentifier.text == element.text }
84+ } != null
85+ if (isInlineFunctionArgument) {
86+ applyColor(element, ElmColor .INLINE_FUNCTION_ARGUMENT )
87+ return true
88+ }
89+
90+ val isUnionPattern =
91+ element.ancestors.any { it is ElmCaseOfBranch && it.destructuredNames.any { name -> name.nameIdentifier.text == element.text } }
92+ if (isUnionPattern) {
93+ applyColor(element, ElmColor .PATTERN_ARGUMENT )
94+ return true
95+ }
96+
97+ return false
98+ }
99+
100+ private fun AnnotationHolder.valueExpr (element : ElmValueExpr ) {
101+ if (element.flavor == Flavor .BareConstructor || element.flavor == Flavor .QualifiedConstructor ) {
102+ return
103+ }
104+
105+ if (annotateArgument(element)) {
106+ return
107+ }
108+
109+ val isLocalFunction = element.ancestors
110+ .filterIsInstance<ElmLetInExpr >()
111+ .any {
112+ it.valueDeclarationList.any { decl -> decl.functionDeclarationLeft?.lowerCaseIdentifier?.text == element.text }
113+ }
114+ if (isLocalFunction) {
115+ applyColor(element, ElmColor .LOCAL_FUNCTION )
116+ return
117+ }
118+
119+ val functionDeclaration =
120+ element.elmFile.children.any { it is ElmValueDeclaration && it.functionDeclarationLeft?.name == element.text }
121+ if (functionDeclaration) {
122+ applyColor(element, ElmColor .DEFINITION_NAME )
123+ return
124+ }
125+
126+ val isPortAnnotation =
127+ element.elmFile.children.any { it is ElmPortAnnotation && it.lowerCaseIdentifier.text == element.text }
128+ if (isPortAnnotation) {
129+ applyColor(element, ElmColor .PORT )
130+ return
131+ }
132+
133+ val qid = element.valueQID
134+ if (qid != null && qid.isQualified == true ) {
135+ qid.qualifiers.forEach {
136+ applyColor(it, ElmColor .EXTERNAL_MODULE )
137+ }
138+ applyColor(qid.lowerCaseIdentifier, ElmColor .EXTERNAL_FUNCTION_CALL )
139+ return
140+ }
141+
142+ applyColor(element, ElmColor .EXTERNAL_FUNCTION_CALL )
143+ }
144+
145+ private fun AnnotationHolder.functionArgument (element : ElmLowerPattern ) {
146+ val parentFunction = PsiTreeUtil .getParentOfType(
147+ element,
148+ ElmFunctionDeclarationLeft ::class .java
149+ );
150+ if (parentFunction != null ) {
151+ if (parentFunction.isTopLevel) {
152+ applyColor(element, ElmColor .FUNCTION_ARGUMENT )
153+ } else {
154+ applyColor(element, ElmColor .LOCAL_FUNCTION_ARGUMENT )
155+ }
156+ return
157+ }
158+
159+ val anonymousFunction = PsiTreeUtil .getParentOfType(
160+ element,
161+ ElmAnonymousFunctionExpr ::class .java
162+ );
163+ if (anonymousFunction != null ) {
164+ applyColor(element, ElmColor .INLINE_FUNCTION_ARGUMENT )
165+ return
166+ }
167+
168+ val unionPattern = PsiTreeUtil .getParentOfType(
169+ element,
170+ ElmUnionPattern ::class .java
171+ );
172+ if (unionPattern != null ) {
173+ applyColor(element, ElmColor .PATTERN_ARGUMENT )
174+ return
31175 }
32176 }
33177
@@ -62,7 +206,13 @@ class ElmSyntaxHighlightAnnotator : Annotator {
62206
63207 private fun AnnotationHolder.valueDeclaration (declaration : ElmValueDeclaration ) {
64208 declaration.declaredNames(includeParameters = false ).forEach {
65- applyColor(it.nameIdentifier, ElmColor .DEFINITION_NAME )
209+ if (it is ElmFunctionDeclarationLeft ) {
210+ if (it.ancestors.filterIsInstance<ElmLetInExpr >().any()) {
211+ applyColor(it.nameIdentifier, ElmColor .LOCAL_FUNCTION )
212+ } else {
213+ applyColor(it.nameIdentifier, ElmColor .DEFINITION_NAME )
214+ }
215+ }
66216 }
67217 }
68218
@@ -80,6 +230,9 @@ class ElmSyntaxHighlightAnnotator : Annotator {
80230 }
81231
82232 private fun AnnotationHolder.applyColor (element : PsiElement , color : ElmColor ) {
83- newSilentAnnotation(HighlightSeverity .INFORMATION ).textAttributes(color.textAttributesKey).range(element.textRange).create()
233+ newSilentAnnotation(HighlightSeverity .INFORMATION )
234+ .textAttributes(color.textAttributesKey)
235+ .range(element.textRange)
236+ .create()
84237 }
85238}
0 commit comments