diff --git a/annotations/com/intellij/testFramework/annotations.xml b/annotations/com/intellij/testFramework/annotations.xml new file mode 100644 index 00000000000..128954237ea --- /dev/null +++ b/annotations/com/intellij/testFramework/annotations.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/annotations/com/intellij/testFramework/fixtures/annotations.xml b/annotations/com/intellij/testFramework/fixtures/annotations.xml new file mode 100644 index 00000000000..d9c8ac57348 --- /dev/null +++ b/annotations/com/intellij/testFramework/fixtures/annotations.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/LibrarySourceHacks.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/LibrarySourceHacks.java new file mode 100644 index 00000000000..1ad375fe0c7 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/LibrarySourceHacks.java @@ -0,0 +1,66 @@ +/* + * 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; + +import com.google.common.collect.Lists; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; + +import java.util.Collection; +import java.util.List; + +import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; + +public class LibrarySourceHacks { + private LibrarySourceHacks() { + } + + public static final Key SKIP_TOP_LEVEL_MEMBERS = Key.create("SKIP_TOP_LEVEL_MEMBERS"); // used when analyzing library source + + + public static List filterOutMembersFromLibrarySource(Collection members, BindingTrace trace) { + List filteredMembers = Lists.newArrayList(); + for (D member : members) { + if (!shouldSkip(member, trace)) { + filteredMembers.add(member); + } + } + return filteredMembers; + } + + private static boolean shouldSkip(CallableDescriptor member, BindingTrace trace) { + CallableDescriptor original = member.getOriginal(); + if (!(original instanceof CallableMemberDescriptor)) { + return false; + } + if (!(original.getContainingDeclaration() instanceof NamespaceDescriptor)) { + return false; + } + + PsiElement declaration = callableDescriptorToDeclaration(trace.getBindingContext(), + (CallableMemberDescriptor) original); + if (declaration == null) { + return false; + } + PsiFile file = declaration.getContainingFile(); + return file != null && Boolean.TRUE.equals(file.getUserData(SKIP_TOP_LEVEL_MEMBERS)); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollector.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollector.java index c5129b48a02..e8288345815 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollector.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollector.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls.tasks; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; @@ -26,11 +27,11 @@ import java.util.Collection; public interface CallableDescriptorCollector { @NotNull - Collection getNonExtensionsByName(JetScope scope, Name name); + Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace); @NotNull - Collection getMembersByName(@NotNull JetType receiver, Name name); + Collection getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace); @NotNull - Collection getNonMembersByName(JetScope scope, Name name); + Collection getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java index a01738101df..ef5ab5513be 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java @@ -20,6 +20,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.ErrorUtils; @@ -27,10 +28,15 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.*; +import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource; + public class CallableDescriptorCollectors { - public static CallableDescriptorCollector FUNCTIONS = new FunctionCollector(); - public static CallableDescriptorCollector VARIABLES = new VariableCollector(); - public static CallableDescriptorCollector PROPERTIES = new PropertyCollector(); + public static CallableDescriptorCollector FUNCTIONS = + new FilteredCollector(new FunctionCollector()); + public static CallableDescriptorCollector VARIABLES = + new FilteredCollector(new VariableCollector()); + public static CallableDescriptorCollector PROPERTIES = + new FilteredCollector(new PropertyCollector()); public static List> FUNCTIONS_AND_VARIABLES = Lists.newArrayList(FUNCTIONS, VARIABLES); @@ -38,7 +44,7 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getNonExtensionsByName(JetScope scope, Name name) { + public Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { Set functions = Sets.newLinkedHashSet(); for (FunctionDescriptor function : scope.getFunctions(name)) { if (function.getReceiverParameter() == null) { @@ -51,7 +57,7 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getMembersByName(@NotNull JetType receiverType, Name name) { + public Collection getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) { JetScope receiverScope = receiverType.getMemberScope(); Set members = Sets.newHashSet(receiverScope.getFunctions(name)); addConstructors(receiverScope, name, members); @@ -60,7 +66,7 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getNonMembersByName(JetScope scope, Name name) { + public Collection getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { return scope.getFunctions(name); } @@ -82,7 +88,7 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getNonExtensionsByName(JetScope scope, Name name) { + public Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { VariableDescriptor localVariable = scope.getLocalVariable(name); if (localVariable != null) { return Collections.singleton(localVariable); @@ -99,13 +105,13 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getMembersByName(@NotNull JetType receiverType, Name name) { + public Collection getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) { return receiverType.getMemberScope().getProperties(name); } @NotNull @Override - public Collection getNonMembersByName(JetScope scope, Name name) { + public Collection getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { Collection result = Sets.newLinkedHashSet(); VariableDescriptor localVariable = scope.getLocalVariable(name); @@ -135,20 +141,20 @@ public class CallableDescriptorCollectors { @NotNull @Override - public Collection getNonExtensionsByName(JetScope scope, Name name) { - return filterProperties(VARIABLES.getNonExtensionsByName(scope, name)); + public Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { + return filterProperties(VARIABLES.getNonExtensionsByName(scope, name, bindingTrace)); } @NotNull @Override - public Collection getMembersByName(@NotNull JetType receiver, Name name) { - return filterProperties(VARIABLES.getMembersByName(receiver, name)); + public Collection getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) { + return filterProperties(VARIABLES.getMembersByName(receiver, name, bindingTrace)); } @NotNull @Override - public Collection getNonMembersByName(JetScope scope, Name name) { - return filterProperties(VARIABLES.getNonMembersByName(scope, name)); + public Collection getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { + return filterProperties(VARIABLES.getNonMembersByName(scope, name, bindingTrace)); } @Override @@ -156,6 +162,37 @@ public class CallableDescriptorCollectors { return "PROPERTIES"; } } + + private static class FilteredCollector implements CallableDescriptorCollector { + private final CallableDescriptorCollector delegate; + + private FilteredCollector(CallableDescriptorCollector delegate) { + this.delegate = delegate; + } + + @NotNull + @Override + public Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { + return filterOutMembersFromLibrarySource(delegate.getNonExtensionsByName(scope, name, bindingTrace), bindingTrace); + } + + @NotNull + @Override + public Collection getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) { + return filterOutMembersFromLibrarySource(delegate.getMembersByName(receiver, name, bindingTrace), bindingTrace); + } + + @NotNull + @Override + public Collection getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { + return filterOutMembersFromLibrarySource(delegate.getNonMembersByName(scope, name, bindingTrace), bindingTrace); + } + + @Override + public String toString() { + return delegate.toString(); + } + } private CallableDescriptorCollectors() { } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 601ed93de8e..5f5b9ef845c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetSuperExpression; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.LibrarySourceHacks; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.name.Name; @@ -41,7 +42,7 @@ import java.util.Collections; import java.util.List; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; -import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.*; +import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; public class TaskPrioritizer { @@ -130,7 +131,8 @@ public class TaskPrioritizer { for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { Collection> members = Lists.newArrayList(); for (ReceiverValue variant : variantsForExplicitReceiver) { - Collection membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), c.name); + Collection membersForThisVariant = + callableDescriptorCollector.getMembersByName(variant.getType(), c.name, c.context.trace); convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members, resolveInvoke); } @@ -144,9 +146,9 @@ public class TaskPrioritizer { callableDescriptorCollector, c, resolveInvoke); } //extensions - Collection> extensionFunctions = convertWithImpliedThis( - c.scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name)); - c.result.addCandidates(extensionFunctions); + Collection> extensions = convertWithImpliedThis( + c.scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name, c.context.trace)); + c.result.addCandidates(extensions); } } @@ -157,7 +159,7 @@ public class TaskPrioritizer { boolean resolveInvoke ) { Collection memberExtensions = callableDescriptorCollector.getNonMembersByName( - implicitReceiver.getType().getMemberScope(), c.name); + implicitReceiver.getType().getMemberScope(), c.name, c.context.trace); List variantsForImplicitReceiver = c.autoCastService.getVariantsForReceiver(implicitReceiver); c.result.addCandidates(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver, resolveInvoke)); @@ -173,7 +175,7 @@ public class TaskPrioritizer { Collection> members = convertWithImpliedThis(c.scope, Collections.singletonList(NO_RECEIVER), callableDescriptorCollector - .getNonExtensionsByName(c.scope, c.name)); + .getNonExtensionsByName(c.scope, c.name, c.context.trace)); List> nonlocals = Lists.newArrayList(); List> locals = Lists.newArrayList(); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java index cdb8efb9da0..70e291e686c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java @@ -54,7 +54,7 @@ public final class DeserializedDescriptorResolver { @Nullable @Override public ClassDescriptor findClass(@NotNull ClassId classId) { - return javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.asSingleFqName()), IGNORE_KOTLIN_SOURCES); + return javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.asSingleFqName()), INCLUDE_KOTLIN_SOURCES); } @Nullable diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java index a814c70b471..e057ab3670f 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java @@ -91,7 +91,7 @@ public class JetPsiChecker implements Annotator { @Override public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { - if (!JetPluginUtil.isInSourceContent(element) || + if (!JetPluginUtil.isInSource(element) || JetPluginUtil.isKtFileInGradleProjectInWrongFolder(element)) { return; } @@ -106,7 +106,7 @@ public class JetPsiChecker implements Annotator { try { BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(file).getBindingContext(); - if (JetPluginUtil.isInSourceContent(element, false)) { + if (JetPluginUtil.isInSourceContent(element, /* includeLibrarySources = */ false)) { Collection diagnostics = Sets.newLinkedHashSet(bindingContext.getDiagnostics()); Set redeclarations = Sets.newHashSet(); for (Diagnostic diagnostic : diagnostics) { diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java index 8bc47acdb32..b7e363cc62c 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java @@ -185,7 +185,10 @@ public final class AnalyzerFacadeWithCache { VirtualFile virtualFile = fileToCache.getVirtualFile(); if (LightClassUtil.belongsToKotlinBuiltIns(fileToCache) || virtualFile != null && LibraryUtil.findLibraryEntry(virtualFile, fileToCache.getProject()) != null) { - /* For library sources we should resolve it, not only project files (as KotlinCacheManager do) */ + // Library sources: + // Mark file to skip + fileToCache.putUserData(LibrarySourceHacks.SKIP_TOP_LEVEL_MEMBERS, true); + // Resolve this file, not only project files (as KotlinCacheManager do) return AnalyzerFacadeForJVM.INSTANCE.analyzeFiles( fileToCache.getProject(), Collections.singleton(fileToCache), diff --git a/idea/tests/org/jetbrains/jet/plugin/PluginTestCaseBase.java b/idea/tests/org/jetbrains/jet/plugin/PluginTestCaseBase.java index fbde57a2bfd..731fcea1da5 100644 --- a/idea/tests/org/jetbrains/jet/plugin/PluginTestCaseBase.java +++ b/idea/tests/org/jetbrains/jet/plugin/PluginTestCaseBase.java @@ -26,6 +26,8 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.codegen.forTestCompile.ForTestPackJdkAnnotations; +import java.io.File; + public class PluginTestCaseBase { public static final String TEST_DATA_PROJECT_RELATIVE = "/idea/testData"; @@ -37,8 +39,8 @@ public class PluginTestCaseBase { return JetTestCaseBuilder.getHomeDirectory() + TEST_DATA_PROJECT_RELATIVE; } - public static Sdk jdkFromIdeaHome() { - Sdk sdk = new JavaSdkImpl().createJdk("JDK", "compiler/testData/mockJDK/jre", true); + private static Sdk getSdk(String sdkHome) { + Sdk sdk = new JavaSdkImpl().createJdk("JDK", sdkHome, true); SdkModificator modificator = sdk.getSdkModificator(); VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(ForTestPackJdkAnnotations.jdkAnnotationsForTests()); assert file != null; @@ -46,4 +48,15 @@ public class PluginTestCaseBase { modificator.commitChanges(); return sdk; } + + public static Sdk jdkFromIdeaHome() { + return getSdk("compiler/testData/mockJDK/jre"); + } + + public static Sdk fullJdk() { + String javaHome = System.getProperty("java.home"); + assert new File(javaHome).isDirectory(); + return getSdk(javaHome); + } + } diff --git a/idea/tests/org/jetbrains/jet/plugin/highlighter/NoErrorsInStdlibTest.kt b/idea/tests/org/jetbrains/jet/plugin/highlighter/NoErrorsInStdlibTest.kt new file mode 100644 index 00000000000..a8bbbbb1488 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/highlighter/NoErrorsInStdlibTest.kt @@ -0,0 +1,73 @@ +/* + * 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.plugin.highlighter + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.jet.plugin.ProjectDescriptorWithStdlibSources +import com.intellij.openapi.roots.ModuleRootManager +import org.jetbrains.jet.plugin.JetJdkAndLibraryProjectDescriptor +import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.vfs.VfsUtil +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache +import org.jetbrains.jet.lang.psi.JetFile +import org.jetbrains.jet.lang.diagnostics.Severity +import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.jet.cli.common.messages.MessageCollectorPlainTextToStream +import com.intellij.openapi.projectRoots.Sdk +import org.jetbrains.jet.plugin.PluginTestCaseBase +import kotlin.test.assertEquals + +public class NoErrorsInStdlibTest: LightCodeInsightFixtureTestCase() { + public fun testNoErrors() { + val orderEntries = ModuleRootManager.getInstance(myModule!!)!!.getOrderEntries() + val orderEntry = orderEntries.find { it.getPresentableName() == JetJdkAndLibraryProjectDescriptor.LIBRARY_NAME }!! + val root = orderEntry.getFiles(OrderRootType.SOURCES)[0] + + val psiManager = getPsiManager() // workaround for KT-3974 IllegalAccessError when accessing protected method inherited by outer class + + var totalErrors = 0 + + VfsUtil.processFileRecursivelyWithoutIgnored(root) { file -> + if (!file!!.isDirectory()) { + val psiFile = psiManager.findFile(file) + if (psiFile is JetFile) { + var bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(psiFile).getBindingContext() + val errors = bindingContext.getDiagnostics().filter { it.getSeverity() == Severity.ERROR } + + if (!errors.isEmpty()) { + System.err.println("${psiFile.getName()}: ${errors.size()} errors") + AnalyzerWithCompilerReport.reportDiagnostics( + bindingContext, MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR) + + totalErrors += errors.size() + } + } + } + + true + } + + assertEquals(0, totalErrors) + } + + override fun getProjectDescriptor(): LightProjectDescriptor { + return object : ProjectDescriptorWithStdlibSources() { + override fun getSdk(): Sdk? = PluginTestCaseBase.fullJdk() + } + } +}