Skip to content

Commit

Permalink
Consider external paths in search scope (eclipse-jdt#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
gerking authored and iloveeclipse committed May 3, 2024
1 parent 68e8c0c commit 7b101c3
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public String getDescription() {
public IClasspathEntry[] getClasspathEntries() {
if (TestExternalLibContainerInitializer.this.entries == null) {
TestExternalLibContainerInitializer.this.entries = new IClasspathEntry[] {
JavaCore.newLibraryEntry(containerPath, null, null)
JavaCore.newLibraryEntry(containerPath, containerPath, null)
};
}
return TestExternalLibContainerInitializer.this.entries;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (c) 2022 Christopher Gerking and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christopher Gerking - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchRequestor;

import junit.framework.Test;

public class JavaSearchIssue190Test extends AbstractJavaSearchTests {

public String getProjectName() {
return "JavaSearchIssue190";
}

public JavaSearchIssue190Test(String name) {
super(name);
}

public static Test suite() {
return buildModelTestSuite(JavaSearchIssue190Test.class, BYTECODE_DECLARATION_ORDER);
}

@Override
public void setUpSuite() throws Exception {
super.setUpSuite();

createExternalFolder("TestContainer/p");

String sourceWorkspacePath = getSourceWorkspacePath();
IWorkspace targetWorkspace = ResourcesPlugin.getWorkspace();
File targetWorkspaceLocation = new File(targetWorkspace.getRoot().getLocation().toOSString());

File javaFileSrc = new File(sourceWorkspacePath, "JavaSearchMultipleProjects2/lib/p/Y.java");
File javaFileDst = new File(targetWorkspaceLocation.getParentFile().getCanonicalFile(), "TestContainer/p/Y.java");
copy(javaFileSrc, javaFileDst);

File classFileSrc = new File(sourceWorkspacePath, "JavaSearchMultipleProjects2/lib/p/Y.class");
File classFileDst = new File(targetWorkspaceLocation.getParentFile().getCanonicalFile(), "TestContainer/p/Y.class");
copy(classFileSrc, classFileDst);

JAVA_PROJECT = setUpJavaProject(getProjectName(), "11");

JavaCore.setOptions(JavaCore.getDefaultOptions());
}

@Override
IJavaSearchScope getJavaSearchScope() {
IJavaElement[] elements = new IJavaElement[] { getJavaProject(getProjectName()) };
return SearchEngine.createJavaSearchScope(elements, true);
}

public void testIssue190() throws CoreException, IOException {
List<String> searchResults = new ArrayList<String>();

SearchRequestor searchRequestor = new SearchRequestor() {
public void acceptSearchMatch(SearchMatch match) {
Object element = match.getElement();

if (element instanceof IType) {
String fqn = ((IType) element).getFullyQualifiedName();
searchResults.add(fqn);
}
}
};

search("Y", IJavaSearchConstants.CLASS,
IJavaSearchConstants.DECLARATIONS, getJavaSearchScope(), searchRequestor);

assertTrue("Searched class not found in external classpath container", searchResults.contains("p.Y"));
}

@Override
public void tearDownSuite() throws Exception {
deleteProject(getProjectName());
deleteExternalResource("TestContainer");
super.tearDownSuite();
JAVA_PROJECT = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public static Test suite() {
allClasses.add(JavaSearchBug565512Test.class);
allClasses.add(JavaSearchNameEnvironmentTest.class);
allClasses.add(JavaSearchSuperAfterStatementTests.class);
allClasses.add(JavaSearchIssue190Test.class);

// Reset forgotten subsets of tests
TestCase.TESTS_PREFIX = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.core.tests.model.TEST_EXTERNAL_LIB_CONTAINER"/>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.jdt.core.tests.model.issue190</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ private int indexOf(String fullPath) {
String currentRelativePath = this.relativePaths[i];
if (currentRelativePath == null) continue;
String currentContainerPath = this.containerPaths[i];
currentContainerPath = convertInternalToExternalPath(currentContainerPath, fullPath);
String currentFullPath = currentRelativePath.length() == 0 ? currentContainerPath : (currentContainerPath + '/' + currentRelativePath);
if (encloses(currentFullPath, fullPath, i))
return i;
Expand Down Expand Up @@ -401,6 +402,7 @@ private int indexOf(String containerPath, String relativePath) {
index = (containerPath.hashCode()& 0x7FFFFFFF) % length;
String currentContainerPath;
while ((currentContainerPath = this.containerPaths[index]) != null) {
currentContainerPath = convertInternalToExternalPath(currentContainerPath, containerPath);
if (currentContainerPath.equals(containerPath)) {
String currentRelativePath = this.relativePaths[index];
if (encloses(currentRelativePath, relativePath, index))
Expand All @@ -413,6 +415,34 @@ private int indexOf(String containerPath, String relativePath) {
return -1;
}

/**
* If the given path is internal but represents an external folder,
* converts it to the corresponding external path.
* The reference path indicates if conversion is necessary.
* No conversion takes place if the given path does not represent an external folder,
* or if conversion is unnecessary because the reference path also represents an external folder.
* @param given the given path to convert if necessary
* @param reference the reference path that indicates if conversion is necessary
* @return the external path that corresponds to the given path,
* or the given path itself if no conversion is necessary
*/
private String convertInternalToExternalPath(String given, String reference) {
IPath givenPath = new Path(given);
if (ExternalFoldersManager.isInternalPathForExternalFolder(givenPath)) {
IPath referencePath = new Path(reference);
if (!ExternalFoldersManager.isInternalPathForExternalFolder(referencePath)) {
IResource targetResource = JavaModel.getWorkspaceTarget(givenPath);
if (targetResource != null) {
IPath targetLocation = targetResource.getLocation();
if (targetLocation != null)
return targetLocation.toString();
}
}
}

return given;
}

/*
* Returns whether the enclosing path encloses the given path (or is equal to it)
*/
Expand Down

0 comments on commit 7b101c3

Please sign in to comment.