Diagnostics for wrong inlinable usage
This commit is contained in:
@@ -560,6 +560,13 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, ClassDescriptor> INACCESSIBLE_OUTER_CLASS_EXPRESSION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
//Inline and inlinable parameters
|
||||
DiagnosticFactory2<JetElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
|
||||
DiagnosticFactory2<JetElement, JetNamedDeclaration, DeclarationDescriptor> NOT_YET_SUPPORTED_IN_INLINE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<JetElement, DeclarationDescriptor> NOTHING_TO_INLINE = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory2<JetElement, JetExpression, DeclarationDescriptor> USAGE_IS_NOT_INLINABLE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<JetElement, JetElement, DeclarationDescriptor> NULLABLE_INLINE_PARAMETER = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<JetElement> DECLARATION_CANT_BE_INLINED = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Error sets
|
||||
ImmutableSet<? extends DiagnosticFactory> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
|
||||
|
||||
+9
@@ -33,6 +33,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.DECLARATION_CANT_BE_INLINED;
|
||||
import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.*;
|
||||
|
||||
public class DefaultErrorMessages {
|
||||
@@ -471,6 +472,14 @@ public class DefaultErrorMessages {
|
||||
"''{0}'' is a member and an extension at the same time. References to such elements are not allowed", TO_STRING);
|
||||
MAP.put(CALLABLE_REFERENCE_LHS_NOT_A_CLASS, "Callable reference left-hand side cannot be a type parameter");
|
||||
|
||||
//Inline
|
||||
MAP.put(INVISIBLE_MEMBER_FROM_INLINE, "Cannot access effectively non-public-api ''{0}'' member from effectively public-api ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "''{0}'' construction not yet supported in inline functions", ELEMENT_TEXT, TO_STRING);
|
||||
MAP.put(DECLARATION_CANT_BE_INLINED, "Inline annotation could be present only on nonvirtual members (private or final)");
|
||||
MAP.put(NOTHING_TO_INLINE, "There are no parameters of Function types to be inlined in ''{0}''", TO_STRING);
|
||||
MAP.put(USAGE_IS_NOT_INLINABLE, "Illegal usage of inline-parameter ''{0}'' in ''{1}''. Annotate the parameter with [noinline]", ELEMENT_TEXT, TO_STRING);
|
||||
MAP.put(NULLABLE_INLINE_PARAMETER, "Inline-parameter ''{0}'' of ''{1}'' must not be nullable. Annotate the parameter with [noinline] or make not nullable", ELEMENT_TEXT, TO_STRING);
|
||||
|
||||
MAP.setImmutable();
|
||||
|
||||
for (Field field : Errors.class.getFields()) {
|
||||
|
||||
+10
-4
@@ -20,9 +20,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,7 +37,7 @@ public class FunctionAnalyzerExtension {
|
||||
private BindingTrace trace;
|
||||
|
||||
@Inject
|
||||
public void setTrace(BindingTrace trace) {
|
||||
public void setTrace(@NotNull BindingTrace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@@ -52,8 +53,13 @@ public class FunctionAnalyzerExtension {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<AnalyzerExtension> getExtensions(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
return Collections.emptyList();
|
||||
private static List<AnalyzerExtension> getExtensions(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
List<AnalyzerExtension> list = new ArrayList<AnalyzerExtension>();
|
||||
if (functionDescriptor instanceof SimpleFunctionDescriptor &&
|
||||
((SimpleFunctionDescriptor) functionDescriptor).isInline()) {
|
||||
list.add(InlineAnalyzerExtension.INSTANCE);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-2
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.calls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
@@ -69,8 +70,13 @@ public class CallResolverExtensionProvider {
|
||||
}
|
||||
|
||||
// with default one at the end
|
||||
private void appendExtensionsFor(DeclarationDescriptor declarationDescriptor, List<CallResolverExtension> extensions) {
|
||||
// add your extensions here
|
||||
private static void appendExtensionsFor(DeclarationDescriptor declarationDescriptor, List<CallResolverExtension> extensions) {
|
||||
if (declarationDescriptor instanceof SimpleFunctionDescriptor) {
|
||||
SimpleFunctionDescriptor descriptor = (SimpleFunctionDescriptor) declarationDescriptor;
|
||||
if (descriptor.isInline()) {
|
||||
extensions.add(new InlineCallResolverExtension(descriptor));
|
||||
}
|
||||
}
|
||||
extensions.add(DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.resolve.calls;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.InlineUtil;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class InlineCallResolverExtension implements CallResolverExtension {
|
||||
|
||||
private SimpleFunctionDescriptor descriptor;
|
||||
|
||||
private Set<DeclarationDescriptor> inlinableParameters = new HashSet<DeclarationDescriptor>();
|
||||
|
||||
public InlineCallResolverExtension(@NotNull SimpleFunctionDescriptor descriptor) {
|
||||
assert descriptor.isInline() : "This extension should be created only for inline functions but not " + descriptor;
|
||||
|
||||
this.descriptor = descriptor;
|
||||
Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ValueParameterDescriptor next = iterator.next();
|
||||
JetType type = next.getType();
|
||||
if (KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type)) {
|
||||
//TODO check annotations
|
||||
if (!InlineUtil.hasNoinlineAnnotation(next)) {
|
||||
inlinableParameters.add(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add extension receiver as inlineable
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
if (isExactFunctionOrExtensionFunctionType(receiverParameter.getType())) {
|
||||
inlinableParameters.add(receiverParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <F extends CallableDescriptor> void run(
|
||||
@NotNull ResolvedCall<F> resolvedCall, @NotNull BasicCallResolutionContext context
|
||||
) {
|
||||
CallableDescriptor targetDescriptor = resolvedCall.getResultingDescriptor();
|
||||
JetExpression expression = context.call.getCalleeExpression();
|
||||
if (expression == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//checking that only invoke or inlinable extension called on function parameter
|
||||
checkCallWithReceiver(context, targetDescriptor, resolvedCall.getThisObject(), expression);
|
||||
checkCallWithReceiver(context, targetDescriptor, resolvedCall.getReceiverArgument(), expression);
|
||||
|
||||
boolean isInlinableClosure = inlinableParameters.contains(targetDescriptor);
|
||||
if (isInlinableClosure) {
|
||||
PsiElement parent = expression.getParent();
|
||||
if (parent instanceof JetValueArgument || parent instanceof JetBinaryExpression || parent instanceof JetDotQualifiedExpression || parent instanceof JetCallExpression) {
|
||||
//check that it's in inlineable call would be in resolve call of parent
|
||||
} else {
|
||||
context.trace.report(Errors.USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
|
||||
ResolvedValueArgument value = entry.getValue();
|
||||
if (value instanceof ExpressionValueArgument) {
|
||||
JetExpression jetExpression = ((ExpressionValueArgument) value).getValueArgument().getArgumentExpression();
|
||||
|
||||
DeclarationDescriptor varDescriptor = getDescriptor(context, jetExpression);
|
||||
|
||||
if (varDescriptor != null && inlinableParameters.contains(varDescriptor)) {
|
||||
checkFunctionCall(context, targetDescriptor, jetExpression);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO default and vararg
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCallWithReceiver(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallableDescriptor targetDescriptor,
|
||||
@NotNull ReceiverValue receiver,
|
||||
@Nullable JetExpression expression
|
||||
) {
|
||||
if (receiver.exists()) {
|
||||
CallableDescriptor varDescriptor = null;
|
||||
JetExpression receiverExpression = null;
|
||||
if (receiver instanceof ExpressionReceiver) {
|
||||
receiverExpression = ((ExpressionReceiver) receiver).getExpression();
|
||||
varDescriptor = getDescriptor(context, receiverExpression);
|
||||
}
|
||||
else if (receiver instanceof ExtensionReceiver) {
|
||||
ExtensionReceiver extensionReceiver = (ExtensionReceiver) receiver;
|
||||
CallableDescriptor extensionFunction = extensionReceiver.getDeclarationDescriptor();
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = extensionFunction.getReceiverParameter();
|
||||
assert receiverParameter != null : "Extension function should have receiverParameterDescriptor: " + extensionFunction;
|
||||
varDescriptor = receiverParameter;
|
||||
|
||||
receiverExpression = expression;
|
||||
}
|
||||
|
||||
if (varDescriptor != null) {
|
||||
if (inlinableParameters.contains(varDescriptor)) {
|
||||
//check that it's invoke
|
||||
checkFunctionCall(context, targetDescriptor, receiverExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CallableDescriptor getDescriptor(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull JetExpression expression
|
||||
) {
|
||||
ResolvedCall<? extends CallableDescriptor> thisCall = context.trace.get(BindingContext.RESOLVED_CALL, expression);
|
||||
return thisCall != null ? thisCall.getResultingDescriptor() : null;
|
||||
}
|
||||
|
||||
private void checkFunctionCall(
|
||||
BasicCallResolutionContext context,
|
||||
CallableDescriptor targetDescriptor,
|
||||
JetExpression receiverExpresssion
|
||||
) {
|
||||
if (!isInvokeOrInlineExtension(targetDescriptor)) {
|
||||
context.trace.report(Errors.USAGE_IS_NOT_INLINABLE.on(receiverExpresssion, receiverExpresssion, descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) {
|
||||
return KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type);
|
||||
}
|
||||
|
||||
private static boolean isInvokeOrInlineExtension(@NotNull CallableDescriptor descriptor) {
|
||||
if (!(descriptor instanceof SimpleFunctionDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
boolean isInvoke = descriptor.getName().asString().equals("invoke") &&
|
||||
containingDeclaration instanceof ClassDescriptor &&
|
||||
isExactFunctionOrExtensionFunctionType(((ClassDescriptor) containingDeclaration).getDefaultType());
|
||||
|
||||
return isInvoke ||
|
||||
//or inline extension
|
||||
((SimpleFunctionDescriptor) descriptor).isInline();
|
||||
}
|
||||
|
||||
private void checkVisibility(){
|
||||
|
||||
}
|
||||
|
||||
interface FunctionParameter {
|
||||
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.resolve.extension;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
|
||||
|
||||
public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.AnalyzerExtension {
|
||||
|
||||
public static final InlineAnalyzerExtension INSTANCE = new InlineAnalyzerExtension();
|
||||
|
||||
private InlineAnalyzerExtension() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(
|
||||
@NotNull final FunctionDescriptor descriptor, @NotNull JetNamedFunction function, @NotNull final BindingTrace trace
|
||||
) {
|
||||
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
|
||||
@Override
|
||||
public void visitJetElement(@NotNull JetElement element) {
|
||||
super.visitJetElement(element);
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClass(@NotNull JetClass klass) {
|
||||
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(klass, klass, descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) {
|
||||
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, declaration, descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(@NotNull JetNamedFunction function) {
|
||||
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(function, function, descriptor));
|
||||
}
|
||||
};
|
||||
|
||||
function.acceptChildren(visitor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
fun Function1<Int, Unit>.noInlineExt(p: Int) {}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt2(p: Int) {
|
||||
{
|
||||
<!USAGE_IS_NOT_INLINABLE!>noInlineExt<!>(11)
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!>.noInlineExt(11)
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!> noInlineExt 11
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!>
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt() {
|
||||
{
|
||||
inlineExt2(1)
|
||||
this.inlineExt2(1)
|
||||
this inlineExt2 1
|
||||
this(11)
|
||||
}()
|
||||
}
|
||||
|
||||
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) {
|
||||
{
|
||||
s(11)
|
||||
s.invoke(11)
|
||||
s invoke 11
|
||||
}()
|
||||
}
|
||||
|
||||
inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit) {
|
||||
{
|
||||
s(11)
|
||||
s.invoke(11)
|
||||
s invoke 11
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
inline fun testExtension(s: (p: Int) -> Unit) {
|
||||
{
|
||||
s.inlineExt()
|
||||
} ()
|
||||
}
|
||||
|
||||
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
|
||||
{
|
||||
<!USAGE_IS_NOT_INLINABLE!>s<!>.noInlineExt(11)
|
||||
} ()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Z(s: (Int) -> Int) {
|
||||
|
||||
}
|
||||
|
||||
public inline fun test(s : (Int) -> Int) {
|
||||
<!INVISIBLE_MEMBER_FROM_INLINE!>Z<!>(<!USAGE_IS_NOT_INLINABLE!>s<!>)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
fun Function1<Int, Unit>.noInlineExt(p: Int) {}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt2(p: Int) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>noInlineExt<!>(11)
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!>.noInlineExt(11)
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!> noInlineExt 11
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!>
|
||||
}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt() {
|
||||
inlineExt2(1)
|
||||
this.inlineExt2(1)
|
||||
this inlineExt2 1
|
||||
}
|
||||
|
||||
inline fun testExtension(s: (p: Int) -> Unit) {
|
||||
s.inlineExt()
|
||||
}
|
||||
|
||||
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>s<!>.noInlineExt(11)
|
||||
}
|
||||
|
||||
inline fun inlineFunNoInline(noinline s: (p: Int) -> Unit) {
|
||||
s.noInlineExt(11)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -UNNECESSARY_NOT_NULL_ASSERTION -UNNECESSARY_SAFE_CALL
|
||||
|
||||
fun getFun(s: (p: Int) -> Unit): Function1<Int, Int> = {11}
|
||||
|
||||
inline fun getInlineFun(s: (p: Int) -> Unit): Function1<Int, Int> = {11}
|
||||
|
||||
inline fun testExtension(s: (p: Int) -> Unit) {
|
||||
getFun(<!USAGE_IS_NOT_INLINABLE!>s<!>).invoke(10)
|
||||
getInlineFun(s).invoke(10)
|
||||
getInlineFun(s)!!.invoke(10)
|
||||
getInlineFun(s)?.invoke(10)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
||||
s(11)
|
||||
s.invoke(11)
|
||||
s invoke 11
|
||||
|
||||
11.ext(11)
|
||||
11 ext 11
|
||||
}
|
||||
|
||||
inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
||||
s(11)
|
||||
s.invoke(11)
|
||||
s invoke 11
|
||||
|
||||
11.ext(11)
|
||||
11 ext 11
|
||||
}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt() {
|
||||
invoke(11)
|
||||
this.invoke(11)
|
||||
this invoke 11
|
||||
this(11)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
||||
subInline(s, ext)
|
||||
subNoInline(<!USAGE_IS_NOT_INLINABLE!>s<!>, <!USAGE_IS_NOT_INLINABLE!>ext<!>)
|
||||
}
|
||||
|
||||
inline fun inlineFunWithInvokeClosure(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
||||
subInline({(p: Int) -> s(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
subNoInline({(p: Int) -> s(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
}
|
||||
|
||||
//No inline
|
||||
inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit, noinline ext: Int.(p: Int) -> Unit) {
|
||||
subInline(s, ext)
|
||||
subNoInline(s, ext)
|
||||
}
|
||||
|
||||
inline fun inlineFunWithInvokeClosureNoinline(noinline s: (p: Int) -> Unit, noinline ext: Int.(p: Int) -> Unit) {
|
||||
subInline({(p: Int) -> s(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
subNoInline({(p: Int) -> s(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
}
|
||||
|
||||
//ext function
|
||||
inline fun Function1<Int, Unit>.inlineExt(ext: Int.(p: Int) -> Unit) {
|
||||
subInline(this, ext)
|
||||
subNoInline(<!USAGE_IS_NOT_INLINABLE!>this<!>, <!USAGE_IS_NOT_INLINABLE!>ext<!>)
|
||||
}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExtWithClosure(ext: Int.(p: Int) -> Unit) {
|
||||
subInline({(p: Int) -> this(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
subNoInline({(p: Int) -> this(p)}, {Int.(p:Int) -> this.ext(p)})
|
||||
}
|
||||
|
||||
inline fun subInline(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {}
|
||||
|
||||
fun subNoInline(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {}
|
||||
@@ -0,0 +1,20 @@
|
||||
inline fun inlineFun(s: (p: Int) -> Unit) : (p: Int) -> Unit {
|
||||
return <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
}
|
||||
|
||||
inline fun inlineFun2(s: (p: Int) -> Unit) : (p: Int) -> Unit = <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
|
||||
|
||||
inline fun inlineFunWithExt(ext: Int.(p: Int) -> Unit) : Int.(p: Int) -> Unit {
|
||||
return <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
}
|
||||
|
||||
inline fun inlineFunWithExt2(ext: Int.(p: Int) -> Unit) : Int.(p: Int) -> Unit = <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
|
||||
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt(): Function1<Int, Unit> {
|
||||
return <!USAGE_IS_NOT_INLINABLE!>this<!>
|
||||
}
|
||||
|
||||
inline fun Function1<Int, Unit>.inlineExt2(): Function1<Int, Unit> = <!USAGE_IS_NOT_INLINABLE!>this<!>
|
||||
@@ -0,0 +1,26 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
inline fun unsupported() {
|
||||
|
||||
<!NOT_YET_SUPPORTED_IN_INLINE!>class A {
|
||||
fun a() {
|
||||
class AInner {}
|
||||
}
|
||||
}<!>
|
||||
|
||||
<!NOT_YET_SUPPORTED_IN_INLINE!>object B{
|
||||
object BInner {}
|
||||
}<!>
|
||||
|
||||
val s = <!NOT_YET_SUPPORTED_IN_INLINE!>object {
|
||||
fun a() {
|
||||
val sInner = object {
|
||||
fun aInner() {}
|
||||
}
|
||||
}
|
||||
}<!>
|
||||
|
||||
<!NOT_YET_SUPPORTED_IN_INLINE!>fun local() {
|
||||
fun localInner() {}
|
||||
}<!>
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
|
||||
|
||||
inline fun inlineFunWrongUsage(s: (p: Int) -> Unit) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
|
||||
if (true) <!USAGE_IS_NOT_INLINABLE!>s<!> else 0
|
||||
|
||||
var c = <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
c = <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
}
|
||||
|
||||
inline fun inlineFunWrongUsageExt(ext: Int.(p: Int) -> Unit) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
|
||||
if (true) <!USAGE_IS_NOT_INLINABLE!>ext<!> else 0
|
||||
|
||||
var c = <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
c = <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
}
|
||||
|
||||
inline fun inlineFunWrongUsageInClosure(s: (p: Int) -> Unit) {
|
||||
{
|
||||
<!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
|
||||
if (true) <!USAGE_IS_NOT_INLINABLE!>s<!> else 0
|
||||
|
||||
var c = <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
c = <!USAGE_IS_NOT_INLINABLE!>s<!>
|
||||
}()
|
||||
}
|
||||
|
||||
inline fun inlineFunWrongUsageInClosureExt(ext: Int.(p: Int) -> Unit) {
|
||||
{
|
||||
<!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
|
||||
if (true) <!USAGE_IS_NOT_INLINABLE!>ext<!> else 0
|
||||
|
||||
var c = <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
c = <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||
}()
|
||||
}
|
||||
|
||||
inline fun inlineFunNoInline(noinline s: (p: Int) -> Unit) {
|
||||
s
|
||||
if (true) s else 0
|
||||
var c = s
|
||||
c = s
|
||||
}
|
||||
|
||||
inline fun inlineFunNoInline(noinline ext: Int.(p: Int) -> Unit) {
|
||||
ext
|
||||
if (true) ext else 0
|
||||
var c = ext
|
||||
c = ext
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -UNNECESSARY_SAFE_CALL -UNNECESSARY_NOT_NULL_ASSERTION
|
||||
|
||||
public inline fun assertNot(message: String, block: ()-> Boolean) {}
|
||||
|
||||
public inline fun assertNot(block: ()-> Boolean) : Unit = assertNot(<!USAGE_IS_NOT_INLINABLE!>block<!>.toString(), block)
|
||||
|
||||
|
||||
public fun <T> callable(action: ()-> T) {
|
||||
|
||||
}
|
||||
|
||||
public inline fun <T> String.submit(action: ()->T) {
|
||||
callable(<!USAGE_IS_NOT_INLINABLE!>action<!>)
|
||||
}
|
||||
|
||||
public inline fun <T> Function1<Int, Int>.submit() {
|
||||
<!USAGE_IS_NOT_INLINABLE!>this<!>?.invoke(11)
|
||||
<!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>this<!>!!.invoke(11)
|
||||
}
|
||||
|
||||
public inline fun <T> submit(action: Function1<Int, Int>) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>action<!>?.invoke(10)
|
||||
<!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>action<!>!!.invoke(10)
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
|
||||
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class})
|
||||
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
|
||||
@TestMetadata("compiler/testData/diagnostics/tests")
|
||||
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Varargs.class, Tests.When.class})
|
||||
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Varargs.class, Tests.When.class})
|
||||
public static class Tests extends AbstractDiagnosticsTestWithEagerResolve {
|
||||
@TestMetadata("Abstract.kt")
|
||||
public void testAbstract() throws Exception {
|
||||
@@ -3750,6 +3750,64 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inline")
|
||||
public static class Inline extends AbstractDiagnosticsTestWithEagerResolve {
|
||||
public void testAllFilesPresentInInline() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inline"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("capture.kt")
|
||||
public void testCapture() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/capture.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("constructor.kt")
|
||||
public void testConstructor() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/constructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionOnFunction.kt")
|
||||
public void testExtensionOnFunction() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/extensionOnFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functions.kt")
|
||||
public void testFunctions() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/functions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/invoke.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propagation.kt")
|
||||
public void testPropagation() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/propagation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returns.kt")
|
||||
public void testReturns() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/returns.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsupportedConstruction.kt")
|
||||
public void testUnsupportedConstruction() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("wrongUsage.kt")
|
||||
public void testWrongUsage() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/wrongUsage.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("wrongUsage2.kt")
|
||||
public void testWrongUsage2() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/wrongUsage2.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inner")
|
||||
@InnerTestClasses({Inner.QualifiedExpression.class})
|
||||
public static class Inner extends AbstractDiagnosticsTestWithEagerResolve {
|
||||
@@ -6255,6 +6313,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
suite.addTest(IncompleteCode.innerSuite());
|
||||
suite.addTest(Inference.innerSuite());
|
||||
suite.addTestSuite(Infos.class);
|
||||
suite.addTestSuite(Inline.class);
|
||||
suite.addTest(Inner.innerSuite());
|
||||
suite.addTestSuite(J_k.class);
|
||||
suite.addTest(Jdk_annotations.innerSuite());
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class ExtensionReceiver extends AbstractReceiverValue implements ThisRece
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor getDeclarationDescriptor() {
|
||||
public CallableDescriptor getDeclarationDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user