Skip to content

Commit

Permalink
[ annotator ] enhance
Browse files Browse the repository at this point in the history
  • Loading branch information
zxj5470 committed Jan 31, 2019
1 parent 989aade commit 12a01b7
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 59 deletions.
21 changes: 12 additions & 9 deletions grammar/julia-grammar.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ expr ::=
| assignLevel
| arrowOp
| ternaryOp
| quoteLevel
| lambda
| miscArrowsOp
| orOp
| andOp
| comparisonLevelOp
| pipeLevelOp
| quoteLevel
| plusLevelOp
| bitwiseLevel
| multiplyLevel
Expand Down Expand Up @@ -278,12 +278,14 @@ private assignLevel ::=
assignOp
| assignLevelOp

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

private statementEvenStupid ::= moduleDeclaration | typeDeclaration | abstractTypeDeclaration | expr

multiAssignOp ::= strictExpressionList commaSep? (EQ_SYM | ASSIGN_SYM) endOfLine expressionList
assignLevelOp ::= expr assignLevelOperator endOfLine expressionList { rightAssociative=true }
assignLevelOperator ::=
Expand Down Expand Up @@ -428,18 +430,19 @@ comparisonLevelOperator ::=
pipeLevelOperator ::= PIPE_SYM | INVERSE_PIPE_SYM
pipeLevelOp ::= expr pipeLevelOperator endOfLine expr

// before lambda
private quoteLevel ::=
spliceOp
| colonOp
// | colonOp
| quoteOp
| compoundQuoteOp

colonSymBegins::= COLON_SYM endOfLine LEFT_BRACKET
colonOp ::= expr colonSymBegins expr RIGHT_BRACKET
//colonSymBegins::= COLON_SYM endOfLine LEFT_BRACKET
//colonOp ::= expr colonSymBegins expr RIGHT_BRACKET
spliceOp ::= expr SLICE_SYM
compoundQuoteOp ::= QUOTE_KEYWORD endOfLine (expr endOfLine)* END_KEYWORD
quoteOp ::= COLON_SYM quotable
private allowQuoteSymbols::= DOUBLE_COLON
private allowQuoteSymbols::= DOUBLE_COLON | DOT_SYM | privateOperaSymbols
private quotable ::=
unaryOpAsSymbol
| interpolateAsOp // unbracketed is useless, and idk why
Expand Down Expand Up @@ -699,8 +702,8 @@ primitiveTypeDeclaration ::=
macro ::=
MACRO_KEYWORD endOfLine
symbol endOfLine
untypedVariables endOfLine
<<lazyBlockNotParseEndImpl>>
untypedVariables? endOfLine
<<lazyBlockNotParseEndImpl>>?
END_KEYWORD {
pin=1
extends=expr
Expand Down Expand Up @@ -729,7 +732,7 @@ export ::=
importAllExpr ::=
IMPORTALL_KEYWORD access { pin=1 extends=expr }

private imported ::= access (COLON_SYM endOfLine symbolAndMacroSymbol)? (commaSep access)*
private imported ::= access (COLON_SYM endOfLine access)? (commaSep access)*

importExpr ::= IMPORT_KEYWORD endOfLine imported { pin=1 extends=expr }
using ::= USING_KEYWORD endOfLine imported { pin=1 extends=expr }
Expand Down
4 changes: 3 additions & 1 deletion res/org/ice1000/julia/lang/julia-bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ julia.lint.function-param-hints.show=Show function params hints
julia.lint.apply-function-param-hints.show=Show apply function params hints. (unimplemented)
julia.lint.version-number.argument-error= ArgumentError: invalid version string:
julia.lint.variable.assign-from-nothing.warning=The variable will become nothing.
julia.lint.variable.type-declarations.global-error=type declarations on global variables are not yet supported
julia.lint.variable.assign-to-module-error=ERROR: syntax: "module" expression not at top level.
julia.lint.variable.assign-from-nothing-replace=remove the assignment and just keep the right.
julia.lint.variable.type-declarations.global-error=ERROR: syntax: type declarations on global variables are not yet supported
julia.lint.variable.type-declarations.global-error-replace=remove the type annotation
julia.modules.type=Julia Module
Expand Down
24 changes: 21 additions & 3 deletions src/org/ice1000/julia/lang/editing/julia-annotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,27 @@ $JULIA_DOC_SURROUNDING
JuliaBundle.message("julia.lint.variable.type-declarations.global-error-replace")
))
}
val rightElement = element.exprList.lastOrNull() ?: return
if (rightElement is JuliaUsing || rightElement is JuliaImportExpr) {
holder.createWarningAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-from-nothing.warning"))
// element after `=` if stupid!
val leftElement = element.exprList.firstOrNull()
val rightElement = leftElement?.nextRealSibling?.nextRealSibling ?: return
when (rightElement) {
is JuliaUsing,
is JuliaImportExpr,
is IJuliaTypeDeclaration ->
holder
.createWarningAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-from-nothing.warning"))
.registerFix(JuliaReplaceWithTextIntention(element,
rightElement.text,
JuliaBundle.message("julia.lint.variable.assign-from-nothing-replace")
))
is JuliaModuleDeclaration -> {
holder
.createErrorAnnotation(element, JuliaBundle.message("julia.lint.variable.assign-to-module-error"))
.registerFix(JuliaReplaceWithTextIntention(element,
rightElement.text,
JuliaBundle.message("julia.lint.variable.assign-from-nothing-replace")
))
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/org/ice1000/julia/lang/editing/julia-completion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class JuliaBasicCompletionContributor : CompletionContributor() {
JuliaCompletionProvider(functionInside))
extend(CompletionType.BASIC,
psiElement()
.inside(JuliaUsing::class.java),
.inside(JuliaStatements::class.java),
JuliaModuleStubCompletionProvider())
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/org/ice1000/julia/lang/module/julia-language-server.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ end
// language=Julia
val command = """
try
repr(Docs.doc($name))
repr(@doc $name)
catch e
println("__INTELLIJ__"*repr(e))
end
Expand Down
13 changes: 13 additions & 0 deletions src/org/ice1000/julia/lang/psi/impl/julia-psi-ext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,16 @@ val PsiElement.prevRealSibling: PsiElement?
}
return pre
}

val PsiElement.nextRealSibling: PsiElement?
get() {
var next = this.nextSibling
while (next != null) {
if (next is PsiWhiteSpace) {
next = next.nextSibling
} else {
return next
}
}
return next
}
34 changes: 22 additions & 12 deletions src/org/ice1000/julia/lang/psi/julia-navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -141,29 +141,39 @@ class JuliaLineMarkerProvider : LineMarkerProvider {
if (element is IJuliaSymbol) {
when {
element.parent is JuliaAbstractTypeDeclaration -> {
val builder = NavigationGutterIconBuilder
return NavigationGutterIconBuilder
.create(overridenTypeIcon)
.setTooltipText("Please Click name to navigate to Subtypes")
.setTarget(element)
return builder.createLineMarkerInfo(element)
.createLineMarkerInfo(element)
}
// function Base.+
element.parent is JuliaFunction
&& element.prevSibling.elementType == JuliaTypes.DOT_SYM
&& element.prevSibling.prevSibling.elementType == JuliaTypes.SYM -> {
val builder = NavigationGutterIconBuilder
.create(overridingIcon)
.setTooltipText("navigate to overrided function. (This feature is still working)")
// TODO stubIndex
.setTarget(element)
return builder.createLineMarkerInfo(element)
&& element.prevSibling?.elementType == JuliaTypes.DOT_SYM
&& element.prevSibling?.prevSibling?.elementType == JuliaTypes.SYM -> {
val moduleName = element.prevSibling.prevSibling.text
val overridingName = element.text
val modules = JuliaModuleDeclarationIndex.findElementsByName(project, moduleName)
val targets = modules.flatMap { module ->
module.statements?.let { stmt ->
stmt.children.filter { (it is IJuliaFunctionDeclaration) && it.nameIdentifier?.text == overridingName }
} ?: emptyList()
}
return if (targets.isNotEmpty()) {
NavigationGutterIconBuilder
.create(overridingIcon)
.setTooltipText("navigate to overrided function. (This feature is still working)")
.setTargets(targets)
.createLineMarkerInfo(element)
} else null
}
element.isSuperTypeExpr || element.parent is JuliaType && element.parent.isSuperTypeExpr -> {
val target = JuliaTypeDeclarationIndex.findElementsByName(project, element.text) + JuliaAbstractTypeDeclarationIndex.findElementsByName(project, element.text)
val builder = NavigationGutterIconBuilder
return NavigationGutterIconBuilder
.create(overridingIcon)
.setTooltipText("navigate to overrided type.")
.setTargets(target)
return builder.createLineMarkerInfo(element)
.createLineMarkerInfo(element)
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions testData/parsing/ParseFor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ for α ∈ [1, 2, 3, 4]
println(β)
end)")
end

for j = 1:(i < lc ? 64 : last_chunk_len)
if Imsk & u != 0
lx < c && throw_setindex_mismatch(X, c)
@inbounds x = convert(Bool, X[c])
C = ifelse(x, C | u, C & ~u)
c += 1
end
u <<= 1
end
140 changes: 140 additions & 0 deletions testData/parsing/ParseFor.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,144 @@ FILE
PsiElement(QUOTE_END)('"')
PsiElement(RIGHT_BRACKET)(')')
PsiElement(EOL)('\n')
PsiElement(END_KEYWORD)('end')
PsiElement(EOL)('\n\n')
JuliaForExprImpl(FOR_EXPR)
PsiElement(FOR_KEYWORD)('for')
JuliaSingleIndexerImpl(SINGLE_INDEXER)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('j')
PsiElement(EQ_SYM)('=')
JuliaRangeOpImpl(RANGE_OP)
JuliaIntegerImpl(INTEGER)
PsiElement(INT_LITERAL)('1')
PsiElement(COLON_SYM)(':')
JuliaTupleImpl(TUPLE)
PsiElement(LEFT_BRACKET)('(')
JuliaTernaryOpImpl(TERNARY_OP)
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('i')
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
PsiElement(LESS_THAN_SYM)('<')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('lc')
PsiElement(QUESTION_SYM)('?')
JuliaRangeOpImpl(RANGE_OP)
JuliaIntegerImpl(INTEGER)
PsiElement(INT_LITERAL)('64')
PsiElement(COLON_SYM)(':')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('last_chunk_len')
PsiElement(RIGHT_BRACKET)(')')
JuliaStatementsImpl(STATEMENTS)
PsiElement(EOL)('\n')
JuliaIfExprImpl(IF_EXPR)
PsiElement(IF_KEYWORD)('if')
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
JuliaMultiplyLevelOpImpl(MULTIPLY_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('Imsk')
JuliaMultiplyLevelOperatorImpl(MULTIPLY_LEVEL_OPERATOR)
PsiElement(BITWISE_AND_SYM)('&')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('u')
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
PsiElement(UNEQUAL_SYM)('!=')
JuliaIntegerImpl(INTEGER)
PsiElement(INT_LITERAL)('0')
PsiElement(EOL)('\n')
JuliaStatementsImpl(STATEMENTS)
JuliaAndOpImpl(AND_OP)
JuliaComparisonLevelOpImpl(COMPARISON_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('lx')
JuliaComparisonLevelOperatorImpl(COMPARISON_LEVEL_OPERATOR)
PsiElement(LESS_THAN_SYM)('<')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('c')
PsiElement(AND_SYM)('&&')
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('throw_setindex_mismatch')
PsiElement(LEFT_BRACKET)('(')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('X')
PsiElement(COMMA_SYM)(',')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('c')
PsiElement(RIGHT_BRACKET)(')')
PsiElement(EOL)('\n')
JuliaApplyMacroOpImpl(APPLY_MACRO_OP)
JuliaMacroSymbolImpl(MACRO_SYMBOL)
PsiElement(MACRO_SYM)('@inbounds')
JuliaAssignOpImpl(ASSIGN_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('x')
PsiElement(EQ_SYM)('=')
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('convert')
PsiElement(LEFT_BRACKET)('(')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('Bool')
PsiElement(COMMA_SYM)(',')
JuliaApplyIndexOpImpl(APPLY_INDEX_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('X')
PsiElement(LEFT_M_BRACKET)('[')
JuliaExprWrapperImpl(EXPR_WRAPPER)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('c')
PsiElement(RIGHT_M_BRACKET)(']')
PsiElement(RIGHT_BRACKET)(')')
PsiElement(EOL)('\n')
JuliaAssignOpImpl(ASSIGN_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('C')
PsiElement(EQ_SYM)('=')
JuliaApplyFunctionOpImpl(APPLY_FUNCTION_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('ifelse')
PsiElement(LEFT_BRACKET)('(')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('x')
PsiElement(COMMA_SYM)(',')
JuliaPlusLevelOpImpl(PLUS_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('C')
JuliaPlusLevelOperatorImpl(PLUS_LEVEL_OPERATOR)
PsiElement(BITWISE_OR_SYM)('|')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('u')
PsiElement(COMMA_SYM)(',')
JuliaMultiplyLevelOpImpl(MULTIPLY_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('C')
JuliaMultiplyLevelOperatorImpl(MULTIPLY_LEVEL_OPERATOR)
PsiElement(BITWISE_AND_SYM)('&')
JuliaBitWiseNotOpImpl(BIT_WISE_NOT_OP)
PsiElement(BITWISE_NOT_SYM)('~')
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('u')
PsiElement(RIGHT_BRACKET)(')')
PsiElement(EOL)('\n')
JuliaAssignLevelOpImpl(ASSIGN_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('c')
JuliaAssignLevelOperatorImpl(ASSIGN_LEVEL_OPERATOR)
PsiElement(PLUS_ASSIGN_SYM)('+=')
JuliaIntegerImpl(INTEGER)
PsiElement(INT_LITERAL)('1')
PsiElement(EOL)('\n')
PsiElement(END_KEYWORD)('end')
PsiElement(EOL)('\n')
JuliaAssignLevelOpImpl(ASSIGN_LEVEL_OP)
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('u')
JuliaAssignLevelOperatorImpl(ASSIGN_LEVEL_OPERATOR)
PsiElement(SHL_ASSIGN_SYM)('<<=')
JuliaIntegerImpl(INTEGER)
PsiElement(INT_LITERAL)('1')
PsiElement(EOL)('\n')
PsiElement(END_KEYWORD)('end')
5 changes: 3 additions & 2 deletions testData/parsing/ParseImport.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ FILE
JuliaSymbolImpl(SYMBOL)
PsiElement(SYM)('Base')
PsiElement(COLON_SYM)(':')
JuliaSymbolImpl(SYMBOL)
PsiElement(PLUS_SYM)('+')
JuliaMemberAccessImpl(MEMBER_ACCESS)
JuliaOpAsSymbolImpl(OP_AS_SYMBOL)
PsiElement(PLUS_SYM)('+')
PsiElement(COMMA_SYM)(',')
JuliaMemberAccessImpl(MEMBER_ACCESS)
JuliaOpAsSymbolImpl(OP_AS_SYMBOL)
Expand Down
Loading

0 comments on commit 12a01b7

Please sign in to comment.