From 6e31e9f68fb51fa3cecef3cc04245465f24843cf Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 27 Aug 2024 14:20:21 +0200 Subject: [PATCH] [23] Tests for link completion inside markdown comments. (#1616) After https://github.com/eclipse-jdt/eclipse.jdt.ui/issues/1542 enabled completion inside markdown comments, this change adds infrastructure and smoketests for end-to-end testing of markdown link completion. Also adds another forgotten test class to the suite. --- .../contentassist/CodeCompletionTest23.java | 226 ++++++++++++++++++ .../contentassist/ContentAssistTestSuite.java | 2 + .../jdt/testplugin/JavaProjectHelper.java | 26 ++ .../core/rules/Java23ProjectTestSetup.java | 80 +++++++ 4 files changed, 334 insertions(+) create mode 100644 org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest23.java create mode 100644 org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/rules/Java23ProjectTestSetup.java diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest23.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest23.java new file mode 100644 index 00000000000..6d8a1755b6c --- /dev/null +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest23.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * 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 API and implementation + *******************************************************************************/ +package org.eclipse.jdt.text.tests.contentassist; + +import static org.junit.Assert.assertEquals; + +import java.util.Hashtable; +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; + +import org.eclipse.jdt.testplugin.JavaProjectHelper; +import org.eclipse.jdt.testplugin.TestOptions; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; + +import org.eclipse.jdt.internal.core.manipulation.CodeTemplateContextType; +import org.eclipse.jdt.internal.core.manipulation.StubUtility; + +import org.eclipse.jdt.ui.JavaUI; +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.tests.core.rules.Java23ProjectTestSetup; +import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; + +import org.eclipse.jdt.internal.ui.JavaPlugin; +import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; +import org.eclipse.jdt.internal.ui.text.java.JavaAllCompletionProposalComputer; +import org.eclipse.jdt.internal.ui.text.java.JavaTypeCompletionProposalComputer; + +/** + * Those tests are made to run on Java 23 + */ +public class CodeCompletionTest23 extends AbstractCompletionTest { + @Rule + public Java23ProjectTestSetup j23s= new Java23ProjectTestSetup(true); + + private IJavaProject fJProject1; + + @Override + public void setUp() throws Exception { + fJProject1= j23s.getProject(); + + Hashtable options= TestOptions.getDefaultOptions(); + options.put(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, "1"); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); + options.put(JavaCore.CODEASSIST_FIELD_PREFIXES, "f"); + JavaCore.setOptions(options); + + IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); + store.setValue(PreferenceConstants.CODEGEN_ADD_COMMENTS, true); + store.setValue(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, true); + store.setValue(PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS, true); + + StubUtility.setCodeTemplate(CodeTemplateContextType.OVERRIDECOMMENT_ID, "/* (non-Javadoc)\n * ${see_to_overridden}\n */", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.DELEGATECOMMENT_ID, "/* (non-Javadoc)\n * ${see_to_target}\n */", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.METHODSTUB_ID, "//TODO\n${body_statement}", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORCOMMENT_ID, "/**\n * Constructor.\n */", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.METHODCOMMENT_ID, "/**\n * Method.\n */", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORSTUB_ID, "//TODO\n${body_statement}", null); + StubUtility.setCodeTemplate(CodeTemplateContextType.GETTERCOMMENT_ID, "/**\n * @return the ${bare_field_name}\n */", fJProject1); + StubUtility.setCodeTemplate(CodeTemplateContextType.SETTERCOMMENT_ID, "/**\n * @param ${param} the ${bare_field_name} to set\n */", fJProject1); + } + + @Override + public void tearDown() throws Exception { + IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); + store.setToDefault(PreferenceConstants.CODEGEN_ADD_COMMENTS); + store.setToDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS); + store.setToDefault(PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS); + closeAllEditors(); + JavaProjectHelper.clear(fJProject1, j23s.getDefaultClasspath()); + } + + public static void closeEditor(IEditorPart editor) { + IWorkbenchPartSite site; + IWorkbenchPage page; + if (editor != null && (site= editor.getSite()) != null && (page= site.getPage()) != null) + page.closeEditor(editor, false); + } + + public static void closeAllEditors() { + for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + for (IWorkbenchPage page : window.getPages()) { + for (IEditorReference editorReference : page.getEditorReferences()) { + closeEditor(editorReference.getEditor(false)); + } + } + } + } + + private JavaContentAssistInvocationContext createContext(int offset, ICompilationUnit cu) throws PartInitException, JavaModelException { + JavaEditor editor= (JavaEditor) JavaUI.openInEditor(cu); + ISourceViewer viewer= editor.getViewer(); + return new JavaContentAssistInvocationContext(viewer, offset, editor); + } + + @Test + public void testMarkdownLink_method() throws CoreException { + IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); + + IPackageFragment pack1= sourceFolder.createPackageFragment("javadoc", false, null); + String contents= + """ + package javadoc; + /// + /// see [#me] for details + public class Test { + void method() {} + } + """; + ICompilationUnit cu= pack1.createCompilationUnit("Test.java", contents, false, null); + + + String str= "#me"; + + int offset= contents.indexOf(str) + str.length() - 1; + + JavaTypeCompletionProposalComputer comp= new JavaAllCompletionProposalComputer(); + + List proposals= comp.computeCompletionProposals(createContext(offset, cu), null); + ICompletionProposal proposal = proposals.get(0); + + IEditorPart part= JavaUI.openInEditor(cu); + IDocument doc= JavaUI.getDocumentProvider().getDocument(part.getEditorInput()); + if (proposal != null) { + proposal.apply(doc); + } + + String expectedContents= + """ + package javadoc; + /// + /// see [#method()] for details + public class Test { + void method() {} + } + """; + assertEquals(expectedContents, doc.get()); + } + + @Test + public void testMarkdownLink_type() throws CoreException { + IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); + + IPackageFragment pack1= sourceFolder.createPackageFragment("javadoc", false, null); + String contents= + """ + package javadoc; + public class Test { + /// + /// see [Tes + /// + void method() {} + } + """; + ICompilationUnit cu= pack1.createCompilationUnit("Test.java", contents, false, null); + + + String str= "[Tes"; + + int offset= contents.indexOf(str) + str.length() - 1; + + JavaTypeCompletionProposalComputer comp= new JavaAllCompletionProposalComputer(); + + List proposals= comp.computeCompletionProposals(createContext(offset, cu), null); + ICompletionProposal proposal = proposals.get(0); + + IEditorPart part= JavaUI.openInEditor(cu); + IDocument doc= JavaUI.getDocumentProvider().getDocument(part.getEditorInput()); + if (proposal != null) { + proposal.apply(doc); + } + + String expectedContents= + """ + package javadoc; + public class Test { + /// + /// see [Test + /// + void method() {} + } + """; + assertEquals(expectedContents, doc.get()); + } + +} diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/ContentAssistTestSuite.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/ContentAssistTestSuite.java index 569e85c4466..bb539ae074d 100644 --- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/ContentAssistTestSuite.java +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/ContentAssistTestSuite.java @@ -39,6 +39,8 @@ SpecialMethodsCompletionTest.class, CodeCompletionTest.class, CodeCompletionTest1d8.class, + CodeCompletionTest16.class, + CodeCompletionTest23.class, ContinuousTypingCompletionTest.class, ChainCompletionTest.class, PostFixCompletionTest.class diff --git a/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaProjectHelper.java b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaProjectHelper.java index a64e147ff54..27eeb35322c 100644 --- a/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaProjectHelper.java +++ b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaProjectHelper.java @@ -356,6 +356,23 @@ public static void set18CompilerOptions(IJavaProject project) { project.setOptions(options); } + /** + * Sets the compiler options to 23 for the given project. + * + * @param project the java project + * @param enable_preview_feature sets enable-preview compliance project option based on the + * value specified. + */ + public static void set23CompilerOptions(IJavaProject project, boolean enable_preview_feature) { + Map options= project.getOptions(false); + set23_CompilerOptions(options); + if (enable_preview_feature) { + options.put(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED); + options.put(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE); + } + project.setOptions(options); + } + /** * Sets the compiler options to 9. * @@ -437,6 +454,15 @@ public static void set17_CompilerOptions(Map options) { JavaCore.setComplianceOptions(JavaCore.VERSION_17, options); } + /** + * Sets the compiler options to 23. + * + * @param options the compiler options to configure + */ + public static void set23_CompilerOptions(Map options) { + JavaCore.setComplianceOptions(JavaCore.VERSION_23, options); + } + /** * Sets the compiler options to 1.8 * diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/rules/Java23ProjectTestSetup.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/rules/Java23ProjectTestSetup.java new file mode 100644 index 00000000000..f5c9da64e5f --- /dev/null +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/rules/Java23ProjectTestSetup.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * 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 API and implementation + *******************************************************************************/ +package org.eclipse.jdt.ui.tests.core.rules; + +import org.eclipse.jdt.testplugin.JavaProjectHelper; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; + +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; + +import org.eclipse.jdt.internal.core.ClasspathEntry; + +/** Variant derived from Java17ProjectTestSetup */ +public class Java23ProjectTestSetup extends ProjectTestSetup { + + public static final String PROJECT_NAME23= "TestSetupProject23"; + + private final String projectName; + + private final boolean enable_preview_feature; + + @Override + public IJavaProject getProject() { + IProject project= ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + return JavaCore.create(project); + } + + @Override + public IClasspathEntry[] getDefaultClasspath() throws CoreException { + IPath[] rtJarPath= JavaProjectHelper.findRtJar(JavaProjectHelper.RT_STUBS17); + IClasspathAttribute[] extraAttributes= { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, Boolean.TRUE.toString()) }; + return new IClasspathEntry[] { JavaCore.newLibraryEntry(rtJarPath[0], rtJarPath[1], rtJarPath[2], ClasspathEntry.NO_ACCESS_RULES, extraAttributes, true) }; + } + + public Java23ProjectTestSetup( boolean enable_preview_feature) { + this.enable_preview_feature= enable_preview_feature; + projectName= PROJECT_NAME23; + } + + public Java23ProjectTestSetup( String projectName, boolean enable_preview_feature) { + this.enable_preview_feature= enable_preview_feature; + this.projectName= projectName; + } + + @Override + protected boolean projectExists() { + return getProject().exists(); + } + + @Override + protected IJavaProject createAndInitializeProject() throws CoreException { + IJavaProject javaProject= JavaProjectHelper.createJavaProject(projectName, "bin"); + javaProject.setRawClasspath(getDefaultClasspath(), null); + JavaProjectHelper.set23CompilerOptions(javaProject, enable_preview_feature); + return javaProject; + } + +}