diff options
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt')
24 files changed, 273 insertions, 173 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java index e62e8e210..40c728273 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 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 @@ -9,9 +9,12 @@ * IBM Corporation - initial API and implementation * Luiz-Otavio Zorzella <zorzella at gmail dot com> - Improve CamelCase algorithm * Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions + * Stefan Xenos <sxenos@gmail.com> (Google) - Bug 501283 - Lots of hash collisions during indexing *******************************************************************************/ package org.eclipse.jdt.core.compiler; +import java.util.Arrays; + import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; /** @@ -2281,19 +2284,9 @@ public static final boolean fragmentEquals( * * @param array the array for which a hashcode is required * @return the hashcode - * @throws NullPointerException if array is null */ public static final int hashCode(char[] array) { - int length = array.length; - int hash = length == 0 ? 31 : array[0]; - if (length < 8) { - for (int i = length; --i > 0;) - hash = (hash * 31) + array[i]; - } else { - // 8 characters is enough to compute a decent hash code, don't waste time examining every character - for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2) - hash = (hash * 31) + array[i]; - } + int hash = Arrays.hashCode(array); return hash & 0x7FFFFFFF; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index 96ac0a2e3..fa8ee852a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -1873,6 +1873,12 @@ void setSourceStart(int sourceStart); int IllegalDefaultModifierSpecification = MethodRelated + 1058; /** @since 3.13 */ int CannotInferInvocationType = TypeRelated + 1059; + + /** @since 3.13 */ + int TypeAnnotationAtQualifiedName = Internal + Syntax + 1060; + + /** @since 3.13 */ + int NullAnnotationAtQualifyingType = Internal + Syntax + 1061; /** @since 3.10 */ int GenericInferenceError = 1100; // FIXME: This is just a stop-gap measure, be more specific via https://bugs.eclipse.org/404675 @@ -1880,6 +1886,8 @@ void setSourceStart(int sourceStart); /** @deprecated - problem is no longer generated (implementation issue has been resolved) * @since 3.10 */ int LambdaShapeComputationError = 1101; + /** @since 3.13 */ + int ProblemNotAnalysed = 1102; //{ObjectTeams: int OTJ_RELATED = 1000000; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java index 80e2e1b9c..9fc88ae55 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java @@ -750,8 +750,11 @@ public abstract class ASTNode implements TypeConstants, TypeIds { } else { updatedArgumentType = argument.resolveType(scope); } - if (updatedArgumentType != null && updatedArgumentType.kind() != Binding.POLY_TYPE) + if (updatedArgumentType != null && updatedArgumentType.kind() != Binding.POLY_TYPE) { argumentTypes[i] = updatedArgumentType; + if (candidateMethod.isPolymorphic()) + candidateMethod.parameters[i] = updatedArgumentType; + } } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java index 828fa15f1..dfb613a58 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -654,7 +654,7 @@ public abstract class Annotation extends Expression { // no need to check annotation usage if missing return; } - if (! isAnnotationTargetAllowed(repeatingAnnotation, scope, containerAnnotationType, repeatingAnnotation.recipient.kind())) { + if (isAnnotationTargetAllowed(repeatingAnnotation, scope, containerAnnotationType, repeatingAnnotation.recipient.kind()) != AnnotationTargetAllowed.YES) { scope.problemReporter().disallowedTargetForContainerAnnotation(repeatingAnnotation, containerAnnotationType); } } @@ -987,75 +987,83 @@ public abstract class Annotation extends Expression { return this.resolvedType; } - private static boolean isAnnotationTargetAllowed(Binding recipient, BlockScope scope, TypeBinding annotationType, int kind, long metaTagBits) { + public enum AnnotationTargetAllowed { + YES, TYPE_ANNOTATION_ON_QUALIFIED_NAME, NO; + } + + private static AnnotationTargetAllowed isAnnotationTargetAllowed(Binding recipient, BlockScope scope, TypeBinding annotationType, int kind, long metaTagBits) { switch (kind) { case Binding.PACKAGE : if ((metaTagBits & TagBits.AnnotationForPackage) != 0) - return true; + return AnnotationTargetAllowed.YES; else if (scope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_6) { SourceTypeBinding sourceType = (SourceTypeBinding) recipient; if (CharOperation.equals(sourceType.sourceName, TypeConstants.PACKAGE_INFO_NAME)) - return true; + return AnnotationTargetAllowed.YES; } break; case Binding.TYPE_USE : if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { // jsr 308 - return true; + return AnnotationTargetAllowed.YES; } if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) { // already reported as syntax error; don't report secondary problems - return true; + return AnnotationTargetAllowed.YES; } break; case Binding.TYPE : case Binding.GENERIC_TYPE : if (((ReferenceBinding)recipient).isAnnotationType()) { if ((metaTagBits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) { - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForPackage) != 0) { if (CharOperation.equals(((ReferenceBinding) recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME)) - return true; + return AnnotationTargetAllowed.YES; } //{ObjectTeams: allow @Override for roles: if ( (((ReferenceBinding)recipient).isRole()) && (annotationType.id == TypeIds.T_JavaLangOverride)) - return true; + return AnnotationTargetAllowed.YES; //SH} break; //{ObjectTeams: method mappings // TODO(SH): should annotations for method mappings be controlled separately? case Binding.BINDING : if ((metaTagBits & TagBits.AnnotationForMethod) != 0) - return true; + return AnnotationTargetAllowed.YES; break; //SH} case Binding.METHOD : MethodBinding methodBinding = (MethodBinding) recipient; if (methodBinding.isConstructor()) { if ((metaTagBits & (TagBits.AnnotationForConstructor | TagBits.AnnotationForTypeUse)) != 0) - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForMethod) != 0) { - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { SourceTypeBinding sourceType = (SourceTypeBinding) methodBinding.declaringClass; MethodDeclaration methodDecl = (MethodDeclaration) sourceType.scope.referenceContext.declarationOf(methodBinding); if (isTypeUseCompatible(methodDecl.returnType, scope)) { - return true; + return AnnotationTargetAllowed.YES; + } else { + return AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME; } } break; case Binding.FIELD : if ((metaTagBits & TagBits.AnnotationForField) != 0) { - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { FieldBinding sourceField = (FieldBinding) recipient; SourceTypeBinding sourceType = (SourceTypeBinding) sourceField.declaringClass; FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField); if (isTypeUseCompatible(fieldDeclaration.type, scope)) { - return true; + return AnnotationTargetAllowed.YES; + } else { + return AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME; } } break; @@ -1063,27 +1071,31 @@ public abstract class Annotation extends Expression { LocalVariableBinding localVariableBinding = (LocalVariableBinding) recipient; if ((localVariableBinding.tagBits & TagBits.IsArgument) != 0) { if ((metaTagBits & TagBits.AnnotationForParameter) != 0) { - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) { - return true; + return AnnotationTargetAllowed.YES; + } else { + return AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME; } } } else if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0) { - return true; + return AnnotationTargetAllowed.YES; } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) { - return true; + return AnnotationTargetAllowed.YES; + } else { + return AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME; } } break; case Binding.TYPE_PARAMETER : // jsr308 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391196 if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) { - return true; + return AnnotationTargetAllowed.YES; } } - return false; + return AnnotationTargetAllowed.NO; } public static boolean isAnnotationTargetAllowed(BlockScope scope, TypeBinding annotationType, Binding recipient) { @@ -1091,10 +1103,10 @@ public abstract class Annotation extends Expression { if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) { return true; } - return isAnnotationTargetAllowed(recipient, scope, annotationType, recipient.kind(), metaTagBits); + return isAnnotationTargetAllowed(recipient, scope, annotationType, recipient.kind(), metaTagBits)==AnnotationTargetAllowed.YES; } - static boolean isAnnotationTargetAllowed(Annotation annotation, BlockScope scope, TypeBinding annotationType, int kind) { + static AnnotationTargetAllowed isAnnotationTargetAllowed(Annotation annotation, BlockScope scope, TypeBinding annotationType, int kind) { long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) { @@ -1102,7 +1114,7 @@ public abstract class Annotation extends Expression { if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) { scope.problemReporter().explitAnnotationTargetRequired(annotation); } - return true; + return AnnotationTargetAllowed.YES; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201 @@ -1129,8 +1141,13 @@ public abstract class Annotation extends Expression { // no need to check annotation usage if missing return; } - if (! isAnnotationTargetAllowed(annotation, scope, annotationType, kind)) { + AnnotationTargetAllowed annotationTargetAllowed = isAnnotationTargetAllowed(annotation, scope, annotationType, kind); + if (annotationTargetAllowed != AnnotationTargetAllowed.YES) { + if(annotationTargetAllowed == AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME) { + scope.problemReporter().typeAnnotationAtQualifiedName(annotation); + } else { scope.problemReporter().disallowedTargetForAnnotation(annotation); + } if (recipient instanceof TypeBinding) ((TypeBinding)recipient).tagBits &= ~tagBitsToRevert; } @@ -1199,7 +1216,7 @@ public abstract class Annotation extends Expression { continue nextAnnotation; } else { if (annotation.hasNullBit(TypeIds.BitNonNullAnnotation|TypeIds.BitNullableAnnotation)) { - scope.problemReporter().nullAnnotationUnsupportedLocation(annotation); + scope.problemReporter().nullAnnotationAtQualifyingType(annotation); continue nextAnnotation; } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java index 13f06d9e1..bf50c2a28 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java @@ -360,6 +360,9 @@ public static void checkNeedForArgumentCasts(BlockScope scope, int operator, int } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int ttlForFieldCheck) { + if((this.resolvedType.tagBits & TagBits.AnnotationNonNull) != 0) { + return true; + } checkNPEbyUnboxing(scope, flowContext, flowInfo); return this.expression.checkNPE(scope, flowContext, flowInfo, ttlForFieldCheck); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index 98e3208cb..04287d411 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -376,22 +376,28 @@ public void finalizeProblems() { Constant cst = inits[iToken].constant; if (cst != Constant.NotAConstant && cst.typeID() == TypeIds.T_JavaLangString) { IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); - if (tokenIrritants != null - && !tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") - && options.isAnyEnabled(tokenIrritants) // if irritant is effectively enabled - && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem - if (unusedWarningTokenIsWarning) { - int start = value.sourceStart, end = value.sourceEnd; - nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { - long position = this.suppressWarningScopePositions[jSuppress]; - int startSuppress = (int) (position >>> 32); - int endSuppress = (int) position; - if (start < startSuppress) continue nextSuppress; - if (end > endSuppress) continue nextSuppress; - if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? + if (tokenIrritants != null) { + if (!tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") + && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem + if (unusedWarningTokenIsWarning) { + int start = value.sourceStart, end = value.sourceEnd; + nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { + long position = this.suppressWarningScopePositions[jSuppress]; + int startSuppress = (int) (position >>> 32); + int endSuppress = (int) position; + if (start < startSuppress) continue nextSuppress; + if (end > endSuppress) continue nextSuppress; + if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? + } + } + int id = options.getIgnoredIrritant(tokenIrritants); + if (id > 0) { + String key = CompilerOptions.optionKeyFromIrritant(id); + this.scope.problemReporter().problemNotAnalysed(inits[iToken], key); + } else { + this.scope.problemReporter().unusedWarningToken(inits[iToken]); } } - this.scope.problemReporter().unusedWarningToken(inits[iToken]); } } } @@ -400,22 +406,28 @@ public void finalizeProblems() { Constant cst = value.constant; if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); - if (tokenIrritants != null - && !tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") - && options.isAnyEnabled(tokenIrritants) // if irritant is effectively enabled - && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem - if (unusedWarningTokenIsWarning) { - int start = value.sourceStart, end = value.sourceEnd; - nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { - long position = this.suppressWarningScopePositions[jSuppress]; - int startSuppress = (int) (position >>> 32); - int endSuppress = (int) position; - if (start < startSuppress) continue nextSuppress; - if (end > endSuppress) continue nextSuppress; - if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? + if (tokenIrritants != null) { + if (!tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") + && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem + if (unusedWarningTokenIsWarning) { + int start = value.sourceStart, end = value.sourceEnd; + nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { + long position = this.suppressWarningScopePositions[jSuppress]; + int startSuppress = (int) (position >>> 32); + int endSuppress = (int) position; + if (start < startSuppress) continue nextSuppress; + if (end > endSuppress) continue nextSuppress; + if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? + } + } + int id = options.getIgnoredIrritant(tokenIrritants); + if (id > 0) { + String key = CompilerOptions.optionKeyFromIrritant(id); + this.scope.problemReporter().problemNotAnalysed(value, key); + } else { + this.scope.problemReporter().unusedWarningToken(value); } } - this.scope.problemReporter().unusedWarningToken(value); } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index d6a97919f..0b3762cd8 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -867,8 +867,11 @@ public TypeBinding resolveType(BlockScope scope) { // MW,JH,SH} if (receiverCast && this.actualReceiverType != null) { // due to change of declaring class with receiver type, only identity cast should be notified - if (TypeBinding.equalsEquals(((CastExpression)this.receiver).expression.resolvedType, this.actualReceiverType)) { - scope.problemReporter().unnecessaryCast((CastExpression)this.receiver); + TypeBinding resolvedType2 = ((CastExpression)this.receiver).expression.resolvedType; + if (TypeBinding.equalsEquals(resolvedType2, this.actualReceiverType)) { + if (!scope.environment().usesNullTypeAnnotations() || !NullAnnotationMatching.analyse(this.actualReceiverType, resolvedType2, -1).isAnyMismatch()) { + scope.problemReporter().unnecessaryCast((CastExpression) this.receiver); + } } } // resolve type arguments (for generic constructor call) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java index b7095550b..ae21034c6 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java @@ -128,8 +128,15 @@ public class QualifiedTypeReference extends TypeReference { for (int j = 0; j < i; j++) { Annotation[] qualifierAnnot = this.annotations[j]; if (qualifierAnnot != null && qualifierAnnot.length > 0) { - scope.problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]); - this.annotations[j] = null; + if (j == 0) { + for (int k = 0; k < qualifierAnnot.length; k++) { + scope.problemReporter().typeAnnotationAtQualifiedName(qualifierAnnot[k]); + } + } else { + scope.problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], + qualifierAnnot[qualifierAnnot.length - 1]); + this.annotations[j] = null; + } } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java index 004ddafbd..3a2af2c64 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java @@ -239,7 +239,7 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx } // Process the lambda, taking care not to double report diagnostics. Don't expect any from resolve, Any from code generation should surface, but not those from flow analysis. - implicitLambda.resolve(currentScope); + implicitLambda.resolveType(currentScope, true); IErrorHandlingPolicy oldPolicy = currentScope.problemReporter().switchErrorHandlingPolicy(silentErrorHandlingPolicy); try { implicitLambda.analyseCode(currentScope, diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index f7709c443..5cdf5b42e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -2797,7 +2797,7 @@ public void generateSyntheticBodyForDeserializeLambda(SyntheticMethodBinding met invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature); - checkcast(isLambda ? mb.declaringClass : ((ReferenceExpression)funcEx).receiverType); + checkcast(mb.declaringClass); sig.append(mb.declaringClass.signature()); } for (int p = 0, max = outerLocalVariables == null ? 0 : outerLocalVariables.length; p < max; p++) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java index c4add1b80..c65ac55d3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java @@ -1622,6 +1622,22 @@ public class CompilerOptions { return this.warningThreshold.isAnySet(irritants) || this.errorThreshold.isAnySet(irritants) || this.infoThreshold.isAnySet(irritants); } + /* + * Just return the first irritant id that is set to 'ignored'. + */ + public int getIgnoredIrritant(IrritantSet irritants) { + int[] bits = irritants.getBits(); + for (int i = 0; i < IrritantSet.GROUP_MAX; i++) { + int bit = bits[i]; + if (bit > 0) { + bit |= (i << IrritantSet.GROUP_SHIFT); + if (!(this.warningThreshold.isSet(bit) || this.errorThreshold.isSet(bit) || this.infoThreshold.isSet(bit))) { + return bit; + } + } + } + return 0; + } protected void resetDefaults() { // problem default severities defined on IrritantSet diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java index 80db44d0e..6635519df 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java @@ -335,7 +335,9 @@ public class IrritantSet { int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; return (this.bits[group] & singleGroupIrritants) != 0; } - + public int[] getBits() { + return this.bits; + } public IrritantSet set(int singleGroupIrritants) { int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; this.bits[group] |= (singleGroupIrritants & ~GROUP_MASK); // erase the group bits diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 616c23709..68f82cfdf 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -2237,7 +2237,9 @@ private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBin } // no annotation found on the type or its enclosing types // check the package-info for default annotation if not already done before - if (packageBinding.defaultNullness == Binding.NO_NULL_DEFAULT && !isPackageInfo) { + if (packageBinding.defaultNullness == Binding.NO_NULL_DEFAULT && !isPackageInfo + && ((this.typeBits & (TypeIds.BitAnyNullAnnotation)) == 0)) + { // this will scan the annotations in package-info ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME); if (packageInfo == null) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java index c6e2a0233..5d9ecc06e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java @@ -18,6 +18,8 @@ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; @@ -94,6 +96,8 @@ public class CompilationUnitScope extends Scope { boolean connectingHierarchy; private ArrayList<Invocation> inferredInvocations; + /** Cache of interned inference variables. Access only via {@link InferenceVariable#get(TypeBinding, int, InvocationSite, Scope, ReferenceBinding)}. */ + Map<InferenceVariable.InferenceVarKey, InferenceVariable> uniqueInferenceVariables = new HashMap<>(); //{ObjectTeams: when used as a baseimport scope, remember the original scope during this current lookup public Scope originalScope; // store parser for on-demand Dependencies.setup() lateron: diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java index 8fd61f808..8dd65d1a4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java @@ -304,7 +304,7 @@ public class ImplicitNullAnnotationVerifier { this.environment.getNonNullAnnotationName()); break returnType; } else { - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, useTypeAnnotations); + scope.problemReporter().cannotImplementIncompatibleNullness(scope.referenceContext(), currentMethod, inheritedMethod, useTypeAnnotations); return; } } @@ -320,7 +320,7 @@ public class ImplicitNullAnnotationVerifier { scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod, this.environment.getNonNullAnnotationName()); else - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, useTypeAnnotations); + scope.problemReporter().cannotImplementIncompatibleNullness(scope.referenceContext(), currentMethod, inheritedMethod, useTypeAnnotations); return; } } @@ -412,7 +412,7 @@ public class ImplicitNullAnnotationVerifier { inheritedMethod.declaringClass, (inheritedNonNullNess == null) ? null : this.environment.getNullableAnnotationName()); } else { - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); + scope.problemReporter().cannotImplementIncompatibleNullness(scope.referenceContext(), currentMethod, inheritedMethod, false); } continue; } else if (currentNonNullNess == null) @@ -425,7 +425,7 @@ public class ImplicitNullAnnotationVerifier { inheritedMethod.declaringClass, annotationName); } else { - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); + scope.problemReporter().cannotImplementIncompatibleNullness(scope.referenceContext(), currentMethod, inheritedMethod, false); } continue; } else if (inheritedNonNullNess == Boolean.TRUE) { @@ -450,7 +450,7 @@ public class ImplicitNullAnnotationVerifier { if (currentArgument != null) scope.problemReporter().illegalParameterRedefinition(currentArgument, inheritedMethod.declaringClass, inheritedParameter); else - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); + scope.problemReporter().cannotImplementIncompatibleNullness(scope.referenceContext(), currentMethod, inheritedMethod, false); } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index 2bae65c59..ab2691c3c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -131,7 +131,6 @@ public class InferenceContext18 { /** The inference variables for which as solution is sought. */ InferenceVariable[] inferenceVariables; - int nextVarId; /** Constraints that have not yet been reduced and incorporated. */ ConstraintFormula[] initialConstraints; @@ -165,43 +164,12 @@ public class InferenceContext18 { /** Not per JLS: signal when current is ready to directly merge all bounds from inner. */ private boolean directlyAcceptingInnerBounds = false; - // InferenceVariable interning: - private InferenceVariable[] internedVariables; - - private InferenceVariable getInferenceVariable(TypeBinding typeParameter, int rank, InvocationSite site) { - InferenceContext18 outermostContext = this.environment.currentInferenceContext; - if (outermostContext == null) - outermostContext = this; - int i = 0; - InferenceVariable[] interned = outermostContext.internedVariables; - if (interned == null) { - outermostContext.internedVariables = new InferenceVariable[10]; - } else { - int len = interned.length; - for (i = 0; i < len; i++) { - InferenceVariable var = interned[i]; - if (var == null) - break; - if (var.typeParameter == typeParameter && var.rank == rank && isSameSite(var.site, site)) //$IDENTITY-COMPARISON$ - return var; - } - if (i >= len) - System.arraycopy(interned, 0, outermostContext.internedVariables = new InferenceVariable[len+10], 0, len); - } - boolean differentContext = outermostContext != this; - int id = differentContext ? Math.max(this.nextVarId, outermostContext.nextVarId) : this.nextVarId; - this.nextVarId = id + 1; - if (differentContext) - outermostContext.nextVarId = this.nextVarId; - return outermostContext.internedVariables[i] = new InferenceVariable(typeParameter, rank, id, site, this.environment, this.object); - } - - boolean isSameSite(InvocationSite site1, InvocationSite site2) { + public static boolean isSameSite(InvocationSite site1, InvocationSite site2) { if (site1 == site2) return true; if (site1 == null || site2 == null) return false; - if (site1.sourceStart() == site2.sourceStart() && site1.sourceEnd() == site2.sourceEnd() && site1.toString().equals(site2.toString())) + if (site1.sourceStart() == site2.sourceStart() && site1.sourceEnd() == site2.sourceEnd()) return true; return false; } @@ -337,7 +305,7 @@ public class InferenceContext18 { } InferenceVariable[] newVariables = new InferenceVariable[len]; for (int i = 0; i < len; i++) - newVariables[i] = getInferenceVariable(typeVariables[i], i, this.currentInvocation); + newVariables[i] = InferenceVariable.get(typeVariables[i], i, this.currentInvocation, this.scope, this.object); addInferenceVariables(newVariables); return newVariables; } @@ -365,7 +333,7 @@ public class InferenceContext18 { newVariables[i] = (InferenceVariable) typeVariables[i]; // prevent double substitution of an already-substituted inferenceVariable else toAdd[numToAdd++] = - newVariables[i] = getInferenceVariable(typeVariables[i], i, this.currentInvocation); + newVariables[i] = InferenceVariable.get(typeVariables[i], i, this.currentInvocation, this.scope, this.object); } if (numToAdd > 0) { int start = 0; @@ -1571,18 +1539,6 @@ public class InferenceContext18 { if (!isSameSite(innerCtx.currentInvocation, this.currentInvocation)) innerCtx.outerContext = this; this.usesUncheckedConversion = innerCtx.usesUncheckedConversion; - for (InferenceVariable variable : this.inferenceVariables) - if (!isInterned(variable)) - variable.updateSourceName(this.nextVarId++); - } - - boolean isInterned(InferenceVariable iv) { - if (this.internedVariables != null) - for (int i = 0; i < this.internedVariables.length; i++) { - if (this.internedVariables[i] == iv) //$IDENTITY-COMPARISON$ - return true; - } - return false; } public void resumeSuspendedInference(SuspendedInferenceRecord record) { @@ -1595,8 +1551,6 @@ public class InferenceContext18 { // move to back, add previous to front: System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables=new InferenceVariable[l1+l2], l2, l1); System.arraycopy(record.inferenceVariables, 0, this.inferenceVariables, 0, l2); - for (int i=l1;i<l1+l2;i++) - this.inferenceVariables[i].updateSourceName(this.nextVarId++); } // replace invocation site & arguments: diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java index c76e3ba63..c7dd516e9 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java @@ -38,7 +38,7 @@ public class InferenceSubstitution extends Scope.Substitutor implements Substitu public TypeBinding substitute(Substitution substitution, TypeBinding originalType) { for (int i = 0; i < this.variables.length; i++) { InferenceVariable variable = this.variables[i]; - if (this.site == variable.site && TypeBinding.equalsEquals(getP(i), originalType)) { + if (InferenceContext18.isSameSite(this.site, variable.site) && TypeBinding.equalsEquals(getP(i), originalType)) { if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && originalType.hasNullTypeAnnotations()) return this.environment.createAnnotatedType(variable.withoutToplevelNullAnnotation(), originalType.getTypeAnnotations()); return variable; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java index 87560640a..9b852a81f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; +import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; @@ -18,14 +19,74 @@ import org.eclipse.jdt.core.compiler.CharOperation; * Implementation of 18.1.1 in JLS8 */ public class InferenceVariable extends TypeVariableBinding { + + /** Structured key for interning. */ + static class InferenceVarKey { + /*@NonNull*/ TypeBinding typeParameter; + long position; + int rank; + InferenceVarKey(TypeBinding typeParameter, InvocationSite site, int rank) { + this.typeParameter = typeParameter; + this.position = ((long) site.sourceStart() << 32) + site.sourceEnd(); + this.rank = rank; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (this.position ^ (this.position >>> 32)); + result = prime * result + this.rank; + result = prime * result + this.typeParameter.id; + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof InferenceVarKey)) + return false; + InferenceVarKey other = (InferenceVarKey) obj; + if (this.position != other.position) + return false; + if (this.rank != other.rank) + return false; + if (TypeBinding.notEquals(this.typeParameter, other.typeParameter)) + return false; + return true; + } + } + + /** + * Create or retrieve the inference variable representing the given typeParameter. + * Inference variables are interned to avoid duplication due to lambda copying. + */ + public static InferenceVariable get(TypeBinding typeParameter, int rank, InvocationSite site, Scope scope, ReferenceBinding object) { + Map<InferenceVarKey, InferenceVariable> uniqueInferenceVariables = scope.compilationUnitScope().uniqueInferenceVariables; + InferenceVariable var = null; + InferenceVarKey key = null; + if (site != null && typeParameter != null) { + key = new InferenceVarKey(typeParameter, site, rank); + var = uniqueInferenceVariables.get(key); + } + if (var == null) { + int newVarId = uniqueInferenceVariables.size(); + var = new InferenceVariable(typeParameter, rank, newVarId, site, scope.environment(), object); + if (key != null) + uniqueInferenceVariables.put(key, var); + } + return var; + } + InvocationSite site; TypeBinding typeParameter; long nullHints; // one of TagBits.{AnnotationNonNull,AnnotationNullable} may steer inference into inferring nullness as well; set both bits to request avoidance. private InferenceVariable prototype; - int varId; // this is used for constructing a source name like T#0. NB: varId and sourceName are mutable, to be updated when two InferenceContext18 are integrated. + int varId; // this is used for constructing a source name like T#0. - public InferenceVariable(TypeBinding typeParameter, int parameterRank, int iVarId, InvocationSite site, LookupEnvironment environment, ReferenceBinding object) { + private InferenceVariable(TypeBinding typeParameter, int parameterRank, int iVarId, InvocationSite site, LookupEnvironment environment, ReferenceBinding object) { this(typeParameter, parameterRank, site, CharOperation.concat(typeParameter.shortReadableName(), Integer.toString(iVarId).toCharArray(), '#'), environment, object); @@ -49,15 +110,7 @@ public class InferenceVariable extends TypeVariableBinding { this.superclass = object; this.prototype = this; } - void updateSourceName(int newId) { - int hashPos = CharOperation.indexOf('#', this.sourceName); - this.varId = newId; - this.sourceName = CharOperation.concat( - CharOperation.subarray(this.sourceName, 0, hashPos), - Integer.toString(this.varId).toCharArray(), - '#'); - } - + @Override public TypeBinding clone(TypeBinding enclosingType) { InferenceVariable clone = new InferenceVariable(this.typeParameter, this.rank, this.site, this.sourceName, this.environment, this.superclass); @@ -137,17 +190,18 @@ public class InferenceVariable extends TypeVariableBinding { public int hashCode() { int code = this.typeParameter.hashCode() + 17 * this.rank; - if (this.site != null) - return 31 * code + this.site.hashCode(); - else - return code; + if (this.site != null) { + code = 31 * code + this.site.sourceStart(); + code = 31 * code + this.site.sourceEnd(); + } + return code; } public boolean equals(Object obj) { if (!(obj instanceof InferenceVariable)) return false; InferenceVariable other = (InferenceVariable) obj; return this.rank == other.rank - && this.site == other.site + && InferenceContext18.isSameSite(this.site, other.site) && TypeBinding.equalsEquals(this.typeParameter, other.typeParameter); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index 6979eaaa6..6cfe6aaca 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -70,6 +70,12 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin */ public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod, TypeBinding[] arguments, Scope scope, InvocationSite invocationSite) { + LookupEnvironment environment = scope.environment(); + if ((originalMethod.tagBits & TagBits.IsNullnessKnown) == 0) { + // ensure nullness of originalMethod is known (but we are not interested in reporting problems against originalMethod) + new ImplicitNullAnnotationVerifier(environment, environment.globalOptions.inheritNullAnnotations) + .checkImplicitNullAnnotations(originalMethod, null/*srcMethod*/, false, scope); + } ParameterizedGenericMethodBinding methodSubstitute; TypeVariableBinding[] typeVariables = originalMethod.typeVariables; TypeBinding[] substitutes = invocationSite.genericTypeArguments(); @@ -90,7 +96,7 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin // incompatible due to wrong arity return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes, ProblemReasons.TypeParameterArityMismatch); } - methodSubstitute = scope.environment().createParameterizedGenericMethod(originalMethod, substitutes); + methodSubstitute = environment.createParameterizedGenericMethod(originalMethod, substitutes); break computeSubstitutes; } // perform type argument inference (15.12.2.7) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java index af32c7801..7749b66f3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java @@ -251,6 +251,7 @@ public interface TypeIds { final int BitNullableAnnotation = 64; /** Bit for a type configured as a @NonNullByDefault annotation. */ final int BitNonNullByDefaultAnnotation = 128; + final int BitAnyNullAnnotation = BitNonNullAnnotation | BitNullableAnnotation | BitNonNullByDefaultAnnotation; /** * Set of type bits that should be inherited by any sub types. diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java index ca9ebeb7e..85421e94f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java @@ -224,19 +224,7 @@ public class TypeSystem { urb = (UnresolvedReferenceBinding) type; ReferenceBinding resolvedType = urb.resolvedType; if (resolvedType != null) { - if(CharOperation.indexOf('$', type.sourceName()) > 0) { - type = this.environment.convertToRawType(resolvedType, false); - } else { - type = resolvedType; - } - } else if (CharOperation.indexOf('$', type.sourceName()) > 0) { - boolean mayTolerateMissingType = this.environment.mayTolerateMissingType; - this.environment.mayTolerateMissingType = true; - try { - type = BinaryTypeBinding.resolveType(type, this.environment, true); // to ensure unique id assignment (when enclosing type is parameterized, inner type is also) - } finally { - this.environment.mayTolerateMissingType = mayTolerateMissingType; - } + type = resolvedType; } } try { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 62d041dfb..48664dcc3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -1119,8 +1119,7 @@ public class TypeVariableBinding extends ReferenceBinding { TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization(); for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) { TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i]; - if (annotatedType.firstBound == null) - annotatedType.firstBound = firstBound; + annotatedType.firstBound = firstBound; } } if (firstBound != null && firstBound.hasNullTypeAnnotations()) @@ -1136,8 +1135,7 @@ public class TypeVariableBinding extends ReferenceBinding { TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization(); for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) { TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i]; - if (annotatedType.superclass == null) - annotatedType.superclass = superclass; + annotatedType.superclass = superclass; } } return superclass; @@ -1151,8 +1149,7 @@ public class TypeVariableBinding extends ReferenceBinding { TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization(); for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) { TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i]; - if (annotatedType.superInterfaces == null) - annotatedType.superInterfaces = superInterfaces; + annotatedType.superInterfaces = superInterfaces; } } return superInterfaces; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index b2efb250c..88b5e90ad 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -1807,6 +1807,8 @@ public int computeSeverity(int problemID){ return ProblemSeverities.Warning; case IProblem.IllegalUseOfUnderscoreAsAnIdentifier: return this.underScoreIsLambdaParameter ? ProblemSeverities.Error : ProblemSeverities.Warning; + case IProblem.ProblemNotAnalysed: + return ProblemSeverities.Info; // Not configurable } int irritant = getIrritant(problemID); if (irritant != 0) { @@ -6438,6 +6440,19 @@ public void nullAnnotationUnsupportedLocation(Annotation annotation) { severity, annotation.sourceStart, annotation.sourceEnd); } +public void nullAnnotationAtQualifyingType(Annotation annotation) { + String[] arguments = new String[] { + String.valueOf(annotation.resolvedType.readableName()) + }; + String[] shortArguments = new String[] { + String.valueOf(annotation.resolvedType.shortReadableName()) + }; + int severity = ProblemSeverities.Error | ProblemSeverities.Fatal; + handle(IProblem.NullAnnotationAtQualifyingType, + arguments, shortArguments, + severity, + annotation.sourceStart, annotation.sourceEnd); +} public void nullAnnotationUnsupportedLocation(TypeReference type) { int sourceEnd = type.sourceEnd; if (type instanceof ParameterizedSingleTypeReference) { @@ -9710,6 +9725,14 @@ public void unusedWarningToken(Expression token) { token.sourceStart, token.sourceEnd); } +public void problemNotAnalysed(Expression token, String optionKey) { + this.handle( + IProblem.ProblemNotAnalysed, + optionKey != null ? new String[]{optionKey} : new String[]{}, + new String[] { token.constant.stringValue() }, + token.sourceStart, + token.sourceEnd); +} public void useAssertAsAnIdentifier(int sourceStart, int sourceEnd) { this.handle( IProblem.UseAssertAsAnIdentifier, @@ -14047,11 +14070,11 @@ public void expressionPotentialNullReference(ASTNode location) { location.sourceEnd); } -public void cannotImplementIncompatibleNullness(MethodBinding currentMethod, MethodBinding inheritedMethod, boolean showReturn) { +public void cannotImplementIncompatibleNullness(ReferenceContext context, MethodBinding currentMethod, MethodBinding inheritedMethod, boolean showReturn) { int sourceStart = 0, sourceEnd = 0; - if (this.referenceContext instanceof TypeDeclaration) { - sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart; - sourceEnd = ((TypeDeclaration) this.referenceContext).sourceEnd; + if (context instanceof TypeDeclaration) { + sourceStart = ((TypeDeclaration) context).sourceStart; + sourceEnd = ((TypeDeclaration) context).sourceEnd; } String[] problemArguments = { showReturn @@ -14800,6 +14823,10 @@ public void disallowedTargetForContainerAnnotation(Annotation annotation, TypeBi annotation.sourceStart, annotation.sourceEnd); } +public void typeAnnotationAtQualifiedName(Annotation annotation) { + this.handle(IProblem.TypeAnnotationAtQualifiedName, NoArgument, NoArgument, annotation.sourceStart, + annotation.sourceEnd); + } public void genericInferenceError(String message, InvocationSite invocationSite) { genericInferenceProblem(message, invocationSite, ProblemSeverities.Error); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 3beee8e97..98c08302e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -861,9 +861,12 @@ 1057 = strictfp is not permitted for abstract interface method {0} 1058 = Default methods are allowed only in interfaces. 1059 = Cannot infer type argument(s) for <{0}> {1} +1060 = Illegally placed annotation: type annotations must directly precede the simple name of the type they are meant to affect (or the [] for arrays) +1061 = The nullness annotation ''{0}'' is not applicable at this location, it must be placed directly before the nested type name. 1100 = Problem detected during type inference: {0} - +#1101 is already used up but deprecated +1102 = At least one of the problems in category ''{0}'' is not analysed due to a compiler option being ignored ### ELABORATIONS ## Access restrictions 78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'') |