From 7b244bdbb5592301027cbe608275d89833269f1d Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 20 Aug 2024 19:51:16 +0200 Subject: [PATCH] [23] Selection for module imports + implement selection for module imports + includes new ResolveTests23 + also add forgotten ResolveTests21 to the suite - but remove tests for withdrawn string template feature fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2838 --- .../core/tests/model/AllJavaModelTests.java | 2 + .../jdt/core/tests/model/ResolveTests21.java | 103 ----------- .../jdt/core/tests/model/ResolveTests23.java | 173 ++++++++++++++++++ .../internal/codeassist/SelectionEngine.java | 13 +- .../codeassist/impl/AssistParser.java | 5 +- 5 files changed, 189 insertions(+), 107 deletions(-) create mode 100644 org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests23.java diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java index 43eac170bed..51f54913912 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java @@ -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 diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests21.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests21.java index 8fd5dddd65a..e8c00d054c9 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests21.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests21.java @@ -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 [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 [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 [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 [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 { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests23.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests23.java new file mode 100644 index 00000000000..4cf88e91429 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests23.java @@ -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 [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 [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 [in mod.one.jar [in Resolve]]]]", + elements + ); + } finally { + removeLibrary(this.currentProject, jarName1, null); + removeLibrary(this.currentProject, jarName2, null); + } +} +} diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java index 7231ad77150..55b2b5b1df2 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java @@ -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 @@ -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 - contributions for: @@ -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); @@ -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); } } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java index 6084b8807b3..f94966b95ff 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java @@ -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];