Skip to content

Commit

Permalink
[23] Selection for module imports
Browse files Browse the repository at this point in the history
+ implement selection for module imports
+ includes new ResolveTests23
+ also add forgotten ResolveTests21 to the suite
  - but remove tests for withdrawn string template feature

fixes eclipse-jdt#2838
  • Loading branch information
stephan-herrmann committed Aug 20, 2024
1 parent 9b33f16 commit 7b244bd
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ private static Class[] getAllTestClasses() {
ResolveTests9.class,
ResolveTests10.class,
ResolveTests12To15.class,
ResolveTests21.class,
ResolveTests23.class,
SelectionJavadocModelTests.class,

// Some test suite above breaks completion tests below
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,109 +65,6 @@ protected void tearDown() throws Exception {
super.tearDown();
}

public void test001() throws JavaModelException {
this.wc = getWorkingCopy("/Resolve/src/X.java",
"public class X {\n"
+ " private String abc = \"abc\"; // unused\n"
+ " public void main(String[] args) {\n"
+ " String s = STR.\"A simple String \\{clone(abc)}\";\n"
+ " System.out.println(s);\n"
+ " }\n"
+ " public String clone(String s) {\n"
+ " return \"clone\";\n"
+ " }\n"
+ "}");
String str = this.wc.getSource();
String selection = "clone";
int start = str.indexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"clone(String) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]",
elements
);
}
public void test002() throws JavaModelException {
this.wc = getWorkingCopy("/Resolve/src/X.java",
"public class X {\n"
+ " private String abc = \"abc\"; // unused\n"
+ " public void main(String[] args) {\n"
+ " String s = STR.\"A simple String \\{clone(abc)}\";\n"
+ " System.out.println(s);\n"
+ " }\n"
+ " public String clone(String s) {\n"
+ " return \"clone\";\n"
+ " }\n"
+ "}");
String str = this.wc.getSource();
String selection = "abc";
int start = str.lastIndexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"abc [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]",
elements
);
}
public void test003() throws JavaModelException {
this.wc = getWorkingCopy("/Resolve/src/X.java",
"public class X {\n"
+ " static int CONST = 0;\n"
+ " private static int foo() {\n"
+ " return CONST;\n"
+ " }\n"
+ " public static void main(String argv[]) {\n"
+ " String str = STR.\"{\\{new Object() { class Test { int i; Test() { i = foo();}}}.new Test().i\\u007d}\";\n"
+ " System.out.println(str.equals(\"{0}\"));\n"
+ " }\n"
+ "}");
String str = this.wc.getSource();
String selection = "foo";
int start = str.lastIndexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"foo() [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]",
elements
);
}
public void test004() throws JavaModelException {
this.wc = getWorkingCopy("/Resolve/src/X.java",
"public class X {\n"
+ " private final static int LF = (char) 0x000A;\n"
+ " private static boolean compare(String s) {\n"
+ " char[] chars = new char[] {LF,'a','b','c','d'};\n"
+ " if (chars.length != s.length())\n"
+ " return false;\n"
+ " for (int i = 0; i < s.length(); i++) {\n"
+ " if(chars[i] != s.charAt(i)) {\n"
+ " return false;\n"
+ " }\n"
+ " }\n"
+ " return true;\n"
+ " }\n"
+ " public static void main(String argv[]) {\n"
+ " String abcd = \"abcd\"; //$NON-NLS-1$\n"
+ " String textBlock = STR.\"\"\"\n"
+ " \n"
+ "\\{abcd}\"\"\";//$NON-NLS-1$\n"
+ " System.out.println(compare(textBlock));\n"
+ " }\n"
+ "}");
String str = this.wc.getSource();
String selection = "abcd";
int start = str.lastIndexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"abcd [in main(String[]) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]",
elements
);
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2572
// [code select] ClassCastException when hovering in switch case yield
public void testIssue2572() throws JavaModelException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*******************************************************************************
* Copyright (c) 2024 GK Software SE 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
*
* This is an implementation of an early-draft specification developed under the Java
* Community Process (JCP) and is made available for testing and evaluation purposes
* only. The code is not compatible with any specification of the JCP.
*
* Contributors:
* Stephan herrmann - initial implementation
*******************************************************************************/

package org.eclipse.jdt.core.tests.model;

import java.io.IOException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;

import junit.framework.Test;

public class ResolveTests23 extends AbstractJavaModelTests {
ICompilationUnit wc = null;

static {
// TESTS_NAMES = new String[] { "testModuleImport3_firstSegment" };
// TESTS_NUMBERS = new int[] { 124 };
// TESTS_RANGE = new int[] { 16, -1 };
}
public static Test suite() {
return buildModelTestSuite(ResolveTests23.class);
}
public ResolveTests23(String name) {
super(name);
}
@Override
public ICompilationUnit getWorkingCopy(String path, String source) throws JavaModelException {
return super.getWorkingCopy(path, source, this.wcOwner);
}
@Override
public void setUpSuite() throws Exception {
super.setUpSuite();
this.currentProject = setUpJavaProject("Resolve", "23", false);
this.currentProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
waitUntilIndexesReady();
}
@Override
protected void setUp() throws Exception {
super.setUp();
this.wcOwner = new WorkingCopyOwner(){};
}
@Override
public void tearDownSuite() throws Exception {
deleteProject("Resolve");
super.tearDownSuite();
}

@Override
protected void tearDown() throws Exception {
if (this.wc != null) {
this.wc.discardWorkingCopy();
}
super.tearDown();
}

public void testModuleImport1() throws IOException, CoreException {
String jarName = "mod.one.jar";
addModularLibrary(this.currentProject, jarName, "mod.one.zip",
new String[] {
"module-info.java",
"module mod.one {}"
},
"23");
try {
this.wc = getWorkingCopy("/Resolve/src/p/X.java",
"""
package p;
import module mod.one;
class X{}
""");
String str = this.wc.getSource();
String selection = "one";
int start = str.indexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"mod.one [in module-info.class [in <default> [in mod.one.jar [in Resolve]]]]",
elements
);
} finally {
removeLibrary(this.currentProject, jarName, null);
}
}
public void testModuleImport2_prefix() throws IOException, CoreException {
String jarName = "mod.one.jar";
addModularLibrary(this.currentProject, jarName, "mod.one.zip",
new String[] {
"module-info.java",
"module mod.one {}"
},
"23");
try {
this.wc = getWorkingCopy("/Resolve/src/p/X.java",
"""
package p;
import module mod.o;
class X{}
""");
String str = this.wc.getSource();
String selection = "mod.o";
int start = str.indexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"mod.one [in module-info.class [in <default> [in mod.one.jar [in Resolve]]]]",
elements
);
} finally {
removeLibrary(this.currentProject, jarName, null);
}
}
public void testModuleImport3_firstSegment() throws IOException, CoreException {
// assert that selecting only the first segment of a module name still uses the full name for module lookup
String jarName1 = "mod.one.jar";
addModularLibrary(this.currentProject, jarName1, "mod.one.zip",
new String[] {
"module-info.java",
"module mod.one {}"
},
"23");
// second module for potential ambiguity of name part "mod":
String jarName2 = "mod.two.jar";
addModularLibrary(this.currentProject, jarName2, "mod.two.zip",
new String[] {
"module-info.java",
"module mod.two {}"
},
"23");
try {
this.wc = getWorkingCopy("/Resolve/src/p/X.java",
"""
package p;
import module mod.one;
class X{}
""");
String str = this.wc.getSource();
String selection = "mod.one";
int start = str.indexOf(selection);
int length = "mod".length(); // <<== only first segment
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"mod.one [in module-info.class [in <default> [in mod.one.jar [in Resolve]]]]",
elements
);
} finally {
removeLibrary(this.currentProject, jarName1, null);
removeLibrary(this.currentProject, jarName2, null);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -8,6 +8,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*
* This is an implementation of an early-draft specification developed under the Java
* Community Process (JCP) and is made available for testing and evaluation purposes
* only. The code is not compatible with any specification of the JCP.
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jesper Steen Møller <[email protected]> - contributions for:
Expand Down Expand Up @@ -1013,6 +1017,10 @@ public void select(
if (importReference instanceof SelectionOnImportReference) {
char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
this.noProposal = false;
if ((importReference.modifiers & ClassFileConstants.AccModule) != 0 && this.compilerOptions.enablePreviewFeatures) {
this.nameEnvironment.findModules(CharOperation.concatWithAll(tokens, '.'), this, null);
return;
}
this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), false, false, IJavaSearchConstants.TYPE, this);

Expand Down Expand Up @@ -2059,7 +2067,6 @@ private Object visitInheritDocInterfaces(ArrayList visited, ReferenceBinding cur

@Override
public void acceptModule(char[] moduleName) {
// TODO Auto-generated method stub

this.requestor.acceptModule(moduleName, moduleName, this.actualSelectionStart, this.actualSelectionEnd);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,10 @@ protected void consumeSingleModifierImportDeclarationName(int modifier) {
/* retrieve identifiers subset and whole positions, the assist node positions
should include the entire replaced source. */
int length = this.identifierLengthStack[this.identifierLengthPtr];
char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
int subsetLength = modifier == ClassFileConstants.AccStatic
? index + 1 // include the assistIdentifier
: length; // segments of a module name have no semantic relevance, use the entire name
char[][] subset = identifierSubSet(subsetLength);
this.identifierLengthPtr--;
this.identifierPtr -= length;
long[] positions = new long[length];
Expand Down

0 comments on commit 7b244bd

Please sign in to comment.