diff options
author | Stephan Herrmann | 2023-03-30 15:48:39 +0000 |
---|---|---|
committer | Stephan Herrmann | 2023-03-30 15:48:39 +0000 |
commit | db1b02a94a8b8d4fa852179d5aa01ccda802d1a6 (patch) | |
tree | d79ea02da2d75e73b18f3f95d43537b6ba0ac870 | |
parent | 368c8fd108ff3f873eb5cf25c0f2b088c06349f7 (diff) | |
download | org.eclipse.objectteams-db1b02a94a8b8d4fa852179d5aa01ccda802d1a6.tar.gz org.eclipse.objectteams-db1b02a94a8b8d4fa852179d5aa01ccda802d1a6.tar.xz org.eclipse.objectteams-db1b02a94a8b8d4fa852179d5aa01ccda802d1a6.zip |
update jdt.core to 2e651fafefe7eb36baab915076f5230cc977a033
(right before the Java20 merge)
32 files changed, 998 insertions, 119 deletions
diff --git a/org.eclipse.jdt.core.compiler.batch/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.compiler.batch/META-INF/MANIFEST.MF index 7fb103483..553499fea 100644 --- a/org.eclipse.jdt.core.compiler.batch/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.compiler.batch/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Compiler for Java(TM) Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch -Bundle-Version: 3.33.0.OTDT_r282_qualifier +Bundle-Version: 3.33.100.OTDT_r282_qualifier Bundle-ClassPath: . Bundle-Vendor: Eclipse.org Automatic-Module-Name: org.eclipse.jdt.core.compiler.batch diff --git a/org.eclipse.jdt.core.compiler.batch/pom.xml b/org.eclipse.jdt.core.compiler.batch/pom.xml index b9fa6f2a9..c19acde72 100644 --- a/org.eclipse.jdt.core.compiler.batch/pom.xml +++ b/org.eclipse.jdt.core.compiler.batch/pom.xml @@ -14,10 +14,10 @@ <parent> <artifactId>eclipse.jdt.core</artifactId> <groupId>org.eclipse.jdt</groupId> - <version>4.27.0-SNAPSHOT</version> + <version>4.28.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId> - <version>3.33.0-SNAPSHOT</version> + <version>3.33.100-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index 2346f40da..68e6b2dfb 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -17,6 +17,7 @@ * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335 * Frits Jalvingh - contributions for bug 533830. * Red Hat Inc. - add module-info Javadoc support + * Red Hat Inc. - add NLS support for Text Blocks *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -847,7 +848,7 @@ void reportNLSProblems() { int i = 0; stringLiteralsLoop: for (; i < stringLiteralsLength; i++) { literal = this.stringLiterals[i]; - final int literalLineNumber = literal.lineNumber; + final int literalLineNumber = literal instanceof TextBlock ? ((TextBlock)literal).endLineNumber : literal.lineNumber; if (lastLineNumber != literalLineNumber) { indexInLine = 1; lastLineNumber = literalLineNumber; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TextBlock.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TextBlock.java index a4e8a571a..e092b6de9 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TextBlock.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TextBlock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 IBM Corporation and others. + * Copyright (c) 2019, 2023 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 @@ -14,7 +14,11 @@ package org.eclipse.jdt.internal.compiler.ast; public class TextBlock extends StringLiteral { - public TextBlock(char[] token, int start, int end, int lineNumber) { + public int endLineNumber; + + public TextBlock(char[] token, int start, int end, int lineNumber, int endLineNumber) { super(token, start,end, lineNumber); + this.endLineNumber= endLineNumber - 1; // line number is 1 based } + } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java index 5ad8ee805..9947ef646 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java @@ -39,6 +39,8 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; */ public class IntersectionTypeBinding18 extends ReferenceBinding { + private static final char[] INTERSECTION_PACKAGE_NAME = "<package intersection>".toCharArray(); //$NON-NLS-1$ + public ReferenceBinding [] intersectingTypes; private ReferenceBinding javaLangObject; int length; @@ -256,6 +258,11 @@ public class IntersectionTypeBinding18 extends ReferenceBinding { } @Override + public char[] qualifiedPackageName() { + return INTERSECTION_PACKAGE_NAME; + } + + @Override public char[] qualifiedSourceName() { StringBuilder qualifiedSourceName = new StringBuilder(16); for (int i = 0; i < this.length; i++) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 7637348c9..d63ca0d12 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -2881,7 +2881,7 @@ public MethodBinding[] methods() { computeRecordComponents(); MethodBinding recordExplicitCanon = checkAndGetExplicitCanonicalConstructors(); if (recordExplicitCanon != null) { - if (recordCanonIndex != -1 ) { + if (recordCanonIndex != -1 && resolvedMethods[recordCanonIndex] instanceof SyntheticMethodBinding) { removeSyntheticRecordCanonicalConstructor((SyntheticMethodBinding) resolvedMethods[recordCanonIndex]); resolvedMethods[recordCanonIndex] = null; failed++; @@ -3098,6 +3098,15 @@ public MethodBinding[] methods() { // handle forward references to potential default abstract methods addDefaultAbstractMethods(); this.tagBits |= TagBits.AreMethodsComplete; + if (this.isRecordDeclaration) { + /* https://github.com/eclipse-jdt/eclipse.jdt.core/issues/365 */ + for (int i = 0; i < this.methods.length; i++) { + MethodBinding method = this.methods[i]; + if ((method.tagBits & TagBits.AnnotationSafeVarargs) == 0 && method.sourceMethod() != null) { + checkAndFlagHeapPollution(method, method.sourceMethod()); + } + } + } } return this.methods; } @@ -3586,7 +3595,10 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin methodDecl.scope.problemReporter().safeVarargsOnNonFinalInstanceMethod(method); } } else { - checkAndFlagHeapPollution(method, methodDecl); + /* https://github.com/eclipse-jdt/eclipse.jdt.core/issues/365 */ + if (!this.isRecordDeclaration) { + checkAndFlagHeapPollution(method, methodDecl); + } } } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java index 2daab753f..bb71d4d59 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java @@ -1841,7 +1841,9 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { } consumeToken(); token = readTokenSafely(); - if (token==TerminalTokens.TokenNameERROR||token==TerminalTokens.TokenNameStringLiteral){ + if (token==TerminalTokens.TokenNameERROR + || token==TerminalTokens.TokenNameStringLiteral + || token==TerminalTokens.TokenNameIdentifier){ regionName = this.scanner.getCurrentTokenString(); consumeToken(); lastIndex = regionName.length() - 1; @@ -2007,8 +2009,9 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { indexOfLastComment = indexOfLastSingleComment(commentLine.substring(2),noSingleLineComm); commentStr = commentLine.substring(indexOfLastComment+2); } - Scanner commentScanner = new Scanner(false, false, false, this.scanner.sourceLevel, this.scanner.complianceLevel, - null, null, false, false); + Scanner commentScanner = new JavadocScanner(false, false, false/* nls */, this.scanner.sourceLevel, this.scanner.complianceLevel, + null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */, false, true, true); + if (commentStr.startsWith("//")) { //$NON-NLS-1$ commentStr = commentStr.substring(2); } @@ -2064,6 +2067,25 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { isRegion = true; break; default: + if (getRegionValue) { + String regionStr = commentScanner.getCurrentTokenString(); + regionStr = stripQuotes(regionStr); + if (START.equals(attribute) && regionStr.equals(region)) { + insideRegion = true; + regionStarted = true; + } + if (END.equals(attribute)) { + if (regionStr.equals(region)) { + insideRegion = false; + } + stack.removeFirst(); + } + if (!END.equals(attribute) && insideRegion) { + stack.addFirst(attribute); + } + attribute = null; + getRegionValue = false; + } isRegion = false; break; } @@ -2402,7 +2424,9 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { case TerminalTokens.TokenNameIdentifier: if (processValue) { value = slScanner.getCurrentTokenString(); - if (map.get(attribute) == null) { + if (REGION.equals(attribute)) { + regionName = value; + } else if (map.get(attribute) == null) { map.put(attribute, value); if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null)) || (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java index 749d4ec44..dd012b5a5 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -40,6 +40,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -12325,12 +12326,15 @@ protected void consumeTextBlock() { textBlock2, this.scanner.startPosition, this.scanner.currentPosition - 1, - Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr)); + Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr), + Util.getLineNumber(this.scanner.currentPosition - 1, this.scanner.lineEnds, 0, this.scanner.linePtr)); + this.compilationUnit.recordStringLiteral(textBlock, this.currentElement != null); } else { textBlock = new TextBlock( textBlock2, this.scanner.startPosition, this.scanner.currentPosition - 1, + 0, 0); } pushOnExpressionStack(textBlock); @@ -13854,19 +13858,16 @@ protected void consumeRecordDeclaration() { TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; this.recordNestedMethodLevels.remove(typeDecl); problemReporter().validateJavaFeatureSupport(JavaFeature.RECORDS, typeDecl.sourceStart, typeDecl.sourceEnd); + /* create canonical constructor - check for the clash later at binding time */ + /* https://github.com/eclipse-jdt/eclipse.jdt.core/issues/365 */ + typeDecl.createDefaultConstructor(!(this.diet && this.dietInt == 0), true); //convert constructor that do not have the type's name into methods ConstructorDeclaration cd = typeDecl.getConstructor(this); - if (cd == null) { - /* create canonical constructor - check for the clash later at binding time */ - cd = typeDecl.createDefaultConstructor(!(this.diet && this.dietInt == 0), true); - } else { - if (cd instanceof CompactConstructorDeclaration - || ((typeDecl.recordComponents == null || typeDecl.recordComponents.length == 0) - && (cd.arguments == null || cd.arguments.length == 0))) { - cd.bits |= ASTNode.IsCanonicalConstructor; - } + if (cd instanceof CompactConstructorDeclaration + || ((typeDecl.recordComponents == null || typeDecl.recordComponents.length == 0) + && (cd.arguments == null || cd.arguments.length == 0))) { + cd.bits |= ASTNode.IsCanonicalConstructor; } - if (this.scanner.containsAssertKeyword) { typeDecl.bits |= ASTNode.ContainsAssertion; } @@ -13875,7 +13876,10 @@ protected void consumeRecordDeclaration() { if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) { typeDecl.bits |= ASTNode.UndocumentedEmptyBlock; } - TypeReference superClass = new QualifiedTypeReference(TypeConstants.JAVA_LANG_RECORD, new long[] {0}); + char[][] sources = TypeConstants.JAVA_LANG_RECORD; + long[] poss = new long[sources.length]; + Arrays.fill(poss, 0); + TypeReference superClass = new QualifiedTypeReference(sources, poss); superClass.bits |= ASTNode.IsSuperType; typeDecl.superclass = superClass; typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF index b444b1577..e63756694 100644 --- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true -Bundle-Version: 3.12.2100.qualifier +Bundle-Version: 3.12.2200.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core.tests.compiler, diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml index f090fab59..ebb0d5f8a 100644 --- a/org.eclipse.jdt.core.tests.compiler/pom.xml +++ b/org.eclipse.jdt.core.tests.compiler/pom.xml @@ -15,11 +15,11 @@ <parent> <artifactId>tests-pom</artifactId> <groupId>org.eclipse.jdt</groupId> - <version>4.27.0-SNAPSHOT</version> + <version>4.28.0-SNAPSHOT</version> <relativePath>../tests-pom/</relativePath> </parent> <artifactId>org.eclipse.jdt.core.tests.compiler</artifactId> - <version>3.12.2100-SNAPSHOT</version> + <version>3.12.2200-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> @@ -31,7 +31,6 @@ <plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>tycho-surefire-plugin</artifactId> - <version>${tycho.version}</version> <configuration> <includes> <include>org/eclipse/jdt/core/tests/compiler/parser/TestAll.class</include> diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiteralsTest_15.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiteralsTest_15.java new file mode 100644 index 000000000..4674ceec7 --- /dev/null +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiteralsTest_15.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * Copyright (c) 2003, 2014 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.core.tests.compiler.regression; + +import java.util.Map; + +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import junit.framework.Test; + +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class ExternalizeStringLiteralsTest_15 extends AbstractRegressionTest { + +private static final JavacTestOptions JAVAC_OPTIONS = new JavacTestOptions("-source 15"); + +static { +// TESTS_NAMES = new String[] { "test000" }; +// TESTS_NUMBERS = new int[] { 6 }; +// TESTS_RANGE = new int[] { 11, -1 }; +} +public ExternalizeStringLiteralsTest_15(String name) { + super(name); +} +public static Test suite() { + return buildMinimalComplianceTestSuite(testClass(), F_15); +} + +public void test001() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + + this.runNegativeTest( + true, + new String[] { + "X.java", + "public class X\n" + + "{\n" + + " String x = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\";\n" + + "}" + }, + null, + customOptions, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " String x = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\";\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "Non-externalized string literal; it should be followed by //$NON-NLS-<n>$\n" + + "----------\n", + JAVAC_OPTIONS); +} +public void test002() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + + this.runNegativeTest( + true, + new String[] { + "X.java", + "public class X\n" + + "{\n" + + " String x = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\"; //$NON-NLS-1$ //$NON-NLS-2$\n" + + "}" + }, + null, + customOptions, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " \"\"\"; //$NON-NLS-1$ //$NON-NLS-2$\n" + + " ^^^^^^^^^^^^^\n" + + "Unnecessary $NON-NLS$ tag\n" + + "----------\n", + JAVAC_OPTIONS); +} +public void test003() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.WARNING); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + + this.runNegativeTest( + true, + new String[] { + "X.java", + "public class X\n" + + "{\n" + + " String x = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\";\n" + + " @SuppressWarnings(\"nls\")\n" + + " void foo() {\n" + + " String x2 = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\";\n" + + " }\n" + + "}" + }, + null, + customOptions, + "----------\n" + + "1. WARNING in X.java (at line 3)\n" + + " String x = \"\"\"\n" + + " abcdefg\n" + + " hijklmn\n" + + " \"\"\";\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "Non-externalized string literal; it should be followed by //$NON-NLS-<n>$\n" + + "----------\n", + JAVAC_OPTIONS); +} +public void test004() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + this.runNegativeTest( + true, + new String[] { + "X.java", + "class X {\n" + + "\n" + + " void foo() {\n" + + " String s6 = \"\"\"\n" + + " SUCCESS\n" + + " \"\"\";\n" + + " System.out.println(s6);\n" + + " }\n" + + "}", + }, + null, customOptions, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + " String s6 = \"\"\"\n" + + " SUCCESS\n" + + " \"\"\";\n" + + " ^^^^^^^^^^^^^^^^^^^^^\n" + + "Non-externalized string literal; it should be followed by //$NON-NLS-<n>$\n" + + "----------\n", + JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); +} +public void test005() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.WARNING); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + "\n" + + " public static void main(String[] args) {\n" + + " String s6 = \"\"\"\n" + + " SUCCESS\n" + + " \"\"\"; //$NON-NLS-1$\n" + + " System.out.println(s6);\n" + + " }\n" + + "}", + }, + "SUCCESS", + null, + true, + null, + customOptions, + null); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=237245 +public void test006() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); + customOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " @Annot({\n" + + " @A(name = \"\"\"\n" + + " name\n" + + " \"\"\", //$NON-NLS-1$\n" + + " value = \"\"\"\n" + + " Test\n" + + " \"\"\") //$NON-NLS-1$\n" + + " })\n" + + " @X2(\"\"\"\n" + + " \"\"\") //$NON-NLS-1$\n" + + " void foo() {\n" + + " }\n" + + "}\n" + + "@interface Annot {\n" + + " A[] value();\n" + + "}\n" + + "@interface A {\n" + + " String name();\n" + + " String value();\n" + + "}\n" + + "@interface X2 {\n" + + " String value();\n" + + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " \"\"\", //$NON-NLS-1$\n" + + " ^^^^^^^^^^^^^\n" + + "Unnecessary $NON-NLS$ tag\n" + + "----------\n" + + "2. ERROR in X.java (at line 8)\n" + + " \"\"\") //$NON-NLS-1$\n" + + " ^^^^^^^^^^^^^\n" + + "Unnecessary $NON-NLS$ tag\n" + + "----------\n" + + "3. ERROR in X.java (at line 11)\n" + + " \"\"\") //$NON-NLS-1$\n" + + " ^^^^^^^^^^^^^\n" + + "Unnecessary $NON-NLS$ tag\n" + + "----------\n", + null, + true, + customOptions); +} +public static Class testClass() { + return ExternalizeStringLiteralsTest_15.class; +} +} diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiterals15Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiteralsTest_1_5.java index bc8501f0b..31cc9e40e 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiterals15Test.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExternalizeStringLiteralsTest_1_5.java @@ -21,14 +21,14 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; @SuppressWarnings({ "unchecked", "rawtypes" }) -public class ExternalizeStringLiterals15Test extends AbstractRegressionTest { +public class ExternalizeStringLiteralsTest_1_5 extends AbstractRegressionTest { static { // TESTS_NAMES = new String[] { "test000" }; // TESTS_NUMBERS = new int[] { 7 }; // TESTS_RANGE = new int[] { 11, -1 }; } -public ExternalizeStringLiterals15Test(String name) { +public ExternalizeStringLiteralsTest_1_5(String name) { super(name); } public static Test suite() { @@ -274,6 +274,6 @@ public void test007() { customOptions); } public static Class testClass() { - return ExternalizeStringLiterals15Test.class; + return ExternalizeStringLiteralsTest_1_5.class; } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java index 993234735..e0a02bc54 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java @@ -576,6 +576,7 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { "----------\n"); } public void testBug550750_025() { + getPossibleComplianceLevels(); this.runNegativeTest( new String[] { "X.java", @@ -602,9 +603,15 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { " record Point(int myInt, int myZ, int myZ) implements I {\n" + " ^^^\n" + "Duplicate component myZ in record\n" + + "----------\n" + + "3. ERROR in X.java (at line 6)\n" + + " record Point(int myInt, int myZ, int myZ) implements I {\n" + + " ^^^\n" + + "Duplicate parameter myZ\n" + "----------\n"); } public void testBug550750_026() { + getPossibleComplianceLevels(); this.runNegativeTest( new String[] { "X.java", @@ -634,8 +641,18 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { "----------\n" + "3. ERROR in X.java (at line 6)\n" + " record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" + + " ^^^^^\n" + + "Duplicate parameter myInt\n" + + "----------\n" + + "4. ERROR in X.java (at line 6)\n" + + " record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" + " ^^^^^\n" + "Duplicate component myInt in record\n" + + "----------\n" + + "5. ERROR in X.java (at line 6)\n" + + " record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" + + " ^^^^^\n" + + "Duplicate parameter myInt\n" + "----------\n"); } public void testBug550750_027() { @@ -1112,6 +1129,7 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { "----------\n"); } public void testBug553152_008() { + getPossibleComplianceLevels(); this.runNegativeTest( new String[] { "X.java", @@ -1133,22 +1151,17 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { "interface I {}\n" }, "----------\n" + - "1. ERROR in X.java (at line 7)\n" + - " public Point {\n" + - " ^^^^^\n" + - "Duplicate method Point(Integer, int) in type Point\n" + - "----------\n" + - "2. ERROR in X.java (at line 8)\n" + + "1. ERROR in X.java (at line 8)\n" + " this.myInt = 0;\n" + " ^^^^^^^^^^\n" + "Illegal explicit assignment of a final field myInt in compact constructor\n" + "----------\n" + - "3. ERROR in X.java (at line 9)\n" + + "2. ERROR in X.java (at line 9)\n" + " this.myZ = 0;\n" + " ^^^^^^^^\n" + "Illegal explicit assignment of a final field myZ in compact constructor\n" + "----------\n" + - "4. ERROR in X.java (at line 11)\n" + + "3. ERROR in X.java (at line 11)\n" + " public Point(Integer myInt, int myZ) {\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Duplicate method Point(Integer, int) in type Point\n" + @@ -7361,6 +7374,7 @@ public void testBug563182_01() { //Test that in presence of an explicit canonical constructor that is NOT annotated with @SafeVarargs, // we don't report the warning on the record type but report on the explicit canonical constructor public void testBug563182_02() { + getPossibleComplianceLevels(); Map<String, String> customOptions = getCompilerOptions(); this.runNegativeTest( new String[] { @@ -7388,6 +7402,7 @@ public void testBug563182_02() { //Test that in presence of an explicit canonical constructor that IS annotated with @SafeVarargs, //we don't report the warning on neither the record type nor the explicit canonical constructor public void testBug563182_03() { + getPossibleComplianceLevels(); Map<String, String> customOptions = getCompilerOptions(); this.runNegativeTest( new String[] { @@ -7437,6 +7452,7 @@ public void testBug563182_04() { //Test that in presence of a compact canonical constructor that IS annotated with @SafeVarargs, //we don't report the warning on neither the record type nor the compact canonical constructor public void testBug563182_05() { + getPossibleComplianceLevels(); Map<String, String> customOptions = getCompilerOptions(); this.runNegativeTest( new String[] { @@ -8992,6 +9008,7 @@ public void testBug572934_003() { options.put(CompilerOptions.OPTION_ReportSpecialParameterHidingField, CompilerOptions.DISABLED); } public void testBug573195_001() throws Exception { + getPossibleComplianceLevels(); runConformTest( new String[] { "X.java", @@ -9009,19 +9026,20 @@ public void testBug573195_001() throws Exception { }, "1"); String expectedOutput = // constructor - " // Method descriptor #12 (I)V\n" + + " // Method descriptor #8 (I)V\n" + " // Stack: 2, Locals: 2\n" + - " protected X$R(int arg0);\n" + + " protected X$R(int i);\n" + " 0 aload_0 [this]\n" + - " 1 invokespecial java.lang.Record() [36]\n" + + " 1 invokespecial java.lang.Record() [10]\n" + " 4 aload_0 [this]\n" + - " 5 iload_1 [arg0]\n" + - " 6 putfield X$R.i : int [20]\n" + + " 5 iload_1 [i]\n" + + " 6 putfield X$R.i : int [13]\n" + " 9 return\n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X$R.class", ClassFileBytesDisassembler.SYSTEM); } public void testBug574284_001() throws Exception { + getPossibleComplianceLevels(); runConformTest( new String[] { "X.java", @@ -9042,17 +9060,17 @@ public void testBug574284_001() throws Exception { }, "0"); String expectedOutput = // constructor - " // Method descriptor #14 (Z[I)V\n" + + " // Method descriptor #10 (Z[I)V\n" + " // Stack: 2, Locals: 3\n" + - " X$Rec(boolean arg0, int... arg1);\n" + + " X$Rec(boolean isHidden, int... indexes);\n" + " 0 aload_0 [this]\n" + - " 1 invokespecial java.lang.Record() [41]\n" + + " 1 invokespecial java.lang.Record() [12]\n" + " 4 aload_0 [this]\n" + - " 5 iload_1 [arg0]\n" + - " 6 putfield X$Rec.isHidden : boolean [21]\n" + + " 5 iload_1 [isHidden]\n" + + " 6 putfield X$Rec.isHidden : boolean [15]\n" + " 9 aload_0 [this]\n" + - " 10 aload_2 [arg1]\n" + - " 11 putfield X$Rec.indexes : int[] [24]\n" + + " 10 aload_2 [indexes]\n" + + " 11 putfield X$Rec.indexes : int[] [17]\n" + " 14 return\n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X$Rec.class", ClassFileBytesDisassembler.SYSTEM); @@ -9173,4 +9191,36 @@ public void testBug576806_001() { false, options); } + +public void testIssue365_001() throws Exception { + getPossibleComplianceLevels(); + runConformTest( + new String[] { + "A.java", + "import java.util.Collections;\n" + + "import java.util.List;\n" + + "public record A(List<String> names) {\n" + + " public A(String name) {\n" + + " this(Collections.singletonList(name));\n" + + " }\n" + + " public static void main(String[] args) {\n" + + " System.out.println(0);\n" + + " }" + + "}\n" + }, + "0"); + String expectedOutput = // constructor + " // Method descriptor #10 (Ljava/util/List;)V\n" + + " // Signature: (Ljava/util/List<Ljava/lang/String;>;)V\n" + + " // Stack: 2, Locals: 2\n" + + " public A(java.util.List names);\n" + + " 0 aload_0 [this]\n" + + " 1 invokespecial java.lang.Record() [13]\n" + + " 4 aload_0 [this]\n" + + " 5 aload_1 [names]\n" + + " 6 putfield A.names : java.util.List [16]\n" + + " 9 return\n"; + RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "A.class", ClassFileBytesDisassembler.SYSTEM); + +} } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java index 4445a9858..40b0186cc 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java @@ -118,7 +118,7 @@ public static Test suite() { since_1_5.add(BatchCompilerTest.class); since_1_5.add(NullAnnotationBatchCompilerTest.class); since_1_5.add(ConcurrentBatchCompilerTest.class); - since_1_5.add(ExternalizeStringLiterals15Test.class); + since_1_5.add(ExternalizeStringLiteralsTest_1_5.class); since_1_5.add(Deprecated15Test.class); since_1_5.add(InnerEmulationTest_1_5.class); since_1_5.add(AssignmentTest_1_5.class); @@ -210,6 +210,7 @@ public static Test suite() { since_15.add(Unicode13Test.class); since_15.add(BatchCompilerTest_15.class); since_15.add(TextBlockTest.class); + since_15.add(ExternalizeStringLiteralsTest_15.class); // add 16 specific test here (check duplicates) ArrayList since_16 = new ArrayList(); diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF index dbb452b27..e3402e3a1 100644 --- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true -Bundle-Version: 3.11.400.qualifier +Bundle-Version: 3.11.600.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core.tests, diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml index a0c04d431..ac0fc3b83 100644 --- a/org.eclipse.jdt.core.tests.model/pom.xml +++ b/org.eclipse.jdt.core.tests.model/pom.xml @@ -15,11 +15,11 @@ <parent> <artifactId>tests-pom</artifactId> <groupId>org.eclipse.jdt</groupId> - <version>4.27.0-SNAPSHOT</version> + <version>4.28.0-SNAPSHOT</version> <relativePath>../tests-pom/</relativePath> </parent> <artifactId>org.eclipse.jdt.core.tests.model</artifactId> - <version>3.11.400-SNAPSHOT</version> + <version>3.11.600-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java index 33bc581fe..2ca29d14a 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java @@ -693,6 +693,9 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException { addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance, null); } + protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance, boolean exported) throws CoreException, IOException { + addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance, null, exported); + } protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws CoreException, IOException { addLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, null, null, compliance, null); } @@ -720,6 +723,19 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { String[] librariesExclusionPatterns, String compliance, Map options) throws CoreException, IOException { + addLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, librariesInclusionPatterns, librariesExclusionPatterns, compliance, options, true); + } + private void addLibrary( + IJavaProject javaProject, + String jarName, + String sourceZipName, + String[] pathAndContents, + String[] nonJavaResources, + String[] librariesInclusionPatterns, + String[] librariesExclusionPatterns, + String compliance, + Map options, + boolean exported) throws CoreException, IOException { IProject project = createLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, compliance, options); String projectPath = '/' + project.getName() + '/'; addLibraryEntry( @@ -729,7 +745,7 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { null, toIPathArray(librariesInclusionPatterns), toIPathArray(librariesExclusionPatterns), - true + exported ); } protected IProject createLibrary( diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests11.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests11.java index b34ad053a..b2b70d19d 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests11.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests11.java @@ -17,6 +17,9 @@ import org.eclipse.jdt.core.JavaModelException; import junit.framework.Test; public class CompletionTests11 extends AbstractJavaModelCompletionTests { + static { + // TESTS_NAMES = new String[] {}; + } public CompletionTests11(String name) { super(name); @@ -58,4 +61,190 @@ public void test_var_in_parameter_in_lambda() throws JavaModelException { requestor.getResults()); } +public void test_members_matching_paramater_name_on_getter() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(Task task) { \n" + + " create(task.);\n" + + " }\n" + + " public static void create(String name, boolean completed, int details) {}\n" + + " public static class Task {\n" + + " public String getName() {return null;}\n" + + " public boolean isCompleted() {return false;}\n" + + " public String details() {return null;}\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "task."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertTrue(requestor.getResults(), requestor.getResults() + .contains("getName[METHOD_REF]{getName(), Ltest.Smart$Task;, ()Ljava.lang.String;, getName, null, " + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_CASE + R_CASE + R_EXACT_EXPECTED_TYPE + + R_NON_STATIC + R_NON_RESTRICTED + R_RESOLVED) + + "}")); +} + +public void test_members_matching_paramater_name_on_non_getter() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(Task task) { \n" + + " create(task.getName(), false, task.);\n" + + " }\n" + + " public static void create(String name, boolean completed, String details, String assignee) {}\n" + + + " public static class Task {\n" + + " public String getName() {return null;}\n" + + " public boolean isCompleted() {return false;}\n" + + " public String details() {return null;}\n" + + " public int getAssignee() {return null;}\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "task."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertTrue(requestor.getResults(), requestor.getResults() + .contains("details[METHOD_REF]{details(), Ltest.Smart$Task;, ()Ljava.lang.String;, details, null, " + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_CASE + R_CASE + R_EXACT_EXPECTED_TYPE + + R_NON_STATIC + R_NON_RESTRICTED + R_RESOLVED) + + "}")); +} + +public void test_members_matching_paramater_name_on_boolean_getter() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(Task task) { \n" + + " create(task.getName(), task.);\n" + + " }\n" + + " public static void create(String name, boolean completed, String details, String assignee) {}\n" + + + " public static class Task {\n" + + " public String getName() {return null;}\n" + + " public boolean isCompleted() {return false;}\n" + + " public String details() {return null;}\n" + + " public int getAssignee() {return null;}\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "task."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertTrue(requestor.getResults(), requestor.getResults() + .contains( + "isCompleted[METHOD_REF]{isCompleted(), Ltest.Smart$Task;, ()Z, isCompleted, null, " + + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_CASE + R_CASE + R_EXACT_EXPECTED_TYPE + + R_NON_STATIC + R_NON_RESTRICTED + R_RESOLVED) + + "}")); +} + +public void test_members_matching_paramater_name_on_wrong_type() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(Task task) { \n" + + " create(task.getName(), false, \"\", task.);\n" + + " }\n" + + " public static void create(String name, boolean completed, String details, String assignee) {}\n" + + + " public static class Task {\n" + + " public String getName() {return null;}\n" + + " public boolean isCompleted() {return false;}\n" + + " public String details() {return null;}\n" + + " public int getAssignee() {return null;}\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "task."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertFalse(requestor.getResults(), requestor.getResults() + .contains( + "getAssignee[METHOD_REF]{getAssignee(), Ltest.Smart$Task;, ()Ljava.lang.String;, getAssignee, null, " + + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_EXACT_EXPECTED_TYPE + R_NON_STATIC + + R_NON_RESTRICTED + R_RESOLVED) + + "}")); +} + +public void test_members_matching_paramater_name_on_field() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(Task task) { \n" + + " create(task.getName(), false, \"\", task.);\n" + + " }\n" + + " public static void create(String name, boolean completed, String details, String assignee) {}\n" + + + " public static class Task {\n" + + " public String getName() {return null;}\n" + + " public boolean isCompleted() {return false;}\n" + + " public String details() {return null;}\n" + + " public int getAssignee() {return null;}\n" + + " public String assignee;}\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "task."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertTrue(requestor.getResults(), requestor.getResults() + .contains( + "assignee[FIELD_REF]{assignee, Ltest.Smart$Task;, Ljava.lang.String;, assignee, null, " + + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_CASE + R_CASE + R_EXACT_EXPECTED_TYPE + + R_NON_STATIC + R_NON_RESTRICTED + R_RESOLVED) + + "}")); +} + +public void test_members_matching_paramater_name_on_local_variable() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Smart.java", + "package test;\n" + + "public class Smart {\n" + + " public static void persist(String name, String shortName) { \n" + + " create(null, false, null, null);\n" + + " }\n" + + " public static void create(String name, boolean completed, String details, String assignee) {}\n" + + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "create("; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertTrue(requestor.getResults(), requestor.getResults() + .contains( + "name[LOCAL_VARIABLE_REF]{name, null, Ljava.lang.String;, name, null, " + + + (R_DEFAULT + R_INTERESTING + R_EXACT_NAME + R_CASE + R_NON_STATIC + R_NON_RESTRICTED + + R_UNQUALIFIED) + + "}")); +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java index 5ab2d775f..864669cef 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java @@ -6753,4 +6753,50 @@ public void testGH583_onArrayCreationSupplier_expectNewMethodRefCompletions() th assertTrue(String.format("Result doesn't contain expected methods (%s)", result), result.contains("new[KEYWORD]{new, null, null, new, null, 49}")); } +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/767 +public void testGH767() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/Foo.java", + "public class Foo {\n" + + " public void foo() {\n" + + " \"abc\".substring(i)." + + " }\n" + + "}"); + + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + + String str = this.workingCopies[0].getSource(); + String completeBehind = "substring(i)."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor()); + + String result = requestor.getResults(); + assertTrue(String.format("Result doesn't contain expected method (%s)", result), + result.contains("length[METHOD_REF]{length(), Ljava.lang.String;, ()I, length, null, 60}\n")); +} +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/831 +public void testIntersection18GH831() throws Exception { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/Foo.java", + "public class Foo {\n" + + " public void foo() {\n" + + " java.util.Optional.of(true ? 0 : \"\")." + + " }\n" + + "}"); + + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + requestor.allowAllRequiredProposals(); + + String str = this.workingCopies[0].getSource(); + String completeBehind = "of(true ? 0 : \"\")."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor()); + + String result = requestor.getResults(); + assertTrue(String.format("Result doesn't contain expected method (%s)", result), + result.contains("get[METHOD_REF]{get(), Ljava.util.Optional<Ljava.io.Serializable;>;, ()Ljava.io.Serializable;, get, null, 60}\n")); +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs16Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs16Tests.java index 8123f7832..ba6ade14b 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs16Tests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs16Tests.java @@ -16,9 +16,11 @@ import java.io.IOException; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.ILocalVariable; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.search.IJavaSearchScope; @@ -621,6 +623,44 @@ public class JavaSearchBugs16Tests extends AbstractJavaSearchTests { } } + + /* + * A record defined in a JRE class causes an AIOOBE during a call hierarchy computation. + * The record is encountered while indexing a Java project with a snippet, + * when computing the call hierarchy of a field in the snippet. + * The same AIOOBE can be reproduced with a reference search in the same snippet. + * https://github.com/eclipse-jdt/eclipse.jdt.core/issues/790 + */ + public void testAIOOBEForRecordClassGh790() throws Exception { + String testProjectName = "gh790AIOOBEForRecordClass"; + try { + IJavaProject project = createJava16Project(testProjectName, new String[] {"src"}); + String packageFolder = "/" + testProjectName + "/src/test"; + createFolder(packageFolder); + String testSource = + "package test;\n" + + "public class Test {\n" + + "protected final java.util.HashMap<?, ?> internal;\n" + + "protected final java.util.HashMap<?, ?> map;\n" + + " public Test() {\n" + + " internal = new java.util.HashMap<>();\n" + + " map = internal;\n" + + " }\n" + + "}\n"; + createFile(packageFolder + "/Test.java", testSource); + buildAndExpectNoProblems(project); + + IType type = project.findType("test.Test"); + IField field = type.getField("internal"); + search(field, REFERENCES, EXACT_RULE, SearchEngine.createWorkspaceScope(), this.resultCollector); + assertSearchResults( + "src/test/Test.java test.Test() [internal] EXACT_MATCH\n" + + "src/test/Test.java test.Test() [internal] EXACT_MATCH"); + } finally { + deleteProject(testProjectName); + } + } + } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java index e7c98ee78..7ecabdae7 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java @@ -15422,7 +15422,7 @@ public void testMethodReferenceAfterCompileErrorBugGh438() throws Exception { } /* - * Test that having a module conflict in projects that are on the compile classpath + * Test that having a module conflict in libraries that are on the compile classpath * (and not the compile module path) doesn't affect searching for types in those projects. * https://github.com/eclipse-jdt/eclipse.jdt.core/issues/675 */ @@ -15482,6 +15482,82 @@ public void testModuleConflictForClasspathProjectsBugGh675() throws Exception { } } +/** + * A modular project refers to a modular library defining a type {@code TestClass}, + * this project also references a non-modular project on its classpath. + * The non-modular project uses a non-modular library that defines the same type {@code TestClass}. + * Since neither project exports the library, there is no compile error and no module conflict for the type. + * This test ensures the search doesn't run into a module conflict due to not considering whether the libraries are exported. + * + * Originally the problem was observed by using a Java 8 project and a Java 11 project, + * with {@code java.util.Locale} as the type that causes the search to run into a module conflict. + * + * https://github.com/eclipse-jdt/eclipse.jdt.core/issues/723 + */ +public void testModuleConflictGh723() throws Exception { + String projectName = "gh723Project"; + String modularProjectName = "gh723ProjectModular"; + try { + IJavaProject project = createJavaProject(projectName, new String[] {"src"}, new String[] {"JCL11_LIB"}, "bin", "11"); + IJavaProject modularProject = createJavaProject(modularProjectName, new String[] {"src"}, new String[] {"JCL11_LIB"}, "bin", "11"); + + createFolder("/" + projectName + "/src/test/"); + createFile("/" + projectName + "/src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " public static void test(testpackage.TestClass t) {\n" + + " }\n" + + "}"); + + createFolder("/" + modularProjectName + "/src/testmodular/"); + createFile("/" + modularProjectName + "/src/testmodular/TestModular.java", + "package testmodular;\n" + + "public class TestModular {\n" + + " public void testModular() {\n" + + " test.Test.test(null);\n" + + " }\n" + + "}"); + + String ambiguousTypeDefinition = + "package testpackage;\n" + + "public class TestClass {\n" + + "}"; + + addLibrary(project, + "libGh723.jar", + "libGh723.src.zip", + new String[] { + "testpackage/TestClass.java", + ambiguousTypeDefinition }, + JavaCore.VERSION_1_8, + false); + + addModularLibrary(modularProject, + "libGh723_modular.jar", + "libGh723_modular.src.zip", + new String[] { + "module-info.java", + "module testmodule {\n" + + " exports testpackage;\n" + + "}", + "testpackage/TestClass.java", + ambiguousTypeDefinition }, + JavaCore.VERSION_11); + + addClasspathEntry(modularProject, JavaCore.newProjectEntry(project.getPath())); + buildAndExpectNoProblems(project, modularProject); + + IType type = project.findType("test.Test"); + IMethod method = type.getMethod("test", new String [] {"Qtestpackage.TestClass;"}); + search(method, REFERENCES, EXACT_RULE, SearchEngine.createWorkspaceScope(), this.resultCollector); + assertSearchResults( + "src/testmodular/TestModular.java void testmodular.TestModular.testModular() [test(null)] EXACT_MATCH"); + } finally { + deleteProject(projectName); + deleteProject(modularProjectName); + } +} + private static String toString(char[][] modules) { StringBuilder sb = new StringBuilder(); for (char[] m : modules) { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java index 470c02045..2b81638d6 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java @@ -40,8 +40,10 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jdt.core.IAccessRule; +import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; @@ -2835,6 +2837,65 @@ public class JavaSearchBugsTests2 extends AbstractJavaSearchTests { } } + /** + * Test that a diamond in a type name doesn't result in an AIOOBE during a search. + * See: https://github.com/eclipse-jdt/eclipse.jdt.core/issues/825 + */ + public void testOutOfBoundsIndexExceptionDuringSearchGh825() throws Exception { + String projectName = "testGh825"; + try { + IJavaProject project = createJavaProject(projectName, new String[] {"src"}, new String[] {"JCL11_LIB"}, "bin", "11"); + String srcFolder = "/" + projectName + "/src/"; + String packageFolder = srcFolder + "test"; + createFolder(packageFolder); + String snippet = String.join(System.lineSeparator(), new String[] { + "package test;", + "public class Test {", + " public interface TestInterface<T> {", + " void testMethod(T t);", + " }", + " TestInterface<String> SUP = new TestInterface<>() {", + " public void testMethod(String s) {}", + " };", + " static void shouldFail() {}", + "}", + }); + createFile(packageFolder + "/Test.java", snippet); + + String module = "module tester {}"; + createFile(srcFolder + "/module-info.java", module); + + String testFolder = "/" + projectName + "/test"; + createFolder(testFolder); + IClasspathAttribute[] testAttrs = { JavaCore.newClasspathAttribute(IClasspathAttribute.TEST, Boolean.toString(true)) }; + addClasspathEntry(project, JavaCore.newSourceEntry( + new Path(testFolder), + null, + null, + new Path("/" + projectName + "/bin-test"), + testAttrs)); + + addLibrary(project, + "libGh825.jar", + "libGh825.src.zip", + new String[] { + "testpackage/TestClass.java", + "package testpackage;\n" + + "public class TestClass {}" + }, + JavaCore.VERSION_11); + + buildAndExpectNoProblems(project); + IType type = project.findType("test.Test"); + IMethod method = type.getMethod("shouldFail", new String[0]); + search(method, REFERENCES, EXACT_RULE, SearchEngine.createWorkspaceScope(), this.resultCollector); + // we expect no matches and no exceptions + assertSearchResults(""); + } finally { + deleteProject(projectName); + } + } + private static void printJavaElements(IJavaProject javaProject, PrintStream output) throws Exception { output.println("Printing Java elements of Java project: " + javaProject); List<IJavaElement> queue = new LinkedList<>(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java index c7811cbac..3e3f73d9f 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java @@ -5604,7 +5604,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { try { IClasspathAttribute[] attributes = { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), - JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.desktop=/missing.path::java.base=/org.astro.patch/src:/org.astro.patch/src2") + JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.desktop=/missing.path::java.base=/org.astro.patch/src"+File.pathSeparator+"/org.astro.patch/src2") }; IJavaProject patchProject = createJava9ProjectWithJREAttributes("org.astro.patch", new String[]{"src", "src2"}, attributes); diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF index b6d7e883f..2d8c4b2c2 100644 --- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true -Bundle-Version: 3.33.0.OTDT_r282_qualifier +Bundle-Version: 3.33.100.OTDT_r282_qualifier Bundle-Activator: org.eclipse.jdt.core.JavaCore Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -52,7 +52,7 @@ Require-Bundle: org.eclipse.core.resources;bundle-version="[3.18.0,4.0.0)", org.eclipse.core.filesystem;bundle-version="[1.7.0,2.0.0)", org.eclipse.text;bundle-version="[3.6.0,4.0.0)", org.eclipse.team.core;bundle-version="[3.1.0,4.0.0)";resolution:=optional, - org.eclipse.jdt.core.compiler.batch;bundle-version="3.33.0.OTDT_r282";visibility:=reexport + org.eclipse.jdt.core.compiler.batch;bundle-version="3.33.100.OTDT_r282";visibility:=reexport Bundle-RequiredExecutionEnvironment: JavaSE-11 Eclipse-ExtensibleAPI: true Bundle-ActivationPolicy: lazy diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java index d54d61793..5cde37727 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java @@ -25,13 +25,15 @@ package org.eclipse.jdt.internal.codeassist; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.StreamSupport; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -261,7 +263,7 @@ import org.eclipse.jdt.internal.core.SourceMethodElementInfo; import org.eclipse.jdt.internal.core.SourceType; import org.eclipse.jdt.internal.core.SourceTypeElementInfo; import org.eclipse.jdt.internal.core.search.BasicSearchEngine; -import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment; +import org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; import org.eclipse.objectteams.otdt.core.IOTType; @@ -501,8 +503,7 @@ public final class CompletionEngine //{ObjectTeams: prefixes for callout-to-field: private static final char[] SET = "set".toCharArray(); //$NON-NLS-1$ - - private static final char[] GET = "get".toCharArray(); //$NON-NLS-1$ + // GET is declared below (regular JDT) // SH} public static char[] createBindingKey(char[] packageName, char[] typeName) { @@ -722,6 +723,8 @@ public final class CompletionEngine createTypeSignature(CharOperation.concatWith(JAVA_LANG, '.'), OBJECT); private final static char[] JAVA_LANG_NAME = CharOperation.concatWith(JAVA_LANG, '.'); + private final static char[] GET = "get".toCharArray(); //$NON-NLS-1$ + private final static char[] IS = "is".toCharArray(); //$NON-NLS-1$ private final static int NONE = 0; private final static int SUPERTYPE = 1; @@ -5022,16 +5025,28 @@ public final class CompletionEngine } return 0; } - int computeRelevanceForCaseMatching(char[] token, char[] proposalName){ - if(CharOperation.equals(token, proposalName, true)) { + + int computeRelevanceForCaseMatching(char[][] tokens, char[] proposalName) { + int finalRelevance = 0; + for (int i = 0; i < tokens.length; i++) { + int relevance = computeRelevanceForCaseMatching(tokens[i], proposalName); + if (relevance > finalRelevance) { + finalRelevance = relevance; + } + } + return finalRelevance; + } + + int computeRelevanceForCaseMatching(char[] token, char[] proposalName) { + if (CharOperation.equals(token, proposalName, true)) { return R_EXACT_NAME + R_CASE; - } else if(CharOperation.equals(token, proposalName, false)) { + } else if (CharOperation.equals(token, proposalName, false)) { return R_EXACT_NAME; } else if (CharOperation.prefixEquals(token, proposalName, false)) { if (CharOperation.prefixEquals(token, proposalName, true)) return R_CASE; - } else if (this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, proposalName)){ - return R_CAMEL_CASE; + } else if (this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, proposalName)) { + return R_CAMEL_CASE; } else if (this.options.substringMatch && CharOperation.substringMatch(token, proposalName)) { return R_SUBSTRING; } else if (this.options.subwordMatch && CharOperation.subWordMatch(token, proposalName)) { @@ -7303,6 +7318,9 @@ public final class CompletionEngine } } } + + char[] boostMatches = findParameterNameAtLocationFromAssistParent(new ObjectVector()); + // Inherited fields which are hidden by subclasses are filtered out // No visibility checks can be performed without the scope & invocationSite @@ -7481,6 +7499,9 @@ public final class CompletionEngine relevance += computeRelevanceForResolution(); relevance += computeRelevanceForInterestingProposal(field); relevance += computeRelevanceForCaseMatching(fieldName, field.name); + if(boostMatches.length > 0) { + relevance += computeRelevanceForCaseMatching(boostMatches, field.name); + } int computeRelevanceForExpectingType = computeRelevanceForExpectingType(field.type); if(this.strictMatchForExtepectedType && computeRelevanceForExpectingType <= 0) { continue; @@ -9875,6 +9896,14 @@ public final class CompletionEngine int minTypeArgLength = typeArgTypes == null ? 0 : typeArgTypes.length; int minArgLength = argTypes == null ? 0 : argTypes.length; + char[][] boostMatches = new char[0][]; + char[] parameterName = findParameterNameAtLocationFromAssistParent(new ObjectVector()); + if(parameterName.length > 0) { + char[] nameForMethods = capitalize(parameterName); + boostMatches = new char[][] { parameterName, CharOperation.concat(GET, nameForMethods), + CharOperation.concat(IS, nameForMethods) }; + } + next : for (int f = methods.length; --f >= 0;) { MethodBinding method = methods[f]; @@ -10128,6 +10157,9 @@ public final class CompletionEngine relevance += computeRelevanceForResolution(); relevance += computeRelevanceForInterestingProposal(); relevance += computeRelevanceForCaseMatching(methodName, method.selector); + if(boostMatches.length > 0) { + relevance += computeRelevanceForCaseMatching(boostMatches, method.selector); + } int computeRelevanceForExpectingType = computeRelevanceForExpectingType(method.returnType); if(this.strictMatchForExtepectedType && computeRelevanceForExpectingType <= 0) { continue; @@ -10292,6 +10324,55 @@ public final class CompletionEngine methodsFound.addAll(newMethodsFound); } + + private char[] capitalize(char[] name) { + char[] result = new char[name.length]; + for (int i = 0; i < name.length; i++) { + if (i == 0) { + result[i] = Character.toUpperCase(name[i]); + } else { + result[i] = name[i]; + } + } + return result; + } + + private char[] findParameterNameAtLocationFromAssistParent(ObjectVector methodsFound) { + char[] parameterName = new char[0]; + MethodBinding[] candidates; + final MessageSend parent; + if (this.parser.assistNodeParent instanceof MessageSend) { + parent = (MessageSend) this.parser.assistNodeParent; + candidates = Optional.ofNullable(parent.actualReceiverType) + .or(() -> Optional.ofNullable(parent.receiver).map(r -> r.resolvedType)) + .map(t -> t.getMethods(parent.selector)).orElse(new MethodBinding[0]); + } else if (this.parser.assistNode instanceof MessageSend) { + parent = (MessageSend) this.parser.assistNode; + candidates = StreamSupport.stream(methodsFound.spliterator(), false) + .filter(Objects::nonNull) + .filter(o -> o instanceof Object[]).map(o -> (Object[]) o) + .map(o -> o[0]).filter(o -> o instanceof MethodBinding).map(b -> (MethodBinding) b) + .filter(b -> CharOperation.equals(parent.selector, b.selector)).findFirst() + .map(m -> new MethodBinding[] { m }).orElse(new MethodBinding[0]); + } else { + return parameterName; + } + + final int argumentLength = (parent.arguments != null) ? parent.arguments.length : 1; + for (MethodBinding binding : candidates) { + if (binding.parameterNames.length >= argumentLength) { + for (int i = 0; i < argumentLength; i++) { + if (parent.arguments == null || parent.arguments[i] == this.parser.assistNode) { + parameterName = binding.parameterNames[i]; + } + } + } + if (parameterName.length > 0) { + break; + } + } + return parameterName; + } private void findLocalMethodsFromFavorites( char[] methodName, MethodBinding[] methods, @@ -13896,6 +13977,8 @@ public final class CompletionEngine Scope currentScope = scope; + char[] boostMatches = findParameterNameAtLocationFromAssistParent(methodsFound); + if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found @@ -13975,6 +14058,9 @@ public final class CompletionEngine relevance += computeRelevanceForResolution(); relevance += computeRelevanceForInterestingProposal(local); relevance += computeRelevanceForCaseMatching(token, local.name); + if(boostMatches.length > 0) { + relevance += computeRelevanceForCaseMatching(boostMatches, local.name); + } int computeRelevanceForExpectingType = computeRelevanceForExpectingType(local.type); if(this.strictMatchForExtepectedType && computeRelevanceForExpectingType <= 0) { continue; @@ -14274,7 +14360,7 @@ public final class CompletionEngine private INameEnvironment getNoCacheNameEnvironment() { if (this.noCacheNameEnvironment == null) { JavaModelManager.getJavaModelManager().cacheZipFiles(this); - this.noCacheNameEnvironment = IndexBasedJavaSearchEnvironment.create(Collections.singletonList(this.javaProject), this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/)); + this.noCacheNameEnvironment = new JavaSearchNameEnvironment(this.javaProject, this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/)); } return this.noCacheNameEnvironment; } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java index dbb7888a8..a4d3cb43d 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java @@ -82,6 +82,9 @@ public class CompletionOnMemberAccess extends FieldReference { ProblemMethodBinding problemMethodBinding = new ProblemMethodBinding(messageSend.selector, argBindings, ProblemReasons.NotFound); throw new CompletionNodeFound(this, problemMethodBinding, scope); } + if (messageSend.binding != null) { + throw new CompletionNodeFound(this, messageSend.binding.declaringClass, scope); + } } if (this.actualReceiverType == null || !this.actualReceiverType.isValidBinding()) diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java index a56925643..3b07cf141 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java @@ -602,9 +602,12 @@ public abstract class TypeConverter { /* rebuild identifiers and dimensions */ if (identCount == 1) { // simple type reference if (dim == 0) { + int n = typeName.length; + boolean hasDiamond = n > 2 && typeName[n - 2] == '<' && typeName[n - 1] == '>'; char[] nameFragment; - if (nameFragmentStart != 0 || nameFragmentEnd >= 0) { - int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1; + int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1; + boolean hasEmptyFragment = nameFragmentLength == 0 && hasDiamond; + if ((nameFragmentStart != 0 || nameFragmentEnd >= 0) && !hasEmptyFragment) { System.arraycopy(typeName, nameFragmentStart, nameFragment = new char[nameFragmentLength], 0, nameFragmentLength); } else { nameFragment = typeName; @@ -618,7 +621,11 @@ public abstract class TypeConverter { return new TypeAnchorReference(name, start); } // SH} - return new SingleTypeReference(nameFragment, ((long) start << 32) + end); + SingleTypeReference singleTypeReference = new SingleTypeReference(nameFragment, ((long) start << 32) + end); + if (hasDiamond) { + singleTypeReference.bits |= ASTNode.IsDiamond; + } + return singleTypeReference; } else { int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1; char[] nameFragment = new char[nameFragmentLength]; diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml index fa2d20b13..323ec7315 100644 --- a/org.eclipse.jdt.core/pom.xml +++ b/org.eclipse.jdt.core/pom.xml @@ -14,10 +14,10 @@ <parent> <artifactId>eclipse.jdt.core</artifactId> <groupId>org.eclipse.jdt</groupId> - <version>4.27.0-SNAPSHOT</version> + <version>4.28.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jdt.core</artifactId> - <version>3.33.0-SNAPSHOT</version> + <version>3.33.100-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java index 0a80f8ab9..19415b96d 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java @@ -13,13 +13,11 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.search.indexing; -import java.util.Collections; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; -import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.CharOperation; @@ -55,7 +53,7 @@ import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.SourceTypeElementInfo; import org.eclipse.jdt.internal.core.jdom.CompilationUnit; -import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment; +import org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment; import org.eclipse.jdt.internal.core.search.matching.MethodPattern; import org.eclipse.jdt.internal.core.search.processing.JobManager; import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config; @@ -176,7 +174,7 @@ public class SourceIndexer extends AbstractIndexer implements ITypeRequestor, Su this.cud = this.basicParser.parse(this.compilationUnit, new CompilationResult(this.compilationUnit, 0, 0, this.options.maxProblemsPerUnit)); JavaModelManager.getJavaModelManager().cacheZipFiles(this); // use model only for caching // Use a non model name environment to avoid locks, monitors and such. - INameEnvironment nameEnvironment = IndexBasedJavaSearchEnvironment.create(Collections.singletonList((IJavaProject)javaProject), JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, true/*add primary WCs*/)); + INameEnvironment nameEnvironment = new JavaSearchNameEnvironment(javaProject, JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, true/*add primary WCs*/)); this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, nameEnvironment); reduceParseTree(this.cud); //{ObjectTeams: need Dependencies configured: diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/IndexBasedJavaSearchEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/IndexBasedJavaSearchEnvironment.java deleted file mode 100644 index 65c2e14da..000000000 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/IndexBasedJavaSearchEnvironment.java +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2018 Google, Inc 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: - * Stefan Xenos (Google) - Initial implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.core.search.matching; - -import java.util.Iterator; -import java.util.List; - -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.internal.compiler.env.INameEnvironment; -import org.eclipse.jdt.internal.core.JavaProject; - -public class IndexBasedJavaSearchEnvironment { - - public static INameEnvironment create(List<IJavaProject> javaProjects, org.eclipse.jdt.core.ICompilationUnit[] copies) { - Iterator<IJavaProject> next = javaProjects.iterator(); - JavaSearchNameEnvironment result = new JavaSearchNameEnvironment(next.next(), copies); - - while (next.hasNext()) { - result.addProjectClassPath((JavaProject)next.next()); - } - return result; - } -} diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java index 7c21e9803..3fcb71f1b 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java @@ -17,7 +17,9 @@ import static java.util.stream.Collectors.joining; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -40,6 +42,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; @@ -159,6 +162,10 @@ public void cleanup() { } protected /* visible for testing only */ void addProjectClassPath(JavaProject javaProject) { + addProjectClassPath(javaProject, false); +} + +void addProjectClassPath(JavaProject javaProject, boolean onlyExported) { long start = 0; if (NameLookup.VERBOSE) { Util.verbose(" EXTENDING JavaSearchNameEnvironment"); //$NON-NLS-1$ @@ -166,7 +173,7 @@ protected /* visible for testing only */ void addProjectClassPath(JavaProject ja start = System.currentTimeMillis(); } - LinkedHashSet<ClasspathLocation> locations = computeClasspathLocations(javaProject); + LinkedHashSet<ClasspathLocation> locations = computeClasspathLocations(javaProject, onlyExported); if (locations != null) this.locationSet.addAll(locations); if (NameLookup.VERBOSE) { @@ -177,6 +184,10 @@ protected /* visible for testing only */ void addProjectClassPath(JavaProject ja } private LinkedHashSet<ClasspathLocation> computeClasspathLocations(JavaProject javaProject) { + return computeClasspathLocations(javaProject, false); +} + +private LinkedHashSet<ClasspathLocation> computeClasspathLocations(JavaProject javaProject, boolean onlyExported) { IPackageFragmentRoot[] roots = null; try { @@ -195,7 +206,11 @@ private LinkedHashSet<ClasspathLocation> computeClasspathLocations(JavaProject j int length = roots.length; JavaModelManager manager = JavaModelManager.getJavaModelManager(); for (int i = 0; i < length; i++) { - ClasspathLocation cp = mapToClassPathLocation(manager, (PackageFragmentRoot) roots[i], imd); + PackageFragmentRoot root = (PackageFragmentRoot) roots[i]; + if (onlyExported && !isSourceOrExported(root)) { + continue; + } + ClasspathLocation cp = mapToClassPathLocation(manager, root, imd); if (cp != null) { try { indexPackageNames(cp, roots[i]); @@ -561,6 +576,16 @@ public char[][] getAllAutomaticModules() { return set.toArray(new char[set.size()][]); } +public static INameEnvironment createWithReferencedProjects(IJavaProject javaProject, List<IJavaProject> referencedProjects, org.eclipse.jdt.core.ICompilationUnit[] copies) { + JavaSearchNameEnvironment result = new JavaSearchNameEnvironment(javaProject, copies); + + Iterator<IJavaProject> next = referencedProjects.iterator(); + while (next.hasNext()) { + result.addProjectClassPath((JavaProject)next.next(), true); + } + return result; +} + private static boolean isComplianceJava9OrHigher(IJavaProject javaProject) { if (javaProject == null) { return false; @@ -607,4 +632,15 @@ private static boolean hasSystemModule(PackageFragmentRoot fragmentRoot) { } return false; } + +private static boolean isSourceOrExported(PackageFragmentRoot root) { + boolean isExported = true; // if we run into exceptions, assume exported + try { + IClasspathEntry entry = root.getRawClasspathEntry(); + isExported = entry.getEntryKind() == IClasspathEntry.CPE_SOURCE || entry.isExported(); + } catch (JavaModelException e) { + Util.log(e, "Error checking whether package fragment root is exported!"); //$NON-NLS-1$ + } + return isExported; +} } diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java index fad008d2a..64a7e90c4 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java @@ -1329,14 +1329,13 @@ public void initialize(JavaProject project, int possibleMatchSize) throws JavaMo SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.workingCopies); List<IJavaProject> projects = new ArrayList<>(); - projects.add(project); if (this.pattern.focus != null) { IJavaProject focusProject = this.pattern.focus.getJavaProject(); if (!project.equals(focusProject)) { projects.add(focusProject); } } - this.nameEnvironment = IndexBasedJavaSearchEnvironment.create(projects, this.workingCopies); + this.nameEnvironment = JavaSearchNameEnvironment.createWithReferencedProjects(project, projects, this.workingCopies); // create lookup environment Map map = project.getOptions(true); |