فهرست منبع

[display] support hover in conditional compilation

Simon Krajewski 6 سال پیش
والد
کامیت
c9b2e1c536
3فایلهای تغییر یافته به همراه45 افزوده شده و 3 حذف شده
  1. 1 0
      src/syntax/parser.ml
  2. 9 3
      src/syntax/parserEntry.ml
  3. 35 0
      src/typing/typeloadParse.ml

+ 1 - 0
src/syntax/parser.ml

@@ -73,6 +73,7 @@ type parse_error = (error_msg * pos)
 type parser_display_information = {
 	pd_errors : parse_error list;
 	pd_dead_blocks : pos list;
+	pd_conditions : expr list;
 }
 
 type 'a parse_result =

+ 9 - 3
src/syntax/parserEntry.ml

@@ -131,6 +131,7 @@ let parse ctx code file =
 	let was_display_file = !in_display_file in
 	let old_code = !code_ref in
 	let old_macro = !in_macro in
+	let conditions = ref [] in
 	code_ref := code;
 	in_display := display_position#get <> null_pos;
 	in_display_file := !in_display && Path.unique_full_path file = (display_position#get).pfile;
@@ -179,7 +180,8 @@ let parse ctx code file =
 			(match !mstack with
 			| [] -> tk
 			| _ :: l ->
-				let _,(_,pe) = parse_macro_cond sraw in
+				let _,(e,pe) = parse_macro_cond sraw in
+				conditions := (e,pe) :: !conditions;
 				dbc#open_dead_block pe;
 				mstack := l;
 				let tk = skip_tokens (pos tk) false in
@@ -212,6 +214,7 @@ let parse ctx code file =
 
 	and enter_macro p =
 		let tk, e = parse_macro_cond sraw in
+		conditions := e :: !conditions;
 		let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in
 		if is_true (eval ctx e) then begin
 			mstack := p :: !mstack;
@@ -228,7 +231,8 @@ let parse ctx code file =
 			Lexer.token code
 		| Sharp "elseif" when not test ->
 			dbc#close_dead_block (pos tk);
-			let _,(_,pe) = parse_macro_cond sraw in
+			let _,(e,pe) = parse_macro_cond sraw in
+			conditions := (e,pe) :: !conditions;
 			dbc#open_dead_block pe;
 			skip_tokens p test
 		| Sharp "else" when not test ->
@@ -244,6 +248,8 @@ let parse ctx code file =
 			enter_macro (snd tk)
 		| Sharp "if" ->
 			dbc#open_dead_block (pos tk);
+			let _,e = parse_macro_cond sraw in
+			conditions := e :: !conditions;
 			let tk = skip_tokens p false in
 			skip_tokens_loop p test tk
 		| Sharp ("error" | "line") ->
@@ -270,7 +276,7 @@ let parse ctx code file =
 		restore();
 		Lexer.restore old;
 		if was_display_file then
-			ParseDisplayFile(l,{pd_errors = List.rev !syntax_errors;pd_dead_blocks = dbc#get_dead_blocks})
+			ParseDisplayFile(l,{pd_errors = List.rev !syntax_errors;pd_dead_blocks = dbc#get_dead_blocks;pd_conditions = !conditions})
 		else begin match List.rev !syntax_errors with
 			| [] -> ParseSuccess l
 			| error :: errors -> ParseError(l,error,errors)

+ 35 - 0
src/typing/typeloadParse.ml

@@ -144,6 +144,40 @@ let resolve_module_file com m remap p =
 	let timer = Timer.timer ["typing";"resolve_module_file"] in
 	Std.finally timer (resolve_module_file com m remap) p *)
 
+module ConditionDisplay = struct
+	open ParserEntry
+	open CompletionItem.CompletionType
+
+	exception Result of expr
+
+	let ct name = CTAbstract {
+		ct_pack = [];
+		ct_type_name = name;
+		ct_module_name = name;
+		ct_params = [];
+		ct_import_status = Imported;
+	}
+
+	let convert_small_type com = function
+		| TNull -> "null",(Type.mk_mono(),CTMono)
+		| TBool b -> string_of_bool b,(com.basic.tbool,ct "Bool")
+		| TFloat f -> string_of_float f,(com.basic.tfloat,ct "Float")
+		| TString s -> s,(com.basic.tstring,ct "String")
+		| TVersion(r,p) -> Semver.to_string (r,p),(com.basic.tstring,ct "String")
+
+	let check_condition com e =
+		let rec loop (e,p) =
+			Ast.iter_expr loop (e,p);
+			if DisplayPosition.display_position#enclosed_in p then raise (Result (e,p))
+		in
+		try
+			loop e;
+		with Result e ->
+			let v = eval com.defines e in
+			let s,(t,ct) = convert_small_type com v in
+			DisplayException.raise_hover (CompletionItem.make_ci_literal s (t,ct)) None (pos e)
+end
+
 let parse_module_file com file p =
 	let handle_parser_error msg p =
 		let msg = Parser.error_msg msg in
@@ -160,6 +194,7 @@ let parse_module_file com file p =
 			| [] -> ()
 			end;
 			if pdi.pd_dead_blocks <> [] then Hashtbl.replace com.display_information.dead_blocks file pdi.pd_dead_blocks;
+			List.iter (ConditionDisplay.check_condition com) pdi.pd_conditions;
 			data
 		| ParseError(data,(msg,p),_) ->
 			handle_parser_error msg p;