Skip to content

Commit

Permalink
Format files using DocumentFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
davidanthoff authored Oct 14, 2022
1 parent b3b804a commit 47b9dfa
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 265 deletions.
6 changes: 3 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ makedocs(;
repo="https://github.com/julia-vscode/StaticLint.jl/blob/{commit}{path}#L{line}",
sitename="StaticLint.jl",
format=Documenter.HTML(;
prettyurls=prettyurls = get(ENV, "CI", nothing) == "true",
prettyurls=prettyurls = get(ENV, "CI", nothing) == "true"
# canonical="https://www.julia-vscode.org/StaticLint.jl",
# assets=String[],
),
pages=[
"Home" => "index.md",
"Syntax Reference" => "syntax.md",
],
]
)

deploydocs(;
repo="github.com/julia-vscode/StaticLint.jl",
repo="github.com/julia-vscode/StaticLint.jl"
)
8 changes: 4 additions & 4 deletions src/StaticLint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ Meta() = Meta(nothing, nothing, nothing, nothing)

function Base.show(io::IO, m::Meta)
m.binding !== nothing && show(io, m.binding)
m.ref !== nothing && printstyled(io, " * ", color = :red)
m.scope !== nothing && printstyled(io, " new scope", color = :green)
m.error !== nothing && printstyled(io, " lint ", color = :red)
m.ref !== nothing && printstyled(io, " * ", color=:red)
m.scope !== nothing && printstyled(io, " new scope", color=:green)
m.error !== nothing && printstyled(io, " lint ", color=:red)
end
hasmeta(x::EXPR) = x.meta isa Meta
hasbinding(m::Meta) = m.binding isa Binding
Expand Down Expand Up @@ -166,7 +166,7 @@ end
Performs a semantic pass across a project from the entry point `file`. A first pass traverses the top-level scope after which secondary passes handle delayed scopes (e.g. functions). These secondary passes can be, optionally, very light and only seek to resovle references (e.g. link symbols to bindings). This can be done by supplying a list of expressions on which the full secondary pass should be made (`modified_expr`), all others will receive the light-touch version.
"""
function semantic_pass(file, modified_expr = nothing)
function semantic_pass(file, modified_expr=nothing)
server = file.server
env = getenv(file, server)
setscope!(getcst(file), Scope(nothing, getcst(file), Dict(), Dict{Symbol,Any}(:Base => env.symbols[:Base], :Core => env.symbols[:Core]), nothing))
Expand Down
4 changes: 2 additions & 2 deletions src/bindings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ function mark_binding!(x::EXPR, val=x)
return x
end

function mark_parameters(sig::EXPR, params = String[])
function mark_parameters(sig::EXPR, params=String[])
if CSTParser.issubtypedecl(sig)
mark_parameters(sig.args[1], params)
elseif iswhere(sig)
Expand Down Expand Up @@ -365,7 +365,7 @@ function add_binding(x, state, scope=state.scope)
end

function enforce_hard_scope(x::EXPR, scope)
scope.expr.head === :for && is_in_fexpr(x, x-> x == scope.expr.args[1])
scope.expr.head === :for && is_in_fexpr(x, x -> x == scope.expr.args[1])
end

name_is_getfield(x) = parentof(x) isa EXPR && parentof(parentof(x)) isa EXPR && CSTParser.is_getfield_w_quotenode(parentof(parentof(x)))
Expand Down
2 changes: 1 addition & 1 deletion src/coretypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ isva(x::SymbolServer.FakeUnionAll) = isva(x.body)
@static if Core.Vararg isa Core.Type
function isva(x)
return (x isa SymbolServer.FakeTypeName && x.name.name == :Vararg &&
x.name.parent isa SymbolServer.VarRef && x.name.parent.name == :Core)
x.name.parent isa SymbolServer.VarRef && x.name.parent.name == :Core)
end
else
isva(x) = x isa SymbolServer.FakeTypeofVararg
Expand Down
2 changes: 1 addition & 1 deletion src/exception_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ end

function Base.showerror(io::IO, ex::SLInvalidPath)
print(io, ex.msg)
end
end
14 changes: 7 additions & 7 deletions src/imports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ end

function has_workspace_package(server, name)
haskey(server.workspacepackages, name) &&
hasscope(getcst(server.workspacepackages[name])) &&
haskey(scopeof(getcst(server.workspacepackages[name])).names, name) &&
scopeof(getcst(server.workspacepackages[name])).names[name] isa Binding &&
scopeof(getcst(server.workspacepackages[name])).names[name].val isa EXPR &&
CSTParser.defines_module(scopeof(getcst(server.workspacepackages[name])).names[name].val)
hasscope(getcst(server.workspacepackages[name])) &&
haskey(scopeof(getcst(server.workspacepackages[name])).names, name) &&
scopeof(getcst(server.workspacepackages[name])).names[name] isa Binding &&
scopeof(getcst(server.workspacepackages[name])).names[name].val isa EXPR &&
CSTParser.defines_module(scopeof(getcst(server.workspacepackages[name])).names[name].val)
end

function add_to_imported_modules(scope::Scope, name::Symbol, val)
Expand Down Expand Up @@ -121,8 +121,8 @@ function _get_field(par, arg, state)
if par isa SymbolServer.EnvStore
if (arg_scope = retrieve_scope(arg)) !== nothing && (tlm = get_named_toplevel_module(arg_scope, arg_str_rep)) !== nothing && hasbinding(tlm)
return bindingof(tlm)
# elseif has_workspace_package(state.server, arg_str_rep)
# return scopeof(getcst(state.server.workspacepackages[arg_str_rep])).names[arg_str_rep]
# elseif has_workspace_package(state.server, arg_str_rep)
# return scopeof(getcst(state.server.workspacepackages[arg_str_rep])).names[arg_str_rep]
elseif haskey(par, Symbol(arg_str_rep))
if isempty(state.env.project_deps) || Symbol(arg_str_rep) in state.env.project_deps
return par[Symbol(arg_str_rep)]
Expand Down
10 changes: 5 additions & 5 deletions src/interface.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
function setup_server(env = dirname(SymbolServer.Pkg.Types.Context().env.project_file), depot = first(SymbolServer.Pkg.depots()), cache = joinpath(dirname(pathof(SymbolServer)), "..", "store"))
function setup_server(env=dirname(SymbolServer.Pkg.Types.Context().env.project_file), depot=first(SymbolServer.Pkg.depots()), cache=joinpath(dirname(pathof(SymbolServer)), "..", "store"))
server = StaticLint.FileServer()
ssi = SymbolServerInstance(depot, cache)
_, server.symbolserver = SymbolServer.getstore(ssi, env)
server.symbol_extends = SymbolServer.collect_extended_methods(server.symbolserver)
server.symbol_extends = SymbolServer.collect_extended_methods(server.symbolserver)
server
end

Expand All @@ -13,7 +13,7 @@ Parse a string and run a semantic pass over it. This will mark scopes, bindings,
references, and lint hints. An annotated `EXPR` is returned or, if `gethints = true`,
it is paired with a collected list of errors/hints.
"""
function lint_string(s::String, server = setup_server(); gethints = false)
function lint_string(s::String, server=setup_server(); gethints=false)
empty!(server.files)
f = File("", s, CSTParser.parse(s, true), nothing, server)
env = getenv(f, server)
Expand All @@ -37,7 +37,7 @@ in the project will be loaded automatically (calls to `include` with complicated
are not handled, see `followinclude` for details). A `FileServer` will be returned
containing the `File`s of the package.
"""
function lint_file(rootpath, server = setup_server(); gethints = false)
function lint_file(rootpath, server=setup_server(); gethints=false)
empty!(server.files)
root = loadfile(server, rootpath)
semantic_pass(root)
Expand All @@ -46,7 +46,7 @@ function lint_file(rootpath, server = setup_server(); gethints = false)
end
if gethints
hints = []
for (p,f) in server.files
for (p, f) in server.files
append!(hints, [(x, string(haserror(x) ? LintCodeDescriptions[x.meta.error] : "Missing reference", " at offset ", offset, " of ", p)) for (offset, x) in collect_hints(f.cst, getenv(f, server))])
end
return root, hints
Expand Down
84 changes: 41 additions & 43 deletions src/linting/checks.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
@enum(
LintCodes,

MissingRef,
LintCodes, MissingRef,
IncorrectCallArgs,
IncorrectIterSpec,
NothingEquality,
Expand Down Expand Up @@ -177,9 +175,9 @@ function func_nargs(x::EXPR)
maxargs !== typemax(Int) && (maxargs += 1)
end
elseif issplat(arg) ||
(isdeclaration(arg) &&
((isidentifier(arg.args[2]) && valofid(arg.args[2]) == "Vararg") ||
(iscurly(arg.args[2]) && isidentifier(arg.args[2].args[1]) && valofid(arg.args[2].args[1]) == "Vararg")))
(isdeclaration(arg) &&
((isidentifier(arg.args[2]) && valofid(arg.args[2]) == "Vararg") ||
(iscurly(arg.args[2]) && isidentifier(arg.args[2].args[1]) && valofid(arg.args[2].args[1]) == "Vararg")))
maxargs = typemax(Int)
else
minargs += 1
Expand Down Expand Up @@ -243,9 +241,9 @@ end
# compare_f_call(m_counts, call_counts) = true # fallback method

function compare_f_call(
(ref_minargs, ref_maxargs, ref_kws, kwsplat),
(act_minargs, act_maxargs, act_kws),
)
(ref_minargs, ref_maxargs, ref_kws, kwsplat),
(act_minargs, act_maxargs, act_kws),
)
# check matching on positional arguments
if act_maxargs == typemax(Int)
act_minargs <= act_maxargs < ref_minargs && return false
Expand All @@ -265,10 +263,10 @@ end

function is_something_with_methods(x::Binding)
(CoreTypes.isfunction(x.type) && x.val isa EXPR) ||
(CoreTypes.isdatatype(x.type) && x.val isa EXPR && CSTParser.defines_struct(x.val)) ||
(x.val isa SymbolServer.FunctionStore || x.val isa SymbolServer.DataTypeStore)
(CoreTypes.isdatatype(x.type) && x.val isa EXPR && CSTParser.defines_struct(x.val)) ||
(x.val isa SymbolServer.FunctionStore || x.val isa SymbolServer.DataTypeStore)
end
is_something_with_methods(x::T) where T <: Union{SymbolServer.FunctionStore,SymbolServer.DataTypeStore} = true
is_something_with_methods(x::T) where T<:Union{SymbolServer.FunctionStore,SymbolServer.DataTypeStore} = true
is_something_with_methods(x) = false

function check_call(x, env::ExternalEnv)
Expand Down Expand Up @@ -372,13 +370,13 @@ function check_incorrect_iter_spec(x, body, env)
if headof(rng) === :FLOAT || headof(rng) === :INTEGER || (iscall(rng) && refof(rng.args[1]) === getsymbols(env)[:Base][:length])
seterror!(x, IncorrectIterSpec)
elseif iscall(rng) && valof(rng.args[1]) == ":" &&
length(rng.args) === 3 &&
headof(rng.args[2]) === :INTEGER &&
iscall(rng.args[3]) &&
length(rng.args[3].args) > 1 && (
refof(rng.args[3].args[1]) === getsymbols(env)[:Base][:length] ||
refof(rng.args[3].args[1]) === getsymbols(env)[:Base][:size]
)
length(rng.args) === 3 &&
headof(rng.args[2]) === :INTEGER &&
iscall(rng.args[3]) &&
length(rng.args[3].args) > 1 && (
refof(rng.args[3].args[1]) === getsymbols(env)[:Base][:length] ||
refof(rng.args[3].args[1]) === getsymbols(env)[:Base][:size]
)
if length(x.args) >= 1
lhs = x.args[1]
arr = rng.args[3].args[2]
Expand Down Expand Up @@ -421,14 +419,14 @@ end
function check_nothing_equality(x::EXPR, env::ExternalEnv)
if isbinarycall(x) && length(x.args) == 3
if valof(x.args[1]) == "==" && (
(valof(x.args[2]) == "nothing" && refof(x.args[2]) === getsymbols(env)[:Core][:nothing]) ||
(valof(x.args[3]) == "nothing" && refof(x.args[3]) === getsymbols(env)[:Core][:nothing])
)
(valof(x.args[2]) == "nothing" && refof(x.args[2]) === getsymbols(env)[:Core][:nothing]) ||
(valof(x.args[3]) == "nothing" && refof(x.args[3]) === getsymbols(env)[:Core][:nothing])
)
seterror!(x.args[1], NothingEquality)
elseif valof(x.args[1]) == "!=" && (
(valof(x.args[2]) == "nothing" && refof(x.args[2]) === getsymbols(env)[:Core][:nothing]) ||
(valof(x.args[3]) == "nothing" && refof(x.args[3]) === getsymbols(env)[:Core][:nothing])
)
(valof(x.args[2]) == "nothing" && refof(x.args[2]) === getsymbols(env)[:Core][:nothing]) ||
(valof(x.args[3]) == "nothing" && refof(x.args[3]) === getsymbols(env)[:Core][:nothing])
)
seterror!(x.args[1], NothingNotEq)
end
end
Expand Down Expand Up @@ -520,9 +518,9 @@ end

function check_modulename(x::EXPR)
if CSTParser.defines_module(x) && # x is a module
scopeof(x) isa Scope && parentof(scopeof(x)) isa Scope && # it has a scope and a parent scope
CSTParser.defines_module(parentof(scopeof(x)).expr) && # the parent scope is a module
valof(CSTParser.get_name(x)) == valof(CSTParser.get_name(parentof(scopeof(x)).expr)) # their names match
scopeof(x) isa Scope && parentof(scopeof(x)) isa Scope && # it has a scope and a parent scope
CSTParser.defines_module(parentof(scopeof(x)).expr) && # the parent scope is a module
valof(CSTParser.get_name(x)) == valof(CSTParser.get_name(parentof(scopeof(x)).expr)) # their names match
seterror!(CSTParser.get_name(x), InvalidModuleName)
end
end
Expand All @@ -532,7 +530,7 @@ function check_farg_unused(x::EXPR)
if CSTParser.defines_function(x)
sig = CSTParser.rem_wheres_decls(CSTParser.get_sig(x))
if (headof(x) === :function && length(x.args) == 2 && x.args[2] isa EXPR && length(x.args[2].args) == 1 && CSTParser.isliteral(x.args[2].args[1])) ||
(length(x.args) > 1 && headof(x.args[2]) === :block && length(x.args[2].args) == 1 && CSTParser.isliteral(x.args[2].args[1]))
(length(x.args) > 1 && headof(x.args[2]) === :block && length(x.args[2].args) == 1 && CSTParser.isliteral(x.args[2].args[1]))
return # Allow functions that return constants
end
if iscall(sig)
Expand Down Expand Up @@ -566,12 +564,12 @@ function check_farg_unused_(arg, arg_names)
valof(b.name) isa String && all_underscore(valof(b.name)) && return false

if b === nothing ||
# no refs:
# no refs:
isempty(b.refs) ||
# only self ref:
# only self ref:
(length(b.refs) == 1 && first(b.refs) == b.name) ||
# first usage has binding:
(length(b.refs) > 1 && b.refs[2] isa EXPR && hasbinding(b.refs[2]))
# first usage has binding:
(length(b.refs) > 1 && b.refs[2] isa EXPR && hasbinding(b.refs[2]))
seterror!(arg, UnusedFunctionArgument)
end

Expand All @@ -591,8 +589,8 @@ end

function is_nospecialize_call(x)
CSTParser.ismacrocall(x) &&
CSTParser.ismacroname(x.args[1]) &&
is_nospecialize(x.args[1])
CSTParser.ismacroname(x.args[1]) &&
is_nospecialize(x.args[1])
end

"""
Expand All @@ -612,8 +610,8 @@ function collect_hints(x::EXPR, env, missingrefs=:all, isquoted=false, errs=Tupl
push!(errs, (pos, x))
elseif !isquoted
if missingrefs != :none && isidentifier(x) && !hasref(x) &&
!(valof(x) == "var" && parentof(x) isa EXPR && isnonstdid(parentof(x))) &&
!((valof(x) == "stdcall" || valof(x) == "cdecl" || valof(x) == "fastcall" || valof(x) == "thiscall" || valof(x) == "llvmcall") && is_in_fexpr(x, x -> iscall(x) && isidentifier(x.args[1]) && valof(x.args[1]) == "ccall"))
!(valof(x) == "var" && parentof(x) isa EXPR && isnonstdid(parentof(x))) &&
!((valof(x) == "stdcall" || valof(x) == "cdecl" || valof(x) == "fastcall" || valof(x) == "thiscall" || valof(x) == "llvmcall") && is_in_fexpr(x, x -> iscall(x) && isidentifier(x.args[1]) && valof(x.args[1]) == "ccall"))

push!(errs, (pos, x))
elseif haserror(x) && errorof(x) isa StaticLint.LintCodes
Expand Down Expand Up @@ -642,7 +640,7 @@ end

function should_mark_missing_getfield_ref(x, env)
if isidentifier(x) && !hasref(x) && # x has no ref
parentof(x) isa EXPR && headof(parentof(x)) === :quotenode && parentof(parentof(x)) isa EXPR && is_getfield(parentof(parentof(x))) # x is the rhs of a getproperty
parentof(x) isa EXPR && headof(parentof(x)) === :quotenode && parentof(parentof(x)) isa EXPR && is_getfield(parentof(parentof(x))) # x is the rhs of a getproperty
lhsref = refof_maybe_getfield(parentof(parentof(x)).args[1])
hasref(x) && return false # We've resolved
if lhsref isa SymbolServer.ModuleStore || (lhsref isa Binding && lhsref.val isa SymbolServer.ModuleStore)
Expand Down Expand Up @@ -711,14 +709,14 @@ function is_type_of_call_to_getproperty(x::EXPR)
if iscall(x)
func_name = x.args[1]
return (isidentifier(func_name) && valof(func_name) == "getproperty") || # getproperty()
(is_getfield_w_quotenode(func_name) && isidentifier(func_name.args[2].args[1]) && valof(func_name.args[2].args[1]) == "getproperty") # Base.getproperty()
(is_getfield_w_quotenode(func_name) && isidentifier(func_name.args[2].args[1]) && valof(func_name.args[2].args[1]) == "getproperty") # Base.getproperty()
end
return false
end

return parentof(x) isa EXPR && parentof(parentof(x)) isa EXPR &&
((isdeclaration(parentof(x)) && x === parentof(x).args[2] && is_call_to_getproperty(parentof(parentof(x)))) ||
(iscurly(parentof(x)) && x === parentof(x).args[1] && isdeclaration(parentof(parentof(x))) && parentof(parentof(parentof(x))) isa EXPR && is_call_to_getproperty(parentof(parentof(parentof(x))))))
((isdeclaration(parentof(x)) && x === parentof(x).args[2] && is_call_to_getproperty(parentof(parentof(x)))) ||
(iscurly(parentof(x)) && x === parentof(x).args[1] && isdeclaration(parentof(parentof(x))) && parentof(parentof(parentof(x))) isa EXPR && is_call_to_getproperty(parentof(parentof(parentof(x))))))
end

isunionfaketype(t::SymbolServer.FakeTypeName) = t.name.name === :Union && t.name.parent isa SymbolServer.VarRef && t.name.parent.name === :Core
Expand Down Expand Up @@ -951,8 +949,8 @@ function check_unused_binding(b::Binding, scope::Scope)
if headof(scope.expr) !== :struct && headof(scope.expr) !== :tuple && !all_underscore(valof(b.name))
refs = loose_refs(b)
if (isempty(refs) || length(refs) == 1 && refs[1] == b.name) &&
!is_sig_arg(b.name) && !is_overwritten_in_loop(b.name) &&
!is_overwritten_subsequently(b, scope) && !is_kw_of_macrocall(b)
!is_sig_arg(b.name) && !is_overwritten_in_loop(b.name) &&
!is_overwritten_subsequently(b, scope) && !is_kw_of_macrocall(b)
seterror!(b.name, UnusedBinding)
end
end
Expand Down
Loading

0 comments on commit 47b9dfa

Please sign in to comment.