-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Json format return message for lintserver() #194
Changes from 7 commits
4242143
6ca5e53
0c68068
ab52c79
8351265
f4440a6
1ccc0e9
39c50f5
a81d069
c5ce694
ddefddb
343f842
0222c9d
8e268fb
91dd2f0
175ab5c
f814b29
b4593be
78dfe6c
38ccf65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ module Lint | |
|
||
using Base.Meta | ||
using Compat | ||
using JSON | ||
|
||
export LintMessage, LintContext, LintStack | ||
export lintfile, lintstr, lintpkg, lintserver, @lintpragma | ||
|
@@ -340,7 +341,7 @@ function lintinclude(ctx::LintContext, file::AbstractString) | |
end | ||
|
||
""" | ||
Lint all *.jl files at a given directory. | ||
Lint all \*.jl files at a given directory. | ||
Will ignore LintContext file and already included files. | ||
""" | ||
function lintdir{T<:AbstractString}(dir::T, ctx::LintContext=LintContext()) | ||
|
@@ -355,34 +356,110 @@ function lintdir{T<:AbstractString}(dir::T, ctx::LintContext=LintContext()) | |
ctx.messages | ||
end | ||
|
||
function readandwritethestream(conn) | ||
# println("Connection accepted") | ||
# Get file, code length and code | ||
file = strip(readline(conn)) | ||
# println("file: ", file) | ||
code_len = parse(Int, strip(readline(conn))) | ||
# println("Code bytes: ", code_len) | ||
code = Compat.UTF8String(read(conn, code_len)) | ||
# println("Code received") | ||
# Do the linting | ||
msgs = lintfile(file, code) | ||
# Write response to socket | ||
for i in msgs | ||
write(conn, string(i)) | ||
function convertmsgtojson(msgs, style) | ||
if style == "lint-message" | ||
return JSON.json(msgs) | ||
end | ||
output = [] | ||
for msg in msgs | ||
evar = msg.variable | ||
txt = msg.message | ||
file = msg.file | ||
linenumber = msg.line | ||
# Atom index starts from zero thus minus one | ||
errorrange = Array[[linenumber-1, 0], [linenumber-1, 80]] | ||
code = string(msg.code) | ||
if code[1] == 'I' | ||
etype = "info" | ||
etypenumber = 3 | ||
elseif code[1] == 'W' | ||
etype = "warning" | ||
etypenumber = 2 | ||
else | ||
etype = "error" | ||
etypenumber = 1 | ||
end | ||
|
||
if style == "standard-linter-v1" | ||
push!(output, Dict("type" => etype, | ||
"text" => "$code $evar $txt", | ||
"range" => errorrange, | ||
"filePath" => file)) | ||
elseif style == "vscode" | ||
push!(output, Dict("severity" => etypenumber, | ||
"message" => "$evar $txt", | ||
"range" => errorrange, | ||
"filePath" => file, | ||
"code" => code, | ||
"source" => "Lint.jl")) | ||
elseif style == "standard-linter-v2" | ||
push!(output, Dict("severity" => etype, | ||
"location" => Dict("file" => file, | ||
"position" => errorrange), | ||
"excerpt" => code, | ||
"description" => "$evar $txt")) | ||
|
||
end | ||
end | ||
return JSON.json(output) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I think it might be better to just return the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this idea. I will make the changes. |
||
end | ||
|
||
|
||
function filtermsgs(msgs,dict_data) | ||
if haskey(dict_data,"ignore_warnings") | ||
if dict_data["ignore_warnings"] | ||
msgs = filter(i -> !iswarning(i), msgs) | ||
end | ||
end | ||
if haskey(dict_data,"ignore_info") | ||
if dict_data["ignore_info"] | ||
msgs = filter(i -> !isinfo(i), msgs) | ||
end | ||
end | ||
if haskey(dict_data,"ignore_codes") | ||
msgs = filter(i -> !(string(i.code) in dict_data["ignore_codes"]), msgs) | ||
end | ||
return msgs | ||
end | ||
|
||
|
||
function readandwritethestream(conn,style) | ||
if style == "original_behaviour" | ||
# println("Connection accepted") | ||
# Get file, code length and code | ||
file = strip(readline(conn)) | ||
# println("file: ", file) | ||
code_len = parse(Int, strip(readline(conn))) | ||
# println("Code bytes: ", code_len) | ||
code = Compat.UTF8String(read(conn, code_len)) | ||
# println("Code received") | ||
# Do the linting | ||
msgs = lintfile(file, code) | ||
# Write response to socket | ||
for i in msgs | ||
write(conn, string(i)) | ||
write(conn, "\n") | ||
end | ||
# Blank line to indicate end of messages | ||
write(conn, "\n") | ||
else | ||
json_data = readline(conn) | ||
dict_data = JSON.parse(json_data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe you can parse the connection directly; i.e. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, I really appreciate your effort to review and improve my code. |
||
msgs = lintfile(dict_data["file"], dict_data["code_str"]) | ||
msgs = filtermsgs(msgs,dict_data) | ||
out = convertmsgtojson(msgs,style) | ||
write(conn,out) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, we can do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this idea. I will make the changes. |
||
end | ||
# Blank line to indicate end of messages | ||
write(conn, "\n") | ||
end | ||
|
||
function lintserver(port) | ||
function lintserver(port,style="original_behaviour") | ||
server = listen(port) | ||
try | ||
println("Server running on port $port ...") | ||
println("Server running on port/pipe $port ...") | ||
while true | ||
conn = accept(server) | ||
@async try | ||
readandwritethestream(conn) | ||
readandwritethestream(conn,style) | ||
catch err | ||
println(STDERR, "connection ended with error $err") | ||
finally | ||
|
@@ -396,6 +473,7 @@ function lintserver(port) | |
end | ||
end | ||
|
||
|
||
# precompile hints | ||
include("precompile.jl") | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,33 @@ port = conn[1] | |
server = @async lintserver(port) | ||
sleep(1) #let server start | ||
|
||
function lintbyserver(socket,str) | ||
println(socket, "none") | ||
println(socket, sizeof(str)) # bytes of code | ||
println(socket, str) # code | ||
end | ||
|
||
function readfromserver_old(socket) | ||
response = "" | ||
line = "" | ||
while line != "\n" | ||
response *= line | ||
line = readline(socket) | ||
end | ||
return response | ||
end | ||
|
||
function readfromserver_new(socket) | ||
response = "" | ||
line = "" | ||
while isopen(socket) | ||
response *= line | ||
line = readline(socket) | ||
end | ||
return response | ||
end | ||
|
||
|
||
@testset "lintserver() tests" begin | ||
conn = connect(port) | ||
write(conn, "empty\n") | ||
|
@@ -24,41 +51,130 @@ sleep(1) #let server start | |
end | ||
|
||
@testset "Testing the lintserver addition" begin | ||
function lintbyserver(socket) | ||
str = """ | ||
test = "Hello" + "World" | ||
""" | ||
println(socket, "none") | ||
println(socket, sizeof(str)) # bytes of code | ||
println(socket, str) # code | ||
end | ||
|
||
str = """ | ||
test = "Hello" + "World" | ||
""" | ||
socket = connect(port) | ||
lintbyserver(socket) | ||
response = "" | ||
line = "" | ||
while line != "\n" | ||
response *= line | ||
line = readline(socket) | ||
end | ||
|
||
lintbyserver(socket,str) | ||
response = readfromserver_old(socket) | ||
@test response == "none:1 E422 : string uses * to concatenate\n" | ||
|
||
socket = connect(port) | ||
lintbyserver(socket) | ||
res = "" | ||
line = "" | ||
while isopen(socket) | ||
res *= line | ||
line = readline(socket) | ||
end | ||
|
||
lintbyserver(socket,str) | ||
res = readfromserver_new(socket) | ||
@test res == "none:1 E422 : string uses * to concatenate\n\n" | ||
end | ||
|
||
# This isn't working on the nightly build. Ideally we explicitly stop the server process (as | ||
# it loops forever). It seems to get stopped when the tests end, so it's not necessary. | ||
# | ||
#try # close the server | ||
# Base.throwto(server, InterruptException()) | ||
#end | ||
@testset "Testing lintserver() with named pipe and JSON format" begin | ||
if is_windows() | ||
pipe = "\\\\.\\pipe\\testsocket" | ||
pipe2 = "\\\\.\\pipe\\testsocket2" | ||
pipe3 = "\\\\.\\pipe\\testsocket3" | ||
pipe4 = "\\\\.\\pipe\\testsocket4" | ||
else | ||
pipe = tempname() | ||
pipe2 = tempname() | ||
pipe3 = tempname() | ||
pipe4 = tempname() | ||
end | ||
server_LintMessage = @async lintserver(pipe,"lint-message") | ||
sleep(1) | ||
socket = connect(pipe) | ||
json_input = JSON.json(Dict("file" => "none", "code_str" => "something")) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["line"] == 1 | ||
@test results_array[1]["message"] == "use of undeclared symbol" | ||
@test results_array[1]["file"] == "none" | ||
@test results_array[1]["code"] == "E321" | ||
|
||
server_slv1 = @async lintserver(pipe2,"standard-linter-v1") | ||
sleep(1) | ||
socket = connect(pipe2) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["text"] == "E321 something use of undeclared symbol" | ||
@test results_array[1]["filePath"] == "none" | ||
@test results_array[1]["range"] == Array[[0, 0], [0, 80]] | ||
@test results_array[1]["type"] == "error" | ||
|
||
|
||
socket = connect(pipe2) | ||
json_input2 = JSON.json(Dict("file" => "none", | ||
"code_str" => "pi=3")) | ||
write(socket, json_input2 * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["text"] == "W351 pi redefining mathematical constant" | ||
@test results_array[1]["filePath"] == "none" | ||
@test results_array[1]["range"] == Array[[0, 0], [0, 80]] | ||
@test results_array[1]["type"] == "warning" | ||
|
||
socket = connect(pipe2) | ||
json_input3 = JSON.json(Dict("file" => "none", | ||
"code_str" => "function a(b)\nend")) | ||
write(socket, json_input3 * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["text"] == "I382 b argument declared but not used" | ||
@test results_array[1]["filePath"] == "none" | ||
@test results_array[1]["range"] == Array[[0, 0], [0, 80]] | ||
@test results_array[1]["type"] == "info" | ||
|
||
|
||
server_vscode = @async lintserver(pipe3,"vscode") | ||
sleep(1) | ||
socket = connect(pipe3) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["message"] == "something use of undeclared symbol" | ||
@test results_array[1]["filePath"] == "none" | ||
@test results_array[1]["range"] == Array[[0, 0], [0, 80]] | ||
@test results_array[1]["code"] == "E321" | ||
@test results_array[1]["severity"] == 1 | ||
@test results_array[1]["source"] == "Lint.jl" | ||
|
||
|
||
server_slv2 = @async lintserver(pipe4,"standard-linter-v2") | ||
sleep(1) | ||
socket = connect(pipe4) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test results_array[1]["description"] == "something use of undeclared symbol" | ||
@test results_array[1]["location"]["file"] == "none" | ||
@test results_array[1]["location"]["position"] == Array[[0, 0], [0, 80]] | ||
@test results_array[1]["severity"] == "error" | ||
@test results_array[1]["excerpt"] == "E321" | ||
|
||
|
||
json_input = JSON.json(Dict("file" => "none", | ||
"code_str" => "function a(b)\nend", | ||
"ignore_info" => true)) | ||
socket = connect(pipe) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test isempty(results_array) | ||
|
||
json_input = JSON.json(Dict("file" => "none", | ||
"code_str" => "pi = 1", | ||
"ignore_warnings" => true)) | ||
socket = connect(pipe) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't need to strip json, here and elsewhere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, I forgot this one. |
||
@test isempty(results_array) | ||
|
||
json_input = JSON.json(Dict("file" => "none", | ||
"code_str" => "pi = 1\nfunction a(b)\nend", | ||
"ignore_codes" => ["I382","W351"])) | ||
socket = connect(pipe) | ||
write(socket, json_input * "\n") | ||
json_output = readline(socket) | ||
results_array = JSON.parse(strip(json_output)) | ||
@test isempty(results_array) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you're escaping the markdown here, but I don't think this works. Need two backslashes, that is
\\*
, because\*
is the same as*
in a string.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I forgot it here. This is atom-language-julia bug of syntax highlighting. I just use the backslash to show the rest of the file highlighting properly.