Refactor ModifiersChecker to be more component-like
A couple of minor prettifications
This commit is contained in:
@@ -54,6 +54,7 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
|||||||
|
|
||||||
public class BodyResolver {
|
public class BodyResolver {
|
||||||
@NotNull private final ScriptBodyResolver scriptBodyResolverResolver;
|
@NotNull private final ScriptBodyResolver scriptBodyResolverResolver;
|
||||||
|
@NotNull private final ModifiersChecker modifiersChecker;
|
||||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
||||||
@NotNull private final CallResolver callResolver;
|
@NotNull private final CallResolver callResolver;
|
||||||
@NotNull private final ObservableBindingTrace trace;
|
@NotNull private final ObservableBindingTrace trace;
|
||||||
@@ -78,7 +79,8 @@ public class BodyResolver {
|
|||||||
@NotNull FunctionAnalyzerExtension functionAnalyzerExtension,
|
@NotNull FunctionAnalyzerExtension functionAnalyzerExtension,
|
||||||
@NotNull ScriptBodyResolver scriptBodyResolverResolver,
|
@NotNull ScriptBodyResolver scriptBodyResolverResolver,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull ValueParameterResolver valueParameterResolver
|
@NotNull ValueParameterResolver valueParameterResolver,
|
||||||
|
@NotNull ModifiersChecker modifiersChecker
|
||||||
) {
|
) {
|
||||||
this.additionalCheckerProvider = additionalCheckerProvider;
|
this.additionalCheckerProvider = additionalCheckerProvider;
|
||||||
this.annotationResolver = annotationResolver;
|
this.annotationResolver = annotationResolver;
|
||||||
@@ -90,6 +92,7 @@ public class BodyResolver {
|
|||||||
this.expressionTypingServices = expressionTypingServices;
|
this.expressionTypingServices = expressionTypingServices;
|
||||||
this.functionAnalyzerExtension = functionAnalyzerExtension;
|
this.functionAnalyzerExtension = functionAnalyzerExtension;
|
||||||
this.scriptBodyResolverResolver = scriptBodyResolverResolver;
|
this.scriptBodyResolverResolver = scriptBodyResolverResolver;
|
||||||
|
this.modifiersChecker = modifiersChecker;
|
||||||
this.trace = new ObservableBindingTrace(trace);
|
this.trace = new ObservableBindingTrace(trace);
|
||||||
this.valueParameterResolver = valueParameterResolver;
|
this.valueParameterResolver = valueParameterResolver;
|
||||||
}
|
}
|
||||||
@@ -512,7 +515,7 @@ public class BodyResolver {
|
|||||||
|
|
||||||
annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
|
annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
|
||||||
|
|
||||||
ModifiersChecker.reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY), trace);
|
modifiersChecker.withTrace(trace).reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
|
private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembe
|
|||||||
|
|
||||||
public class DeclarationsChecker {
|
public class DeclarationsChecker {
|
||||||
@NotNull private final BindingTrace trace;
|
@NotNull private final BindingTrace trace;
|
||||||
@NotNull private final ModifiersChecker modifiersChecker;
|
@NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker;
|
||||||
@NotNull private final DescriptorResolver descriptorResolver;
|
@NotNull private final DescriptorResolver descriptorResolver;
|
||||||
|
|
||||||
public DeclarationsChecker(
|
public DeclarationsChecker(
|
||||||
@@ -54,7 +54,7 @@ public class DeclarationsChecker {
|
|||||||
@NotNull BindingTrace trace
|
@NotNull BindingTrace trace
|
||||||
) {
|
) {
|
||||||
this.descriptorResolver = descriptorResolver;
|
this.descriptorResolver = descriptorResolver;
|
||||||
this.modifiersChecker = modifiersChecker;
|
this.modifiersChecker = modifiersChecker.withTrace(trace);
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public class DeclarationsChecker {
|
|||||||
}
|
}
|
||||||
AnnotationTargetChecker.INSTANCE$.check(packageDirective, trace, null);
|
AnnotationTargetChecker.INSTANCE$.check(packageDirective, trace, null);
|
||||||
|
|
||||||
ModifiersChecker.reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY), trace);
|
modifiersChecker.reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) {
|
private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) {
|
||||||
@@ -532,7 +532,7 @@ public class DeclarationsChecker {
|
|||||||
PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
|
PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
|
||||||
JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null;
|
JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null;
|
||||||
if (getterModifierList != null && getterDescriptor != null) {
|
if (getterModifierList != null && getterDescriptor != null) {
|
||||||
Map<JetModifierKeywordToken, ASTNode> nodes = ModifiersChecker.getNodesCorrespondingToModifiers(getterModifierList, Sets
|
Map<JetModifierKeywordToken, ASTNode> nodes = modifiersChecker.getNodesCorrespondingToModifiers(getterModifierList, Sets
|
||||||
.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD,
|
.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD,
|
||||||
JetTokens.INTERNAL_KEYWORD));
|
JetTokens.INTERNAL_KEYWORD));
|
||||||
if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
|
if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
|
||||||
|
|||||||
@@ -61,12 +61,6 @@ import static org.jetbrains.kotlin.resolve.source.SourcePackage.toSourceElement;
|
|||||||
|
|
||||||
public class DescriptorResolver {
|
public class DescriptorResolver {
|
||||||
public static final Name COPY_METHOD_NAME = Name.identifier("copy");
|
public static final Name COPY_METHOD_NAME = Name.identifier("copy");
|
||||||
private static final Set<JetModifierKeywordToken> MODIFIERS_ILLEGAL_ON_PARAMETERS;
|
|
||||||
static {
|
|
||||||
MODIFIERS_ILLEGAL_ON_PARAMETERS = Sets.newHashSet();
|
|
||||||
MODIFIERS_ILLEGAL_ON_PARAMETERS.addAll(Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY));
|
|
||||||
MODIFIERS_ILLEGAL_ON_PARAMETERS.remove(JetTokens.VARARG_KEYWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull private final TypeResolver typeResolver;
|
@NotNull private final TypeResolver typeResolver;
|
||||||
@NotNull private final AnnotationResolver annotationResolver;
|
@NotNull private final AnnotationResolver annotationResolver;
|
||||||
@@ -1165,24 +1159,6 @@ public class DescriptorResolver {
|
|||||||
return getParentOfType(scope.getContainingDeclaration(), ClassDescriptor.class, false);
|
return getParentOfType(scope.getContainingDeclaration(), ClassDescriptor.class, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkParameterHasNoValOrVar(
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull JetParameter parameter,
|
|
||||||
@NotNull DiagnosticFactory1<PsiElement, JetKeywordToken> diagnosticFactory
|
|
||||||
) {
|
|
||||||
PsiElement valOrVar = parameter.getValOrVarKeyword();
|
|
||||||
if (valOrVar != null) {
|
|
||||||
trace.report(diagnosticFactory.on(valOrVar, ((JetKeywordToken) valOrVar.getNode().getElementType())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkParameterHasNoModifier(
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull JetParameter parameter
|
|
||||||
) {
|
|
||||||
ModifiersChecker.reportIllegalModifiers(parameter.getModifierList(), MODIFIERS_ILLEGAL_ON_PARAMETERS, trace);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void resolvePackageHeader(
|
public static void resolvePackageHeader(
|
||||||
@NotNull JetPackageDirective packageDirective,
|
@NotNull JetPackageDirective packageDirective,
|
||||||
@NotNull ModuleDescriptor module,
|
@NotNull ModuleDescriptor module,
|
||||||
|
|||||||
@@ -16,13 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.builtins
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.*
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl.create
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -33,6 +34,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorResolver.*
|
import org.jetbrains.kotlin.resolve.DescriptorResolver.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl
|
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl
|
||||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
@@ -47,12 +49,13 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class FunctionDescriptorResolver(
|
class FunctionDescriptorResolver(
|
||||||
val typeResolver: TypeResolver,
|
private val typeResolver: TypeResolver,
|
||||||
val descriptorResolver: DescriptorResolver,
|
private val descriptorResolver: DescriptorResolver,
|
||||||
val annotationResolver: AnnotationResolver,
|
private val annotationResolver: AnnotationResolver,
|
||||||
val storageManager: StorageManager,
|
private val storageManager: StorageManager,
|
||||||
val expressionTypingServices: ExpressionTypingServices,
|
private val expressionTypingServices: ExpressionTypingServices,
|
||||||
val builtIns: KotlinBuiltIns
|
private val builtIns: KotlinBuiltIns,
|
||||||
|
private val modifiersChecker: ModifiersChecker
|
||||||
) {
|
) {
|
||||||
public fun resolveFunctionDescriptor(
|
public fun resolveFunctionDescriptor(
|
||||||
containingDescriptor: DeclarationDescriptor,
|
containingDescriptor: DeclarationDescriptor,
|
||||||
@@ -336,11 +339,13 @@ class FunctionDescriptorResolver(
|
|||||||
|
|
||||||
if (functionDescriptor !is ConstructorDescriptor || !functionDescriptor.isPrimary()) {
|
if (functionDescriptor !is ConstructorDescriptor || !functionDescriptor.isPrimary()) {
|
||||||
val isConstructor = functionDescriptor is ConstructorDescriptor
|
val isConstructor = functionDescriptor is ConstructorDescriptor
|
||||||
DescriptorResolver.checkParameterHasNoValOrVar(
|
with (modifiersChecker.withTrace(trace)) {
|
||||||
trace, valueParameter,
|
checkParameterHasNoValOrVar(
|
||||||
if (isConstructor) VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER else VAL_OR_VAR_ON_FUN_PARAMETER
|
valueParameter,
|
||||||
)
|
if (isConstructor) VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER else VAL_OR_VAR_ON_FUN_PARAMETER
|
||||||
DescriptorResolver.checkParameterHasNoModifier(trace, valueParameter)
|
)
|
||||||
|
checkParameterHasNoModifier(valueParameter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
checkConstructorParameterHasNoModifier(trace, valueParameter)
|
checkConstructorParameterHasNoModifier(trace, valueParameter)
|
||||||
@@ -357,7 +362,7 @@ class FunctionDescriptorResolver(
|
|||||||
private fun checkConstructorParameterHasNoModifier(trace: BindingTrace, parameter: JetParameter) {
|
private fun checkConstructorParameterHasNoModifier(trace: BindingTrace, parameter: JetParameter) {
|
||||||
// If is not a property, then it must have no modifier
|
// If is not a property, then it must have no modifier
|
||||||
if (!parameter.hasValOrVar()) {
|
if (!parameter.hasValOrVar()) {
|
||||||
DescriptorResolver.checkParameterHasNoModifier(trace, parameter)
|
modifiersChecker.withTrace(trace).checkParameterHasNoModifier(parameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
|
import org.jetbrains.kotlin.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
@@ -50,188 +52,12 @@ public class ModifiersChecker {
|
|||||||
private static final Collection<JetModifierKeywordToken> VISIBILITY_MODIFIERS =
|
private static final Collection<JetModifierKeywordToken> VISIBILITY_MODIFIERS =
|
||||||
Lists.newArrayList(PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD);
|
Lists.newArrayList(PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD);
|
||||||
|
|
||||||
public static void reportIllegalModifiers(
|
private static final Set<JetModifierKeywordToken> MODIFIERS_ILLEGAL_ON_PARAMETERS;
|
||||||
@Nullable JetModifierList modifierList,
|
|
||||||
@NotNull Collection<JetModifierKeywordToken> illegalModifiers,
|
|
||||||
@NotNull BindingTrace trace
|
|
||||||
) {
|
|
||||||
if (modifierList == null) return;
|
|
||||||
|
|
||||||
for (JetModifierKeywordToken modifierToken : illegalModifiers) {
|
static {
|
||||||
if (modifierList.hasModifier(modifierToken)) {
|
MODIFIERS_ILLEGAL_ON_PARAMETERS = Sets.newHashSet();
|
||||||
PsiElement modifierPsi = modifierList.getModifier(modifierToken);
|
MODIFIERS_ILLEGAL_ON_PARAMETERS.addAll(Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY));
|
||||||
assert modifierPsi != null;
|
MODIFIERS_ILLEGAL_ON_PARAMETERS.remove(JetTokens.VARARG_KEYWORD);
|
||||||
trace.report(ILLEGAL_MODIFIER.on(modifierPsi, modifierToken));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkIncompatibleModifiers(
|
|
||||||
@Nullable JetModifierList modifierList,
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull Collection<JetModifierKeywordToken> availableModifiers,
|
|
||||||
@NotNull Collection<JetModifierKeywordToken>... availableCombinations
|
|
||||||
) {
|
|
||||||
if (modifierList == null) return;
|
|
||||||
Collection<JetModifierKeywordToken> presentModifiers = Sets.newLinkedHashSet();
|
|
||||||
for (JetModifierKeywordToken modifier : availableModifiers) {
|
|
||||||
if (modifierList.hasModifier(modifier)) {
|
|
||||||
presentModifiers.add(modifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkRepeatedModifiers(modifierList, trace, availableModifiers);
|
|
||||||
|
|
||||||
if (presentModifiers.size() == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (Collection<JetModifierKeywordToken> combination : availableCombinations) {
|
|
||||||
if (presentModifiers.containsAll(combination) && combination.containsAll(presentModifiers)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (JetModifierKeywordToken token : presentModifiers) {
|
|
||||||
trace.report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token).getPsi(), presentModifiers));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkRepeatedModifiers(
|
|
||||||
@NotNull JetModifierList modifierList,
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull Collection<JetModifierKeywordToken> availableModifiers
|
|
||||||
) {
|
|
||||||
for (JetModifierKeywordToken token : availableModifiers) {
|
|
||||||
if (!modifierList.hasModifier(token)) continue;
|
|
||||||
|
|
||||||
List<ASTNode> nodesOfRepeatedTokens = Lists.newArrayList();
|
|
||||||
ASTNode node = modifierList.getNode().getFirstChildNode();
|
|
||||||
while (node != null) {
|
|
||||||
if (node.getElementType() == token) {
|
|
||||||
nodesOfRepeatedTokens.add(node);
|
|
||||||
}
|
|
||||||
node = node.getTreeNext();
|
|
||||||
}
|
|
||||||
if (nodesOfRepeatedTokens.size() > 1) {
|
|
||||||
for (ASTNode repeatedToken : nodesOfRepeatedTokens) {
|
|
||||||
trace.report(REPEATED_MODIFIER.on(repeatedToken.getPsi(), token));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkIncompatibleVarianceModifiers(@Nullable JetModifierList modifierList, @NotNull BindingTrace trace) {
|
|
||||||
checkIncompatibleModifiers(modifierList, trace, Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final BindingTrace trace;
|
|
||||||
@NotNull
|
|
||||||
private final AdditionalCheckerProvider additionalCheckerProvider;
|
|
||||||
|
|
||||||
public ModifiersChecker(@NotNull BindingTrace trace, @NotNull AdditionalCheckerProvider additionalCheckerProvider) {
|
|
||||||
this.trace = trace;
|
|
||||||
this.additionalCheckerProvider = additionalCheckerProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ModifiersChecker create(@NotNull BindingTrace trace, @NotNull AdditionalCheckerProvider provider) {
|
|
||||||
return new ModifiersChecker(trace, provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkModifiersForDeclaration(@NotNull JetDeclaration modifierListOwner, @NotNull MemberDescriptor descriptor) {
|
|
||||||
if (modifierListOwner instanceof JetEnumEntry) {
|
|
||||||
reportIllegalModifiers(modifierListOwner, Arrays.asList(MODIFIER_KEYWORDS_ARRAY));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
checkInnerModifier(modifierListOwner, descriptor);
|
|
||||||
checkDefaultModifier(modifierListOwner);
|
|
||||||
checkModalityModifiers(modifierListOwner);
|
|
||||||
checkVisibilityModifiers(modifierListOwner, descriptor);
|
|
||||||
checkVarianceModifiers(modifierListOwner);
|
|
||||||
checkVarargsModifiers(modifierListOwner, descriptor);
|
|
||||||
}
|
|
||||||
checkPlatformNameApplicability(descriptor);
|
|
||||||
runDeclarationCheckers(modifierListOwner, descriptor);
|
|
||||||
AnnotationTargetChecker.INSTANCE$.check(modifierListOwner, trace,
|
|
||||||
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkVarargsModifiers(@NotNull JetDeclaration owner, @NotNull MemberDescriptor descriptor) {
|
|
||||||
if (!(owner instanceof JetParameter)) {
|
|
||||||
reportIllegalModifiers(owner, Collections.singleton(VARARG_KEYWORD));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkModifiersForLocalDeclaration(@NotNull JetDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
|
||||||
reportIllegalModalityModifiers(modifierListOwner);
|
|
||||||
reportIllegalVisibilityModifiers(modifierListOwner);
|
|
||||||
checkPlatformNameApplicability(descriptor);
|
|
||||||
runDeclarationCheckers(modifierListOwner, descriptor);
|
|
||||||
AnnotationTargetChecker.INSTANCE$.check(modifierListOwner, trace,
|
|
||||||
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reportIllegalModalityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
|
||||||
reportIllegalModifiers(modifierListOwner, MODALITY_MODIFIERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reportIllegalVisibilityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
|
||||||
reportIllegalModifiers(modifierListOwner, VISIBILITY_MODIFIERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkModalityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
|
||||||
JetModifierList modifierList = modifierListOwner.getModifierList();
|
|
||||||
if (modifierList == null) return;
|
|
||||||
|
|
||||||
checkRedundantModifier(modifierList, Pair.create(OPEN_KEYWORD, ABSTRACT_KEYWORD), Pair.create(OPEN_KEYWORD, OVERRIDE_KEYWORD));
|
|
||||||
|
|
||||||
checkCompatibility(modifierList, Arrays.asList(ABSTRACT_KEYWORD, OPEN_KEYWORD, FINAL_KEYWORD),
|
|
||||||
Arrays.asList(ABSTRACT_KEYWORD, OPEN_KEYWORD));
|
|
||||||
|
|
||||||
if (modifierListOwner instanceof JetObjectDeclaration) {
|
|
||||||
reportIllegalModalityModifiers(modifierListOwner);
|
|
||||||
}
|
|
||||||
else if (modifierListOwner instanceof JetClassOrObject) {
|
|
||||||
reportIllegalModifiers(modifierListOwner, Collections.singletonList(OVERRIDE_KEYWORD));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkVisibilityModifiers(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
|
||||||
JetModifierList modifierList = modifierListOwner.getModifierList();
|
|
||||||
if (modifierList == null) return;
|
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
|
||||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
|
||||||
if (modifierList.hasModifier(PROTECTED_KEYWORD)) {
|
|
||||||
trace.report(Errors.PACKAGE_MEMBER_CANNOT_BE_PROTECTED.on(modifierListOwner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCompatibility(modifierList, VISIBILITY_MODIFIERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkInnerModifier(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
|
||||||
if (modifierListOwner.hasModifier(INNER_KEYWORD)) {
|
|
||||||
switch (checkIllegalInner(descriptor)) {
|
|
||||||
case ALLOWED:
|
|
||||||
break;
|
|
||||||
case ILLEGAL_POSITION:
|
|
||||||
reportIllegalModifiers(modifierListOwner, Collections.singletonList(INNER_KEYWORD));
|
|
||||||
break;
|
|
||||||
case IN_TRAIT:
|
|
||||||
trace.report(INNER_CLASS_IN_TRAIT.on(modifierListOwner));
|
|
||||||
break;
|
|
||||||
case IN_OBJECT:
|
|
||||||
trace.report(INNER_CLASS_IN_OBJECT.on(modifierListOwner));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (modifierListOwner instanceof JetClass && !(modifierListOwner instanceof JetEnumEntry)) {
|
|
||||||
JetClass aClass = (JetClass) modifierListOwner;
|
|
||||||
boolean localEnumError = aClass.isLocal() && aClass.isEnum();
|
|
||||||
if (!localEnumError && isIllegalNestedClass(descriptor)) {
|
|
||||||
trace.report(NESTED_CLASS_NOT_ALLOWED.on(aClass));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIllegalInner(@NotNull DeclarationDescriptor descriptor) {
|
public static boolean isIllegalInner(@NotNull DeclarationDescriptor descriptor) {
|
||||||
@@ -245,15 +71,10 @@ public class ModifiersChecker {
|
|||||||
IN_OBJECT,
|
IN_OBJECT,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDefaultModifier(@NotNull JetDeclaration declaration) {
|
|
||||||
if (declaration.hasModifier(COMPANION_KEYWORD) && !isDefaultModifierAllowed(declaration)) {
|
|
||||||
reportIllegalModifiers(declaration, Collections.singletonList(COMPANION_KEYWORD));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: just checks if this is legal context for companion modifier (Companion object descriptor can be created)
|
// NOTE: just checks if this is legal context for companion modifier (Companion object descriptor can be created)
|
||||||
// COMPANION_OBJECT_NOT_ALLOWED can be reported later
|
// COMPANION_OBJECT_NOT_ALLOWED can be reported later
|
||||||
public static boolean isDefaultModifierAllowed(@NotNull JetDeclaration declaration) {
|
public static boolean isCompanionModifierAllowed(@NotNull JetDeclaration declaration) {
|
||||||
if (declaration instanceof JetObjectDeclaration) {
|
if (declaration instanceof JetObjectDeclaration) {
|
||||||
JetDeclaration containingDeclaration = getContainingDeclaration(declaration);
|
JetDeclaration containingDeclaration = getContainingDeclaration(declaration);
|
||||||
if (containingDeclaration instanceof JetClassOrObject) {
|
if (containingDeclaration instanceof JetClassOrObject) {
|
||||||
@@ -264,7 +85,7 @@ public class ModifiersChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static InnerModifierCheckResult checkIllegalInner(DeclarationDescriptor descriptor) {
|
private static InnerModifierCheckResult checkIllegalInner(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION;
|
if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION;
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
||||||
|
|
||||||
@@ -292,81 +113,15 @@ public class ModifiersChecker {
|
|||||||
return containingClass.isInner() || containingClass.getContainingDeclaration() instanceof FunctionDescriptor;
|
return containingClass.isInner() || containingClass.getContainingDeclaration() instanceof FunctionDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPlatformNameApplicability(@NotNull DeclarationDescriptor descriptor) {
|
@NotNull
|
||||||
AnnotationDescriptor annotation = descriptor.getAnnotations().findAnnotation(new FqName("kotlin.platform.platformName"));
|
public static Modality resolveModalityFromModifiers(
|
||||||
if (annotation == null) return;
|
|
||||||
|
|
||||||
JetAnnotationEntry annotationEntry = trace.get(BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotation);
|
|
||||||
if (annotationEntry == null) return;
|
|
||||||
|
|
||||||
if (descriptor instanceof FunctionDescriptor && !isRenamableFunction((FunctionDescriptor) descriptor)) {
|
|
||||||
trace.report(INAPPLICABLE_PLATFORM_NAME.on(annotationEntry));
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = null;
|
|
||||||
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
|
|
||||||
if (!values.isEmpty()) {
|
|
||||||
ConstantValue<?> name = values.iterator().next();
|
|
||||||
if (name instanceof StringValue) {
|
|
||||||
value = ((StringValue) name).getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value == null || !Name.isValidIdentifier(value)) {
|
|
||||||
trace.report(ILLEGAL_PLATFORM_NAME.on(annotationEntry, String.valueOf(value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor instanceof CallableMemberDescriptor) {
|
|
||||||
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) descriptor;
|
|
||||||
if (DescriptorUtils.isOverride(callableMemberDescriptor) || callableMemberDescriptor.getModality().isOverridable()) {
|
|
||||||
trace.report(INAPPLICABLE_PLATFORM_NAME.on(annotationEntry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isRenamableFunction(@NotNull FunctionDescriptor descriptor) {
|
|
||||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
|
||||||
|
|
||||||
return containingDescriptor instanceof PackageFragmentDescriptor || containingDescriptor instanceof ClassDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkCompatibility(@Nullable JetModifierList modifierList, Collection<JetModifierKeywordToken> availableModifiers, Collection<JetModifierKeywordToken>... availableCombinations) {
|
|
||||||
checkIncompatibleModifiers(modifierList, trace, availableModifiers, availableCombinations);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkRedundantModifier(@NotNull JetModifierList modifierList, Pair<JetModifierKeywordToken, JetModifierKeywordToken>... redundantBundles) {
|
|
||||||
for (Pair<JetModifierKeywordToken, JetModifierKeywordToken> tokenPair : redundantBundles) {
|
|
||||||
JetModifierKeywordToken redundantModifier = tokenPair.getFirst();
|
|
||||||
JetModifierKeywordToken sufficientModifier = tokenPair.getSecond();
|
|
||||||
if (modifierList.hasModifier(redundantModifier) && modifierList.hasModifier(sufficientModifier)) {
|
|
||||||
trace.report(Errors.REDUNDANT_MODIFIER.on(modifierList.getModifierNode(redundantModifier).getPsi(), redundantModifier, sufficientModifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reportIllegalModifiers(
|
|
||||||
@NotNull JetModifierListOwner modifierListOwner,
|
@NotNull JetModifierListOwner modifierListOwner,
|
||||||
@NotNull Collection<JetModifierKeywordToken> illegalModifiers
|
@NotNull Modality defaultModality
|
||||||
) {
|
) {
|
||||||
reportIllegalModifiers(modifierListOwner.getModifierList(), illegalModifiers, trace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Map<JetModifierKeywordToken, ASTNode> getNodesCorrespondingToModifiers(@NotNull JetModifierList modifierList, @NotNull Collection<JetModifierKeywordToken> possibleModifiers) {
|
|
||||||
Map<JetModifierKeywordToken, ASTNode> nodes = Maps.newHashMap();
|
|
||||||
for (JetModifierKeywordToken modifier : possibleModifiers) {
|
|
||||||
if (modifierList.hasModifier(modifier)) {
|
|
||||||
nodes.put(modifier, modifierList.getModifierNode(modifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Modality resolveModalityFromModifiers(@NotNull JetModifierListOwner modifierListOwner, @NotNull Modality defaultModality) {
|
|
||||||
return resolveModalityFromModifiers(modifierListOwner.getModifierList(), defaultModality);
|
return resolveModalityFromModifiers(modifierListOwner.getModifierList(), defaultModality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public static Modality resolveModalityFromModifiers(@Nullable JetModifierList modifierList, @NotNull Modality defaultModality) {
|
public static Modality resolveModalityFromModifiers(@Nullable JetModifierList modifierList, @NotNull Modality defaultModality) {
|
||||||
if (modifierList == null) return defaultModality;
|
if (modifierList == null) return defaultModality;
|
||||||
boolean hasAbstractModifier = modifierList.hasModifier(ABSTRACT_KEYWORD);
|
boolean hasAbstractModifier = modifierList.hasModifier(ABSTRACT_KEYWORD);
|
||||||
@@ -395,7 +150,10 @@ public class ModifiersChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Visibility resolveVisibilityFromModifiers(@NotNull JetModifierListOwner modifierListOwner, @NotNull Visibility defaultVisibility) {
|
public static Visibility resolveVisibilityFromModifiers(
|
||||||
|
@NotNull JetModifierListOwner modifierListOwner,
|
||||||
|
@NotNull Visibility defaultVisibility
|
||||||
|
) {
|
||||||
return resolveVisibilityFromModifiers(modifierListOwner.getModifierList(), defaultVisibility);
|
return resolveVisibilityFromModifiers(modifierListOwner.getModifierList(), defaultVisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,19 +179,317 @@ public class ModifiersChecker {
|
|||||||
return Visibilities.INTERNAL;
|
return Visibilities.INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runDeclarationCheckers(@NotNull JetDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
|
|
||||||
for (DeclarationChecker checker : additionalCheckerProvider.getDeclarationCheckers()) {
|
public class ModifiersCheckingProcedure {
|
||||||
checker.check(declaration, descriptor, trace, trace.getBindingContext());
|
|
||||||
|
@NotNull
|
||||||
|
private final BindingTrace trace;
|
||||||
|
|
||||||
|
private ModifiersCheckingProcedure(@NotNull BindingTrace trace) {
|
||||||
|
this.trace = trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkParameterHasNoValOrVar(
|
||||||
|
@NotNull JetParameter parameter,
|
||||||
|
@NotNull DiagnosticFactory1<PsiElement, JetKeywordToken> diagnosticFactory
|
||||||
|
) {
|
||||||
|
PsiElement valOrVar = parameter.getValOrVarKeyword();
|
||||||
|
if (valOrVar != null) {
|
||||||
|
trace.report(diagnosticFactory.on(valOrVar, ((JetKeywordToken) valOrVar.getNode().getElementType())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportIllegalModifiers(
|
||||||
|
@Nullable JetModifierList modifierList,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken> illegalModifiers
|
||||||
|
) {
|
||||||
|
if (modifierList == null) return;
|
||||||
|
|
||||||
|
for (JetModifierKeywordToken modifierToken : illegalModifiers) {
|
||||||
|
if (modifierList.hasModifier(modifierToken)) {
|
||||||
|
PsiElement modifierPsi = modifierList.getModifier(modifierToken);
|
||||||
|
assert modifierPsi != null;
|
||||||
|
trace.report(ILLEGAL_MODIFIER.on(modifierPsi, modifierToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportIllegalModifiers(
|
||||||
|
@NotNull JetModifierListOwner modifierListOwner,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken> illegalModifiers
|
||||||
|
) {
|
||||||
|
reportIllegalModifiers(modifierListOwner.getModifierList(), illegalModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkIncompatibleModifiers(
|
||||||
|
@Nullable JetModifierList modifierList,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken> availableModifiers,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken>... availableCombinations
|
||||||
|
) {
|
||||||
|
if (modifierList == null) return;
|
||||||
|
Collection<JetModifierKeywordToken> presentModifiers = Sets.newLinkedHashSet();
|
||||||
|
for (JetModifierKeywordToken modifier : availableModifiers) {
|
||||||
|
if (modifierList.hasModifier(modifier)) {
|
||||||
|
presentModifiers.add(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkRepeatedModifiers(modifierList, availableModifiers);
|
||||||
|
|
||||||
|
if (presentModifiers.size() == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Collection<JetModifierKeywordToken> combination : availableCombinations) {
|
||||||
|
if (presentModifiers.containsAll(combination) && combination.containsAll(presentModifiers)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (JetModifierKeywordToken token : presentModifiers) {
|
||||||
|
trace.report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token).getPsi(), presentModifiers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRepeatedModifiers(
|
||||||
|
@NotNull JetModifierList modifierList,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken> availableModifiers
|
||||||
|
) {
|
||||||
|
for (JetModifierKeywordToken token : availableModifiers) {
|
||||||
|
if (!modifierList.hasModifier(token)) continue;
|
||||||
|
|
||||||
|
List<ASTNode> nodesOfRepeatedTokens = Lists.newArrayList();
|
||||||
|
ASTNode node = modifierList.getNode().getFirstChildNode();
|
||||||
|
while (node != null) {
|
||||||
|
if (node.getElementType() == token) {
|
||||||
|
nodesOfRepeatedTokens.add(node);
|
||||||
|
}
|
||||||
|
node = node.getTreeNext();
|
||||||
|
}
|
||||||
|
if (nodesOfRepeatedTokens.size() > 1) {
|
||||||
|
for (ASTNode repeatedToken : nodesOfRepeatedTokens) {
|
||||||
|
trace.report(REPEATED_MODIFIER.on(repeatedToken.getPsi(), token));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkIncompatibleVarianceModifiers(@Nullable JetModifierList modifierList) {
|
||||||
|
checkIncompatibleModifiers(modifierList, Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void checkModifiersForDeclaration(@NotNull JetDeclaration modifierListOwner, @NotNull MemberDescriptor descriptor) {
|
||||||
|
if (modifierListOwner instanceof JetEnumEntry) {
|
||||||
|
reportIllegalModifiers(modifierListOwner.getModifierList(), Arrays.asList(MODIFIER_KEYWORDS_ARRAY));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
checkInnerModifier(modifierListOwner, descriptor);
|
||||||
|
checkCompanionModifier(modifierListOwner);
|
||||||
|
checkModalityModifiers(modifierListOwner);
|
||||||
|
checkVisibilityModifiers(modifierListOwner, descriptor);
|
||||||
|
checkVarianceModifiers(modifierListOwner);
|
||||||
|
checkVarargsModifiers(modifierListOwner, descriptor);
|
||||||
|
}
|
||||||
|
checkPlatformNameApplicability(descriptor);
|
||||||
|
runDeclarationCheckers(modifierListOwner, descriptor);
|
||||||
|
AnnotationTargetChecker.INSTANCE$.check(modifierListOwner, trace,
|
||||||
|
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkVarargsModifiers(@NotNull JetDeclaration owner, @NotNull MemberDescriptor descriptor) {
|
||||||
|
if (!(owner instanceof JetParameter)) {
|
||||||
|
reportIllegalModifiers(owner.getModifierList(), Collections.singleton(VARARG_KEYWORD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkModifiersForLocalDeclaration(
|
||||||
|
@NotNull JetDeclaration modifierListOwner,
|
||||||
|
@NotNull DeclarationDescriptor descriptor
|
||||||
|
) {
|
||||||
|
reportIllegalModalityModifiers(modifierListOwner);
|
||||||
|
reportIllegalVisibilityModifiers(modifierListOwner);
|
||||||
|
checkPlatformNameApplicability(descriptor);
|
||||||
|
runDeclarationCheckers(modifierListOwner, descriptor);
|
||||||
|
AnnotationTargetChecker.INSTANCE$.check(modifierListOwner, trace,
|
||||||
|
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportIllegalModalityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
||||||
|
reportIllegalModifiers(modifierListOwner, MODALITY_MODIFIERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportIllegalVisibilityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
||||||
|
reportIllegalModifiers(modifierListOwner, VISIBILITY_MODIFIERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkModalityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
||||||
|
JetModifierList modifierList = modifierListOwner.getModifierList();
|
||||||
|
if (modifierList == null) return;
|
||||||
|
|
||||||
|
checkRedundantModifier(modifierList, Pair.create(OPEN_KEYWORD, ABSTRACT_KEYWORD), Pair.create(OPEN_KEYWORD, OVERRIDE_KEYWORD));
|
||||||
|
|
||||||
|
checkCompatibility(modifierList, Arrays.asList(ABSTRACT_KEYWORD, OPEN_KEYWORD, FINAL_KEYWORD),
|
||||||
|
Arrays.asList(ABSTRACT_KEYWORD, OPEN_KEYWORD));
|
||||||
|
|
||||||
|
if (modifierListOwner instanceof JetObjectDeclaration) {
|
||||||
|
reportIllegalModalityModifiers(modifierListOwner);
|
||||||
|
}
|
||||||
|
else if (modifierListOwner instanceof JetClassOrObject) {
|
||||||
|
reportIllegalModifiers(modifierListOwner, Collections.singletonList(OVERRIDE_KEYWORD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkVisibilityModifiers(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
||||||
|
JetModifierList modifierList = modifierListOwner.getModifierList();
|
||||||
|
if (modifierList == null) return;
|
||||||
|
|
||||||
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
|
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||||
|
if (modifierList.hasModifier(PROTECTED_KEYWORD)) {
|
||||||
|
trace.report(Errors.PACKAGE_MEMBER_CANNOT_BE_PROTECTED.on(modifierListOwner));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCompatibility(modifierList, VISIBILITY_MODIFIERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInnerModifier(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (modifierListOwner.hasModifier(INNER_KEYWORD)) {
|
||||||
|
switch (checkIllegalInner(descriptor)) {
|
||||||
|
case ALLOWED:
|
||||||
|
break;
|
||||||
|
case ILLEGAL_POSITION:
|
||||||
|
reportIllegalModifiers(modifierListOwner, Collections.singletonList(INNER_KEYWORD));
|
||||||
|
break;
|
||||||
|
case IN_TRAIT:
|
||||||
|
trace.report(INNER_CLASS_IN_TRAIT.on(modifierListOwner));
|
||||||
|
break;
|
||||||
|
case IN_OBJECT:
|
||||||
|
trace.report(INNER_CLASS_IN_OBJECT.on(modifierListOwner));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (modifierListOwner instanceof JetClass && !(modifierListOwner instanceof JetEnumEntry)) {
|
||||||
|
JetClass aClass = (JetClass) modifierListOwner;
|
||||||
|
boolean localEnumError = aClass.isLocal() && aClass.isEnum();
|
||||||
|
if (!localEnumError && isIllegalNestedClass(descriptor)) {
|
||||||
|
trace.report(NESTED_CLASS_NOT_ALLOWED.on(aClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCompanionModifier(@NotNull JetDeclaration declaration) {
|
||||||
|
if (declaration.hasModifier(COMPANION_KEYWORD) && !isCompanionModifierAllowed(declaration)) {
|
||||||
|
reportIllegalModifiers(declaration, Collections.singletonList(COMPANION_KEYWORD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPlatformNameApplicability(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
AnnotationDescriptor annotation = descriptor.getAnnotations().findAnnotation(new FqName("kotlin.platform.platformName"));
|
||||||
|
if (annotation == null) return;
|
||||||
|
|
||||||
|
JetAnnotationEntry annotationEntry = trace.get(BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotation);
|
||||||
|
if (annotationEntry == null) return;
|
||||||
|
|
||||||
|
if (descriptor instanceof FunctionDescriptor && !isRenamableFunction((FunctionDescriptor) descriptor)) {
|
||||||
|
trace.report(INAPPLICABLE_PLATFORM_NAME.on(annotationEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = null;
|
||||||
|
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
|
||||||
|
if (!values.isEmpty()) {
|
||||||
|
ConstantValue<?> name = values.iterator().next();
|
||||||
|
if (name instanceof StringValue) {
|
||||||
|
value = ((StringValue) name).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value == null || !Name.isValidIdentifier(value)) {
|
||||||
|
trace.report(ILLEGAL_PLATFORM_NAME.on(annotationEntry, String.valueOf(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor instanceof CallableMemberDescriptor) {
|
||||||
|
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) descriptor;
|
||||||
|
if (DescriptorUtils.isOverride(callableMemberDescriptor) || callableMemberDescriptor.getModality().isOverridable()) {
|
||||||
|
trace.report(INAPPLICABLE_PLATFORM_NAME.on(annotationEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isRenamableFunction(@NotNull FunctionDescriptor descriptor) {
|
||||||
|
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||||
|
|
||||||
|
return containingDescriptor instanceof PackageFragmentDescriptor || containingDescriptor instanceof ClassDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCompatibility(
|
||||||
|
@Nullable JetModifierList modifierList,
|
||||||
|
Collection<JetModifierKeywordToken> availableModifiers,
|
||||||
|
Collection<JetModifierKeywordToken>... availableCombinations
|
||||||
|
) {
|
||||||
|
checkIncompatibleModifiers(modifierList, availableModifiers, availableCombinations);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRedundantModifier(
|
||||||
|
@NotNull JetModifierList modifierList,
|
||||||
|
Pair<JetModifierKeywordToken, JetModifierKeywordToken>... redundantBundles
|
||||||
|
) {
|
||||||
|
for (Pair<JetModifierKeywordToken, JetModifierKeywordToken> tokenPair : redundantBundles) {
|
||||||
|
JetModifierKeywordToken redundantModifier = tokenPair.getFirst();
|
||||||
|
JetModifierKeywordToken sufficientModifier = tokenPair.getSecond();
|
||||||
|
if (modifierList.hasModifier(redundantModifier) && modifierList.hasModifier(sufficientModifier)) {
|
||||||
|
trace.report(Errors.REDUNDANT_MODIFIER.on(modifierList.getModifierNode(redundantModifier).getPsi(), redundantModifier,
|
||||||
|
sufficientModifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Map<JetModifierKeywordToken, ASTNode> getNodesCorrespondingToModifiers(
|
||||||
|
@NotNull JetModifierList modifierList,
|
||||||
|
@NotNull Collection<JetModifierKeywordToken> possibleModifiers
|
||||||
|
) {
|
||||||
|
Map<JetModifierKeywordToken, ASTNode> nodes = Maps.newHashMap();
|
||||||
|
for (JetModifierKeywordToken modifier : possibleModifiers) {
|
||||||
|
if (modifierList.hasModifier(modifier)) {
|
||||||
|
nodes.put(modifier, modifierList.getModifierNode(modifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void runDeclarationCheckers(@NotNull JetDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
|
||||||
|
for (DeclarationChecker checker : additionalCheckerProvider.getDeclarationCheckers()) {
|
||||||
|
checker.check(declaration, descriptor, trace, trace.getBindingContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkVarianceModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
||||||
|
reportIllegalModifiers(modifierListOwner.getModifierList(), Arrays.asList(IN_KEYWORD, OUT_KEYWORD, REIFIED_KEYWORD));
|
||||||
|
if (!(modifierListOwner instanceof JetTypeParameterListOwner)) return;
|
||||||
|
List<JetTypeParameter> typeParameters = ((JetTypeParameterListOwner) modifierListOwner).getTypeParameters();
|
||||||
|
for (JetTypeParameter typeParameter : typeParameters) {
|
||||||
|
JetModifierList modifierList = typeParameter.getModifierList();
|
||||||
|
checkIncompatibleVarianceModifiers(modifierList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkParameterHasNoModifier(
|
||||||
|
@NotNull JetParameter parameter
|
||||||
|
) {
|
||||||
|
reportIllegalModifiers(parameter.getModifierList(), MODIFIERS_ILLEGAL_ON_PARAMETERS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkVarianceModifiers(@NotNull JetModifierListOwner modifierListOwner) {
|
@NotNull
|
||||||
reportIllegalModifiers(modifierListOwner, Arrays.asList(IN_KEYWORD, OUT_KEYWORD, REIFIED_KEYWORD));
|
private final AdditionalCheckerProvider additionalCheckerProvider;
|
||||||
if (!(modifierListOwner instanceof JetTypeParameterListOwner)) return;
|
|
||||||
List<JetTypeParameter> typeParameters = ((JetTypeParameterListOwner) modifierListOwner).getTypeParameters();
|
public ModifiersChecker(@NotNull AdditionalCheckerProvider additionalCheckerProvider) {
|
||||||
for (JetTypeParameter typeParameter : typeParameters) {
|
this.additionalCheckerProvider = additionalCheckerProvider;
|
||||||
JetModifierList modifierList = typeParameter.getModifierList();
|
}
|
||||||
checkIncompatibleVarianceModifiers(modifierList, trace);
|
|
||||||
}
|
@NotNull
|
||||||
|
public ModifiersCheckingProcedure withTrace(@NotNull BindingTrace trace) {
|
||||||
|
return new ModifiersCheckingProcedure(trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ public class TypeResolver(
|
|||||||
private val flexibleTypeCapabilitiesProvider: FlexibleTypeCapabilitiesProvider,
|
private val flexibleTypeCapabilitiesProvider: FlexibleTypeCapabilitiesProvider,
|
||||||
private val storageManager: StorageManager,
|
private val storageManager: StorageManager,
|
||||||
private val lazinessToken: TypeLazinessToken,
|
private val lazinessToken: TypeLazinessToken,
|
||||||
private val dynamicTypesSettings: DynamicTypesSettings
|
private val dynamicTypesSettings: DynamicTypesSettings,
|
||||||
|
private val modifiersChecker: ModifiersChecker
|
||||||
) {
|
) {
|
||||||
|
|
||||||
public open class FlexibleTypeCapabilitiesProvider {
|
public open class FlexibleTypeCapabilitiesProvider {
|
||||||
@@ -268,9 +269,9 @@ public class TypeResolver(
|
|||||||
return argumentElements.mapIndexed { i, argumentElement ->
|
return argumentElements.mapIndexed { i, argumentElement ->
|
||||||
|
|
||||||
val projectionKind = argumentElement.getProjectionKind()
|
val projectionKind = argumentElement.getProjectionKind()
|
||||||
ModifiersChecker.checkIncompatibleVarianceModifiers(argumentElement.getModifierList(), c.trace)
|
modifiersChecker.withTrace(c.trace).checkIncompatibleVarianceModifiers(argumentElement.getModifierList())
|
||||||
if (projectionKind == JetProjectionKind.STAR) {
|
if (projectionKind == JetProjectionKind.STAR) {
|
||||||
ModifiersChecker.reportIllegalModifiers(argumentElement.getModifierList(), listOf(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD), c.trace)
|
modifiersChecker.withTrace(c.trace).reportIllegalModifiers(argumentElement.getModifierList(), listOf(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD))
|
||||||
|
|
||||||
val parameters = constructor.getParameters()
|
val parameters = constructor.getParameters()
|
||||||
if (parameters.size() > i) {
|
if (parameters.size() > i) {
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ import java.util.ArrayList
|
|||||||
public class CandidateResolver(
|
public class CandidateResolver(
|
||||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
private val genericCandidateResolver: GenericCandidateResolver,
|
private val genericCandidateResolver: GenericCandidateResolver,
|
||||||
private val reflectionTypes: ReflectionTypes
|
private val reflectionTypes: ReflectionTypes,
|
||||||
|
private val modifiersChecker: ModifiersChecker
|
||||||
){
|
){
|
||||||
|
|
||||||
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(
|
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(
|
||||||
@@ -123,7 +124,7 @@ public class CandidateResolver(
|
|||||||
for (projection in jetTypeArguments) {
|
for (projection in jetTypeArguments) {
|
||||||
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
|
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
|
||||||
trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection))
|
trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection))
|
||||||
ModifiersChecker.checkIncompatibleVarianceModifiers(projection.getModifierList(), trace)
|
modifiersChecker.withTrace(trace).checkIncompatibleVarianceModifiers(projection.getModifierList())
|
||||||
}
|
}
|
||||||
val type = argumentTypeResolver.resolveTypeRefWithDefault(
|
val type = argumentTypeResolver.resolveTypeRefWithDefault(
|
||||||
projection.getTypeReference(), scope, trace,
|
projection.getTypeReference(), scope, trace,
|
||||||
|
|||||||
@@ -20,13 +20,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind;
|
import org.jetbrains.kotlin.descriptors.ClassKind;
|
||||||
import org.jetbrains.kotlin.psi.JetObjectDeclaration;
|
import org.jetbrains.kotlin.psi.JetObjectDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.JetParameter;
|
|
||||||
import org.jetbrains.kotlin.psi.JetTypeParameterList;
|
import org.jetbrains.kotlin.psi.JetTypeParameterList;
|
||||||
import org.jetbrains.kotlin.resolve.ModifiersChecker;
|
import org.jetbrains.kotlin.resolve.ModifiersChecker;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
|
public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
|
||||||
@NotNull
|
@NotNull
|
||||||
private final ClassKind kind;
|
private final ClassKind kind;
|
||||||
@@ -49,6 +45,6 @@ public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCompanionObject() {
|
public boolean isCompanionObject() {
|
||||||
return element.isCompanion() && ModifiersChecker.isDefaultModifierAllowed(element);
|
return element.isCompanion() && ModifiersChecker.isCompanionModifierAllowed(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -26,10 +26,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorResolver;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||||
@@ -426,7 +423,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetType expectedParameterType,
|
JetType expectedParameterType,
|
||||||
ExpressionTypingContext context
|
ExpressionTypingContext context
|
||||||
) {
|
) {
|
||||||
DescriptorResolver.checkParameterHasNoValOrVar(context.trace, loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);
|
components.modifiersChecker.withTrace(context.trace).checkParameterHasNoValOrVar(loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);
|
||||||
|
|
||||||
JetTypeReference typeReference = loopParameter.getTypeReference();
|
JetTypeReference typeReference = loopParameter.getTypeReference();
|
||||||
VariableDescriptor variableDescriptor;
|
VariableDescriptor variableDescriptor;
|
||||||
@@ -468,8 +465,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetParameter catchParameter = catchClause.getCatchParameter();
|
JetParameter catchParameter = catchClause.getCatchParameter();
|
||||||
JetExpression catchBody = catchClause.getCatchBody();
|
JetExpression catchBody = catchClause.getCatchBody();
|
||||||
if (catchParameter != null) {
|
if (catchParameter != null) {
|
||||||
DescriptorResolver.checkParameterHasNoValOrVar(context.trace, catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
|
ModifiersChecker.ModifiersCheckingProcedure modifiersChecking = components.modifiersChecker.withTrace(context.trace);
|
||||||
DescriptorResolver.checkParameterHasNoModifier(context.trace, catchParameter);
|
modifiersChecking.checkParameterHasNoValOrVar(catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
|
||||||
|
modifiersChecking.checkParameterHasNoModifier(catchParameter);
|
||||||
|
|
||||||
VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(
|
VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(
|
||||||
context.scope, catchParameter, context.trace);
|
context.scope, catchParameter, context.trace);
|
||||||
|
|||||||
+6
@@ -51,6 +51,7 @@ public class ExpressionTypingComponents {
|
|||||||
/*package*/ ValueParameterResolver valueParameterResolver;
|
/*package*/ ValueParameterResolver valueParameterResolver;
|
||||||
/*package*/ MultiDeclarationResolver multiDeclarationResolver;
|
/*package*/ MultiDeclarationResolver multiDeclarationResolver;
|
||||||
/*package*/ ConstantExpressionEvaluator constantExpressionEvaluator;
|
/*package*/ ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
|
/*package*/ ModifiersChecker modifiersChecker;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
||||||
@@ -161,4 +162,9 @@ public class ExpressionTypingComponents {
|
|||||||
public void setConstantExpressionEvaluator(@NotNull ConstantExpressionEvaluator constantExpressionEvaluator) {
|
public void setConstantExpressionEvaluator(@NotNull ConstantExpressionEvaluator constantExpressionEvaluator) {
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void setModifiersChecker(ModifiersChecker modifiersChecker) {
|
||||||
|
this.modifiersChecker = modifiersChecker;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -162,7 +162,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.addVariableDescriptor(propertyDescriptor);
|
scope.addVariableDescriptor(propertyDescriptor);
|
||||||
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(property, propertyDescriptor);
|
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor);
|
||||||
return typeInfo.replaceType(DataFlowUtils.checkStatementType(property, context));
|
return typeInfo.replaceType(DataFlowUtils.checkStatementType(property, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -103,8 +103,7 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
|||||||
function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope, context.dataFlowInfo, context.trace
|
function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope, context.dataFlowInfo, context.trace
|
||||||
)
|
)
|
||||||
|
|
||||||
ModifiersChecker.create(context.trace, components.additionalCheckerProvider)
|
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(function, functionDescriptor)
|
||||||
.checkModifiersForLocalDeclaration(function, functionDescriptor)
|
|
||||||
if (!function.hasBody()) {
|
if (!function.hasBody()) {
|
||||||
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user