Browse Source

[parser] keep track of inactive blocks

Simon Krajewski 6 years ago
parent
commit
f3250d6129

+ 3 - 0
src/context/common.ml

@@ -159,6 +159,7 @@ type shared_display_information = {
 type display_information = {
 	mutable unresolved_identifiers : (string * pos * (string * CompletionItem.t * int) list) list;
 	mutable interface_field_implementations : (tclass * tclass_field * tclass * tclass_field option) list;
+	mutable dead_blocks : (string,pos list) Hashtbl.t;
 }
 
 (* This information is shared between normal and macro context. *)
@@ -425,6 +426,7 @@ let create version s_version args =
 		display_information = {
 			unresolved_identifiers = [];
 			interface_field_implementations = [];
+			dead_blocks = Hashtbl.create 0;
 		};
 		sys_args = args;
 		debug = false;
@@ -502,6 +504,7 @@ let clone com =
 		display_information = {
 			unresolved_identifiers = [];
 			interface_field_implementations = [];
+			dead_blocks = Hashtbl.create 0;
 		};
 		defines = {
 			values = com.defines.values;

+ 5 - 0
src/context/display/diagnostics.ml

@@ -193,6 +193,11 @@ module Printer = struct
 		Hashtbl.iter (fun p s ->
 			add DKDeprecationWarning p DiagnosticsSeverity.Warning (JString s);
 		) DeprecationCheck.warned_positions;
+		Hashtbl.iter (fun file ranges ->
+			List.iter (fun p ->
+				add DKInactiveBlock p DiagnosticsSeverity.Hint JNull
+			) ranges
+		) com.display_information.dead_blocks;
 		let jl = Hashtbl.fold (fun file diag acc ->
 			let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc ->
 				(JObject [

+ 2 - 0
src/core/displayTypes.ml

@@ -71,6 +71,7 @@ module DiagnosticsKind = struct
 		| DKRemovableCode
 		| DKParserError
 		| DKDeprecationWarning
+		| DKInactiveBlock
 
 	let to_int = function
 		| DKUnusedImport -> 0
@@ -79,6 +80,7 @@ module DiagnosticsKind = struct
 		| DKRemovableCode -> 3
 		| DKParserError -> 4
 		| DKDeprecationWarning -> 5
+		| DKInactiveBlock -> 6
 end
 
 module CompletionResultKind = struct

+ 1 - 1
src/macro/eval/evalDebugMisc.ml

@@ -81,7 +81,7 @@ exception Parse_expr_error of string
 let parse_expr ctx s p =
 	let error s = raise (Parse_expr_error s) in
 	match ParserEntry.parse_expr_string (ctx.curapi.get_com()).Common.defines s p error true with
-	| ParseSuccess data | ParseDisplayFile(data,_) -> data
+	| ParseSuccess data | ParseDisplayFile(data,_,_) -> data
 	| ParseError(_,(msg,_),_) -> error (Parser.error_msg msg)
 
 (* Vars *)

+ 2 - 2
src/syntax/grammar.mly

@@ -1548,8 +1548,8 @@ let rec parse_macro_cond s =
 				parse_macro_ident (s_keyword k) p s
 			| [< '(Unop op,p); tk, e = parse_macro_cond >] ->
 				tk, make_unop op e p
-			| [< '(POpen,p1); (e,p) = expr; '(PClose,_) >] ->
-				None, (EParenthesis(validate_macro_cond s (e,p)),p1)) in
+			| [< '(POpen,p1); (e,p) = expr; '(PClose,p2) >] ->
+				None, (EParenthesis(validate_macro_cond s (e,p)),punion p1 p2)) in
 		parsing_macro_cond := false;
 		cond
 	with e ->

+ 1 - 1
src/syntax/parser.ml

@@ -72,7 +72,7 @@ type parse_error = (error_msg * pos)
 
 type 'a parse_result =
 	(* Parsed display file. There can be errors. *)
-	| ParseDisplayFile of 'a * parse_error list
+	| ParseDisplayFile of 'a * parse_error list * pos list
 	(* Parsed non-display-file without errors. *)
 	| ParseSuccess of 'a
 	(* Parsed non-display file with errors *)

+ 52 - 7
src/syntax/parserEntry.ml

@@ -104,6 +104,25 @@ and eval_binop_exprs ctx e1 e2 =
 	| TString s, (TVersion _ as v2) -> (parse_version s (snd e1), v2)
 	| v1, v2 -> (v1, v2)
 
+class dead_block_collector = object(self)
+	val dead_blocks = DynArray.create ()
+	val mutable current_block = []
+
+	method open_dead_block (p : pos) =
+		current_block <- {p with pmin = p.pmax} :: current_block
+
+	method close_dead_block (p : pos) = match current_block with
+		| [] ->
+			error (Custom "Internal error: Trying to close dead block that's not open") p;
+		| p0 :: pl ->
+			current_block <- pl;
+			DynArray.add dead_blocks ({p0 with pmax = p.pmin})
+
+	method get_dead_blocks =
+		assert(current_block = []);
+		DynArray.to_list dead_blocks
+end
+
 (* parse main *)
 let parse ctx code file =
 	let old = Lexer.save() in
@@ -135,6 +154,7 @@ let parse ctx code file =
 		error (Custom line) p
 	in
 
+	let dbc = new dead_block_collector in
 	let sraw = Stream.from (fun _ -> Some (Lexer.sharp_token code)) in
 	let rec next_token() = process_token (Lexer.token code)
 
@@ -155,12 +175,23 @@ let parse ctx code file =
 			| _ :: l ->
 				mstack := l;
 				next_token())
-		| Sharp "else" | Sharp "elseif" ->
+		| Sharp "elseif" ->
+			(match !mstack with
+			| [] -> tk
+			| _ :: l ->
+				let _,(_,pe) = parse_macro_cond sraw in
+				dbc#open_dead_block pe;
+				mstack := l;
+				let tk = skip_tokens (pos tk) false in
+				process_token tk)
+		| Sharp "else" ->
 			(match !mstack with
 			| [] -> tk
 			| _ :: l ->
+				dbc#open_dead_block (pos tk);
 				mstack := l;
-				process_token (skip_tokens (snd tk) false))
+				let tk = skip_tokens (pos tk) false in
+				process_token tk)
 		| Sharp "if" ->
 			process_token (enter_macro (snd tk))
 		| Sharp "error" ->
@@ -185,22 +216,36 @@ let parse ctx code file =
 		if is_true (eval ctx e) then begin
 			mstack := p :: !mstack;
 			tk
-		end else
+		end else begin
+			dbc#open_dead_block (pos e);
 			skip_tokens_loop p true tk
+		end
 
 	and skip_tokens_loop p test tk =
 		match fst tk with
 		| Sharp "end" ->
+			dbc#close_dead_block (pos tk);
 			Lexer.token code
-		| Sharp "elseif" | Sharp "else" when not test ->
+		| Sharp "elseif" when not test ->
+			dbc#close_dead_block (pos tk);
+			let _,(_,pe) = parse_macro_cond sraw in
+			dbc#open_dead_block pe;
+			skip_tokens p test
+		| Sharp "else" when not test ->
+			dbc#close_dead_block (pos tk);
+			dbc#open_dead_block (pos tk);
 			skip_tokens p test
 		| Sharp "else" ->
+			dbc#close_dead_block (pos tk);
 			mstack := snd tk :: !mstack;
 			Lexer.token code
 		| Sharp "elseif" ->
+			dbc#close_dead_block (pos tk);
 			enter_macro (snd tk)
 		| Sharp "if" ->
-			skip_tokens_loop p test (skip_tokens p false)
+			dbc#open_dead_block (pos tk);
+			let tk = skip_tokens p false in
+			skip_tokens_loop p test tk
 		| Sharp ("error" | "line") ->
 			skip_tokens p test
 		| Sharp s ->
@@ -225,7 +270,7 @@ let parse ctx code file =
 		restore();
 		Lexer.restore old;
 		if was_display_file then
-			ParseDisplayFile(l,List.rev !syntax_errors)
+			ParseDisplayFile(l,List.rev !syntax_errors,dbc#get_dead_blocks)
 		else begin match List.rev !syntax_errors with
 			| [] -> ParseSuccess l
 			| error :: errors -> ParseError(l,error,errors)
@@ -288,4 +333,4 @@ let parse_expr_string com s p error inl =
 	match parse_string com (head ^ s ^ ";}") p error inl with
 	| ParseSuccess data -> ParseSuccess(extract_expr data)
 	| ParseError(data,error,errors) -> ParseError(extract_expr data,error,errors)
-	| ParseDisplayFile(data,errors) -> ParseDisplayFile(extract_expr data,errors)
+	| ParseDisplayFile(data,errors,dead) -> ParseDisplayFile(extract_expr data,errors,dead)

+ 1 - 1
src/typing/macroContext.ml

@@ -129,7 +129,7 @@ let make_macro_api ctx p =
 			try
 				begin match ParserEntry.parse_expr_string ctx.com.defines s p error inl with
 					| ParseSuccess data -> data
-					| ParseDisplayFile(data,_) when inl -> data (* ignore errors when inline-parsing in display file *)
+					| ParseDisplayFile(data,_,_) when inl -> data (* ignore errors when inline-parsing in display file *)
 					| ParseDisplayFile _ -> assert false (* cannot happen because ParserEntry.parse_string sets `display_position := null_pos;` *)
 					| ParseError _ -> raise MacroApi.Invalid_expr
 				end

+ 1 - 1
src/typing/typeloadModule.ml

@@ -911,7 +911,7 @@ let handle_import_hx ctx m decls p =
 			if Sys.file_exists path then begin
 				let _,r = match !TypeloadParse.parse_hook ctx.com path p with
 					| ParseSuccess data -> data
-					| ParseDisplayFile(data,_) -> data
+					| ParseDisplayFile(data,_,_) -> data
 					| ParseError(_,(msg,p),_) -> Parser.error msg p
 				in
 				List.iter (fun (d,p) -> match d with EImport _ | EUsing _ -> () | _ -> error "Only import and using is allowed in import.hx files" p) r;

+ 4 - 3
src/typing/typeloadParse.ml

@@ -43,7 +43,7 @@ let parse_file_from_lexbuf com file p lexbuf =
 	in
 	begin match !Parser.display_mode,parse_result with
 		| DMModuleSymbols (Some ""),_ -> ()
-		| DMModuleSymbols filter,(ParseSuccess data | ParseDisplayFile(data,_)) when filter = None && DisplayPosition.display_position#is_in_file file ->
+		| DMModuleSymbols filter,(ParseSuccess data | ParseDisplayFile(data,_,_)) when filter = None && DisplayPosition.display_position#is_in_file file ->
 			let ds = DocumentSymbols.collect_module_symbols (filter = None) data in
 			DisplayException.raise_module_symbols (DocumentSymbols.Printer.print_module_symbols com [file,ds] filter);
 		| _ ->
@@ -122,7 +122,7 @@ let resolve_module_file com m remap p =
 			| [] -> []
 		in
 		let meta =  match parse_result with
-			| ParseSuccess(_,decls) | ParseDisplayFile((_,decls),_) -> loop decls
+			| ParseSuccess(_,decls) | ParseDisplayFile((_,decls),_,_) -> loop decls
 			| ParseError _ -> []
 		in
 		if not (Meta.has Meta.NoPackageRestrict meta) then begin
@@ -154,11 +154,12 @@ let parse_module_file com file p =
 	in
 	let pack,decls = match (!parse_hook) com file p with
 		| ParseSuccess data -> data
-		| ParseDisplayFile(data,errors) ->
+		| ParseDisplayFile(data,errors,dead) ->
 			begin match errors with
 			| (msg,p) :: _ -> handle_parser_error msg p
 			| [] -> ()
 			end;
+			if dead <> [] then Hashtbl.replace com.display_information.dead_blocks file dead;
 			data
 		| ParseError(data,(msg,p),_) ->
 			handle_parser_error msg p;

+ 1 - 1
src/typing/typer.ml

@@ -1577,7 +1577,7 @@ and format_string ctx s p =
 				let ep = { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } in
 				try
 					begin match ParserEntry.parse_expr_string ctx.com.defines scode ep error true with
-						| ParseSuccess data | ParseDisplayFile(data,_) -> data
+						| ParseSuccess data | ParseDisplayFile(data,_,_) -> data
 						| ParseError(_,(msg,p),_) -> error (Parser.error_msg msg) p
 					end
 				with Exit ->