Skip to content
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

Run some filters in diagnostics #11220

Merged
merged 12 commits into from
Nov 21, 2023
12 changes: 8 additions & 4 deletions src/compiler/compiler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ let finalize_typing ctx tctx =
com.modules <- modules;
t()

let filter ctx tctx =
let filter ctx tctx before_destruction =
let t = Timer.timer ["filters"] in
DeprecationCheck.run ctx.com;
Filters.run tctx ctx.com.main;
run_or_diagnose ctx Filters.run tctx ctx.com.main before_destruction;
t()

let compile ctx actx callbacks =
Expand Down Expand Up @@ -363,8 +363,12 @@ let compile ctx actx callbacks =
let (tctx,display_file_dot_path) = do_type ctx mctx actx display_file_dot_path macro_cache_enabled in
DisplayProcessing.handle_display_after_typing ctx tctx display_file_dot_path;
finalize_typing ctx tctx;
DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path;
filter ctx tctx;
if is_diagnostics com then
filter ctx tctx (fun () -> DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path)
else begin
DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path;
filter ctx tctx (fun () -> ());
end;
if ctx.has_error then raise Abort;
Generate.check_auxiliary_output com actx;
enter_stage com CGenerationStart;
Expand Down
45 changes: 20 additions & 25 deletions src/context/display/diagnostics.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let find_unused_variables com e =
let vars = Hashtbl.create 0 in
let pmin_map = Hashtbl.create 0 in
let rec loop e = match e.eexpr with
| TVar({v_kind = VUser _} as v,eo) when v.v_name <> "_" ->
| TVar({v_kind = VUser _} as v,eo) when v.v_name <> "_" && not (has_var_flag v VUsedByTyper) ->
Hashtbl.add pmin_map e.epos.pmin v;
let p = match eo with
| None -> e.epos
Expand Down Expand Up @@ -44,18 +44,18 @@ let check_other_things com e =
let pointless_compound s p =
add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DKCompilerMessage Warning;
in
let rec compound compiler_generated s el p =
let rec compound s el p =
let old = !had_effect in
had_effect := false;
List.iter (loop true compiler_generated) el;
if not !had_effect then no_effect p else if not compiler_generated then pointless_compound s p;
List.iter (loop true) el;
if not !had_effect then no_effect p else pointless_compound s p;
had_effect := old;
and loop in_value compiler_generated e = match e.eexpr with
and loop in_value e = match e.eexpr with
| TBlock el ->
let rec loop2 el = match el with
| [] -> ()
| [e] -> loop in_value compiler_generated e
| e :: el -> loop false compiler_generated e; loop2 el
| [e] -> loop in_value e
| e :: el -> loop false e; loop2 el
in
loop2 el
| TMeta((Meta.Extern,_,_),_) ->
Expand All @@ -67,29 +67,27 @@ let check_other_things com e =
()
| TField (_, fa) when PurityState.is_explicitly_impure fa -> ()
| TFunction tf ->
loop false compiler_generated tf.tf_expr
| TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound compiler_generated "call" el e.epos
loop false tf.tf_expr
| TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound "call" el e.epos
| TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_)
| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _)
| TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ ->
had_effect := true;
Type.iter (loop true compiler_generated) e
| TMeta((Meta.CompilerGenerated,_,_),e1) ->
loop in_value true e1
Type.iter (loop true) e
| TParenthesis e1 | TMeta(_,e1) ->
loop in_value compiler_generated e1
loop in_value e1
| TArray _ | TCast (_,None) | TBinop _ | TUnop _
| TField _ | TArrayDecl _ | TObjectDecl _ when in_value ->
Type.iter (loop true compiler_generated) e;
| TArray(e1,e2) -> compound compiler_generated "array access" [e1;e2] e.epos
| TCast(e1,None) -> compound compiler_generated "cast" [e1] e.epos
| TBinop(op,e1,e2) -> compound compiler_generated (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos
| TUnop(op,_,e1) -> compound compiler_generated (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos
| TField(e1,_) -> compound compiler_generated "field access" [e1] e.epos
| TArrayDecl el -> compound compiler_generated "array declaration" el e.epos
| TObjectDecl fl -> compound compiler_generated "object declaration" (List.map snd fl) e.epos
Type.iter (loop true) e;
| TArray(e1,e2) -> compound "array access" [e1;e2] e.epos
| TCast(e1,None) -> compound "cast" [e1] e.epos
| TBinop(op,e1,e2) -> compound (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos
| TUnop(op,_,e1) -> compound (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos
| TField(e1,_) -> compound "field access" [e1] e.epos
| TArrayDecl el -> compound "array declaration" el e.epos
| TObjectDecl fl -> compound "object declaration" (List.map snd fl) e.epos
in
loop true false e
loop true e

let prepare_field dctx dectx com cf = match cf.cf_expr with
| None -> ()
Expand Down Expand Up @@ -177,9 +175,6 @@ let prepare com =
dctx.unresolved_identifiers <- com.display_information.unresolved_identifiers;
dctx

let secure_generated_code ctx e =
if is_diagnostics ctx then mk (TMeta((Meta.CompilerGenerated,[],e.epos),e)) e.etype e.epos else e

let print com =
let dctx = prepare com in
Json.string_of_json (DiagnosticsPrinter.json_of_diagnostics com dctx)
Expand Down
1 change: 0 additions & 1 deletion src/core/displayTypes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ module DisplayMode = struct
| DMDefault | DMDefinition | DMTypeDefinition | DMPackage | DMHover | DMSignature -> settings
| DMUsage _ | DMImplementation -> { settings with
dms_full_typing = true;
dms_populate_cache = !ServerConfig.populate_cache_from_display;
dms_force_macro_typing = true;
dms_display_file_policy = DFPAlso;
dms_exit_during_typing = false
Expand Down
5 changes: 3 additions & 2 deletions src/core/tType.ml
Original file line number Diff line number Diff line change
Expand Up @@ -467,11 +467,12 @@ let flag_tclass_field_names = [
type flag_tvar =
| VCaptured
| VFinal
| VUsed (* used by the analyzer *)
| VAnalyzed
| VAssigned
| VCaught
| VStatic
| VUsedByTyper (* Set if the typer looked up this variable *)

let flag_tvar_names = [
"VCaptured";"VFinal";"VUsed";"VAssigned";"VCaught";"VStatic"
"VCaptured";"VFinal";"VAnalyzed";"VAssigned";"VCaught";"VStatic";"VUsedByTyper"
]
3 changes: 2 additions & 1 deletion src/filters/filters.ml
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ let save_class_state com t =
a.a_meta <- List.filter (fun (m,_,_) -> m <> Meta.ValueUsed) a.a_meta
)

let run tctx main =
let run tctx main before_destruction =
let com = tctx.com in
let detail_times = (try int_of_string (Common.defined_value_safe com ~default:"0" Define.FilterTimes) with _ -> 0) in
let new_types = List.filter (fun t ->
Expand Down Expand Up @@ -1022,4 +1022,5 @@ let run tctx main =
with_timer detail_times "callbacks" None (fun () ->
com.callbacks#run com.error_ext com.callbacks#get_after_save;
);
before_destruction();
destruction tctx detail_times main locals
6 changes: 3 additions & 3 deletions src/optimization/analyzer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -661,22 +661,22 @@ module LocalDce = struct

let apply ctx =
let is_used v =
has_var_flag v VUsed
has_var_flag v VAnalyzed
in
let keep v =
is_used v || ((match v.v_kind with VUser _ | VInlined -> true | _ -> false) && not ctx.config.local_dce) || ExtType.has_reference_semantics v.v_type || has_var_flag v VCaptured || Meta.has Meta.This v.v_meta
in
let rec use v =
if not (is_used v) then begin
add_var_flag v VUsed;
add_var_flag v VAnalyzed;
(try expr (get_var_value ctx.graph v) with Not_found -> ());
begin match Ssa.get_reaching_def ctx.graph v with
| None ->
(* We don't want to fully recurse for the origin variable because we don't care about its
reaching definition (issue #10972). Simply marking it as being used should be sufficient. *)
let v' = get_var_origin ctx.graph v in
if not (is_used v') then
add_var_flag v' VUsed
add_var_flag v' VAnalyzed
| Some v ->
use v;
end
Expand Down
1 change: 0 additions & 1 deletion src/optimization/inline.ml
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ class inline_state ctx ethis params cf f p = object(self)
mk (TBlock (DynArray.to_list el)) tret e.epos
in
let e = inline_metadata e cf.cf_meta in
let e = Diagnostics.secure_generated_code ctx.com e in
if has_params then begin
let mt = map_type cf.cf_type in
let unify_func () = unify_raise mt (TFun (tl,tret)) p in
Expand Down
2 changes: 0 additions & 2 deletions src/optimization/optimizer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,6 @@ let reduce_expr com e =
) l with
| [] -> ec
| l -> { e with eexpr = TBlock (List.rev (ec :: l)) })
| TMeta ((Meta.CompilerGenerated,_,_),ec) ->
{ ec with epos = e.epos }
| TParenthesis ec ->
{ ec with epos = e.epos }
| TTry (e,[]) ->
Expand Down
1 change: 0 additions & 1 deletion src/typing/callUnification.ml
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ object(self)
!ethis_f();
raise exc
in
let e = Diagnostics.secure_generated_code ctx.com e in
ctx.com.error_ext <- old;
!ethis_f();
e
Expand Down
4 changes: 1 addition & 3 deletions src/typing/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,14 @@ module BinopResult = struct
| BinopSpecial(_,needs_assign) -> needs_assign
end

let rec check_assign ctx e =
let check_assign ctx e =
match e.eexpr with
| TLocal v when has_var_flag v VFinal && not (Common.ignore_error ctx.com) ->
raise_typing_error "Cannot assign to final" e.epos
| TLocal {v_extra = None} | TArray _ | TField _ | TIdent _ ->
()
| TConst TThis | TTypeExpr _ when ctx.untyped ->
()
| TMeta ((Meta.CompilerGenerated,_,_),e1) ->
check_assign ctx e1
| _ ->
if not (Common.ignore_error ctx.com) then
invalid_assign e.epos
Expand Down
5 changes: 3 additions & 2 deletions src/typing/typer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ let rec type_ident_raise ctx i p mode with_type =
| _ ->
try
let v = PMap.find i ctx.locals in
add_var_flag v VUsedByTyper;
(match v.v_extra with
| Some ve ->
let (params,e) = (ve.v_params,ve.v_expr) in
Expand Down Expand Up @@ -1062,7 +1063,7 @@ and type_new ctx (path,p_path) el with_type force_inline p =
raise_typing_error (s_type (print_context()) t ^ " cannot be constructed") p
end with Error ({ err_message = No_constructor _ } as err) when ctx.com.display.dms_kind <> DMNone ->
display_error_ext ctx.com err;
Diagnostics.secure_generated_code ctx.com (mk (TConst TNull) t p)
mk (TConst TNull) t p

and type_try ctx e1 catches with_type p =
let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
Expand Down Expand Up @@ -1744,7 +1745,7 @@ and type_call_builtin ctx e el mode with_type p =
s
in
warning ctx WInfo s e1.epos;
Diagnostics.secure_generated_code ctx.com e1
e1
| (EField(e,"match",efk_todo),p), [epat] ->
let et = type_expr ctx e WithType.value in
let rec has_enum_match t = match follow t with
Expand Down
8 changes: 5 additions & 3 deletions src/typing/typerBase.ml
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,11 @@ let get_this ctx p =
| FunMemberClassLocal | FunMemberAbstractLocal ->
let v = match ctx.vthis with
| None ->
let v = if ctx.curfun = FunMemberAbstractLocal then
PMap.find "this" ctx.locals
else
let v = if ctx.curfun = FunMemberAbstractLocal then begin
let v = PMap.find "this" ctx.locals in
add_var_flag v VUsedByTyper;
v
end else
add_local ctx VGenerated (Printf.sprintf "%sthis" gen_local_prefix) ctx.tthis p
in
ctx.vthis <- Some v;
Expand Down
14 changes: 11 additions & 3 deletions tests/display/src/cases/Issue5306.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class Issue5306 extends DisplayTestCase {
class Main {
static function main() {
var ib:Array<Int>;
ib[0] = 0; ib[1] = 1; ib[2]
{-5-}trace{-6-}("test");
{-5-}ib{-6-}[0] = 0; ib[1] = 1; ib[2]
{-7-}trace{-8-}("test");
}
}
**/
Expand All @@ -22,7 +22,7 @@ class Issue5306 extends DisplayTestCase {
// },
{
kind: DKParserError,
range: diagnosticsRange(pos(5), pos(6)),
range: diagnosticsRange(pos(7), pos(8)),
severity: Error,
code: null,
relatedInformation: [],
Expand All @@ -35,6 +35,14 @@ class Issue5306 extends DisplayTestCase {
code: null,
relatedInformation: [],
args: "Type not found : InvalidType"
},
{
kind: DKCompilerError,
range: diagnosticsRange(pos(5), pos(6)),
severity: Error,
code: null,
relatedInformation: [],
args: "Local variable ib used without being initialized"
}
];
arrayEq(expected, diagnostics());
Expand Down
25 changes: 12 additions & 13 deletions tests/server/src/cases/issues/Issue11177.hx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package cases.issues;

class Issue11177 extends TestCase {
// Disabled for now until #11177 is actually fixed, likely by #11220
// function test(_) {
// vfs.putContent("Main.hx", getTemplate("issues/Issue11177/Main.hx"));
// vfs.putContent("Buttons.hx", getTemplate("issues/Issue11177/Buttons.hx"));
// vfs.putContent("KeyCode.hx", getTemplate("issues/Issue11177/KeyCode.hx"));
// var args = ["-main", "Main", "--interp"];
// runHaxe(args.concat(["--display", "Buttons.hx@0@diagnostics"]));
// vfs.putContent("Main.hx", getTemplate("issues/Issue11177/Main2.hx"));
// runHaxeJson([], ServerMethods.Invalidate, {file: new FsPath("Main.hx")});
// runHaxe(args);
// runHaxe(args.concat(["--display", "Buttons.hx@0@diagnostics"]));
// Assert.isTrue(lastResult.stderr.length == 2);
// }
function test(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11177/Main.hx"));
vfs.putContent("Buttons.hx", getTemplate("issues/Issue11177/Buttons.hx"));
vfs.putContent("KeyCode.hx", getTemplate("issues/Issue11177/KeyCode.hx"));
var args = ["-main", "Main", "--interp"];
runHaxe(args.concat(["--display", "Buttons.hx@0@diagnostics"]));
vfs.putContent("Main.hx", getTemplate("issues/Issue11177/Main2.hx"));
runHaxeJson([], ServerMethods.Invalidate, {file: new FsPath("Main.hx")});
runHaxe(args);
runHaxe(args.concat(["--display", "Buttons.hx@0@diagnostics"]));
Assert.isTrue(lastResult.stderr.length == 2);
}

function testWithoutCacheFromDisplay(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11177/Main.hx"));
Expand Down
23 changes: 13 additions & 10 deletions tests/server/src/cases/issues/Issue11184.hx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package cases.issues;

class Issue11184 extends TestCase {
// Disabled for now until #11184 is actually fixed, likely by #11220
// function test(_) {
// vfs.putContent("Main.hx", getTemplate("issues/Issue11184/Main.hx"));
// var args = ["-main", "Main", "-js", "bin/test.js"];
// runHaxe(args.concat(["--display", "Main.hx@0@diagnostics"]));
// runHaxe(args);
// Assert.isTrue(hasErrorMessage("Cannot use Void as value"));
// runHaxe(args);
// Assert.isTrue(hasErrorMessage("Cannot use Void as value"));
// }
function testDiagnostics(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11184/Main.hx"));
var args = ["-main", "Main", "-js", "bin/test.js"];

runHaxe(args.concat(["--display", "Main.hx@0@diagnostics"]));
final diagnostics = haxe.Json.parse(lastResult.stderr)[0].diagnostics;
Assert.equals(diagnostics[0].args, "Cannot use Void as value");

runHaxe(args);
Assert.isTrue(hasErrorMessage("Cannot use Void as value"));
runHaxe(args);
Assert.isTrue(hasErrorMessage("Cannot use Void as value"));
}

function testWithoutCacheFromDisplay(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11184/Main.hx"));
Expand Down
23 changes: 23 additions & 0 deletions tests/server/src/cases/issues/Issue11203.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cases.issues;

class Issue11203 extends TestCase {
function testClass(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11203/MainClass.hx"));
var args = ["Main", "--interp"];
runHaxe(args);
runHaxe(args.concat(["--display", "Main.hx@0@diagnostics"]));

var diag = parseDiagnostics();
Assert.isTrue(diag.length == 0);
}

function testAbstract(_) {
vfs.putContent("Main.hx", getTemplate("issues/Issue11203/MainAbstract.hx"));
var args = ["Main", "--interp"];
runHaxe(args);
runHaxe(args.concat(["--display", "Main.hx@0@diagnostics"]));

var diag = parseDiagnostics();
Assert.isTrue(diag.length == 0);
}
}
Loading
Loading