From ec259110e49db021b08f0d86dd993c3c44b69704 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Mon, 10 Dec 2018 15:03:35 +0800 Subject: [PATCH 1/4] Bulk generate getter and setter Signed-off-by: Jinbo Wang --- .../GenerateGetterSetterOperation.java | 134 +++++ .../proposals/IProposalRelevance.java | 1 + .../text/correction/ActionMessages.java | 28 + .../text/correction/ActionMessages.properties | 12 + .../correction/SourceAssistProcessor.java | 62 ++ .../AbstractSourceTestCase.java | 120 ++++ .../GenerateGetterAndSetterTest.java | 559 ++++++++++++++++++ 7 files changed, 916 insertions(+) create mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java create mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.java create mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.properties create mode 100644 org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/AbstractSourceTestCase.java create mode 100644 org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterAndSetterTest.java diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java new file mode 100644 index 0000000000..a97853a758 --- /dev/null +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java @@ -0,0 +1,134 @@ +/******************************************************************************* +* Copyright (c) 2018 Microsoft Corporation and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Microsoft Corporation - initial API and implementation +*******************************************************************************/ + +package org.eclipse.jdt.ls.core.internal.corext.codemanipulation; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.NodeFinder; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; +import org.eclipse.jdt.core.formatter.CodeFormatter; +import org.eclipse.jdt.core.manipulation.CoreASTProvider; +import org.eclipse.jdt.internal.core.manipulation.StubUtility; +import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil; +import org.eclipse.jdt.internal.corext.dom.ASTNodes; +import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; +import org.eclipse.text.edits.TextEdit; + +public class GenerateGetterSetterOperation { + private final static int generateVisibility = Modifier.PUBLIC; + private final static boolean generateComments = true; + + private final IType type; + private CompilationUnit astRoot; + + public GenerateGetterSetterOperation(IType type, CompilationUnit astRoot) { + Assert.isNotNull(type); + this.type = type; + this.astRoot = astRoot; + } + + public static boolean supportsGetterSetter(IType type) throws JavaModelException { + if (type == null || type.isAnnotation() || type.isInterface() || type.getCompilationUnit() == null) { + return false; + } + + return true; + } + + public TextEdit createTextEdit(IProgressMonitor monitor) throws OperationCanceledException, CoreException { + if (!supportsGetterSetter(type)) { + return null; + } + + final ICompilationUnit unit = type.getCompilationUnit(); + if (astRoot == null) { + astRoot = CoreASTProvider.getInstance().getAST(unit, CoreASTProvider.WAIT_YES, monitor); + } + + final ASTRewrite astRewrite = ASTRewrite.create(astRoot.getAST()); + ListRewrite listRewriter = null; + if (type.isAnonymous()) { + final ClassInstanceCreation creation = ASTNodes.getParent(NodeFinder.perform(astRoot, type.getNameRange()), ClassInstanceCreation.class); + if (creation != null) { + final AnonymousClassDeclaration declaration = creation.getAnonymousClassDeclaration(); + if (declaration != null) { + listRewriter = astRewrite.getListRewrite(declaration, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY); + } + } + } else { + final AbstractTypeDeclaration declaration = ASTNodes.getParent(NodeFinder.perform(astRoot, type.getNameRange()), AbstractTypeDeclaration.class); + if (declaration != null) { + listRewriter = astRewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); + } + } + + if (listRewriter == null) { + return null; + } + + generateGetterSetterMethods(listRewriter); + return astRewrite.rewriteAST(); + } + + private void generateGetterSetterMethods(ListRewrite listRewriter) throws OperationCanceledException, CoreException { + IField[] fields = type.getFields(); + for (IField field : fields) { + int flags = field.getFlags(); + if (!Flags.isEnum(flags)) { + if (GetterSetterUtil.getGetter(field) == null) { + insertMethod(field, listRewriter, GENERATE_KIND.GETTER); + } + + if (!Flags.isFinal(flags) && GetterSetterUtil.getSetter(field) == null) { + insertMethod(field, listRewriter, GENERATE_KIND.SETTER); + } + } + } + } + + private void insertMethod(IField field, ListRewrite rewrite, GENERATE_KIND kind) throws CoreException { + IType type = field.getDeclaringType(); + String delimiter = StubUtility.getLineDelimiterUsed(type); + int flags = generateVisibility | (field.getFlags() & Flags.AccStatic); + String stub; + if (kind == GENERATE_KIND.GETTER) { + String name = GetterSetterUtil.getGetterName(field, null); + stub = GetterSetterUtil.getGetterStub(field, name, generateComments, flags); + } else { + String name = GetterSetterUtil.getSetterName(field, null); + stub = GetterSetterUtil.getSetterStub(field, name, generateComments, flags); + } + + String formattedStub = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, stub, 0, delimiter, type.getJavaProject().getOptions(true)); + MethodDeclaration declaration = (MethodDeclaration) rewrite.getASTRewrite().createStringPlaceholder(formattedStub, ASTNode.METHOD_DECLARATION); + rewrite.insertLast(declaration, null); + } + + enum GENERATE_KIND { + GETTER, SETTER + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/IProposalRelevance.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/IProposalRelevance.java index 4aede5e71e..9c6cea69c4 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/IProposalRelevance.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/IProposalRelevance.java @@ -202,6 +202,7 @@ public interface IProposalRelevance { public static final int CREATE_CONSTANT= 4; public static final int CHANGE_CLASS_TO_INTERFACE= 3; + public static final int GENERATE_GETTER_AND_SETTER = 3; public static final int GENERATE_HASHCODE_AND_EQUALS= 3; public static final int SIMILAR_TYPE= 3; public static final int EXTRACT_LOCAL_ALL_ERROR= 3; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.java new file mode 100644 index 0000000000..a9a47fd44b --- /dev/null +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.java @@ -0,0 +1,28 @@ +/******************************************************************************* +* Copyright (c) 2018 Microsoft Corporation and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Microsoft Corporation - initial API and implementation +*******************************************************************************/ + +package org.eclipse.jdt.ls.core.internal.text.correction; + +import org.eclipse.osgi.util.NLS; + +public final class ActionMessages extends NLS { + private static final String BUNDLE_NAME = ActionMessages.class.getName(); + + private ActionMessages() { + // Do not instantiate + } + + public static String GenerateGetterSetterAction_label; + + static { + NLS.initializeMessages(BUNDLE_NAME, ActionMessages.class); + } +} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.properties b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.properties new file mode 100644 index 0000000000..842b2c6fc8 --- /dev/null +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/ActionMessages.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2018 Microsoft Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Microsoft Corporation - initial API and implementation +############################################################################### + +GenerateGetterSetterAction_label=Generate Getters and Setters \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java index 92076ce027..5c7c6214a2 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java @@ -16,9 +16,16 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.manipulation.OrganizeImportsOperation; import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore; +import org.eclipse.jdt.ls.core.internal.corext.codemanipulation.GenerateGetterSetterOperation; import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages; import org.eclipse.jdt.ls.core.internal.corrections.IInvocationContext; import org.eclipse.jdt.ls.core.internal.corrections.proposals.CUCorrectionProposal; @@ -33,6 +40,7 @@ public List getAssists(IInvocationContext context, IProble ArrayList resultingCollections = new ArrayList<>(); getOrganizeImportsProposal(context, resultingCollections); + getGetterSetterProposal(context, resultingCollections); return resultingCollections; } @@ -55,4 +63,58 @@ protected void addEdits(IDocument document, TextEdit editRoot) throws CoreExcept resultingCollections.add(proposal); } + + private static void getGetterSetterProposal(IInvocationContext context, List resultingCollections) { + final IType type = getSelectionType(context); + try { + if (!GenerateGetterSetterOperation.supportsGetterSetter(type)) { + return; + } + } catch (JavaModelException e) { + return; + } + + ICompilationUnit unit = context.getCompilationUnit(); + CUCorrectionProposal proposal = new CUCorrectionProposal(ActionMessages.GenerateGetterSetterAction_label, CodeActionKind.Source, unit, null, IProposalRelevance.GENERATE_GETTER_AND_SETTER) { + + @Override + protected void addEdits(IDocument document, TextEdit editRoot) throws CoreException { + CompilationUnit astRoot = context.getASTRoot(); + GenerateGetterSetterOperation operation = new GenerateGetterSetterOperation(type, astRoot); + TextEdit textEdit = operation.createTextEdit(null); + if (textEdit != null) { + editRoot.addChild(textEdit); + } + } + }; + + resultingCollections.add(proposal); + } + + private static IType getSelectionType(IInvocationContext context) { + ICompilationUnit unit = context.getCompilationUnit(); + ASTNode node = context.getCoveredNode(); + if (node == null) { + node = context.getCoveringNode(); + } + + ITypeBinding typeBinding = null; + while (node != null && !(node instanceof CompilationUnit)) { + if (node instanceof TypeDeclaration) { + typeBinding = ((TypeDeclaration) node).resolveBinding(); + break; + } else if (node instanceof AnonymousClassDeclaration) { // Anonymous + typeBinding = ((AnonymousClassDeclaration) node).resolveBinding(); + break; + } + + node = node.getParent(); + } + + if (typeBinding != null && typeBinding.getJavaElement() instanceof IType) { + return (IType) typeBinding.getJavaElement(); + } + + return unit.findPrimaryType(); + } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/AbstractSourceTestCase.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/AbstractSourceTestCase.java new file mode 100644 index 0000000000..93357784d2 --- /dev/null +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/AbstractSourceTestCase.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.ls.core.internal.codemanipulation; + +import static org.junit.Assert.assertNotNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.Map; + +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.IType; +import org.eclipse.jdt.core.JavaCore; +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.ls.core.internal.managers.AbstractProjectsManagerBasedTest; +import org.junit.Assert; +import org.junit.Before; + +public class AbstractSourceTestCase extends AbstractProjectsManagerBasedTest { + private IJavaProject fJavaProject; + protected IPackageFragment fPackageP; + protected IType fClassA; + protected ICompilationUnit fCuA; + protected IPackageFragmentRoot fRoot; + + private void initCodeTemplates() { + Map options = fJavaProject.getOptions(true); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.TAB); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); + options.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT, "999"); + options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIELD, "1"); + options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_METHOD, "1"); + fJavaProject.setOptions(options); + + String getterComment = "/**\r\n" + " * @return Returns the ${bare_field_name}.\r\n" + " */"; + String getterBody = "return ${field};"; + + String setterComment = "/**\r\n" + " * @param ${param} The ${bare_field_name} to set.\r\n" + " */"; + String setterBody = "${field} = ${param};"; + + StubUtility.setCodeTemplate(CodeTemplateContextType.GETTERCOMMENT_ID, getterComment, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.SETTERCOMMENT_ID, setterComment, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.GETTERSTUB_ID, getterBody, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.SETTERSTUB_ID, setterBody, null); + + String methodComment = "/**\r\n" + " * ${tags}\r\n" + " */"; + String methodBody = "// ${todo} Auto-generated method stub\r\n" + "${body_statement}"; + + String constructorComment = "/**\r\n" + " * ${tags}\r\n" + " */"; + String constructorBody = "${body_statement}\r\n" + "// ${todo} Auto-generated constructor stub"; + + StubUtility.setCodeTemplate(CodeTemplateContextType.METHODCOMMENT_ID, methodComment, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.METHODSTUB_ID, methodBody, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORCOMMENT_ID, constructorComment, null); + StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORSTUB_ID, constructorBody, null); + } + + @Before + public void setUp() throws Exception { + fJavaProject = newEmptyProject(); + fRoot = fJavaProject.findPackageFragmentRoot(fJavaProject.getPath().append("src")); + assertNotNull(fRoot); + fPackageP = fRoot.createPackageFragment("p", true, null); + fCuA = fPackageP.getCompilationUnit("A.java"); + fClassA = fCuA.createType("public class A {\n}\n", null, true, null); + + initCodeTemplates(); + } + + protected void compareSource(String expected, String actual) throws IOException { + if (actual == null || expected == null) { + if (actual == expected) { + return; + } + if (actual == null) { + Assert.assertTrue("Content not as expected: is 'null' expected: " + expected, false); + } else { + Assert.assertTrue("Content not as expected: expected 'null' is: " + actual, false); + } + } + + BufferedReader read1 = new BufferedReader(new StringReader(actual)); + BufferedReader read2 = new BufferedReader(new StringReader(expected)); + + int line = 1; + do { + String s1 = read1.readLine(); + String s2 = read2.readLine(); + + if (s1 == null || !s1.equals(s2)) { + if (s1 == null && s2 == null) { + return; + } + String diffStr = (s1 == null) ? s2 : s1; + + String message = "Content not as expected: Content is: \n" + actual + "\nDiffers at line " + line + ": " + diffStr + "\nExpected contents: \n" + expected; + Assert.assertEquals(message, expected, actual); + } + line++; + } while (true); + } +} diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterAndSetterTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterAndSetterTest.java new file mode 100644 index 0000000000..e407b1cc99 --- /dev/null +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterAndSetterTest.java @@ -0,0 +1,559 @@ +/******************************************************************************* + * Copyright (c) 2000, 2016 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.ls.core.internal.codemanipulation; + +import static org.junit.Assert.assertNull; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.corext.util.JavaModelUtil; +import org.eclipse.jdt.ls.core.internal.corext.codemanipulation.GenerateGetterSetterOperation; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.TextEdit; +import org.junit.Test; + +public class GenerateGetterAndSetterTest extends AbstractSourceTestCase { + + private void runAndApplyOperation(IType type) throws OperationCanceledException, CoreException, MalformedTreeException, BadLocationException { + TextEdit edit = runOperation(type); + ICompilationUnit unit = type.getCompilationUnit(); + JavaModelUtil.applyEdit(unit, edit, true, null); + } + + private TextEdit runOperation(IType type) throws OperationCanceledException, CoreException { + GenerateGetterSetterOperation operation = new GenerateGetterSetterOperation(type, null); + return operation.createTextEdit(null); + } + + private IType createNewType(String fQName) throws JavaModelException { + final String pkg = fQName.substring(0, fQName.lastIndexOf('.')); + final String typeName = fQName.substring(fQName.lastIndexOf('.') + 1); + final IPackageFragment fragment = fRoot.createPackageFragment(pkg, true, null); + final ICompilationUnit unit = fragment.getCompilationUnit(typeName + ".java"); + return unit.createType("public class " + typeName + " {\n}\n", null, true, null); + } + + /** + * Tests normal getter/setter generation for one field. + * + * @throws Exception + */ + @Test + public void test0() throws Exception { + IField field1 = fClassA.createField("String field1;", null, false, new NullProgressMonitor()); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " String field1;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the field1.\r\n" + + " */\r\n" + + " public String getField1() {\r\n" + + " return field1;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param field1 The field1 to set.\r\n" + + " */\r\n" + + " public void setField1(String field1) {\r\n" + + " this.field1 = field1;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * Tests normal getter/setter generation for one field. + * + * @throws Exception + */ + @Test + public void testDoneWithSmartIs() throws Exception { + IField field1 = fClassA.createField("boolean done;", null, false, new NullProgressMonitor()); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " boolean done;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the done.\r\n" + + " */\r\n" + + " public boolean isDone() {\r\n" + + " return done;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param done The done to set.\r\n" + + " */\r\n" + + " public void setDone(boolean done) {\r\n" + + " this.done = done;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * Tests normal getter/setter generation for one field. + * + * @throws Exception + */ + @Test + public void testIsDoneWithSmartIs() throws Exception { + IField field1= fClassA.createField("boolean isDone;", null, false, new NullProgressMonitor()); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " boolean isDone;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the isDone.\r\n" + + " */\r\n" + + " public boolean isDone() {\r\n" + + " return isDone;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param isDone The isDone to set.\r\n" + + " */\r\n" + + " public void setDone(boolean isDone) {\r\n" + + " this.isDone = isDone;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * No setter for final fields (if skipped by user, as per parameter) + * + * @throws Exception + */ + @Test + public void test1() throws Exception { + IField field1 = fClassA.createField("final String field1 = null;", null, false, new NullProgressMonitor()); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " final String field1 = null;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the field1.\r\n" + + " */\r\n" + + " public String getField1() {\r\n" + + " return field1;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * Tests if full-qualified field declaration type is also full-qualified in + * setter parameter. + * + * @throws Exception + */ + @Test + public void test2() throws Exception { + createNewType("q.Other"); + IField field1 = fClassA.createField("q.Other field1;", null, false, new NullProgressMonitor()); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " q.Other field1;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the field1.\r\n" + + " */\r\n" + + " public q.Other getField1() {\r\n" + + " return field1;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param field1 The field1 to set.\r\n" + + " */\r\n" + + " public void setField1(q.Other field1) {\r\n" + + " this.field1 = field1;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * Test parameterized types in field declarations + * @throws Exception + */ + @Test + public void test3() throws Exception { + /* @formatter:off */ + ICompilationUnit b = fPackageP.createCompilationUnit("B.java", "package p;\r\n" + + "\r\n" + + "import java.util.HashMap;\r\n" + + "import java.util.Map;\r\n" + + "\r\n" + + "public class B {\r\n" + + "\r\n" + + " Map a = new HashMap();\r\n" + + "}\r\n", true, null); + /* @formatter:on */ + + IType classB = b.getType("B"); + runAndApplyOperation(classB); + + /* @formatter:off */ + String expected= "public class B {\r\n" + + "\r\n" + + " Map a = new HashMap();\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the a.\r\n" + + " */\r\n" + + " public Map getA() {\r\n" + + " return a;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param a The a to set.\r\n" + + " */\r\n" + + " public void setA(Map a) {\r\n" + + " this.a = a;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, classB.getSource()); + } + + /** + * Tests enum typed fields + * + * @throws Exception + */ + @Test + public void test4() throws Exception { + IType theEnum = fClassA.createType("private enum ENUM { C,D,E };", null, false, null); + IField field1 = fClassA.createField("private ENUM someEnum;", theEnum, false, null); + runAndApplyOperation(fClassA); + + /* @formatter:off */ + String expected= "public class A {\r\n" + + "\r\n" + + " private ENUM someEnum;\r\n" + + "\r\n" + + " private enum ENUM { C,D,E }\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the someEnum.\r\n" + + " */\r\n" + + " public ENUM getSomeEnum() {\r\n" + + " return someEnum;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param someEnum The someEnum to set.\r\n" + + " */\r\n" + + " public void setSomeEnum(ENUM someEnum) {\r\n" + + " this.someEnum = someEnum;\r\n" + + " };\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, fClassA.getSource()); + } + + /** + * Test generation for more than one field + * @throws Exception + */ + @Test + public void test5() throws Exception { + createNewType("q.Other"); + /* @formatter:off */ + ICompilationUnit b= fPackageP.createCompilationUnit("B.java", "package p;\r\n" + + "\r\n" + + "import q.Other;\r\n" + + "\r\n" + + "public class B {\r\n" + + "\r\n" + + " private String a;\r\n" + + " private String b;\r\n" + + " protected Other c;\r\n" + + " public String d;\r\n" + + "}", true, null); + /* @formatter:on */ + + IType classB= b.getType("B"); + IField field1= classB.getField("a"); + IField field2= classB.getField("b"); + IField field3= classB.getField("c"); + IField field4= classB.getField("d"); + runAndApplyOperation(classB); + + /* @formatter:off */ + String expected= "public class B {\r\n" + + "\r\n" + + " private String a;\r\n" + + " private String b;\r\n" + + " protected Other c;\r\n" + + " public String d;\r\n" + + " /**\r\n" + + " * @return Returns the a.\r\n" + + " */\r\n" + + " public String getA() {\r\n" + + " return a;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @param a The a to set.\r\n" + + " */\r\n" + + " public void setA(String a) {\r\n" + + " this.a = a;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @return Returns the b.\r\n" + + " */\r\n" + + " public String getB() {\r\n" + + " return b;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @param b The b to set.\r\n" + + " */\r\n" + + " public void setB(String b) {\r\n" + + " this.b = b;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @return Returns the c.\r\n" + + " */\r\n" + + " public Other getC() {\r\n" + + " return c;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @param c The c to set.\r\n" + + " */\r\n" + + " public void setC(Other c) {\r\n" + + " this.c = c;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @return Returns the d.\r\n" + + " */\r\n" + + " public String getD() {\r\n" + + " return d;\r\n" + + " }\r\n" + + " /**\r\n" + + " * @param d The d to set.\r\n" + + " */\r\n" + + " public void setD(String d) {\r\n" + + " this.d = d;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, classB.getSource()); + } + + /** + * Test getter/setter generation in anonymous type + * + * @throws Exception + */ + @Test + public void test7() throws Exception { + /* @formatter:off */ + ICompilationUnit b= fPackageP.createCompilationUnit("B.java", "package p;\r\n" + + "\r\n" + + "public class B {\r\n" + + "\r\n" + + " {\r\n" + + " B someAnon = new B() {\r\n" + + " \r\n" + + " A innerfield;\r\n" + + " \r\n" + + " };\r\n" + + " }\r\n" + + "}", true, null); + /* @formatter:on */ + + IType anon = (IType) b.getElementAt(60); // This is the position of the constructor of the anonymous type + runAndApplyOperation(anon); + + /* @formatter:off */ + String expected= "public class B {\r\n" + + "\r\n" + + " {\r\n" + + " B someAnon = new B() {\r\n" + + " \r\n" + + " A innerfield;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the innerfield.\r\n" + + " */\r\n" + + " public A getInnerfield() {\r\n" + + " return innerfield;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param innerfield The innerfield to set.\r\n" + + " */\r\n" + + " public void setInnerfield(A innerfield) {\r\n" + + " this.innerfield = innerfield;\r\n" + + " }\r\n" + + " \r\n" + + " };\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + compareSource(expected, b.getType("B").getSource()); + } + + /** + * Verify existing getters are not overwritten, and setters are created + * + * @throws Exception + */ + @Test + public void test9() throws Exception { + /* @formatter:off */ + ICompilationUnit b= fPackageP.createCompilationUnit("B.java", "package p;\r\n" + + "\r\n" + + "public class B {\r\n" + + "\r\n" + + " private Object o;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the o.\r\n" + + " */\r\n" + + " synchronized Object getO() {\r\n" + + " return o;\r\n" + + " }\r\n" + + "}", true, null); + /* @formatter:on */ + + IType classB = b.getType("B"); + runAndApplyOperation(classB); + + /* @formatter:off */ + String expected= "public class B {\r\n" + + "\r\n" + + " private Object o;\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the o.\r\n" + + " */\r\n" + + " synchronized Object getO() {\r\n" + + " return o;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @param o The o to set.\r\n" + + " */\r\n" + + " public void setO(Object o) {\r\n" + + " this.o = o;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, classB.getSource()); + } + + /** + * Verify existing setters are not overwritten, and getters are created + * + * @throws Exception + */ + @Test + public void test10() throws Exception { + /* @formatter:off */ + ICompilationUnit b= fPackageP.createCompilationUnit("B.java", "package p;\r\n" + + "\r\n" + + "public class B {\r\n" + + "\r\n" + + " private Object o;\r\n" + + "\r\n" + + " /**\r\n" + + " * @param o The o to set.\r\n" + + " */\r\n" + + " synchronized void setO(Object o) {\r\n" + + " this.o = o;\r\n" + + " }\r\n" + + "}", true, null); + /* @formatter:on */ + + IType classB = b.getType("B"); + runAndApplyOperation(classB); + + /* @formatter:off */ + String expected= "public class B {\r\n" + + "\r\n" + + " private Object o;\r\n" + + "\r\n" + + " /**\r\n" + + " * @param o The o to set.\r\n" + + " */\r\n" + + " synchronized void setO(Object o) {\r\n" + + " this.o = o;\r\n" + + " }\r\n" + + "\r\n" + + " /**\r\n" + + " * @return Returns the o.\r\n" + + " */\r\n" + + " public Object getO() {\r\n" + + " return o;\r\n" + + " }\r\n" + + "}"; + /* @formatter:on */ + + compareSource(expected, classB.getSource()); + } + + @Test + public void testNoGeneratorForInterface() throws OperationCanceledException, CoreException { + /* @formatter:off */ + ICompilationUnit b = fPackageP.createCompilationUnit("C.java", "package p;\r\n" + + "\r\n" + + "public interface C {\r\n" + + "\r\n" + + " Object o;\r\n" + + "\r\n" + + "}", true, null); + /* @formatter:on */ + IType classC = b.getType("C"); + assertNull(runOperation(classC)); + } +} From 1261de5c11de884324cc7a2db87e6c1310865976 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Wed, 12 Dec 2018 13:17:05 +0800 Subject: [PATCH 2/4] Fix test case Signed-off-by: Jinbo Wang --- .../correction/AbstractQuickFixTest.java | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java index 0970fb469d..d52b0f9270 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java @@ -17,9 +17,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.stream.Collectors; import org.eclipse.core.runtime.NullProgressMonitor; @@ -82,26 +85,41 @@ protected void assertCodeActions(ICompilationUnit cu, Collection expec assertCodeActions(cu, expected.toArray(new Expected[expected.size()])); } - protected void assertCodeActions(ICompilationUnit cu, Expected... expected) throws Exception { + protected void assertCodeActions(ICompilationUnit cu, Expected... expecteds) throws Exception { List> codeActions = evaluateCodeActions(cu); - if (codeActions.size() != expected.length) { + if (codeActions.size() < expecteds.length) { String res = ""; for (Either command : codeActions) { res += " '" + getCommand(command).getTitle() + "'"; } - assertEquals("Number of code actions: " + res, expected.length, codeActions.size()); + assertEquals("Number of code actions: " + res, expecteds.length, codeActions.size()); + } + + Map expectedActions = new HashMap<>(); + for (Expected expected : expecteds) { + for (Either command : codeActions) { + if (Objects.equals(getCommand(command).getTitle(), expected.name)) { + expectedActions.put(expected.name, expected); + break; + } + } + assertEquals("Should prompt code action: " + expected.name, expectedActions.containsKey(expected.name), true); } int k = 0; String aStr = "", eStr = "", testContent = ""; for (Either c : codeActions) { - String actual = evaluateCodeActionCommand(c); - Expected e = expected[k++]; - if (!e.name.equals(getCommand(c).getTitle()) || !e.content.equals(actual)) { - aStr += '\n' + getCommand(c).getTitle() + '\n' + actual; - eStr += '\n' + e.name + '\n' + e.content; + String title = getCommand(c).getTitle(); + if (expectedActions.containsKey(title)) { + String actual = evaluateCodeActionCommand(c); + Expected e = expectedActions.get(title); + if (!Objects.equals(e.content, actual)) { + aStr += '\n' + title + '\n' + actual; + eStr += '\n' + e.name + '\n' + e.content; + } + testContent += generateTest(actual, getCommand(c).getTitle(), k); + k++; } - testContent += generateTest(actual, getCommand(c).getTitle(), k); } if (aStr.length() > 0) { aStr += '\n' + testContent; From 8f0baacbe7e4fe2d35f09023db05c3da24e15a14 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Wed, 12 Dec 2018 13:27:32 +0800 Subject: [PATCH 3/4] Add a bindable key for bulk generate accessors Signed-off-by: Jinbo Wang --- org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF | 5 +++-- .../GenerateGetterSetterOperation.java | 12 ++++++------ .../core/internal/preferences/ClientPreferences.java | 3 ++- .../text/correction/SourceAssistProcessor.java | 6 ++++-- .../GenerateGetterAndSetterTest.java | 1 - 5 files changed, 15 insertions(+), 12 deletions(-) rename org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/{corext => }/codemanipulation/GenerateGetterSetterOperation.java (93%) diff --git a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF index cf121ca3c7..e6c2e10050 100644 --- a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF @@ -32,6 +32,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0", org.eclipse.jdt.apt.pluggable.core;bundle-version="1.2.0", org.jboss.tools.maven.apt.core;bundle-version="1.3.0" Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls.tests", + org.eclipse.jdt.ls.core.internal.codemanipulation, org.eclipse.jdt.ls.core.internal.commands;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.contentassist;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.corext.codemanipulation;x-friends:="org.eclipse.jdt.ls.tests", @@ -46,11 +47,11 @@ Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls. org.eclipse.jdt.ls.core.internal.corrections;x-internal:=true, org.eclipse.jdt.ls.core.internal.corrections.proposals;x-internal:=true, org.eclipse.jdt.ls.core.internal.handlers;x-friends:="org.eclipse.jdt.ls.tests", + org.eclipse.jdt.ls.core.internal.highlighting;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.javadoc;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.lsp;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.managers;x-friends:="org.eclipse.jdt.ls.tests", - org.eclipse.jdt.ls.core.internal.preferences;x-friends:="org.eclipse.jdt.ls.tests", - org.eclipse.jdt.ls.core.internal.highlighting;x-friends:="org.eclipse.jdt.ls.tests" + org.eclipse.jdt.ls.core.internal.preferences;x-friends:="org.eclipse.jdt.ls.tests" Bundle-ClassPath: lib/jsoup-1.9.2.jar, lib/remark-1.0.0.jar, . diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterSetterOperation.java similarity index 93% rename from org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java rename to org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterSetterOperation.java index a97853a758..cd44d4f44a 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/codemanipulation/GenerateGetterSetterOperation.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/codemanipulation/GenerateGetterSetterOperation.java @@ -9,7 +9,7 @@ * Microsoft Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.codemanipulation; +package org.eclipse.jdt.ls.core.internal.codemanipulation; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; @@ -100,22 +100,22 @@ private void generateGetterSetterMethods(ListRewrite listRewriter) throws Operat int flags = field.getFlags(); if (!Flags.isEnum(flags)) { if (GetterSetterUtil.getGetter(field) == null) { - insertMethod(field, listRewriter, GENERATE_KIND.GETTER); + insertMethod(field, listRewriter, AccessorKind.GETTER); } if (!Flags.isFinal(flags) && GetterSetterUtil.getSetter(field) == null) { - insertMethod(field, listRewriter, GENERATE_KIND.SETTER); + insertMethod(field, listRewriter, AccessorKind.SETTER); } } } } - private void insertMethod(IField field, ListRewrite rewrite, GENERATE_KIND kind) throws CoreException { + private void insertMethod(IField field, ListRewrite rewrite, AccessorKind kind) throws CoreException { IType type = field.getDeclaringType(); String delimiter = StubUtility.getLineDelimiterUsed(type); int flags = generateVisibility | (field.getFlags() & Flags.AccStatic); String stub; - if (kind == GENERATE_KIND.GETTER) { + if (kind == AccessorKind.GETTER) { String name = GetterSetterUtil.getGetterName(field, null); stub = GetterSetterUtil.getGetterStub(field, name, generateComments, flags); } else { @@ -128,7 +128,7 @@ private void insertMethod(IField field, ListRewrite rewrite, GENERATE_KIND kind) rewrite.insertLast(declaration, null); } - enum GENERATE_KIND { + enum AccessorKind { GETTER, SETTER } } \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java index 8614863c8d..4b7b18dbcc 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java @@ -220,7 +220,8 @@ public boolean isSupportedCodeActionKind(String kind) { && capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport() != null && capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport().getCodeActionKind() != null && capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport().getCodeActionKind().getValueSet() != null - && capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport().getCodeActionKind().getValueSet().contains(kind); + && capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport().getCodeActionKind().getValueSet() + .stream().filter(k -> kind.startsWith(k)).findAny().isPresent(); //@formatter:on } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java index 5c7c6214a2..a88f9a585e 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java @@ -25,7 +25,7 @@ import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.manipulation.OrganizeImportsOperation; import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore; -import org.eclipse.jdt.ls.core.internal.corext.codemanipulation.GenerateGetterSetterOperation; +import org.eclipse.jdt.ls.core.internal.codemanipulation.GenerateGetterSetterOperation; import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages; import org.eclipse.jdt.ls.core.internal.corrections.IInvocationContext; import org.eclipse.jdt.ls.core.internal.corrections.proposals.CUCorrectionProposal; @@ -35,6 +35,8 @@ import org.eclipse.text.edits.TextEdit; public class SourceAssistProcessor { + public static final String SOURCE_ACTION_GENERATE_KIND = CodeActionKind.Source + ".generate"; + public static final String SOURCE_ACTION_GENERATE_ACCESSORS_KIND = SOURCE_ACTION_GENERATE_KIND + ".accessors"; public List getAssists(IInvocationContext context, IProblemLocationCore[] locations) { ArrayList resultingCollections = new ArrayList<>(); @@ -75,7 +77,7 @@ private static void getGetterSetterProposal(IInvocationContext context, List Date: Wed, 12 Dec 2018 21:49:08 +0800 Subject: [PATCH 4/4] add x-friends directive for exported package --- org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF index e6c2e10050..a8e3bcf377 100644 --- a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF @@ -32,7 +32,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0", org.eclipse.jdt.apt.pluggable.core;bundle-version="1.2.0", org.jboss.tools.maven.apt.core;bundle-version="1.3.0" Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls.tests", - org.eclipse.jdt.ls.core.internal.codemanipulation, + org.eclipse.jdt.ls.core.internal.codemanipulation;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.commands;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.contentassist;x-friends:="org.eclipse.jdt.ls.tests", org.eclipse.jdt.ls.core.internal.corext.codemanipulation;x-friends:="org.eclipse.jdt.ls.tests",