diff options
author | Till Brychcy | 2017-07-26 14:39:07 +0000 |
---|---|---|
committer | Till Brychcy | 2017-12-17 15:42:28 +0000 |
commit | 9e60b686a9f4ca3cc115c793d65d32f226f9f749 (patch) | |
tree | 66a29ff9e97ea18e416b1a5c90cbc8a8bea090f5 | |
parent | 05dfe0ebf68f8d862634fcc05d3fdf4e82d1dde1 (diff) | |
download | eclipse.jdt.ui-9e60b686a9f4ca3cc115c793d65d32f226f9f749.tar.gz eclipse.jdt.ui-9e60b686a9f4ca3cc115c793d65d32f226f9f749.tar.xz eclipse.jdt.ui-9e60b686a9f4ca3cc115c793d65d32f226f9f749.zip |
Bug 528871 - [1.8][null] Avoid creating redundant @NonNull in "Anonymous
Inner Type" completion
Change-Id: I42532b411a9135b261fe30bd29c6b15bcddccc6a
2 files changed, 135 insertions, 4 deletions
diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest18.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest18.java index d501b941ab..f68c2f9c1f 100644 --- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest18.java +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/contentassist/CodeCompletionTest18.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 GK Software AG, IBM Corporation and others. + * Copyright (c) 2014, 2017 GK Software AG, IBM 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 @@ -12,6 +12,7 @@ package org.eclipse.jdt.text.tests.contentassist; import java.util.Hashtable; +import java.util.Map; import org.eclipse.jdt.testplugin.JavaProjectHelper; import org.eclipse.jdt.testplugin.TestOptions; @@ -21,6 +22,7 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.source.ISourceViewer; @@ -767,4 +769,124 @@ public class CodeCompletionTest18 extends AbstractCompletionTest { buf.append("}\n"); assertEquals(buf.toString(), doc.get()); } + private void prepareNullAnnotations(IPackageFragmentRoot sourceFolder) throws JavaModelException { + Map<String, String> options= fJProject1.getOptions(true); + options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED); + options.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "annots.NonNull"); + options.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "annots.Nullable"); + options.put(JavaCore.COMPILER_NONNULL_BY_DEFAULT_ANNOTATION_NAME, "annots.NonNullByDefault"); + fJProject1.setOptions(options); + + IPackageFragment pack0= sourceFolder.createPackageFragment("annots", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package annots;\n"); + buf.append("\n"); + buf.append("import java.lang.annotation.*;\n"); + buf.append("\n"); + buf.append("@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)\n"); + buf.append("@Target({ ElementType.TYPE_USE })\n"); + buf.append("public @interface NonNull {}\n"); + pack0.createCompilationUnit("NonNull.java", buf.toString(), false, null); + + buf= new StringBuffer(); + buf.append("package annots;\n"); + buf.append("\n"); + buf.append("import java.lang.annotation.*;\n"); + buf.append("\n"); + buf.append("@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)\n"); + buf.append("@Target({ ElementType.TYPE_USE })\n"); + buf.append("public @interface Nullable {}\n"); + pack0.createCompilationUnit("Nullable.java", buf.toString(), false, null); + + buf= new StringBuffer(); + buf.append("package annots;\n"); + buf.append("\n"); + buf.append("public enum DefaultLocation { PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS, TYPE_PARAMETER }\n"); + pack0.createCompilationUnit("DefaultLocation.java", buf.toString(), false, null); + + buf= new StringBuffer(); + buf.append("package annots;\n"); + buf.append("\n"); + buf.append("import java.lang.annotation.*;\n"); + buf.append("import static annots.DefaultLocation.*;\n"); + buf.append("\n"); + buf.append("@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)\n"); + buf.append("@Target({ ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE })\n"); + buf.append("public @interface NonNullByDefault { DefaultLocation[] value() default {PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT}; }\n"); + pack0.createCompilationUnit("NonNullByDefault.java", buf.toString(), false, null); + } + + private static void assertNumberOf(String name, int is, int expected) { + assertTrue("Wrong number of " + name + ", is: " + is + ", expected: " + expected, is == expected); + } + + public void testBug528871() throws Exception { + IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); + prepareNullAnnotations(sourceFolder); + + IPackageFragment pack1= sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("\n"); + buf.append("import annots.NonNull;\n"); + buf.append("import annots.NonNullByDefault;\n"); + buf.append("\n"); + buf.append("interface A {\n"); + buf.append(" @NonNull String m();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("@NonNullByDefault\n"); + buf.append("public class Test {\n"); + buf.append(" void f() {\n"); + buf.append(" new A()\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append(""); + String contents= buf.toString(); + + ICompilationUnit cu= pack1.createCompilationUnit("A.java", contents, false, null); + + String str= "new A("; + + int offset= contents.indexOf(str) + str.length(); + + CompletionProposalCollector collector= createCollector(cu, offset); + collector.setReplacementLength(0); + + codeComplete(cu, offset, collector); + + IJavaCompletionProposal[] proposals= collector.getJavaCompletionProposals(); + + assertNumberOf("proposals", proposals.length, 1); + + IDocument doc= new Document(contents); + + proposals[0].apply(doc); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("\n"); + buf.append("import annots.NonNull;\n"); + buf.append("import annots.NonNullByDefault;\n"); + buf.append("\n"); + buf.append("interface A {\n"); + buf.append(" @NonNull String m();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("@NonNullByDefault\n"); + buf.append("public class Test {\n"); + buf.append(" void f() {\n"); + buf.append(" new A() {\n"); + buf.append(" \n"); + buf.append(" @Override\n"); + buf.append(" public String m() {\n"); + buf.append(" //TODO\n"); + buf.append(" return null;\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append(""); + assertEquals(buf.toString(), doc.get()); + } } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AnonymousTypeCompletionProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AnonymousTypeCompletionProposal.java index 5ba5b509ac..f072901ee2 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AnonymousTypeCompletionProposal.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AnonymousTypeCompletionProposal.java @@ -57,11 +57,13 @@ import org.eclipse.jdt.core.dom.NodeFinder; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; +import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; +import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; @@ -120,7 +122,7 @@ public class AnonymousTypeCompletionProposal extends JavaTypeCompletionProposal return buffer.toString(); } - private String createNewBody(ImportRewrite importRewrite) throws CoreException { + private String createNewBody(ImportRewrite importRewrite, int offset) throws CoreException { if (importRewrite == null) return null; @@ -148,12 +150,18 @@ public class AnonymousTypeCompletionProposal extends JavaTypeCompletionProposal // add an extra block: helps the AST to recover workingCopyContents.insert(insertPosition, '{' + dummyClassContent + '}'); insertPosition++; + if(offset > insertPosition) { + offset += dummyClassContent.length()+2; + } } else { /* * The two empty lines are added because the trackedDeclaration uses the covered range * and hence would also included comments that directly follow the dummy class. */ workingCopyContents.insert(insertPosition, dummyClassContent + "\n\n"); //$NON-NLS-1$ + if(offset > insertPosition) { + offset += dummyClassContent.length()+2; + } } workingCopy.getBuffer().setContents(workingCopyContents.toString()); @@ -164,6 +172,7 @@ public class AnonymousTypeCompletionProposal extends JavaTypeCompletionProposal parser.setSource(workingCopy); CompilationUnit astRoot= (CompilationUnit) parser.createAST(new NullProgressMonitor()); + ImportRewriteContext context=new ContextSensitiveImportRewriteContext(astRoot, offset, importRewrite); ASTNode newType= NodeFinder.perform(astRoot, insertPosition, dummyClassContent.length()); if (!(newType instanceof AbstractTypeDeclaration)) return null; @@ -238,7 +247,7 @@ public class AnonymousTypeCompletionProposal extends JavaTypeCompletionProposal ListRewrite rewriter= rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); for (int i= 0; i < methodsToOverride.length; i++) { IMethodBinding curr= methodsToOverride[i]; - MethodDeclaration stub= StubUtility2.createImplementationStub(workingCopy, rewrite, importRewrite, null, curr, dummyTypeBinding, settings, dummyTypeBinding.isInterface(), contextBinding); + MethodDeclaration stub= StubUtility2.createImplementationStub(workingCopy, rewrite, importRewrite, context, curr, dummyTypeBinding, settings, dummyTypeBinding.isInterface(), contextBinding); rewriter.insertFirst(stub, null); } @@ -385,7 +394,7 @@ public class AnonymousTypeCompletionProposal extends JavaTypeCompletionProposal @Override protected boolean updateReplacementString(IDocument document, char trigger, int offset, ImportRewrite impRewrite) throws CoreException, BadLocationException { fImportRewrite= impRewrite; - String newBody= createNewBody(impRewrite); + String newBody= createNewBody(impRewrite, offset); if (newBody == null) return false; |