Browse Source

[display] take interface field as the base field
for find_references request with WithBaseAndDescendats (#9470)

Aleksandr Kuzmenko 5 years ago
parent
commit
cc725a464a

+ 31 - 15
src/context/display/findReferences.ml

@@ -43,25 +43,41 @@ let collect_reference_positions com =
 				in
 				loop com.types
 			in
-			let cf,c =
-				if find_base then
-					let rec loop c =
-						match c.cl_super with
-						| None -> (PMap.find cf.cf_name c.cl_fields),c
-						| Some (csup,_) ->
-							try loop csup
-							with Not_found -> (PMap.find cf.cf_name c.cl_fields),c
-					in
-					try loop c
-					with Not_found -> cf,c
-				else
-					cf,c
+			let field_class_pairs =
+				(* check classes hierarchy *)
+				let cf,c =
+					if find_base then
+						let rec loop c =
+							match c.cl_super with
+							| None -> (PMap.find cf.cf_name c.cl_fields),c
+							| Some (csup,_) ->
+								try loop csup
+								with Not_found -> (PMap.find cf.cf_name c.cl_fields),c
+						in
+						try loop c
+						with Not_found -> cf,c
+					else
+						cf,c
+				in
+				(* check interfaces of the found base class *)
+				let rec fold_interface acc (i,_) =
+					try loop i @ acc
+					with Not_found -> acc
+				and loop c =
+					match List.fold_left fold_interface [] c.cl_implements with
+					| [] -> [(PMap.find cf.cf_name c.cl_fields),c]
+					| pairs -> pairs
+				in
+				match List.fold_left fold_interface [] c.cl_implements with
+				| [] -> [cf,c]
+				| pairs -> pairs
 			in
 			let full_pos p = { p with pfile = Path.get_full_path p.pfile } in
 			if find_descendants then
+				let extends child_cls (_,c) = extends child_cls c in
 				List.fold_left (fun acc t ->
 					match t with
-					| TClassDecl child_cls when extends child_cls c ->
+					| TClassDecl child_cls when List.exists (extends child_cls) field_class_pairs ->
 						(try
 							let cf = PMap.find cf.cf_name child_cls.cl_fields in
 							(name,full_pos cf.cf_name_pos,SKField (cf,Some child_cls.cl_path)) :: acc
@@ -71,7 +87,7 @@ let collect_reference_positions com =
 						acc
 				) [] com.types
 			else
-				[name,full_pos cf.cf_name_pos,SKField (cf,Some c.cl_path)]
+				List.map (fun (cf,c) -> name,full_pos cf.cf_name_pos,SKField (cf,Some c.cl_path)) field_class_pairs;
 		in
 		(try collect()
 		with Exit -> [name,pos,kind])

+ 1 - 0
tests/server/src/cases/display/issues/Issue9423.hx

@@ -20,6 +20,7 @@ class Issue9423 extends DisplayTestCase {
 		});
 		var result = parseCompletion().result;
 		// TODO: this test does not pass, but the same setup works fine in vscode
+		// TODO: Another test which does not work here, but works in vshaxe: #9423.
 		// Assert.equals(1, result.items.length);
 		Assert.pass();
 	}

+ 34 - 0
tests/server/src/cases/display/issues/Issue9470.hx

@@ -0,0 +1,34 @@
+package cases.display.issues;
+
+class Issue9470 extends DisplayTestCase {
+	/**
+		interface I {
+			function method():Void;
+		}
+
+		class C implements I {
+			public function new() {}
+			public function met{-1-}hod() {}
+		}
+
+		class Main {
+			static public function main() {
+				(new C() : I).{-2-}method{-3-}();
+			}
+		}
+	**/
+	function test(_) {
+		runHaxeJson([], DisplayMethods.FindReferences, {file: file, offset: offset(1)});
+		trace(haxe.Json.parse(lastResult.stderr));
+		var result = parseGotoDefinitionLocations();
+		/*
+			TODO:
+			Something is wrong with our test suite setup.
+			This works in vshaxe, but not here.
+			Similar test #9446 works fine in the test suite.
+			Another test which does not work here, but works in vshaxe: #9423.
+		*/
+		// Assert.same([range(2, 3)], result.map(l -> l.range));
+		Assert.pass();
+	}
+}