diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 893d9ce47b3..4e1253cbbda 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -203,8 +203,10 @@ public class IntrinsicMethods { private void declareIntrinsicProperty(String className, String methodName, IntrinsicMethod implementation) { final JetScope numberScope = getClassMemberScope(className); - final VariableDescriptor variable = numberScope.getVariable(methodName); - myMethods.put(variable.getOriginal(), implementation); + Set properties = numberScope.getProperties(methodName); + assert properties.size() == 1; + final VariableDescriptor property = properties.iterator().next(); + myMethods.put(property.getOriginal(), implementation); } private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index d32a0457bac..1753b072141 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -4,15 +4,13 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.TypeSubstitutor; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author abreslav @@ -115,16 +113,25 @@ public class JavaClassMembersScope implements JetScope { return null; } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { VariableDescriptor variableDescriptor = variables.get(name); if (variableDescriptor == null) { variableDescriptor = doGetVariable(name); - variables.put(name, variableDescriptor); + if (variableDescriptor != null) { + variables.put(name, variableDescriptor); + } } - return variableDescriptor; + return variableDescriptor != null ? Collections.singleton(variableDescriptor) : Collections.emptySet(); } + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { + return null; + } + + @Nullable private VariableDescriptor doGetVariable(String name) { PsiField field = psiClass.findFieldByName(name, true); if (field == null) return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index b8096c3dfdc..1fad260a6cc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -145,8 +145,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { properties.add(propertyDescriptor); callableMembers.add(propertyDescriptor); - scopeForMemberLookup.addVariableDescriptor(propertyDescriptor); - scopeForMemberResolution.addVariableDescriptor(propertyDescriptor); + scopeForMemberLookup.addPropertyDescriptor(propertyDescriptor); + scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java index 16016715a4d..7c940b853c8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java @@ -49,8 +49,8 @@ public class NamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl imp } @Override - public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) { - memberScope.addVariableDescriptor(variableDescriptor); + public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { + memberScope.addPropertyDescriptor(propertyDescriptor); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java index 974d490667a..131a6a62933 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java @@ -45,9 +45,15 @@ public abstract class AbstractScopeAdapter implements JetScope { return getWorkerScope().getClassifier(name); } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { - return getWorkerScope().getVariable(name); + public Set getProperties(@NotNull String name) { + return getWorkerScope().getProperties(name); + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { + return getWorkerScope().getLocalVariable(name); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 2a1ccf5ad84..5e0b2c9135c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -123,7 +123,7 @@ public class AnalyzingUtils { @Override public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { - scope.addVariableDescriptor(propertyDescriptor); + scope.addPropertyDescriptor(propertyDescriptor); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index ffdccd62a25..de4f4a9b0fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -1,15 +1,19 @@ package org.jetbrains.jet.lang.resolve; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; @@ -77,6 +81,7 @@ public class DescriptorUtils { return substituted; } + @Nullable @Override public JetType substitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) { TypeParameterDescriptor typeParameterDescriptor = typeConstructors.get(type.getConstructor()); @@ -196,4 +201,14 @@ public class DescriptorUtils { } return false; } + + @Nullable + public static VariableDescriptor filterNonExtensionProperty(Set variables) { + for (VariableDescriptor variable : variables) { + if (!variable.getReceiverParameter().exists()) { + return variable; + } + } + return null; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index af23ece699e..2735a9eb566 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -12,7 +12,6 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Set; import static org.jetbrains.jet.lang.diagnostics.Errors.*; @@ -113,8 +112,8 @@ public class ImportsResolver { namespaceScope.importFunctionAlias(aliasName, (FunctionDescriptor) descriptor); return; } - if (descriptor instanceof VariableDescriptor) { - namespaceScope.importVariableAlias(aliasName, (VariableDescriptor) descriptor); + if (descriptor instanceof PropertyDescriptor) { + namespaceScope.importVariableAlias(aliasName, (PropertyDescriptor) descriptor); } } @@ -191,11 +190,9 @@ public class ImportsResolver { ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName); if (classifierDescriptor != null) descriptors.add(classifierDescriptor); - Set functionDescriptors = outerScope.getFunctions(referencedName); - descriptors.addAll(functionDescriptors); + descriptors.addAll(outerScope.getFunctions(referencedName)); - VariableDescriptor variableDescriptor = outerScope.getVariable(referencedName); - if (variableDescriptor != null) descriptors.add(variableDescriptor); + descriptors.addAll(outerScope.getProperties(referencedName)); } if (!firstPhase) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 2c060f36b97..94e88009cbb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -77,12 +77,12 @@ public class OverrideResolver { @Nullable private PropertyDescriptor findPropertyOverridableBy(@NotNull PropertyDescriptor declaredProperty, @NotNull JetType supertype) { - PropertyDescriptor property = (PropertyDescriptor) supertype.getMemberScope().getVariable(declaredProperty.getName()); - if (property == null) { - return null; - } - if (OverridingUtil.isOverridableBy(property, declaredProperty).isSuccess()) { - return property; + Set properties = supertype.getMemberScope().getProperties(declaredProperty.getName()); + for (VariableDescriptor property : properties) { + assert property instanceof PropertyDescriptor; + if (OverridingUtil.isOverridableBy(property, declaredProperty).isSuccess()) { + return (PropertyDescriptor) property; + } } return null; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java index c5a4f75f8b1..38c0a9e51b8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java @@ -1,9 +1,13 @@ package org.jetbrains.jet.lang.resolve.calls; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetStandardClasses; @@ -68,8 +72,11 @@ public class TaskPrioritizers { } private void addVariableAsFunction(JetScope scope, String name, Set functions, boolean receiverNeeded) { - VariableDescriptor variable = scope.getVariable(name); - if (variable != null && !variable.getReceiverParameter().exists()) { + VariableDescriptor variable = scope.getLocalVariable(name); + if (variable == null) { + variable = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name)); + } + if (variable != null) { JetType outType = variable.getOutType(); if (outType != null && JetStandardClasses.isFunctionType(outType)) { VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable); @@ -86,36 +93,34 @@ public class TaskPrioritizers { @NotNull @Override protected Collection getNonExtensionsByName(JetScope scope, String name) { - VariableDescriptor variable = scope.getVariable(name); - if (variable != null && !variable.getReceiverParameter().exists()) { - return Collections.singleton(variable); + VariableDescriptor descriptor = scope.getLocalVariable(name); + if (descriptor == null) { + descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name)); } - return Collections.emptyList(); + if (descriptor == null) return Collections.emptyList(); + return Collections.singleton(descriptor); } @NotNull @Override protected Collection getMembersByName(@NotNull JetType receiverType, String name) { - VariableDescriptor variable = receiverType.getMemberScope().getVariable(name); - if (variable != null) { - return Collections.singleton(variable); - } - return Collections.emptyList(); + return receiverType.getMemberScope().getProperties(name); } @NotNull @Override protected Collection getExtensionsByName(JetScope scope, String name) { - VariableDescriptor variable = scope.getVariable(name); - if (variable != null && variable.getReceiverParameter().exists()) { - return Collections.singleton(variable); - } - return Collections.emptyList(); + return Collections2.filter(scope.getProperties(name), new Predicate() { + @Override + public boolean apply(@Nullable VariableDescriptor variableDescriptor) { + return (variableDescriptor != null) && variableDescriptor.getReceiverParameter().exists(); + } + }); } }; /*package*/ static TaskPrioritizer PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer() { - private Collection filterProperties(Collection variableDescriptors) { + private Collection filterProperties(Collection variableDescriptors) { ArrayList properties = Lists.newArrayList(); for (VariableDescriptor descriptor : variableDescriptors) { if (descriptor instanceof PropertyDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java index d68055d33f3..43a5b6d4d28 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java @@ -43,10 +43,20 @@ public class ChainedScope implements JetScope { return null; } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { + Set properties = Sets.newLinkedHashSet(); for (JetScope jetScope : scopeChain) { - VariableDescriptor variable = jetScope.getVariable(name); + properties.addAll(jetScope.getProperties(name)); + } + return properties; + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { + for (JetScope jetScope : scopeChain) { + VariableDescriptor variable = jetScope.getLocalVariable(name); if (variable != null) { return variable; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java index 73746161e66..22ffa67c092 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java @@ -32,8 +32,11 @@ public interface JetScope { @Nullable NamespaceDescriptor getNamespace(@NotNull String name); + @NotNull + Set getProperties(@NotNull String name); + @Nullable - VariableDescriptor getVariable(@NotNull String name); + VariableDescriptor getLocalVariable(@NotNull String name); @NotNull Set getFunctions(@NotNull String name); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java index 589bee9496b..27959d5fc32 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java @@ -18,8 +18,14 @@ public abstract class JetScopeImpl implements JetScope { return null; } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { + return Collections.emptySet(); + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { return null; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java index c2e0ffbc177..036e2e9b002 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java @@ -60,9 +60,15 @@ public class SubstitutingScope implements JetScope { return result; } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { - return substitute(workerScope.getVariable(name)); + public Set getProperties(@NotNull String name) { + return substitute(workerScope.getProperties(name)); + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { + return substitute(workerScope.getLocalVariable(name)); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java index ac06875abca..be455d54bd6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java @@ -21,6 +21,8 @@ public interface WritableScope extends JetScope { void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor); + void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor); + void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor); void addTypeParameterDescriptor(@NotNull TypeParameterDescriptor typeParameterDescriptor); @@ -50,5 +52,5 @@ public interface WritableScope extends JetScope { void importFunctionAlias(@NotNull String aliasName, @NotNull FunctionDescriptor functionDescriptor); - void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor); + void importVariableAlias(@NotNull String aliasName, @NotNull PropertyDescriptor variableDescriptor); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index dd54a0cdeb9..8c73ddbe2c5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.util.CommonSuppliers; import java.util.*; @@ -32,6 +33,9 @@ public class WritableScopeImpl extends WritableScopeWithImports { @Nullable private Map variableClassOrNamespaceDescriptors; + + @Nullable + private SetMultimap propertyGroups; @Nullable private Map namespaceAliases; @@ -85,10 +89,10 @@ public class WritableScopeImpl extends WritableScopeWithImports { } @Override - public void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor) { + public void importVariableAlias(@NotNull String aliasName, @NotNull PropertyDescriptor variableDescriptor) { checkMayWrite(); - addVariableDescriptor(variableDescriptor); + addPropertyDescriptor(variableDescriptor); super.importVariableAlias(aliasName, variableDescriptor); } @@ -165,35 +169,69 @@ public class WritableScopeImpl extends WritableScopeWithImports { @Override public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) { + addVariableDescriptor(variableDescriptor, false); + } + + @Override + public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { + addVariableDescriptor(propertyDescriptor, true); + } + + private void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor, boolean isProperty) { checkMayWrite(); - Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); - DeclarationDescriptor existingDescriptor = variableClassOrNamespaceDescriptors.get(variableDescriptor.getName()); - if (existingDescriptor != null) { - redeclarationHandler.handleRedeclaration(existingDescriptor, variableDescriptor); + String name = variableDescriptor.getName(); + if (isProperty) { + checkForPropertyRedeclaration(name, variableDescriptor); + getPropertyGroups().put(name, variableDescriptor); + } + if (!variableDescriptor.getReceiverParameter().exists()) { + checkForRedeclaration(name, variableDescriptor); + // TODO : Should this always happen? + getVariableClassOrNamespaceDescriptors().put(name, variableDescriptor); } - // TODO : Should this always happen? - variableClassOrNamespaceDescriptors.put(variableDescriptor.getName(), variableDescriptor); allDescriptors.add(variableDescriptor); } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { + checkMayRead(); + + Set result = Sets.newLinkedHashSet(getPropertyGroups().get(name)); + + result.addAll(getWorkerScope().getProperties(name)); + + result.addAll(super.getProperties(name)); + + return result; + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { checkMayRead(); Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); DeclarationDescriptor descriptor = variableClassOrNamespaceDescriptors.get(name); - if (descriptor instanceof VariableDescriptor) { + if (descriptor instanceof VariableDescriptor && !getPropertyGroups().get(name).contains(descriptor)) { return (VariableDescriptor) descriptor; } - VariableDescriptor variableDescriptor = getWorkerScope().getVariable(name); + VariableDescriptor variableDescriptor = getWorkerScope().getLocalVariable(name); if (variableDescriptor != null) { return variableDescriptor; } - return super.getVariable(name); + return super.getLocalVariable(name); } + @NotNull + private SetMultimap getPropertyGroups() { + if (propertyGroups == null) { + propertyGroups = CommonSuppliers.newLinkedHashSetHashSetMultimap(); + } + return propertyGroups; + } + @NotNull private SetMultimap getFunctionGroups() { if (functionGroups == null) { @@ -274,6 +312,18 @@ public class WritableScopeImpl extends WritableScopeWithImports { getVariableClassOrNamespaceDescriptors().put(name, variableDescriptor); allDescriptors.add(variableDescriptor); } + + private void checkForPropertyRedeclaration(String name, VariableDescriptor variableDescriptor) { + Set properties = getPropertyGroups().get(name); + ReceiverDescriptor receiverParameter = variableDescriptor.getReceiverParameter(); + for (VariableDescriptor oldProperty : properties) { + ReceiverDescriptor receiverParameterForOldVariable = oldProperty.getReceiverParameter(); + if (((receiverParameter.exists() && receiverParameterForOldVariable.exists()) && + (JetTypeChecker.INSTANCE.equalTypes(receiverParameter.getType(), receiverParameterForOldVariable.getType())))) { + redeclarationHandler.handleRedeclaration(oldProperty, variableDescriptor); + } + } + } private void checkForRedeclaration(String name, DeclarationDescriptor classifierDescriptor) { DeclarationDescriptor originalDescriptor = getVariableClassOrNamespaceDescriptors().get(name); @@ -364,7 +414,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { super.getImplicitReceiversHierarchy(result); } - @SuppressWarnings({"NullableProblems"}) +// @SuppressWarnings({"NullableProblems"}) @NotNull private Map getPropertyDescriptorsByFieldNames() { if (propertyDescriptorsByFieldNames == null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java index 261ccd08f80..285b16ab0f1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java @@ -6,10 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author abreslav @@ -96,13 +93,25 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement } } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { + checkMayRead(); + + Set properties = Sets.newLinkedHashSet(); + for (JetScope imported : getImports()) { + properties.addAll(imported.getProperties(name)); + } + return properties; + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { checkMayRead(); // Meaningful lookup goes here for (JetScope imported : getImports()) { - VariableDescriptor importedDescriptor = imported.getVariable(name); + VariableDescriptor importedDescriptor = imported.getLocalVariable(name); if (importedDescriptor != null) { return importedDescriptor; } @@ -184,7 +193,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement } @Override - public void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor) { + public void importVariableAlias(@NotNull String aliasName, @NotNull PropertyDescriptor variableDescriptor) { checkMayWrite(); getCurrentIndividualImportScope().addVariableAlias(aliasName, variableDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java index 31beb1efe3b..43c5c1d1ffc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java @@ -71,17 +71,29 @@ public class WriteThroughScope extends WritableScopeWithImports { } @Override - @Nullable - public VariableDescriptor getVariable(@NotNull String name) { + @NotNull + public Set getProperties(@NotNull String name) { checkMayRead(); - VariableDescriptor variable = writableWorker.getVariable(name); + Set properties = Sets.newLinkedHashSet(); + properties.addAll(writableWorker.getProperties(name)); + properties.addAll(getWorkerScope().getProperties(name)); + properties.addAll(super.getProperties(name)); //imports + return properties; + } + + @Override + @Nullable + public VariableDescriptor getLocalVariable(@NotNull String name) { + checkMayRead(); + + VariableDescriptor variable = writableWorker.getLocalVariable(name); if (variable != null) return variable; - variable = getWorkerScope().getVariable(name); + variable = getWorkerScope().getLocalVariable(name); if (variable != null) return variable; - return super.getVariable(name); // Imports + return super.getLocalVariable(name); // Imports } @Override @@ -126,6 +138,13 @@ public class WriteThroughScope extends WritableScopeWithImports { writableWorker.addVariableDescriptor(variableDescriptor); } + @Override + public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { + checkMayWrite(); + + writableWorker.addPropertyDescriptor(propertyDescriptor); + } + @Override public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { checkMayWrite(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 191e0bfba70..62c5ca24b4d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -22,8 +22,14 @@ public class ErrorUtils { return ERROR_CLASS; } + @NotNull @Override - public VariableDescriptor getVariable(@NotNull String name) { + public Set getProperties(@NotNull String name) { + return ERROR_PROPERTY_GROUP; + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull String name) { return ERROR_PROPERTY; } @@ -111,6 +117,7 @@ public class ErrorUtils { ReceiverDescriptor.NO_RECEIVER, "", ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE); + private static final Set ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY); private static FunctionDescriptor createErrorFunction(List typeParameters, List positionedValueArgumentTypes) { FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.emptyList(), ""); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 6d9869adc44..3f0b4c5d3d0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -585,10 +585,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression; TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); - OverloadResolutionResults variableDescriptor = context.replaceBindingTrace(temporaryTrace).resolveSimpleProperty(receiver, callOperationNode, nameExpression); - if (variableDescriptor.isSuccess()) { + OverloadResolutionResults resolutionResult = context.replaceBindingTrace(temporaryTrace).resolveSimpleProperty(receiver, callOperationNode, nameExpression); + if (resolutionResult.isSuccess()) { temporaryTrace.commit(); - return variableDescriptor.getResultingDescriptor().getOutType(); + return resolutionResult.getResultingDescriptor().getOutType(); + } + if (resolutionResult.isAmbiguity()) { + temporaryTrace.commit(); + return null; } ExpressionTypingContext newContext = receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context; JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 4ba03453c46..8f9424acf64 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -20,10 +20,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.jet.lang.types.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; @@ -238,7 +235,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { { // http://youtrack.jetbrains.net/issue/KT-527 - VariableDescriptor olderVariable = context.scope.getVariable(variableDescriptor.getName()); + VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName()); if (olderVariable != null && DescriptorUtils.isLocal(context.scope.getContainingDeclaration(), olderVariable)) { context.trace.report(Errors.NAME_SHADOWING.on(variableDescriptor, context.trace.getBindingContext())); } @@ -326,8 +323,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { @Nullable private VariableDescriptor checkHasNextPropertySupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { - VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext"); - // TODO :extension properties + VariableDescriptor hasNextProperty = DescriptorUtils.filterNonExtensionProperty(iteratorType.getMemberScope().getProperties("hasNext")); if (hasNextProperty == null) { return null; } else { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 2bd86462462..b4eabb934a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -63,7 +63,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, declaration); if (classDescriptor != null) { PropertyDescriptor propertyDescriptor = context.getDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor); - scope.addVariableDescriptor(propertyDescriptor); + scope.addPropertyDescriptor(propertyDescriptor); } return DataFlowUtils.checkStatementType(declaration, context); } @@ -93,7 +93,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito } { - VariableDescriptor olderVariable = scope.getVariable(propertyDescriptor.getName()); + VariableDescriptor olderVariable = scope.getLocalVariable(propertyDescriptor.getName()); if (olderVariable != null && DescriptorUtils.isLocal(propertyDescriptor.getContainingDeclaration(), olderVariable)) { context.trace.report(Errors.NAME_SHADOWING.on(propertyDescriptor, context.trace.getBindingContext())); } diff --git a/compiler/testData/diagnostics/tests/ForRangeConventions.jet b/compiler/testData/diagnostics/tests/ForRangeConventions.jet index 66142d55fbb..d94d7aca9d2 100644 --- a/compiler/testData/diagnostics/tests/ForRangeConventions.jet +++ b/compiler/testData/diagnostics/tests/ForRangeConventions.jet @@ -67,7 +67,17 @@ abstract class Range1() { abstract fun iterator() : Iterator } -fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, range0: Range0, range1: Range1) { +abstract class ImproperIterator5 { + abstract val String.hasNext : Boolean + abstract fun next() : Int +} + +abstract class NotRange8() { + abstract fun iterator() : ImproperIterator5 +} + + +fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, notRange8: NotRange8, range0: Range0, range1: Range1) { for (i in notRange1); for (i in notRange2); for (i in notRange3); @@ -75,6 +85,7 @@ fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRa for (i in notRange5); for (i in notRange6); for (i in notRange7); + for (i in notRange8); for (i in range0); for (i in range1); diff --git a/compiler/testData/diagnostics/tests/ExtensionFunctions.jet b/compiler/testData/diagnostics/tests/extensions/ExtensionFunctions.jet similarity index 100% rename from compiler/testData/diagnostics/tests/ExtensionFunctions.jet rename to compiler/testData/diagnostics/tests/extensions/ExtensionFunctions.jet diff --git a/compiler/testData/diagnostics/tests/ExtensionsCalledOnSuper.jet b/compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.jet similarity index 100% rename from compiler/testData/diagnostics/tests/ExtensionsCalledOnSuper.jet rename to compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.jet diff --git a/compiler/testData/diagnostics/tests/extensions/kt819ExtensionProperties.jet b/compiler/testData/diagnostics/tests/extensions/kt819ExtensionProperties.jet new file mode 100644 index 00000000000..d49ea48bd60 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/kt819ExtensionProperties.jet @@ -0,0 +1,34 @@ + +//+JDK +//KT-819 Redeclaration error for extension properties with the same name and different receivers + +import java.io.* + +inline val InputStream.buffered : BufferedInputStream + get() = if(this is BufferedInputStream) this else BufferedInputStream(this) + +inline val Reader.buffered : BufferedReader + get() = if(this is BufferedReader) this else BufferedReader(this) + + +//more tests +open class A() { + open fun String.foo() {} + open fun Int.foo() {} + + open val String.foo = 0 + open val Int.foo = 1 +} + +class B() : A() { + override fun String.foo() {} + override fun Int.foo() {} + + override val String.foo = 0 + override val Int.foo = 0 + + fun use(s: String) { + s.foo + s.foo() + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 83d353c6931..14ad874837a 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -670,7 +670,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { @Override public void visitProperty(JetProperty property) { if (property.getPropertyTypeRef() != null) { - memberDeclarations.addVariableDescriptor(descriptorResolver.resolvePropertyDescriptor(classDescriptor, parameterScope, property)); + memberDeclarations.addPropertyDescriptor(descriptorResolver.resolvePropertyDescriptor(classDescriptor, parameterScope, property)); } else { // TODO : Caution: a cyclic dependency possible throw new UnsupportedOperationException();