1717import com .microsoft .java .test .plugin .util .TestItemUtils ;
1818
1919import org .eclipse .core .resources .IProject ;
20+ import org .eclipse .core .resources .IResource ;
21+ import org .eclipse .core .resources .ResourcesPlugin ;
2022import org .eclipse .core .runtime .IPath ;
23+ import org .eclipse .jdt .core .IClassFile ;
24+ import org .eclipse .jdt .core .IClasspathEntry ;
2125import org .eclipse .jdt .core .IJavaElement ;
2226import org .eclipse .jdt .core .IJavaProject ;
2327import org .eclipse .jdt .core .IPackageFragment ;
2428import org .eclipse .jdt .core .JavaModelException ;
29+ import org .eclipse .jdt .internal .core .BinaryMember ;
30+ import org .eclipse .jdt .internal .core .BinaryMethod ;
31+ import org .eclipse .jdt .internal .core .BinaryType ;
32+ import org .eclipse .jdt .internal .core .PackageFragmentRoot ;
2533import org .eclipse .jdt .internal .core .manipulation .JavaElementLabelsCore ;
2634import org .eclipse .jdt .ls .core .internal .JDTUtils ;
35+ import org .eclipse .jdt .ls .core .internal .JavaLanguageServerPlugin ;
2736import org .eclipse .jdt .ls .core .internal .ProjectUtils ;
37+ import org .eclipse .lsp4j .Position ;
2838import org .eclipse .lsp4j .Range ;
39+ import org .objectweb .asm .ClassReader ;
40+ import org .objectweb .asm .ClassVisitor ;
41+ import org .objectweb .asm .Label ;
42+ import org .objectweb .asm .MethodVisitor ;
43+ import org .objectweb .asm .Opcodes ;
44+
45+ import java .io .ByteArrayInputStream ;
46+ import java .io .InputStream ;
2947
3048/**
3149 * Builder class to build {@link com.microsoft.java.test.plugin.model.JavaTestItem}
@@ -36,6 +54,7 @@ public class JavaTestItemBuilder {
3654 private IJavaElement element ;
3755 private TestLevel level ;
3856 private TestKind kind ;
57+ private String displayName ;
3958
4059 public JavaTestItemBuilder setJavaElement (IJavaElement element ) {
4160 this .element = element ;
@@ -52,34 +71,124 @@ public JavaTestItemBuilder setKind(TestKind kind) {
5271 return this ;
5372 }
5473
74+ public JavaTestItemBuilder setDisplayName (String displayName ) {
75+ this .displayName = displayName ;
76+ return this ;
77+ }
78+
5579 public JavaTestItem build () throws JavaModelException {
5680 if (this .element == null || this .level == null || this .kind == null ) {
5781 throw new IllegalArgumentException ("Failed to build Java test item due to missing arguments" );
5882 }
5983
60- final String displayName ;
6184 String uri = null ;
62- if (this .element instanceof IJavaProject ) {
63- final IJavaProject javaProject = (IJavaProject ) this .element ;
64- final IProject project = javaProject .getProject ();
65- if (ProjectUtils .isVisibleProject (project )) {
66- displayName = project .getName ();
85+ if (this .displayName == null ) {
86+ if (this .element instanceof IJavaProject ) {
87+ final IJavaProject javaProject = (IJavaProject ) this .element ;
88+ final IProject project = javaProject .getProject ();
89+ if (ProjectUtils .isVisibleProject (project )) {
90+ displayName = project .getName ();
91+ } else {
92+ final IPath realPath = ProjectUtils .getProjectRealFolder (project );
93+ displayName = realPath .lastSegment ();
94+ uri = realPath .toFile ().toURI ().toString ();
95+ }
96+ } else if (this .element instanceof IPackageFragment &&
97+ ((IPackageFragment ) this .element ).isDefaultPackage ()) {
98+ displayName = DEFAULT_PACKAGE_NAME ;
99+ final IResource resource = getResource ((IPackageFragment ) this .element );
100+ if (resource == null || !resource .exists ()) {
101+ return null ;
102+ }
103+ uri = JDTUtils .getFileURI (resource );
67104 } else {
68- final IPath realPath = ProjectUtils .getProjectRealFolder (project );
69- displayName = realPath .lastSegment ();
70- uri = realPath .toFile ().toURI ().toString ();
105+ displayName = JavaElementLabelsCore .getElementLabel (this .element , JavaElementLabelsCore .ALL_DEFAULT );
71106 }
72- } else if (this .element instanceof IPackageFragment && ((IPackageFragment ) this .element ).isDefaultPackage ()) {
73- displayName = DEFAULT_PACKAGE_NAME ;
74- } else {
75- displayName = JavaElementLabelsCore .getElementLabel (this .element , JavaElementLabelsCore .ALL_DEFAULT );
76107 }
108+ Range range = null ;
77109 final String fullName = TestItemUtils .parseFullName (this .element , this .level , this .kind );
78110 if (uri == null ) {
79- uri = JDTUtils .getFileURI (this .element .getResource ());
111+ IResource resource = this .element .getResource ();
112+ if (resource == null && this .element instanceof IPackageFragment ) {
113+ resource = getResource ((IPackageFragment ) this .element );
114+ }
115+ if (resource == null || !resource .exists ()) {
116+ return null ;
117+ }
118+ if (element instanceof BinaryMember ) {
119+ final String [] sources = new String [1 ];
120+ final int [] lines = {-1 };
121+ final IClassFile classFile = ((BinaryMember ) element ).getClassFile ();
122+ try (InputStream is = new ByteArrayInputStream (classFile .getBytes ())) {
123+ final ClassReader cr = new ClassReader (is );
124+ if (element instanceof BinaryType ) {
125+ cr .accept (new ClassVisitor (Opcodes .ASM9 ) {
126+ @ Override
127+ public void visitSource (String source , String debug ) {
128+ sources [0 ] = source ;
129+ }
130+ }, ClassReader .SKIP_CODE | ClassReader .SKIP_FRAMES );
131+ } else if (element instanceof BinaryMethod ) {
132+ final String methodDescriptor = ((BinaryMethod ) element ).getSignature ();
133+ cr .accept (new ClassVisitor (Opcodes .ASM9 ) {
134+ @ Override
135+ public void visitSource (String source , String debug ) {
136+ sources [0 ] = source ;
137+ }
138+
139+ public MethodVisitor visitMethod (int access , String name , String descriptor ,
140+ String signature , String [] exceptions ) {
141+ if (name .equals (element .getElementName ()) && descriptor .equals (methodDescriptor )) {
142+ return new MethodVisitor (Opcodes .ASM9 ) {
143+ @ Override
144+ public void visitLineNumber (int line , Label start ) {
145+ if (lines [0 ] < 0 ) {
146+ lines [0 ] = line ;
147+ if (line > 0 ) {
148+ lines [0 ]--;
149+ }
150+ }
151+ }
152+ };
153+ }
154+ return null ;
155+ }
156+ }, ClassReader .SKIP_FRAMES );
157+ }
158+ } catch (Exception e ) {
159+ JavaLanguageServerPlugin .logException (e );
160+ }
161+ if (sources [0 ] != null ) {
162+ final IPackageFragment packageFragment = (IPackageFragment ) element
163+ .getAncestor (IJavaElement .PACKAGE_FRAGMENT );
164+ if (packageFragment != null ) {
165+ final String packageName = packageFragment .getElementName ();
166+ final IJavaProject project = element .getJavaProject ();
167+ final String packagePath = packageName .replace ('.' , '/' );
168+ for (final IClasspathEntry entry : project .getRawClasspath ()) {
169+ if (entry .getEntryKind () == IClasspathEntry .CPE_SOURCE ) {
170+ final IPath sourceFolderPath = entry .getPath ();
171+ final IPath fullPath = sourceFolderPath .append (packagePath ).append (sources [0 ]);
172+ final IResource candidate = ResourcesPlugin .getWorkspace ().getRoot ()
173+ .findMember (fullPath );
174+ if (candidate != null && candidate .exists ()) {
175+ resource = candidate ;
176+ break ;
177+ }
178+ }
179+ }
180+ }
181+ }
182+ if (lines [0 ] > 0 ) {
183+ final Position line = new Position (lines [0 ] - 1 , 0 );
184+ range = new Range (line , line );
185+ }
186+ }
187+ if (uri == null ) {
188+ uri = JDTUtils .getFileURI (resource );
189+ }
80190 }
81- Range range = null ;
82- if (this .level == TestLevel .CLASS || this .level == TestLevel .METHOD ) {
191+ if (range == null && (this .level == TestLevel .CLASS || this .level == TestLevel .METHOD )) {
83192 range = TestItemUtils .parseTestItemRange (this .element );
84193 }
85194
@@ -89,4 +198,22 @@ public JavaTestItem build() throws JavaModelException {
89198
90199 return result ;
91200 }
201+
202+ private IResource getResource (IPackageFragment packageFragment ) {
203+ if (packageFragment == null ) {
204+ return null ;
205+ }
206+ IResource resource = packageFragment .getResource ();
207+ if (resource == null ) {
208+ final IJavaElement e = packageFragment .getParent ();
209+ if (e instanceof PackageFragmentRoot ) {
210+ final PackageFragmentRoot root = (PackageFragmentRoot ) e ;
211+ resource = root .getResource ();
212+ if (resource == null ) {
213+ resource = root .resource (root );
214+ }
215+ }
216+ }
217+ return resource ;
218+ }
92219}
0 commit comments