Skip to content

Commit

Permalink
handle new a > b parse tree. Add unknown exception warning
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyhffong committed Apr 1, 2016
1 parent 333e8c5 commit 0a29c0d
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 179 deletions.
307 changes: 154 additions & 153 deletions docs/messages.md
Expand Up @@ -36,156 +36,157 @@ errors = filter(i -> !isinfo(i), lintpkg("MyPackage", returnMsgs=true))
## Errors codes
Every error code starts with letter for the severity `E`:`ERROR`, `W`:`WARN` or `I`:`INFO` then has 3 numbers identifying the error. Below is a complete list of error codes:

| code | sample message |
|:----:|:---------------|
|**E1**| *Parsing Error*
| E111 | failed to parse
| E112 | incomplete expression
| E121 | Lint does not understand the expression
| E131 | Lint does not understand the argument #i
| E132 | lint does not understand the argument
| E133 | unknown keyword pattern
| E134 | unknown global pattern
| E135 | local declaration not understood by Lint
| E136 | Lint does not understand macro
| E137 | lintpragma must be called using only string literals
| E138 | incomplete pragma expression
| E139 | Lint fails to parse type: error
| |
|**E2**| *Miscellaneous Error*
| E211 | deprecated message
| E221 | custum error
| E231 | error; Signature: ...
| |
|**E3**| *Existence Error*
| E311 | cannot find include file
| E321 | use of undeclared symbol
| E322 | exporting undefined symbol
| E331 | duplicate argument
| E332 | should not be used as a variable name
| E333 | duplicate exports of symbol
| E334 | duplicate key in Dict
| |
|**E4**| *Usage Error*
| E411 | non-default argument following default arguments
| E412 | named ellipsis ... can only be the last argument
| E413 | positional ellipsis ... can only be the last argument
| E414 | using is not allowed inside function definitions
| E415 | export is not allowed inside function definitions
| E416 | import is not allowed inside function definitions
| E417 | anonymous function inside type definition
| E418 | RHS is a tuple, n of m variables used
| E421 | use Union{...}, with curly, instead of parentheses
| E422 | string uses * to concatenate
| E423 | named keyword argument must have a default
| E424 | nested vect is treated as a 1-dimensional array. Use [a;b] instead
| E425 | use lintpragma macro inside type declaration
| E431 | use of length() in a Boolean context, use isempty()
| E432 | though valid in 0.4, use x() instead of y()
| E433 | for a decreasing range, use a negative step e.g. 10:-1:1
| E434 | value at position #i is the referenced x. Possible typo?
| E435 | new is provided with more arguments than fields
| E436 | more indices than dimensions
| |
|**E5**| *Type Error*
| E511 | apparent non-Bool type
| E512 | lint doesn't understand expresion in a boolean context
| E513 | leaf type as a type constraint it makes no sense
| E516 | type assertion and default seem inconsistent
| E517 | constructor-like function name doesn't match type T
| E518 | key type expects X, provided Y
| E519 | string[] expects Integer, provided X
| E521 | apparent type T is not a container type
| E522 | macro arguments can only be Symbol/Expr
| E523 | constructor parameter collides with a type parameter
| E524 | bitstype needs its 2nd argument to be a new type symbol
| E525 | is of an immutable type
| E531 | multiple key types detected. Use Dict{Any,V}() for mixed type dict
| E532 | multiple value types detected. Use Dict{K,Any}() for mixed type dict
| E533 | type parameters are invariant, try f{T<:Number}(x::T)...
| E534 | introducing a new name for an implicit argument to the function, use {T<:X}
| E535 | introducing a new name for an algebric data type, use {T<:X}
| E536 | use {T<:...} instead of a known type
| E537 | non-existent constructor, use string() for string conversion
| E538 | known type in parametric data type, use {T<:...}
| |
|**E6**| *Structure Error*
| E611 | constructor doesn't seem to return the constructed object
| |
|**W2**| *Miscellaneous Warning*
| W241 | custum warning
| W251 | error; Symbol= X; rhstype= ...
| |
|**W3**| *Existence Warning*
| W341 | local variable declared but not used
| W351 | redefining mathematical constant
| W352 | lambda argument conflicts with a local variable
| W353 | lambda argument conflicts with an argument
| W354 | lambda argument conflicts with an declared global
| W355 | conflicts with function name
| W356 | local variable might cause confusion with a synonymous export from Base
| |
|**W4**| *Usage Warning*
| W441 | probably illegal use of inside curly
| W442 | bit-wise in a boolean context. (&,|) do not have short-circuit behavior
| W443 | did you forget an -> after @doc or make it inline?
| W444 | nested vcat is treated as a 1-dimensional array
| W445 | nested hcat is treated as a 1-row horizontal array of dim=2
| W446 | too many type parameters
| W447 | can't be #i type parameter for h; it should be of type t2
| |
|**W5**| *Type Warning*
| W541 | doesn't eval into a Module
| W542 | comparing apparently incompatible types
| W543 | cannot determine if DataType or not
| W544 | cannot determine if DataType or not
| W545 | previously used variable has apparent type X, but now assigned Y
| |
|**W6**| *Structure Warning*
| W641 | unreachable code after return
| W642 | true branch is unreachable
| W643 | false branch is unreachable
| W644 | redundant if-true statement
| W645 | while false block is unreachable
| W651 | the last of a expresion block looks different. Avg similarity score: X; Last part: Y
| |
|**I1**| *Parsing Info*
| I171 | LHS in assignment not understood by Lint
| |
|**I2**| *Miscellaneous Info*
| I271 | custum info
| |
|**I3**| *Existence Info*
| I371 | use of undeclared symbol
| I372 | unable to follow non-literal include file
| I381 | unused lintpragma
| I382 | argument declared but not used
| I391 | also a global from src
| |
|**I4**| *Usage Info*
| I472 | assignment in the if-predicate clause
| I473 | value at position #i is the referenced y. OK if it represents permutations
| I474 | iteration generates tuples, n of m variables used
| I481 | in 0.4+, replace x() with y()
| I482 | used in a local scope. Improve readability by using 'local' or another name
| I483 | {} may be deprecated. Use Any[]
| I484 | untyped dictionary {a=>b for (a,b) in c}, may be deprecated. Use (Any=>Any)[a=>b for (a,b) in c]
| I485 | untyped dictionary {a for a in c}, may be deprecated. Use (Any)[a for a in c]
| I486 | dictionary [a=>b,...], may be deprecated. Use @compat Dict(a=>b,...)
| I487 | (K=>V)[a=>b,...] may be deprecated. Use @compat Dict{K,V}(a=>b,...)
| |
|**I5**| *Type Info*
| I571 | the 1st statement under the true-branch is a boolean expression
| I572 | assert x type= X but assign a value of Y
| I581 | there is only 1 key type && 1 value type. Use explicit Dict{K,V}() for better performances
| |
|**I6**| *Structure Info*
| I671 | new is provided with fewer arguments than fields
| I672 | iteration works for a number but it may be a typo
| I681 | ambiguity of :end as a symbol vs as part of a range
| I682 | ambiguity of [end -n] as a matrix row vs index [end-n]
| I691 | a type is not given to the field which can be slow
| I692 | array field has no dimension which can be slow
| |
|**I7**| *Style Info*
| I771 | type names should start with an upper case
| code | sample message |
| :----: | :--------------- |
| **E1** | *Parsing Error*
| E111 | failed to parse
| E112 | incomplete expression
| E121 | Lint does not understand the expression
| E131 | Lint does not understand the argument #i
| E132 | lint does not understand the argument
| E133 | unknown keyword pattern
| E134 | unknown global pattern
| E135 | local declaration not understood by Lint
| E136 | Lint does not understand macro
| E137 | lintpragma must be called using only string literals
| E138 | incomplete pragma expression
| E139 | Lint fails to parse type: error
| |
| **E2** | *Miscellaneous Error*
| E211 | deprecated message
| E221 | custum error
| E231 | error; Signature: ...
| |
| **E3** | *Existence Error*
| E311 | cannot find include file
| E321 | use of undeclared symbol
| E322 | exporting undefined symbol
| E331 | duplicate argument
| E332 | should not be used as a variable name
| E333 | duplicate exports of symbol
| E334 | duplicate key in Dict
| |
| **E4** | *Usage Error*
| E411 | non-default argument following default arguments
| E412 | named ellipsis ... can only be the last argument
| E413 | positional ellipsis ... can only be the last argument
| E414 | using is not allowed inside function definitions
| E415 | export is not allowed inside function definitions
| E416 | import is not allowed inside function definitions
| E417 | anonymous function inside type definition
| E418 | RHS is a tuple, n of m variables used
| E421 | use Union{...}, with curly, instead of parentheses
| E422 | string uses * to concatenate
| E423 | named keyword argument must have a default
| E424 | nested vect is treated as a 1-dimensional array. Use [a;b] instead
| E425 | use lintpragma macro inside type declaration
| E431 | use of length() in a Boolean context, use isempty()
| E432 | though valid in 0.4, use x() instead of y()
| E433 | for a decreasing range, use a negative step e.g. 10:-1:1
| E434 | value at position #i is the referenced x. Possible typo?
| E435 | new is provided with more arguments than fields
| E436 | more indices than dimensions
| |
| **E5** | *Type Error*
| E511 | apparent non-Bool type
| E512 | lint doesn't understand expresion in a boolean context
| E513 | leaf type as a type constraint it makes no sense
| E516 | type assertion and default seem inconsistent
| E517 | constructor-like function name doesn't match type T
| E518 | key type expects X, provided Y
| E519 | string[] expects Integer, provided X
| E521 | apparent type T is not a container type
| E522 | macro arguments can only be Symbol/Expr
| E523 | constructor parameter collides with a type parameter
| E524 | bitstype needs its 2nd argument to be a new type symbol
| E525 | is of an immutable type
| E531 | multiple key types detected. Use Dict{Any,V}() for mixed type dict
| E532 | multiple value types detected. Use Dict{K,Any}() for mixed type dict
| E533 | type parameters are invariant, try f{T<:Number}(x::T)...
| E534 | introducing a new name for an implicit argument to the function, use {T<:X}
| E535 | introducing a new name for an algebric data type, use {T<:X}
| E536 | use {T<:...} instead of a known type
| E537 | non-existent constructor, use string() for string conversion
| E538 | known type in parametric data type, use {T<:...}
| |
| **E6** | *Structure Error*
| E611 | constructor doesn't seem to return the constructed object
| |
| **W2** | *Miscellaneous Warning*
| W241 | custum warning
| W251 | error; Symbol= X; rhstype= ...
| |
| **W3** | *Existence Warning*
| W341 | local variable declared but not used
| W351 | redefining mathematical constant
| W352 | lambda argument conflicts with a local variable
| W353 | lambda argument conflicts with an argument
| W354 | lambda argument conflicts with an declared global
| W355 | conflicts with function name
| W356 | local variable might cause confusion with a synonymous export from Base
| |
| **W4** | *Usage Warning*
| W441 | probably illegal use of inside curly
| W442 | bit-wise in a boolean context. (&, | ) do not have short-circuit behavior
| W443 | did you forget an -> after @doc or make it inline?
| W444 | nested vcat is treated as a 1-dimensional array
| W445 | nested hcat is treated as a 1-row horizontal array of dim=2
| W446 | too many type parameters
| W447 | can't be #i type parameter for h; it should be of type t2
| W448 | an exception is instantiated but it is not being thrown
| |
| **W5** | *Type Warning*
| W541 | doesn't eval into a Module
| W542 | comparing apparently incompatible types
| W543 | cannot determine if DataType or not
| W544 | cannot determine if DataType or not
| W545 | previously used variable has apparent type X, but now assigned Y
| |
| **W6** | *Structure Warning*
| W641 | unreachable code after return
| W642 | true branch is unreachable
| W643 | false branch is unreachable
| W644 | redundant if-true statement
| W645 | while false block is unreachable
| W651 | the last of a expresion block looks different. Avg similarity score: X; Last part: Y
| |
| **I1** | *Parsing Info*
| I171 | LHS in assignment not understood by Lint
| |
| **I2** | *Miscellaneous Info*
| I271 | custum info
| |
| **I3** | *Existence Info*
| I371 | use of undeclared symbol
| I372 | unable to follow non-literal include file
| I381 | unused lintpragma
| I382 | argument declared but not used
| I391 | also a global from src
| |
| **I4** | *Usage Info*
| I472 | assignment in the if-predicate clause
| I473 | value at position #i is the referenced y. OK if it represents permutations
| I474 | iteration generates tuples, n of m variables used
| I481 | in 0.4+, replace x() with y()
| I482 | used in a local scope. Improve readability by using 'local' or another name
| I483 | {} may be deprecated. Use Any[]
| I484 | untyped dictionary {a=>b for (a,b) in c}, may be deprecated. Use (Any=>Any)[a=>b for (a,b) in c]
| I485 | untyped dictionary {a for a in c}, may be deprecated. Use (Any)[a for a in c]
| I486 | dictionary [a=>b,...], may be deprecated. Use @compat Dict(a=>b,...)
| I487 | (K=>V)[a=>b,...] may be deprecated. Use @compat Dict{K,V}(a=>b,...)
| |
| **I5** | *Type Info*
| I571 | the 1st statement under the true-branch is a boolean expression
| I572 | assert x type= X but assign a value of Y
| I581 | there is only 1 key type && 1 value type. Use explicit Dict{K,V}() for better performances
| |
| **I6** | *Structure Info*
| I671 | new is provided with fewer arguments than fields
| I672 | iteration works for a number but it may be a typo
| I681 | ambiguity of :end as a symbol vs as part of a range
| I682 | ambiguity of [end -n] as a matrix row vs index [end-n]
| I691 | a type is not given to the field which can be slow
| I692 | array field has no dimension which can be slow
| |
| **I7** | *Style Info*
| I771 | type names should start with an upper case
1 change: 1 addition & 0 deletions src/Lint.jl
Expand Up @@ -12,6 +12,7 @@ export test_similarity_string

const SIMILARITY_THRESHOLD = 10.0
const ASSIGN_OPS = [:(=), :(+=), :(-=), :(*=), :(/=), :(&=), :(|=)]
const COMPARISON_OPS = [:(==), :(<), :(>), :(<=), :(>=), :(!=) ]

# no-op. We have to use macro inside type declaration as it disallows actual function calls
macro lintpragma(s)
Expand Down
34 changes: 30 additions & 4 deletions src/controls.jl
Expand Up @@ -18,7 +18,8 @@ function lintifexpr(ex::Expr, ctx::LintContext)
# generate a INFO, as it could have been a typo
if isexpr(ex.args[2], :block) && length(ex.args[2].args) >= 2 &&
(isexpr(ex.args[2].args[2], :comparison) ||
isexpr(ex.args[2].args[2], :call) && ex.args[2].args[2].args[1] == :(!) ||
isexpr(ex.args[2].args[2], :call) &&
( ex.args[2].args[2].args[1] == :(!) || ex.args[2].args[2].args[1] in COMPARISON_OPS ) ||
isexpr(ex.args[2].args[2], [:(&&), :(||)]) &&
!isexpr(ex.args[2].args[2].args[end], [:call, :error, :throw, :return]))
msg(ctx, :I571, "the 1st statement under the true-branch is a boolean expression")
Expand Down Expand Up @@ -48,7 +49,29 @@ end
# return a duplet of functions, the true branch version predicate and the false-branch version predicate
# if none exists, return (nothing, nothing)
function versionconstraint(ex)
if isexpr(ex, :comparison)

if isexpr(ex, :call) && ex.args[1] in COMPARISON_OPS
if ex.args[2] == :VERSION || ex.args[3] == :VERSION
if ex.args[2] == :VERSION && isexpr(ex.args[3], :macrocall) &&
ex.args[3].args[1] == Symbol( "@v_str" ) &&
typeof(ex.args[3].args[2]) <: AbstractString ||
isexpr(ex.args[2], :macrocall) &&
ex.args[2].args[1] == Symbol( "@v_str" ) &&
typeof(ex.args[2].args[2]) <: AbstractString

localex = deepcopy(ex)
for i in 1:length(localex.args)
if localex.args[i] == :VERSION
localex.args[i] = :_
end
end
l = eval(Main, Expr(:(->), :_, localex))
return (l, _ -> !(l(_)))
else
return (nothing,nothing)
end
end
elseif isexpr(ex, :comparison)
if in(:VERSION, ex.args)
for i = 1:2:length(ex.args)
a = ex.args[i]
Expand All @@ -63,7 +86,7 @@ function versionconstraint(ex)
localex = deepcopy(ex)
for i in 1:length(localex.args)
if localex.args[i] == :VERSION
localex.args[1] = :_
localex.args[i] = :_
end
end
l = eval(Main, Expr(:(->), :_, localex))
Expand Down Expand Up @@ -141,6 +164,9 @@ function lintboolean(ex, ctx::LintContext)
a = ex.args[i]
lintboolean(a, ctx)
end
elseif ex.head == :call && ex.args[1] in COMPARISON_OPS
#reuse lintcomparison by synthetically construct the expr
lintcomparison( Expr( :comparison, ex.args[2], ex.args[1], ex.args[3] ), ctx )
elseif ex.head == :comparison
lintcomparison(ex, ctx)
elseif ex.head == :call && ex.args[1] == :length
Expand Down Expand Up @@ -169,7 +195,7 @@ function lintcomparison(ex::Expr, ctx::LintContext)
lefttype = Any
righttype = Any
for i in 2:2:length(ex.args)
if ex.args[i] in [:(==), :(<), :(>), :(<=), :(>=), :(!=)]
if ex.args[i] in COMPARISON_OPS
if pos != i-1
pos = i-1
lefttype = guesstype(ex.args[i-1], ctx)
Expand Down

1 comment on commit 0a29c0d

@tonyhffong
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.