diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/codeFragmentUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/psi/codeFragmentUtil.kt new file mode 100644 index 00000000000..dab0c1f8998 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/codeFragmentUtil.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2014 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.psi.codeFragmentUtil + +import com.intellij.openapi.util.Key +import com.intellij.psi.PsiFile +import org.jetbrains.jet.lang.psi.JetFile +import org.jetbrains.jet.lang.psi.JetCodeFragment + +public val SKIP_VISIBILITY_CHECK: Key = Key.create("SKIP_VISIBILITY_CHECK") + +fun JetFile.skipVisibilityCheck() = + when (this) { + is JetCodeFragment -> true + is JetFile -> getUserData(SKIP_VISIBILITY_CHECK) ?: false + else -> false + } + +fun JetFile.setSkipVisibilityCheck(skip: Boolean) { + putUserData(SKIP_VISIBILITY_CHECK, skip) +} + diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java index 89d1a3cfba6..bbfdbeeeda2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java @@ -25,6 +25,7 @@ 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.psi.codeFragmentUtil.CodeFragmentUtilPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -420,8 +421,8 @@ public class QualifiedExpressionResolver { private void checkVisibility(@NotNull DeclarationDescriptorWithVisibility descriptor, @NotNull BindingTrace trace, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope scopeToCheckVisibility) { - - if (!Visibilities.isVisible(descriptor, scopeToCheckVisibility.getContainingDeclaration())) { + if (!CodeFragmentUtilPackage.skipVisibilityCheck(referenceExpression.getContainingJetFile()) && + !Visibilities.isVisible(descriptor, scopeToCheckVisibility.getContainingDeclaration())) { trace.report(INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration())); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index 645873b4381..a2a0de17c95 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -24,10 +24,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; +import org.jetbrains.jet.lang.psi.codeFragmentUtil.CodeFragmentUtilPackage; +import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext; @@ -141,6 +139,9 @@ public class CallExpressionResolver { @NotNull ExpressionTypingContext context ) { if (!(classifier instanceof ClassDescriptor)) return; + + if (CodeFragmentUtilPackage.skipVisibilityCheck(expression.getContainingJetFile())) return; + ClassDescriptor classObject = ((ClassDescriptor) classifier).getClassObjectDescriptor(); assert classObject != null : "This check should be done only for classes with class objects: " + classifier; DeclarationDescriptor from = context.containingDeclaration; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 767a527040e..0e177bb43d7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -98,8 +98,6 @@ public class CandidateResolver { if (invisibleMember != null) { candidateCall.addStatus(OTHER_ERROR); context.tracing.invisibleMember(context.trace, invisibleMember); - markAllArgumentsAsUnmapped(context); - return; } if (task.checkArguments == CheckValueArgumentsMode.ENABLED) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java index ffd57bcd3a3..db7d3f9e15c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.codeFragmentUtil.CodeFragmentUtilPackage; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; @@ -41,7 +42,6 @@ import java.util.Collection; import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER; import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType; @@ -175,7 +175,9 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { @Override public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) { - trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration())); + if (!CodeFragmentUtilPackage.skipVisibilityCheck(call.getCallElement().getContainingJetFile())) { + trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration())); + } } @Override diff --git a/compiler/testData/diagnostics/tests/scopes/visibility.kt b/compiler/testData/diagnostics/tests/scopes/visibility.kt index f829e203f02..e7069c4be8d 100644 --- a/compiler/testData/diagnostics/tests/scopes/visibility.kt +++ b/compiler/testData/diagnostics/tests/scopes/visibility.kt @@ -39,7 +39,7 @@ class B { fun test3(a: A) { a.v //todo .bMethod() - a.f(0, 1) //todo .bMethod() + a.f(0, 1) //todo .bMethod() } trait T diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt index e7d01473382..b944bd40810 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -62,6 +62,7 @@ import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults import org.jetbrains.jet.lang.psi.JetCodeFragment import org.jetbrains.jet.lang.psi.JetImportList import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.psi.codeFragmentUtil.setSkipVisibilityCheck import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status object KotlinEvaluationBuilder: EvaluatorBuilder { @@ -225,8 +226,10 @@ private fun createFileForDebugger(codeFragment: JetExpressionCodeFragment, val virtualFile = LightVirtualFile("debugFile.kt", JetLanguage.INSTANCE, fileText) virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET) - return (PsiFileFactory.getInstance(codeFragment.getProject()) as PsiFileFactoryImpl) + val jetFile = (PsiFileFactory.getInstance(codeFragment.getProject()) as PsiFileFactoryImpl) .trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false) as JetFile + jetFile.setSkipVisibilityCheck(true) + return jetFile } fun addImportsToFile(newImportList: JetImportList?, tmpFile: JetFile) { @@ -272,6 +275,8 @@ private fun getFunctionForExtractedFragment( if (lineStart == null) return null val tmpFile = originalFile.createTempCopy { it } + tmpFile.setSkipVisibilityCheck(true) + val elementAtOffset = tmpFile.findElementAt(lineStart) if (elementAtOffset == null) return null diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt index 17f7691f131..e3a3c490aed 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt @@ -98,6 +98,8 @@ import org.jetbrains.jet.lang.psi.JetTypeReference import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status import org.jetbrains.jet.lang.descriptors.FunctionDescriptor +import org.jetbrains.jet.lang.psi.codeFragmentUtil.skipVisibilityCheck +import org.jetbrains.jet.lang.psi.codeFragmentUtil.setSkipVisibilityCheck private val DEFAULT_FUNCTION_NAME = "myFun" private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType() @@ -677,6 +679,9 @@ fun ExtractionDescriptor.generateFunction( val tmpFile = originalFile.createTempCopy { text -> StringBuilder(text).insert(position, getFunctionText() + "\n").toString() } + if (originalFile.skipVisibilityCheck()) { + tmpFile.setSkipVisibilityCheck(true) + } tmpFile.findElementAt(position)?.getParentByType(javaClass())!! } else { diff --git a/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt b/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt new file mode 100644 index 00000000000..f70514484a9 --- /dev/null +++ b/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt @@ -0,0 +1,7 @@ +fun foo() { + val a = 1 +} + +class MyClass { + private fun privateFun(i: Int) = 1 +} \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt.fragment b/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt.fragment new file mode 100644 index 00000000000..fcf1af3ab6f --- /dev/null +++ b/idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt.fragment @@ -0,0 +1 @@ +MyClass().privateFun("s") \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/privateFunTypeArguments.kt b/idea/testData/checker/codeFragments/privateFunTypeArguments.kt new file mode 100644 index 00000000000..0f50fad7667 --- /dev/null +++ b/idea/testData/checker/codeFragments/privateFunTypeArguments.kt @@ -0,0 +1,7 @@ +fun foo() { + val a = 1 +} + +class MyClass { + private fun privateFun(i: T): T = i +} \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/privateFunTypeArguments.kt.fragment b/idea/testData/checker/codeFragments/privateFunTypeArguments.kt.fragment new file mode 100644 index 00000000000..0ee2f983eb9 --- /dev/null +++ b/idea/testData/checker/codeFragments/privateFunTypeArguments.kt.fragment @@ -0,0 +1 @@ +"${MyClass().privateFun(1)} ${MyClass().privateFun("s")}" \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/privateMember.kt b/idea/testData/checker/codeFragments/privateMember.kt new file mode 100644 index 00000000000..b2367f5d73b --- /dev/null +++ b/idea/testData/checker/codeFragments/privateMember.kt @@ -0,0 +1,12 @@ +fun foo() { + val a = 1 +} + +class MyClass { + private fun privateFun() = 1 + private val privateVal = 1 + + private class PrivateClass { + val a = 1 + } +} \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/privateMember.kt.fragment b/idea/testData/checker/codeFragments/privateMember.kt.fragment new file mode 100644 index 00000000000..01abada709a --- /dev/null +++ b/idea/testData/checker/codeFragments/privateMember.kt.fragment @@ -0,0 +1 @@ +MyClass().privateFun() + MyClass().privateVal + MyClass.PrivateClass().a \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/protectedMember.kt b/idea/testData/checker/codeFragments/protectedMember.kt new file mode 100644 index 00000000000..4e41ccc6fbe --- /dev/null +++ b/idea/testData/checker/codeFragments/protectedMember.kt @@ -0,0 +1,12 @@ +fun foo() { + val a = 1 +} + +class MyClass { + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + protected class ProtectedClass { + val a = 1 + } +} \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/protectedMember.kt.fragment b/idea/testData/checker/codeFragments/protectedMember.kt.fragment new file mode 100644 index 00000000000..20009abb368 --- /dev/null +++ b/idea/testData/checker/codeFragments/protectedMember.kt.fragment @@ -0,0 +1 @@ +MyClass().protectedFun() + MyClass().protectedVal + MyClass.ProtectedClass().a \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/privateMember.out b/idea/testData/debugger/tinyApp/outs/privateMember.out new file mode 100644 index 00000000000..beb563cb681 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/privateMember.out @@ -0,0 +1,7 @@ +LineBreakpoint created at privateMember.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! privateMember.PrivateMemberPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +privateMember.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/protectedMember.out b/idea/testData/debugger/tinyApp/outs/protectedMember.out new file mode 100644 index 00000000000..9d9b6c38da6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/protectedMember.out @@ -0,0 +1,7 @@ +LineBreakpoint created at protectedMember.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! protectedMember.ProtectedMemberPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +protectedMember.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt new file mode 100644 index 00000000000..8559185ed2c --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt @@ -0,0 +1,24 @@ +package privateMember + +fun main(args: Array) { + //Breakpoint! + args.size +} + +class MyClass { + private fun privateFun() = 1 + private val privateVal = 1 + + private class PrivateClass { + val a = 1 + } +} + +// EXPRESSION: MyClass().privateFun() +// RESULT: 1: I + +// EXPRESSION: MyClass().privateVal +// RESULT: 1: I + +// EXPRESSION: MyClass.PrivateClass().a +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt new file mode 100644 index 00000000000..82ad3ec25ae --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt @@ -0,0 +1,24 @@ +package protectedMember + +fun main(args: Array) { + //Breakpoint! + args.size +} + +class MyClass { + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + protected class ProtectedClass { + val a = 1 + } +} + +// EXPRESSION: MyClass().protectedFun() +// RESULT: 1: I + +// EXPRESSION: MyClass().protectedVal +// RESULT: 1: I + +// EXPRESSION: MyClass.ProtectedClass().a +// RESULT: 1: I \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java index cfe9ea4822d..403366ca4d2 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java @@ -53,6 +53,26 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH doTest("idea/testData/checker/codeFragments/contextElementAsStatement.kt"); } + @TestMetadata("privateFunArgumentsResolve.kt") + public void testPrivateFunArgumentsResolve() throws Exception { + doTest("idea/testData/checker/codeFragments/privateFunArgumentsResolve.kt"); + } + + @TestMetadata("privateFunTypeArguments.kt") + public void testPrivateFunTypeArguments() throws Exception { + doTest("idea/testData/checker/codeFragments/privateFunTypeArguments.kt"); + } + + @TestMetadata("privateMember.kt") + public void testPrivateMember() throws Exception { + doTest("idea/testData/checker/codeFragments/privateMember.kt"); + } + + @TestMetadata("protectedMember.kt") + public void testProtectedMember() throws Exception { + doTest("idea/testData/checker/codeFragments/protectedMember.kt"); + } + @TestMetadata("simpleNameExpression.kt") public void testSimpleNameExpression() throws Exception { doTest("idea/testData/checker/codeFragments/simpleNameExpression.kt"); diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 7ac7ee2b616..85c2bf3e835 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -96,6 +96,16 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doTest("idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt"); } + @TestMetadata("privateMember.kt") + public void testPrivateMember() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt"); + } + + @TestMetadata("protectedMember.kt") + public void testProtectedMember() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { doTest("idea/testData/debugger/tinyApp/src/evaluate/simple.kt");