diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 671306e4c99..cbffe636710 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -39,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; +import org.jetbrains.jet.lang.types.lang.InlineStrategy; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetTokens; @@ -340,7 +341,7 @@ public class DescriptorResolver { Modality modality = resolveModalityFromModifiers(function, getDefaultModality(containingDescriptor, hasBody)); Visibility visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, containingDescriptor)); JetModifierList modifierList = function.getModifierList(); - boolean isInline = (modifierList != null) && modifierList.hasModifier(JetTokens.INLINE_KEYWORD); + boolean isInline = KotlinBuiltIns.getInstance().getInlineType(functionDescriptor) != InlineStrategy.NOT_INLINE; functionDescriptor.initialize( receiverType, getExpectedThisObjectIfNeeded(containingDescriptor), diff --git a/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java b/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java index 54ce12d59b9..873f1ecbce2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java +++ b/compiler/frontend/src/org/jetbrains/jet/lexer/JetTokens.java @@ -155,7 +155,6 @@ public interface JetTokens { JetKeywordToken CATCH_KEYWORD = JetKeywordToken.softKeyword("catch"); JetKeywordToken OUT_KEYWORD = JetKeywordToken.softKeyword("out"); JetKeywordToken VARARG_KEYWORD = JetKeywordToken.softKeyword("vararg"); - JetKeywordToken INLINE_KEYWORD = JetKeywordToken.softKeyword("inline"); JetKeywordToken REIFIED_KEYWORD = JetKeywordToken.softKeyword("reified"); JetKeywordToken FINALLY_KEYWORD = JetKeywordToken.softKeyword("finally"); @@ -173,12 +172,12 @@ public interface JetTokens { TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD, SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD, - CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD + CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD ); TokenSet MODIFIER_KEYWORDS = TokenSet.create(ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, - PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD + PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD ); TokenSet VISIBILITY_MODIFIERS = TokenSet.create(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineStrategy.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineStrategy.java new file mode 100644 index 00000000000..8f18e29eeb1 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineStrategy.java @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types.lang; + +public enum InlineStrategy { + AS_FUNCTION, + IN_PLACE, + NOT_INLINE; +} diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineUtil.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineUtil.java new file mode 100644 index 00000000000..7e3659b7347 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/InlineUtil.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types.lang; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.Annotated; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.EnumValue; + +import java.util.List; + +public class InlineUtil { + + @NotNull + public static InlineStrategy getInlineType(@NotNull Annotated annotated) { + return getInlineType(annotated.getAnnotations()); + } + + public static boolean hasNoinlineAnnotation(@NotNull CallableDescriptor valueParameterDescriptor) { + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + return KotlinBuiltIns.containsAnnotation(valueParameterDescriptor, builtIns.getNoinlineClassAnnotation()); + } + + @NotNull + public static InlineStrategy getInlineType(@Nullable List annotations) { + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + ClassDescriptor annotationClass = builtIns.getInlineClassAnnotation(); + AnnotationDescriptor annotation = getAnnotation(annotations, annotationClass); + if (annotation != null) { + ValueParameterDescriptor parameterDescriptor = annotationClass.getConstructors().iterator().next().getValueParameters().get(0); + CompileTimeConstant argument = annotation.getValueArgument(parameterDescriptor); + if (argument == null) { + //default parameter + return InlineStrategy.AS_FUNCTION; + } + else { + assert argument instanceof EnumValue : "Inline annotation parameter should be inline entry but was: " + argument + "!"; + PropertyDescriptor value = ((EnumValue)argument).getValue(); + String name = value.getName().asString(); + return name.equals(InlineStrategy.IN_PLACE.name()) ? InlineStrategy.IN_PLACE : InlineStrategy.AS_FUNCTION; + } + } + else { + return InlineStrategy.NOT_INLINE; + } + } + + @Nullable + private static AnnotationDescriptor getAnnotation(@Nullable List annotations, @NotNull ClassDescriptor annotationClass) { + if (annotations != null) { + for (AnnotationDescriptor annotation : annotations) { + if (annotationClass.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) { + return annotation; + } + } + } + return null; + } + + +} + diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 5f37b6fe00e..95e101a2619 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -24,10 +24,14 @@ import org.jetbrains.jet.lang.DefaultModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.EnumValue; +import org.jetbrains.jet.storage.LockBasedStorageManager; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.SpecialNames; @@ -36,7 +40,6 @@ import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.storage.LockBasedStorageManager; import java.io.IOException; import java.util.*; @@ -379,6 +382,15 @@ public class KotlinBuiltIns { return getBuiltInClassByName("data"); } + public ClassDescriptor getNoinlineClassAnnotation() { + return getBuiltInClassByName("noinline"); + } + + @NotNull + public ClassDescriptor getInlineClassAnnotation() { + return getBuiltInClassByName("inline"); + } + @NotNull public ClassDescriptor getSuppressAnnotationClass() { return getBuiltInClassByName("suppress"); @@ -943,7 +955,7 @@ public class KotlinBuiltIns { return containsAnnotation(declarationDescriptor, getDeprecatedAnnotation()); } - private static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) { + static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) { List annotations = descriptor.getOriginal().getAnnotations(); if (annotations != null) { for (AnnotationDescriptor annotation : annotations) { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index e6515ac1bf7..4cab8284aaf 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -237,7 +237,7 @@ public class JetKeywordCompletionContributor extends CompletionContributor { registerScopeKeywordsCompletion(InTopFilter.class.getName(), new InTopFilter(), ABSTRACT_KEYWORD, CLASS_KEYWORD, ENUM_KEYWORD, FINAL_KEYWORD, FUN_KEYWORD, GET_KEYWORD, - IMPORT_KEYWORD, INLINE_KEYWORD, INTERNAL_KEYWORD, + IMPORT_KEYWORD, INTERNAL_KEYWORD, OPEN_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, SET_KEYWORD, TRAIT_KEYWORD, TYPE_KEYWORD, VAL_KEYWORD, VAR_KEYWORD); @@ -247,13 +247,13 @@ public class JetKeywordCompletionContributor extends CompletionContributor { new AndFilter( new SuperParentFilter(new ClassFilter(JetModifierList.class)), new NotFilter(new InTypeParameterFirstChildFilter())), - ABSTRACT_KEYWORD, FINAL_KEYWORD, INLINE_KEYWORD, INTERNAL_KEYWORD, + ABSTRACT_KEYWORD, FINAL_KEYWORD, INTERNAL_KEYWORD, OPEN_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD); registerScopeKeywordsCompletion(InClassBodyFilter.class.getName(), new InClassBodyFilter(), ABSTRACT_KEYWORD, CLASS_KEYWORD, ENUM_KEYWORD, FINAL_KEYWORD, FUN_KEYWORD, GET_KEYWORD, - INLINE_KEYWORD, INTERNAL_KEYWORD, + INTERNAL_KEYWORD, OPEN_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, SET_KEYWORD, TRAIT_KEYWORD, TYPE_KEYWORD, VAL_KEYWORD, VAR_KEYWORD); @@ -264,7 +264,7 @@ public class JetKeywordCompletionContributor extends CompletionContributor { DO_KEYWORD, ELSE_KEYWORD, ENUM_KEYWORD, FALSE_KEYWORD, FINALLY_KEYWORD, FOR_KEYWORD, FUN_KEYWORD, GET_KEYWORD, IF_KEYWORD, - IN_KEYWORD, INLINE_KEYWORD, INTERNAL_KEYWORD, + IN_KEYWORD, INTERNAL_KEYWORD, IS_KEYWORD, NULL_KEYWORD, OBJECT_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, RETURN_KEYWORD, SET_KEYWORD, SUPER_KEYWORD, diff --git a/idea/testData/checker/infos/CapturedInInlinedClosure.kt b/idea/testData/checker/infos/CapturedInInlinedClosure.kt index ce3c54afac4..558b3446c9a 100644 --- a/idea/testData/checker/infos/CapturedInInlinedClosure.kt +++ b/idea/testData/checker/infos/CapturedInInlinedClosure.kt @@ -1,4 +1,4 @@ -inline fun run(f: () -> T) = f() +inline fun run(f: () -> T) = f() fun run2(f: () -> Unit) = f() fun inline() { diff --git a/idea/testData/completion/keywords/InClassBeforeFun.kt b/idea/testData/completion/keywords/InClassBeforeFun.kt index 1e180828fcc..ab93bf8406b 100644 --- a/idea/testData/completion/keywords/InClassBeforeFun.kt +++ b/idea/testData/completion/keywords/InClassBeforeFun.kt @@ -30,7 +30,6 @@ public class Test { // ABSENT: if // ABSENT: import // ABSENT: in -// EXIST: inline // EXIST: internal // ABSENT: is // ABSENT: null diff --git a/idea/testData/completion/keywords/InClassScope.kt b/idea/testData/completion/keywords/InClassScope.kt index c8793d80321..672b8d8d089 100644 --- a/idea/testData/completion/keywords/InClassScope.kt +++ b/idea/testData/completion/keywords/InClassScope.kt @@ -25,7 +25,6 @@ class TestClass { // ABSENT: if // ABSENT: import // ABSENT: in -// EXIST: inline // EXIST: internal // ABSENT: is // ABSENT: null diff --git a/idea/testData/completion/keywords/TopScope.kt b/idea/testData/completion/keywords/TopScope.kt index 5e1f254be14..07a32f340b0 100644 --- a/idea/testData/completion/keywords/TopScope.kt +++ b/idea/testData/completion/keywords/TopScope.kt @@ -21,7 +21,6 @@ // ABSENT: if // EXIST: import // ABSENT: in -// EXIST: inline // EXIST: internal // ABSENT: is // ABSENT: null diff --git a/idea/testData/editor/quickDoc/MethodFromStdLib.kt b/idea/testData/editor/quickDoc/MethodFromStdLib.kt index 024ad34bf58..18a85696d26 100644 --- a/idea/testData/editor/quickDoc/MethodFromStdLib.kt +++ b/idea/testData/editor/quickDoc/MethodFromStdLib.kt @@ -2,4 +2,4 @@ fun test() { listOf(1, 2, 4).filter { it > 0 } } -// INFO: public fun <T> jet.Iterable<T>.filter(predicate: (T) → jet.Boolean): jet.List<T> defined in kotlin

Returns a list containing all elements which match the given *predicate*

\ No newline at end of file +// INFO: jet.inline public fun <T> jet.Iterable<T>.filter(predicate: (T) → jet.Boolean): jet.List<T> defined in kotlin

Returns a list containing all elements which match the given *predicate*

diff --git a/idea/testData/libraries/decompiled/LibrariesPackage.kt b/idea/testData/libraries/decompiled/LibrariesPackage.kt index a358a20ce30..a646243ef55 100644 --- a/idea/testData/libraries/decompiled/LibrariesPackage.kt +++ b/idea/testData/libraries/decompiled/LibrariesPackage.kt @@ -33,4 +33,4 @@ package testData.libraries [public fun processDouble(d: testData.libraries.Double): jet.Unit { /* compiled code */ }] -[public fun T.filter(predicate: (T) -> jet.Boolean): T? { /* compiled code */ }] \ No newline at end of file +[jet.inline public fun T.filter(predicate: (T) -> jet.Boolean): T? { /* compiled code */ }] \ No newline at end of file