Added inline annotation check on local funs

This commit is contained in:
Michael Bogdanov
2014-10-10 13:42:10 +04:00
parent 2a1520228e
commit 605c9f48b4
21 changed files with 104 additions and 48 deletions
@@ -2222,8 +2222,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean isInline = state.isInlineEnabled() &&
descriptor instanceof SimpleFunctionDescriptor &&
((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
//TODO: support local fun inlining
if (!isInline || isLocalNamedFun(descriptor)) return defaultCallGenerator;
if (!isInline) return defaultCallGenerator;
SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal());
return new InlineCodegen(this, state, original, callElement);
@@ -59,6 +59,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallCompleter;
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.ModifiersChecker;
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
import org.jetbrains.jet.lang.resolve.ScriptBodyResolver;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
@@ -125,6 +126,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
private final CandidateResolver candidateResolver;
private final ControlFlowAnalyzer controlFlowAnalyzer;
private final DeclarationsChecker declarationsChecker;
private final ModifiersChecker modifiersChecker;
private final FunctionAnalyzerExtension functionAnalyzerExtension;
private final ScriptBodyResolver scriptBodyResolver;
private final DeclarationResolver declarationResolver;
@@ -197,6 +199,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver);
this.controlFlowAnalyzer = new ControlFlowAnalyzer();
this.declarationsChecker = new DeclarationsChecker();
this.modifiersChecker = new ModifiersChecker(bindingTrace, additionalCheckerProvider);
this.functionAnalyzerExtension = new FunctionAnalyzerExtension();
this.scriptBodyResolver = new ScriptBodyResolver();
this.declarationResolver = new DeclarationResolver();
@@ -309,6 +312,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
declarationsChecker.setAdditionalCheckerProvider(additionalCheckerProvider);
declarationsChecker.setDescriptorResolver(descriptorResolver);
declarationsChecker.setModifiersChecker(modifiersChecker);
declarationsChecker.setTrace(bindingTrace);
functionAnalyzerExtension.setTrace(bindingTrace);
@@ -29,21 +29,39 @@ import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.psi.JetProperty
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import org.jetbrains.jet.lang.diagnostics.DiagnosticSink
import org.jetbrains.jet.lang.descriptors.Visibilities
import org.jetbrains.jet.lang.resolve.annotations.hasInlineAnnotation
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.diagnostics.Errors
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
public object JavaDeclarationCheckerProvider : AdditionalCheckerProvider {
override val annotationCheckers: List<AnnotationChecker> = listOf(PlatformStaticAnnotationChecker())
override val annotationCheckers: List<AnnotationChecker> = listOf(PlatformStaticAnnotationChecker(), LocalFunInlineChecker())
}
public class LocalFunInlineChecker : AnnotationChecker {
override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
if (descriptor.hasInlineAnnotation() &&
declaration is JetNamedFunction &&
descriptor is FunctionDescriptor &&
descriptor.getVisibility() == Visibilities.LOCAL) {
diagnosticHolder.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, declaration, descriptor))
}
}
}
public class PlatformStaticAnnotationChecker : AnnotationChecker {
override fun check(declaration: JetDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink) {
override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
if (descriptor.hasPlatformStaticAnnotation()) {
if (declaration is JetNamedFunction) {
val insideObject = DescriptorUtils.containerKindIs(descriptor, ClassKind.OBJECT)
val insideClassObject = DescriptorUtils.containerKindIs(descriptor, ClassKind.CLASS_OBJECT)
if (!insideObject && !(insideClassObject && DescriptorUtils.containerKindIs(descriptor.getContainingDeclaration(), ClassKind.CLASS))) {
if (!insideObject && !(insideClassObject && DescriptorUtils.containerKindIs(descriptor.getContainingDeclaration()!!, ClassKind.CLASS))) {
diagnosticHolder.report(ErrorsJvm.PLATFORM_STATIC_NOT_IN_OBJECT.on(declaration, descriptor));
}
@@ -43,6 +43,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallCompleter;
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.ModifiersChecker;
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
import org.jetbrains.jet.lang.resolve.ScriptBodyResolver;
import org.jetbrains.annotations.NotNull;
@@ -79,6 +80,7 @@ public class InjectorForBodyResolve {
private final CandidateResolver candidateResolver;
private final ControlFlowAnalyzer controlFlowAnalyzer;
private final DeclarationsChecker declarationsChecker;
private final ModifiersChecker modifiersChecker;
private final FunctionAnalyzerExtension functionAnalyzerExtension;
private final ScriptBodyResolver scriptBodyResolver;
@@ -116,6 +118,7 @@ public class InjectorForBodyResolve {
this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver);
this.controlFlowAnalyzer = new ControlFlowAnalyzer();
this.declarationsChecker = new DeclarationsChecker();
this.modifiersChecker = new ModifiersChecker(bindingTrace, additionalCheckerProvider);
this.functionAnalyzerExtension = new FunctionAnalyzerExtension();
this.scriptBodyResolver = new ScriptBodyResolver();
@@ -185,6 +188,7 @@ public class InjectorForBodyResolve {
declarationsChecker.setAdditionalCheckerProvider(additionalCheckerProvider);
declarationsChecker.setDescriptorResolver(descriptorResolver);
declarationsChecker.setModifiersChecker(modifiersChecker);
declarationsChecker.setTrace(bindingTrace);
functionAnalyzerExtension.setTrace(bindingTrace);
@@ -46,6 +46,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallCompleter;
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.ModifiersChecker;
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
import org.jetbrains.jet.lang.resolve.ScriptBodyResolver;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
@@ -92,6 +93,7 @@ public class InjectorForTopDownAnalyzerBasic {
private final CandidateResolver candidateResolver;
private final ControlFlowAnalyzer controlFlowAnalyzer;
private final DeclarationsChecker declarationsChecker;
private final ModifiersChecker modifiersChecker;
private final FunctionAnalyzerExtension functionAnalyzerExtension;
private final ScriptBodyResolver scriptBodyResolver;
private final DeclarationResolver declarationResolver;
@@ -139,6 +141,7 @@ public class InjectorForTopDownAnalyzerBasic {
this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver);
this.controlFlowAnalyzer = new ControlFlowAnalyzer();
this.declarationsChecker = new DeclarationsChecker();
this.modifiersChecker = new ModifiersChecker(bindingTrace, additionalCheckerProvider);
this.functionAnalyzerExtension = new FunctionAnalyzerExtension();
this.scriptBodyResolver = new ScriptBodyResolver();
this.declarationResolver = new DeclarationResolver();
@@ -234,6 +237,7 @@ public class InjectorForTopDownAnalyzerBasic {
declarationsChecker.setAdditionalCheckerProvider(additionalCheckerProvider);
declarationsChecker.setDescriptorResolver(descriptorResolver);
declarationsChecker.setModifiersChecker(modifiersChecker);
declarationsChecker.setTrace(bindingTrace);
functionAnalyzerExtension.setTrace(bindingTrace);
@@ -19,9 +19,10 @@ package org.jetbrains.jet.lang.resolve
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.descriptors.MemberDescriptor
import org.jetbrains.jet.lang.diagnostics.DiagnosticSink
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
public trait AnnotationChecker {
public fun check(declaration: JetDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink);
public fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink);
}
@@ -22,6 +22,10 @@ import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.resolve.DescriptorUtils
public fun DeclarationDescriptor.hasInlineAnnotation(): Boolean {
return getAnnotations().findAnnotation(FqName("kotlin.inline")) != null
}
public fun DeclarationDescriptor.hasPlatformStaticAnnotation(): Boolean {
return getAnnotations().findAnnotation(FqName("kotlin.platform.platformStatic")) != null
}
@@ -52,7 +52,6 @@ public class DeclarationsChecker {
@Inject
public void setTrace(@NotNull BindingTrace trace) {
this.trace = trace;
this.modifiersChecker = new ModifiersChecker(trace);
}
@Inject
@@ -65,6 +64,11 @@ public class DeclarationsChecker {
this.additionalCheckerProvider = additionalCheckerProvider;
}
@Inject
public void setModifiersChecker(@NotNull ModifiersChecker modifiersChecker) {
this.modifiersChecker = modifiersChecker;
}
public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
for (JetFile file : bodiesResolveContext.getFiles()) {
checkModifiersAndAnnotationsInPackageDirective(file);
@@ -90,7 +94,6 @@ public class DeclarationsChecker {
}
modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor);
runAnnotationCheckers(classOrObject, classDescriptor);
}
Map<JetNamedFunction, SimpleFunctionDescriptor> functions = bodiesResolveContext.getFunctions();
@@ -101,7 +104,6 @@ public class DeclarationsChecker {
if (!bodiesResolveContext.completeAnalysisNeeded(function)) continue;
checkFunction(function, functionDescriptor);
modifiersChecker.checkModifiersForDeclaration(function, functionDescriptor);
runAnnotationCheckers(function, functionDescriptor);
}
Map<JetProperty, PropertyDescriptor> properties = bodiesResolveContext.getProperties();
@@ -112,7 +114,6 @@ public class DeclarationsChecker {
if (!bodiesResolveContext.completeAnalysisNeeded(property)) continue;
checkProperty(property, propertyDescriptor);
modifiersChecker.checkModifiersForDeclaration(property, propertyDescriptor);
runAnnotationCheckers(property, propertyDescriptor);
}
}
@@ -575,10 +576,4 @@ public class DeclarationsChecker {
}
}
}
private void runAnnotationCheckers(@NotNull JetDeclaration declaration, @NotNull MemberDescriptor descriptor) {
for (AnnotationChecker checker : additionalCheckerProvider.getAnnotationCheckers()) {
checker.check(declaration, descriptor, trace);
}
}
}
@@ -65,27 +65,32 @@ public class ModifiersChecker {
@NotNull
private final BindingTrace trace;
@NotNull
private AdditionalCheckerProvider additionalCheckerProvider;
public ModifiersChecker(@NotNull BindingTrace trace) {
public ModifiersChecker(@NotNull BindingTrace trace, @NotNull AdditionalCheckerProvider provider) {
this.trace = trace;
additionalCheckerProvider = provider;
}
public static ModifiersChecker create(@NotNull BindingTrace trace) {
return new ModifiersChecker(trace);
public static ModifiersChecker create(@NotNull BindingTrace trace, @NotNull AdditionalCheckerProvider provider) {
return new ModifiersChecker(trace, provider);
}
public void checkModifiersForDeclaration(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
public void checkModifiersForDeclaration(@NotNull JetDeclaration modifierListOwner, @NotNull MemberDescriptor descriptor) {
JetModifierList modifierList = modifierListOwner.getModifierList();
checkModalityModifiers(modifierList);
checkVisibilityModifiers(modifierListOwner, descriptor);
checkInnerModifier(modifierListOwner, descriptor);
checkPlatformNameApplicability(descriptor);
runAnnotationCheckers(modifierListOwner, descriptor);
}
public void checkModifiersForLocalDeclaration(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
public void checkModifiersForLocalDeclaration(@NotNull JetDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
checkIllegalModalityModifiers(modifierListOwner);
checkIllegalVisibilityModifiers(modifierListOwner);
checkPlatformNameApplicability(descriptor);
runAnnotationCheckers(modifierListOwner, descriptor);
}
public void checkIllegalModalityModifiers(@NotNull JetModifierListOwner modifierListOwner) {
@@ -291,4 +296,10 @@ public class ModifiersChecker {
}
return Visibilities.INTERNAL;
}
private void runAnnotationCheckers(@NotNull JetDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
for (AnnotationChecker checker : additionalCheckerProvider.getAnnotationCheckers()) {
checker.check(declaration, descriptor, trace);
}
}
}
@@ -20,10 +20,7 @@ import com.google.common.collect.Sets;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
@@ -138,7 +135,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
scope.addVariableDescriptor(propertyDescriptor);
ModifiersChecker.create(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor);
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(property, propertyDescriptor);
return DataFlowUtils.checkStatementType(property, context, dataFlowInfo);
}
@@ -175,7 +172,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
components.expressionTypingServices.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(),
scope, context.dataFlowInfo, context.trace, /* needCompleteAnalysis = */ true);
ModifiersChecker.create(context.trace).checkModifiersForLocalDeclaration(function, functionDescriptor);
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function, functionDescriptor);
if (!function.hasBody()) {
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
}
@@ -1,9 +0,0 @@
fun box(): String {
val s = "OK"
[inline] fun localFun(): String {
return s
}
return localFun()
}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
<!NOT_YET_SUPPORTED_IN_INLINE!>[inline] fun a(){
}<!>
}
@@ -0,0 +1,3 @@
package
internal fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
@@ -6,9 +6,8 @@ public fun test() {
}
}
[inline] fun localFun2() {
<!NOT_YET_SUPPORTED_IN_INLINE!>[inline] fun localFun2() {
Z().localFun()
}
}
}<!>
}
@@ -4,8 +4,8 @@ public fun test() {
}
[inline] fun localFun2() {
<!NOT_YET_SUPPORTED_IN_INLINE!>[inline] fun localFun2() {
localFun()
}
}<!>
}
@@ -0,0 +1,8 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.platform.platformStatic
fun main(args: Array<String>) {
<!PLATFORM_STATIC_NOT_IN_OBJECT!>[platformStatic] fun a()<!>{
}
}
@@ -0,0 +1,3 @@
package
internal fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
@@ -5534,6 +5534,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("localFun.kt")
public void testLocalFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/localFun.kt");
doTest(fileName);
}
@TestMetadata("nonVirtualMembersWithInline.kt")
public void testNonVirtualMembersWithInline() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt");
@@ -124,6 +124,12 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
doTest(fileName);
}
@TestMetadata("localFun.kt")
public void testLocalFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/platformStatic/localFun.kt");
doTest(fileName);
}
@TestMetadata("property.kt")
public void testProperty() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/platformStatic/property.kt");
@@ -3505,12 +3505,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/localFunctions"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("disabledInline.kt")
public void testDisabledInline() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/disabledInline.kt");
doTest(fileName);
}
@TestMetadata("kt2895.kt")
public void testKt2895() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/kt2895.kt");
@@ -46,6 +46,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallCompleter;
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.ModifiersChecker;
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
import org.jetbrains.jet.lang.resolve.ScriptBodyResolver;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
@@ -92,6 +93,7 @@ public class InjectorForTopDownAnalyzerForJs {
private final CandidateResolver candidateResolver;
private final ControlFlowAnalyzer controlFlowAnalyzer;
private final DeclarationsChecker declarationsChecker;
private final ModifiersChecker modifiersChecker;
private final FunctionAnalyzerExtension functionAnalyzerExtension;
private final ScriptBodyResolver scriptBodyResolver;
private final DeclarationResolver declarationResolver;
@@ -138,6 +140,7 @@ public class InjectorForTopDownAnalyzerForJs {
this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver);
this.controlFlowAnalyzer = new ControlFlowAnalyzer();
this.declarationsChecker = new DeclarationsChecker();
this.modifiersChecker = new ModifiersChecker(bindingTrace, additionalCheckerProvider);
this.functionAnalyzerExtension = new FunctionAnalyzerExtension();
this.scriptBodyResolver = new ScriptBodyResolver();
this.declarationResolver = new DeclarationResolver();
@@ -233,6 +236,7 @@ public class InjectorForTopDownAnalyzerForJs {
declarationsChecker.setAdditionalCheckerProvider(additionalCheckerProvider);
declarationsChecker.setDescriptorResolver(descriptorResolver);
declarationsChecker.setModifiersChecker(modifiersChecker);
declarationsChecker.setTrace(bindingTrace);
functionAnalyzerExtension.setTrace(bindingTrace);