Skip to content

Commit 12a01b7

Browse files
committed
[ annotator ] enhance
1 parent 989aade commit 12a01b7

File tree

16 files changed

+379
-59
lines changed

16 files changed

+379
-59
lines changed

grammar/julia-grammar.bnf

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,13 @@ expr ::=
225225
| assignLevel
226226
| arrowOp
227227
| ternaryOp
228+
| quoteLevel
228229
| lambda
229230
| miscArrowsOp
230231
| orOp
231232
| andOp
232233
| comparisonLevelOp
233234
| pipeLevelOp
234-
| quoteLevel
235235
| plusLevelOp
236236
| bitwiseLevel
237237
| multiplyLevel
@@ -278,12 +278,14 @@ private assignLevel ::=
278278
assignOp
279279
| assignLevelOp
280280

281-
assignOp ::= expr commaSep? (EQ_SYM | ASSIGN_SYM) endOfLine expr {
281+
assignOp ::= expr commaSep? (EQ_SYM | ASSIGN_SYM) endOfLine statementEvenStupid {
282282
rightAssociative=true
283283
implements=['com.intellij.psi.PsiNameIdentifierOwner']
284284
mixin='org.ice1000.julia.lang.psi.impl.JuliaAssignOpMixin'
285285
}
286286

287+
private statementEvenStupid ::= moduleDeclaration | typeDeclaration | abstractTypeDeclaration | expr
288+
287289
multiAssignOp ::= strictExpressionList commaSep? (EQ_SYM | ASSIGN_SYM) endOfLine expressionList
288290
assignLevelOp ::= expr assignLevelOperator endOfLine expressionList { rightAssociative=true }
289291
assignLevelOperator ::=
@@ -428,18 +430,19 @@ comparisonLevelOperator ::=
428430
pipeLevelOperator ::= PIPE_SYM | INVERSE_PIPE_SYM
429431
pipeLevelOp ::= expr pipeLevelOperator endOfLine expr
430432

433+
// before lambda
431434
private quoteLevel ::=
432435
spliceOp
433-
| colonOp
436+
// | colonOp
434437
| quoteOp
435438
| compoundQuoteOp
436439

437-
colonSymBegins::= COLON_SYM endOfLine LEFT_BRACKET
438-
colonOp ::= expr colonSymBegins expr RIGHT_BRACKET
440+
//colonSymBegins::= COLON_SYM endOfLine LEFT_BRACKET
441+
//colonOp ::= expr colonSymBegins expr RIGHT_BRACKET
439442
spliceOp ::= expr SLICE_SYM
440443
compoundQuoteOp ::= QUOTE_KEYWORD endOfLine (expr endOfLine)* END_KEYWORD
441444
quoteOp ::= COLON_SYM quotable
442-
private allowQuoteSymbols::= DOUBLE_COLON
445+
private allowQuoteSymbols::= DOUBLE_COLON | DOT_SYM | privateOperaSymbols
443446
private quotable ::=
444447
unaryOpAsSymbol
445448
| interpolateAsOp // unbracketed is useless, and idk why
@@ -699,8 +702,8 @@ primitiveTypeDeclaration ::=
699702
macro ::=
700703
MACRO_KEYWORD endOfLine
701704
symbol endOfLine
702-
untypedVariables endOfLine
703-
<<lazyBlockNotParseEndImpl>>
705+
untypedVariables? endOfLine
706+
<<lazyBlockNotParseEndImpl>>?
704707
END_KEYWORD {
705708
pin=1
706709
extends=expr
@@ -729,7 +732,7 @@ export ::=
729732
importAllExpr ::=
730733
IMPORTALL_KEYWORD access { pin=1 extends=expr }
731734

732-
private imported ::= access (COLON_SYM endOfLine symbolAndMacroSymbol)? (commaSep access)*
735+
private imported ::= access (COLON_SYM endOfLine access)? (commaSep access)*
733736

734737
importExpr ::= IMPORT_KEYWORD endOfLine imported { pin=1 extends=expr }
735738
using ::= USING_KEYWORD endOfLine imported { pin=1 extends=expr }

res/org/ice1000/julia/lang/julia-bundle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ julia.lint.function-param-hints.show=Show function params hints
102102
julia.lint.apply-function-param-hints.show=Show apply function params hints. (unimplemented)
103103
julia.lint.version-number.argument-error= ArgumentError: invalid version string:
104104
julia.lint.variable.assign-from-nothing.warning=The variable will become nothing.
105-
julia.lint.variable.type-declarations.global-error=type declarations on global variables are not yet supported
105+
julia.lint.variable.assign-to-module-error=ERROR: syntax: "module" expression not at top level.
106+
julia.lint.variable.assign-from-nothing-replace=remove the assignment and just keep the right.
107+
julia.lint.variable.type-declarations.global-error=ERROR: syntax: type declarations on global variables are not yet supported
106108
julia.lint.variable.type-declarations.global-error-replace=remove the type annotation
107109
108110
julia.modules.type=Julia Module

src/org/ice1000/julia/lang/editing/julia-annotator.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,27 @@ $JULIA_DOC_SURROUNDING
171171
JuliaBundle.message("julia.lint.variable.type-declarations.global-error-replace")
172172
))
173173
}
174-
val rightElement = element.exprList.lastOrNull() ?: return
175-
if (rightElement is JuliaUsing || rightElement is JuliaImportExpr) {
176-
holder.createWarningAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-from-nothing.warning"))
174+
// element after `=` if stupid!
175+
val leftElement = element.exprList.firstOrNull()
176+
val rightElement = leftElement?.nextRealSibling?.nextRealSibling ?: return
177+
when (rightElement) {
178+
is JuliaUsing,
179+
is JuliaImportExpr,
180+
is IJuliaTypeDeclaration ->
181+
holder
182+
.createWarningAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-from-nothing.warning"))
183+
.registerFix(JuliaReplaceWithTextIntention(element,
184+
rightElement.text,
185+
JuliaBundle.message("julia.lint.variable.assign-from-nothing-replace")
186+
))
187+
is JuliaModuleDeclaration -> {
188+
holder
189+
.createErrorAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-to-module-error"))
190+
.registerFix(JuliaReplaceWithTextIntention(element,
191+
rightElement.text,
192+
JuliaBundle.message("julia.lint.variable.assign-from-nothing-replace")
193+
))
194+
}
177195
}
178196
}
179197

src/org/ice1000/julia/lang/editing/julia-completion.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class JuliaBasicCompletionContributor : CompletionContributor() {
237237
JuliaCompletionProvider(functionInside))
238238
extend(CompletionType.BASIC,
239239
psiElement()
240-
.inside(JuliaUsing::class.java),
240+
.inside(JuliaStatements::class.java),
241241
JuliaModuleStubCompletionProvider())
242242
}
243243
}

src/org/ice1000/julia/lang/module/julia-language-server.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ end
8181
// language=Julia
8282
val command = """
8383
try
84-
repr(Docs.doc($name))
84+
repr(@doc $name)
8585
catch e
8686
println("__INTELLIJ__"*repr(e))
8787
end

src/org/ice1000/julia/lang/psi/impl/julia-psi-ext.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,16 @@ val PsiElement.prevRealSibling: PsiElement?
5151
}
5252
return pre
5353
}
54+
55+
val PsiElement.nextRealSibling: PsiElement?
56+
get() {
57+
var next = this.nextSibling
58+
while (next != null) {
59+
if (next is PsiWhiteSpace) {
60+
next = next.nextSibling
61+
} else {
62+
return next
63+
}
64+
}
65+
return next
66+
}

src/org/ice1000/julia/lang/psi/julia-navigation.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,29 +141,39 @@ class JuliaLineMarkerProvider : LineMarkerProvider {
141141
if (element is IJuliaSymbol) {
142142
when {
143143
element.parent is JuliaAbstractTypeDeclaration -> {
144-
val builder = NavigationGutterIconBuilder
144+
return NavigationGutterIconBuilder
145145
.create(overridenTypeIcon)
146146
.setTooltipText("Please Click name to navigate to Subtypes")
147147
.setTarget(element)
148-
return builder.createLineMarkerInfo(element)
148+
.createLineMarkerInfo(element)
149149
}
150+
// function Base.+
150151
element.parent is JuliaFunction
151-
&& element.prevSibling.elementType == JuliaTypes.DOT_SYM
152-
&& element.prevSibling.prevSibling.elementType == JuliaTypes.SYM -> {
153-
val builder = NavigationGutterIconBuilder
154-
.create(overridingIcon)
155-
.setTooltipText("navigate to overrided function. (This feature is still working)")
156-
// TODO stubIndex
157-
.setTarget(element)
158-
return builder.createLineMarkerInfo(element)
152+
&& element.prevSibling?.elementType == JuliaTypes.DOT_SYM
153+
&& element.prevSibling?.prevSibling?.elementType == JuliaTypes.SYM -> {
154+
val moduleName = element.prevSibling.prevSibling.text
155+
val overridingName = element.text
156+
val modules = JuliaModuleDeclarationIndex.findElementsByName(project, moduleName)
157+
val targets = modules.flatMap { module ->
158+
module.statements?.let { stmt ->
159+
stmt.children.filter { (it is IJuliaFunctionDeclaration) && it.nameIdentifier?.text == overridingName }
160+
} ?: emptyList()
161+
}
162+
return if (targets.isNotEmpty()) {
163+
NavigationGutterIconBuilder
164+
.create(overridingIcon)
165+
.setTooltipText("navigate to overrided function. (This feature is still working)")
166+
.setTargets(targets)
167+
.createLineMarkerInfo(element)
168+
} else null
159169
}
160170
element.isSuperTypeExpr || element.parent is JuliaType && element.parent.isSuperTypeExpr -> {
161171
val target = JuliaTypeDeclarationIndex.findElementsByName(project, element.text) + JuliaAbstractTypeDeclarationIndex.findElementsByName(project, element.text)
162-
val builder = NavigationGutterIconBuilder
172+
return NavigationGutterIconBuilder
163173
.create(overridingIcon)
164174
.setTooltipText("navigate to overrided type.")
165175
.setTargets(target)
166-
return builder.createLineMarkerInfo(element)
176+
.createLineMarkerInfo(element)
167177
}
168178
}
169179
}

testData/parsing/ParseFor.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ for α ∈ [1, 2, 3, 4]
66
println(β)
77
end)")
88
end
9+
10+
for j = 1:(i < lc ? 64 : last_chunk_len)
11+
if Imsk & u != 0
12+
lx < c && throw_setindex_mismatch(X, c)
13+
@inbounds x = convert(Bool, X[c])
14+
C = ifelse(x, C | u, C & ~u)
15+
c += 1
16+
end
17+
u <<= 1
18+
end

testData/parsing/ParseFor.txt

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,144 @@ FILE
118118
PsiElement(QUOTE_END)('"')
119119
PsiElement(RIGHT_BRACKET)(')')
120120
PsiElement(EOL)('\n')
121+
PsiElement(END_KEYWORD)('end')
122+
PsiElement(EOL)('\n\n')
123+
JuliaForExprImpl(FOR_EXPR)
124+
PsiElement(FOR_KEYWORD)('for')
125+
JuliaSingleIndexerImpl(SINGLE_INDEXER)
126+
JuliaSymbolImpl(SYMBOL)
127+
PsiElement(SYM)('j')
128+
PsiElement(EQ_SYM)('=')
129+
JuliaRangeOpImpl(RANGE_OP)
130+
JuliaIntegerImpl(INTEGER)
131+
PsiElement(INT_LITERAL)('1')
132+
PsiElement(COLON_SYM)(':')
133+
JuliaTupleImpl(TUPLE)
134+
PsiElement(LEFT_BRACKET)('(')
135+
JuliaTernaryOpImpl(TERNARY_OP)
136+
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
137+
JuliaSymbolImpl(SYMBOL)
138+
PsiElement(SYM)('i')
139+
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
140+
PsiElement(LESS_THAN_SYM)('<')
141+
JuliaSymbolImpl(SYMBOL)
142+
PsiElement(SYM)('lc')
143+
PsiElement(QUESTION_SYM)('?')
144+
JuliaRangeOpImpl(RANGE_OP)
145+
JuliaIntegerImpl(INTEGER)
146+
PsiElement(INT_LITERAL)('64')
147+
PsiElement(COLON_SYM)(':')
148+
JuliaSymbolImpl(SYMBOL)
149+
PsiElement(SYM)('last_chunk_len')
150+
PsiElement(RIGHT_BRACKET)(')')
151+
JuliaStatementsImpl(STATEMENTS)
152+
PsiElement(EOL)('\n')
153+
JuliaIfExprImpl(IF_EXPR)
154+
PsiElement(IF_KEYWORD)('if')
155+
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
156+
JuliaMultiplyLevelOpImpl(MULTIPLY_LEVEL_OP)
157+
JuliaSymbolImpl(SYMBOL)
158+
PsiElement(SYM)('Imsk')
159+
JuliaMultiplyLevelOperatorImpl(MULTIPLY_LEVEL_OPERATOR)
160+
PsiElement(BITWISE_AND_SYM)('&')
161+
JuliaSymbolImpl(SYMBOL)
162+
PsiElement(SYM)('u')
163+
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
164+
PsiElement(UNEQUAL_SYM)('!=')
165+
JuliaIntegerImpl(INTEGER)
166+
PsiElement(INT_LITERAL)('0')
167+
PsiElement(EOL)('\n')
168+
JuliaStatementsImpl(STATEMENTS)
169+
JuliaAndOpImpl(AND_OP)
170+
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
171+
JuliaSymbolImpl(SYMBOL)
172+
PsiElement(SYM)('lx')
173+
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
174+
PsiElement(LESS_THAN_SYM)('<')
175+
JuliaSymbolImpl(SYMBOL)
176+
PsiElement(SYM)('c')
177+
PsiElement(AND_SYM)('&&')
178+
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
179+
JuliaSymbolImpl(SYMBOL)
180+
PsiElement(SYM)('throw_setindex_mismatch')
181+
PsiElement(LEFT_BRACKET)('(')
182+
JuliaSymbolImpl(SYMBOL)
183+
PsiElement(SYM)('X')
184+
PsiElement(COMMA_SYM)(',')
185+
JuliaSymbolImpl(SYMBOL)
186+
PsiElement(SYM)('c')
187+
PsiElement(RIGHT_BRACKET)(')')
188+
PsiElement(EOL)('\n')
189+
JuliaApplyMacroOpImpl(APPLY_MACRO_OP)
190+
JuliaMacroSymbolImpl(MACRO_SYMBOL)
191+
PsiElement(MACRO_SYM)('@inbounds')
192+
JuliaAssignOpImpl(ASSIGN_OP)
193+
JuliaSymbolImpl(SYMBOL)
194+
PsiElement(SYM)('x')
195+
PsiElement(EQ_SYM)('=')
196+
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
197+
JuliaSymbolImpl(SYMBOL)
198+
PsiElement(SYM)('convert')
199+
PsiElement(LEFT_BRACKET)('(')
200+
JuliaSymbolImpl(SYMBOL)
201+
PsiElement(SYM)('Bool')
202+
PsiElement(COMMA_SYM)(',')
203+
JuliaApplyIndexOpImpl(APPLY_INDEX_OP)
204+
JuliaSymbolImpl(SYMBOL)
205+
PsiElement(SYM)('X')
206+
PsiElement(LEFT_M_BRACKET)('[')
207+
JuliaExprWrapperImpl(EXPR_WRAPPER)
208+
JuliaSymbolImpl(SYMBOL)
209+
PsiElement(SYM)('c')
210+
PsiElement(RIGHT_M_BRACKET)(']')
211+
PsiElement(RIGHT_BRACKET)(')')
212+
PsiElement(EOL)('\n')
213+
JuliaAssignOpImpl(ASSIGN_OP)
214+
JuliaSymbolImpl(SYMBOL)
215+
PsiElement(SYM)('C')
216+
PsiElement(EQ_SYM)('=')
217+
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
218+
JuliaSymbolImpl(SYMBOL)
219+
PsiElement(SYM)('ifelse')
220+
PsiElement(LEFT_BRACKET)('(')
221+
JuliaSymbolImpl(SYMBOL)
222+
PsiElement(SYM)('x')
223+
PsiElement(COMMA_SYM)(',')
224+
JuliaPlusLevelOpImpl(PLUS_LEVEL_OP)
225+
JuliaSymbolImpl(SYMBOL)
226+
PsiElement(SYM)('C')
227+
JuliaPlusLevelOperatorImpl(PLUS_LEVEL_OPERATOR)
228+
PsiElement(BITWISE_OR_SYM)('|')
229+
JuliaSymbolImpl(SYMBOL)
230+
PsiElement(SYM)('u')
231+
PsiElement(COMMA_SYM)(',')
232+
JuliaMultiplyLevelOpImpl(MULTIPLY_LEVEL_OP)
233+
JuliaSymbolImpl(SYMBOL)
234+
PsiElement(SYM)('C')
235+
JuliaMultiplyLevelOperatorImpl(MULTIPLY_LEVEL_OPERATOR)
236+
PsiElement(BITWISE_AND_SYM)('&')
237+
JuliaBitWiseNotOpImpl(BIT_WISE_NOT_OP)
238+
PsiElement(BITWISE_NOT_SYM)('~')
239+
JuliaSymbolImpl(SYMBOL)
240+
PsiElement(SYM)('u')
241+
PsiElement(RIGHT_BRACKET)(')')
242+
PsiElement(EOL)('\n')
243+
JuliaAssignLevelOpImpl(ASSIGN_LEVEL_OP)
244+
JuliaSymbolImpl(SYMBOL)
245+
PsiElement(SYM)('c')
246+
JuliaAssignLevelOperatorImpl(ASSIGN_LEVEL_OPERATOR)
247+
PsiElement(PLUS_ASSIGN_SYM)('+=')
248+
JuliaIntegerImpl(INTEGER)
249+
PsiElement(INT_LITERAL)('1')
250+
PsiElement(EOL)('\n')
251+
PsiElement(END_KEYWORD)('end')
252+
PsiElement(EOL)('\n')
253+
JuliaAssignLevelOpImpl(ASSIGN_LEVEL_OP)
254+
JuliaSymbolImpl(SYMBOL)
255+
PsiElement(SYM)('u')
256+
JuliaAssignLevelOperatorImpl(ASSIGN_LEVEL_OPERATOR)
257+
PsiElement(SHL_ASSIGN_SYM)('<<=')
258+
JuliaIntegerImpl(INTEGER)
259+
PsiElement(INT_LITERAL)('1')
260+
PsiElement(EOL)('\n')
121261
PsiElement(END_KEYWORD)('end')

testData/parsing/ParseImport.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ FILE
3636
JuliaSymbolImpl(SYMBOL)
3737
PsiElement(SYM)('Base')
3838
PsiElement(COLON_SYM)(':')
39-
JuliaSymbolImpl(SYMBOL)
40-
PsiElement(PLUS_SYM)('+')
39+
JuliaMemberAccessImpl(MEMBER_ACCESS)
40+
JuliaOpAsSymbolImpl(OP_AS_SYMBOL)
41+
PsiElement(PLUS_SYM)('+')
4142
PsiElement(COMMA_SYM)(',')
4243
JuliaMemberAccessImpl(MEMBER_ACCESS)
4344
JuliaOpAsSymbolImpl(OP_AS_SYMBOL)

0 commit comments

Comments
 (0)