Skip to content

Commit

Permalink
Add quick fixes for E2 warnings and errors (#2871)
Browse files Browse the repository at this point in the history
* Add quick fixes for warnings

* Support for multiple changes, Error fixes

* Support multiple replacements
* Quick fix support for Error, although none currently implemented.
* Add (Quick fix available) at the end of a problem instead of changing icon. It's more clear and works for errors too.

* Parser, Preprocessor, Tokenizer support

* Preprocessor rewritten to use traces instead of mostly columns
* Quick fixes to convert `normal` -> `number` for preprocessor
* Quick fixes to convert non CamelCase variables to camelCase in preprocessor
* Parser supports quick fixes now
* Add warning for use of `normal` type in parser (this should really be handled in analyzer, though..)
* Add quick fix for normal use in parser
* Tokenizer supports quick fixes now
* Added invalid escape quick fix (deletes the \)
  • Loading branch information
Vurv78 authored Dec 9, 2023
1 parent 715f62a commit 33d3fac
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 89 deletions.
27 changes: 17 additions & 10 deletions lua/entities/gmod_wire_expression2/base/compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ end

---@param message string
---@param trace Trace
function Compiler:Error(message, trace)
error( Error.new(message, trace), 0)
---@param quick_fix { replace: string, at: Trace }[]?
function Compiler:Error(message, trace, quick_fix)
error( Error.new(message, trace, nil, quick_fix), 0)
end

---@generic T
Expand All @@ -152,12 +153,13 @@ end

---@param message string
---@param trace Trace
function Compiler:Warning(message, trace)
---@param quick_fix { replace: string, at: Trace }[]?
function Compiler:Warning(message, trace, quick_fix)
if self.include then
local tbl = self.warnings[self.include]
tbl[#tbl + 1] = Warning.new(message, trace)
tbl[#tbl + 1] = Warning.new(message, trace, quick_fix)
else
self.warnings[#self.warnings + 1] = Warning.new(message, trace)
self.warnings[#self.warnings + 1] = Warning.new(message, trace, quick_fix)
end
end

Expand Down Expand Up @@ -229,11 +231,11 @@ local CompileVisitors = {
stmts[i], traces[i] = stmt, trace

if node:isExpr() and node.variant ~= NodeVariant.ExprDynCall and node.variant ~= NodeVariant.ExprCall and node.variant ~= NodeVariant.ExprMethodCall then
self:Warning("This expression has no effect", node.trace)
self:Warning("This expression has no effect", node.trace, { { replace = "", at = node.trace } })
end
end
else
self:Warning("Unreachable code detected", node.trace)
self:Warning("Unreachable code detected", node.trace, { { replace = "", at = node.trace } })
break
end
end
Expand Down Expand Up @@ -608,7 +610,7 @@ local CompileVisitors = {
if err_ty then
self:Assert(err_ty.value == "string", "Error type can only be string, for now", err_ty.trace)
else
self:Warning("You should explicitly annotate the error type as :string", err_var.trace)
self:Warning("You should explicitly annotate the error type as :string", err_var.trace, { { replace = err_var.value .. ":string", at = err_var.trace } })
end

self:Scope(function (scope)
Expand Down Expand Up @@ -665,7 +667,7 @@ local CompileVisitors = {
self:Error("Variadic parameter requires explicit type", param.name.trace)
else
param_types[i] = "n"
self:Warning("Use of implicit parameter type is deprecated (add :number)", param.name.trace)
self:Warning("Use of implicit parameter type is deprecated (add :number)", param.name.trace, { { replace = param.name.value .. ":number", at = param.name.trace } })
end

if param.name.value ~= "_" and existing[param.name.value] then
Expand Down Expand Up @@ -1615,6 +1617,11 @@ local CompileVisitors = {
---@param data { [1]: Token<string>, [2]: Node[] }
[NodeVariant.ExprCall] = function (self, trace, data, used_as_stmt)
local name, args, types = data[1], {}, {}

if name.value == "changed" and data[2][1].variant == NodeVariant.ExprIdent and self.inputs[3][data[2][1].data.value] then
self:Warning("Use ~ instead of changed() for inputs", trace, { { replace = "~" .. data[2][1].data.value, at = trace } })
end

for k, arg in ipairs(data[2]) do
args[k], types[k] = self:CompileExpr(arg)
end
Expand Down Expand Up @@ -1903,7 +1910,7 @@ local CompileVisitors = {
for i, param in ipairs(data[2]) do
local type = param.type and self:CheckType(param.type)
if not type then
self:Warning("Use of implicit parameter type is deprecated (add :number)", param.name.trace)
self:Warning("Use of implicit parameter type is deprecated", param.name.trace, { { replace = param.name.value .. ":number", at = param.name.trace } })
type = "n"
end
params[i] = { param.name.value, type }
Expand Down
14 changes: 8 additions & 6 deletions lua/entities/gmod_wire_expression2/base/debug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ end
---@class Warning
---@field message string
---@field trace Trace
---@field quick_fix { replace: string, at: Trace }[]? # Replacements to be made for quick fix
local Warning = {}
Warning.__index = Warning

---@param message string
---@param trace Trace
---@return Warning
function Warning.new(message, trace)
return setmetatable({ message = message, trace = trace }, Warning)
---@param quick_fix { replace: string, at: Trace }[]? # Replacements for quick fix
function Warning.new(message, trace, quick_fix)
return setmetatable({ message = message, trace = trace, quick_fix = quick_fix }, Warning)
end

function Warning:debug()
Expand All @@ -64,15 +65,16 @@ Warning.__tostring = Warning.debug
---@field message string
---@field trace Trace
---@field userdata ErrorUserdata
---@field quick_fix { replace: string, at: Trace }[]? # Replacements to be made for quick fix
local Error = {}
Error.__index = Error

---@param message string
---@param trace Trace?
---@param userdata ErrorUserdata?
---@return Error
function Error.new(message, trace, userdata)
return setmetatable({ message = message, trace = trace, userdata = userdata }, Error)
---@param quick_fix { replace: string, at: Trace }[]? # Replacements to be made for quick fix
function Error.new(message, trace, userdata, quick_fix)
return setmetatable({ message = message, trace = trace, userdata = userdata, quick_fix = quick_fix }, Error)
end

function Error:debug()
Expand Down
11 changes: 7 additions & 4 deletions lua/entities/gmod_wire_expression2/base/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,16 @@ end

---@param message string
---@param trace Trace?
function Parser:Error(message, trace)
error( Error.new( message, trace or self:Prev().trace ), 2 )
---@param quick_fix { replace: string, at: Trace }[]?
function Parser:Error(message, trace, quick_fix)
error( Error.new( message, trace or self:Prev().trace, nil, quick_fix ), 2 )
end

---@param message string
---@param trace Trace?
function Parser:Warning(message, trace)
self.warnings[#self.warnings + 1] = Warning.new( message, trace or self:Prev().trace )
---@param quick_fix { replace: string, at: Trace }[]?
function Parser:Warning(message, trace, quick_fix)
self.warnings[#self.warnings + 1] = Warning.new( message, trace or self:Prev().trace, quick_fix )
end

---@generic T
Expand Down Expand Up @@ -542,6 +544,7 @@ function Parser:Type()
local type = self:Consume(TokenVariant.LowerIdent)
if type then
if type.value == "normal" then
self:Warning("Use of deprecated type [normal]", type.trace, { { at = type.trace, replace = "number" } })
type.value = "number"
end
else -- workaround to allow "function" as type while also being a keyword
Expand Down
Loading

0 comments on commit 33d3fac

Please sign in to comment.