diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java new file mode 100644 index 0000000000000000000000000000000000000000..893a528dd8211a35d492293c34ffb64e38514673 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2012 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.di; + +import com.intellij.openapi.project.Project; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; +import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; +import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; +import org.jetbrains.jet.lang.resolve.calls.CallResolver; +import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; + +/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ +public class InjectorForLazyResolve { + + private final Project project; + private DescriptorResolver descriptorResolver; + private ExpressionTypingServices expressionTypingServices; + private TypeResolver typeResolver; + private AnnotationResolver annotationResolver; + private CallResolver callResolver; + private OverloadingConflictResolver overloadingConflictResolver; + private QualifiedExpressionResolver qualifiedExpressionResolver; + + public InjectorForLazyResolve( + @NotNull Project project + ) { + this.project = project; + this.descriptorResolver = new DescriptorResolver(); + this.expressionTypingServices = new ExpressionTypingServices(); + this.typeResolver = new TypeResolver(); + this.annotationResolver = new AnnotationResolver(); + this.callResolver = new CallResolver(); + this.overloadingConflictResolver = new OverloadingConflictResolver(); + this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + + this.descriptorResolver.setAnnotationResolver(annotationResolver); + this.descriptorResolver.setExpressionTypingServices(expressionTypingServices); + this.descriptorResolver.setTypeResolver(typeResolver); + + this.expressionTypingServices.setCallResolver(callResolver); + this.expressionTypingServices.setDescriptorResolver(descriptorResolver); + this.expressionTypingServices.setProject(project); + this.expressionTypingServices.setTypeResolver(typeResolver); + + this.typeResolver.setAnnotationResolver(annotationResolver); + this.typeResolver.setDescriptorResolver(descriptorResolver); + this.typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + + annotationResolver.setCallResolver(callResolver); + annotationResolver.setExpressionTypingServices(expressionTypingServices); + + callResolver.setDescriptorResolver(descriptorResolver); + callResolver.setExpressionTypingServices(expressionTypingServices); + callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setTypeResolver(typeResolver); + + } + + @PreDestroy + public void destroy() { + } + + public DescriptorResolver getDescriptorResolver() { + return this.descriptorResolver; + } + + public ExpressionTypingServices getExpressionTypingServices() { + return this.expressionTypingServices; + } + + public TypeResolver getTypeResolver() { + return this.typeResolver; + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java new file mode 100644 index 0000000000000000000000000000000000000000..eee08283aededc3f1d1d383868265b17a66fcd9f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java @@ -0,0 +1,189 @@ +/* + * Copyright 2010-2012 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.lazy; + +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.psi.*; +import org.jetbrains.jet.lang.resolve.name.LabelName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; + +import java.util.*; + +/** + * @author abreslav + */ +public abstract class AbstractLazyMemberScope implements JetScope { + protected final ResolveSession resolveSession; + protected final DP declarationProvider; + protected final D thisDescriptor; + + protected boolean allDescriptorsComputed = false; + + private final Map classDescriptors = Maps.newHashMap(); + private final Map> functionDescriptors = Maps.newHashMap(); + private final Map> propertyDescriptors = Maps.newHashMap(); + + protected AbstractLazyMemberScope( + @NotNull ResolveSession resolveSession, + @NotNull DP declarationProvider, + @NotNull D thisDescriptor + ) { + this.resolveSession = resolveSession; + this.declarationProvider = declarationProvider; + this.thisDescriptor = thisDescriptor; + } + + @Nullable + private ClassDescriptor getClassOrObjectDescriptor(@NotNull Name name, boolean object) { + ClassDescriptor known = classDescriptors.get(name); + if (known != null) return known; + + if (allDescriptorsComputed) return null; + + JetClassOrObject classOrObjectDeclaration = declarationProvider.getClassOrObjectDeclaration(name); + if (classOrObjectDeclaration == null) return null; + + if (object != classOrObjectDeclaration instanceof JetObjectDeclaration) return null; + + ClassMemberDeclarationProvider classMemberDeclarationProvider = + resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classOrObjectDeclaration); + ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name, classMemberDeclarationProvider); + + classDescriptors.put(name, classDescriptor); + + return classDescriptor; + } + + @Override + public ClassifierDescriptor getClassifier(@NotNull Name name) { + return getClassOrObjectDescriptor(name, false); + } + + @Override + public ClassDescriptor getObjectDescriptor(@NotNull Name name) { + // TODO: We shouldn't really allow objects in classes... + return getClassOrObjectDescriptor(name, true); + } + + @NotNull + @Override + public Set getFunctions(@NotNull Name name) { + Set known = functionDescriptors.get(name); + if (known != null) return known; + + // If all descriptors are already computed, we are + if (allDescriptorsComputed) return Collections.emptySet(); + + Set result = Sets.newLinkedHashSet(); + + List declarations = declarationProvider.getFunctionDeclarations(name); + for (JetNamedFunction functionDeclaration : declarations) { + JetScope resolutionScope = getScopeForMemberDeclarationResolution(functionDeclaration); + result.add(resolveSession.getDescriptorResolver().resolveFunctionDescriptor(thisDescriptor, resolutionScope, + functionDeclaration, resolveSession.getTrace())); + } + + getNonDeclaredFunctions(name, result); + + if (!result.isEmpty()) { + functionDescriptors.put(name, result); + } + return result; + } + + @NotNull + protected abstract JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration); + + protected abstract void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set result); + + @NotNull + @Override + public Set getProperties(@NotNull Name name) { + Set known = propertyDescriptors.get(name); + if (known != null) return known; + + // If all descriptors are already computed, we are + if (allDescriptorsComputed) return Collections.emptySet(); + + Set result = Sets.newLinkedHashSet(); + + List declarations = declarationProvider.getPropertyDeclarations(name); + for (JetProperty propertyDeclaration : declarations) { + JetScope resolutionScope = getScopeForMemberDeclarationResolution(propertyDeclaration); + result.add(resolveSession.getDescriptorResolver().resolvePropertyDescriptor(thisDescriptor, resolutionScope, + propertyDeclaration, resolveSession.getTrace())); + } + + getNonDeclaredProperties(name, result); + + if (!result.isEmpty()) { + propertyDescriptors.put(name, result); + } + return result; + } + + protected abstract void getNonDeclaredProperties(@NotNull Name name, @NotNull Set result); + + @NotNull + @Override + public Set getObjectDescriptors() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public VariableDescriptor getLocalVariable(@NotNull Name name) { + return null; + } + + @NotNull + @Override + public DeclarationDescriptor getContainingDeclaration() { + return thisDescriptor; + } + + @NotNull + @Override + public Collection getDeclarationsByLabel(@NotNull LabelName labelName) { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public Collection getAllDescriptors() { + allDescriptorsComputed = true; + throw new UnsupportedOperationException(); // TODO + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + ReceiverDescriptor receiver = getImplicitReceiver(); + if (receiver.exists()) { + result.add(receiver); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..92d5fce04fdb7b1229390f268d04811ee7722f5c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClassOrObject; + +/** + * @author abreslav + */ +public interface ClassMemberDeclarationProvider extends DeclarationProvider { + @NotNull + JetClassOrObject getOwnerClassOrObject(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..cc7dddbdb1f6ad9eed66c3cea400ea1873f273b6 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.resolve.name.Name; + +import java.util.List; + +/** +* @author abreslav +*/ +public interface DeclarationProvider { + List getAllDeclarations(); + + @NotNull + List getFunctionDeclarations(@NotNull Name name); + + @NotNull + List getPropertyDeclarations(@NotNull Name name); + + @Nullable + JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name); + + boolean isPackageDeclared(@NotNull Name name); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProviderFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..28b73f9b108f7f453d50d497406431531d8230a4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProviderFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.resolve.name.FqName; + +/** + * @author abreslav + */ +public interface DeclarationProviderFactory { + @NotNull + ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassOrObject jetClassOrObject); + + @Nullable + DeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/IdentitySmartPointer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/IdentitySmartPointer.java new file mode 100644 index 0000000000000000000000000000000000000000..58fc430972a3bcd7cacb88533112570ca16c852a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/IdentitySmartPointer.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2012 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.lazy; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Segment; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.SmartPsiElementPointer; +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public class IdentitySmartPointer implements SmartPsiElementPointer { + private final E element; + + public IdentitySmartPointer(@NotNull E element) { + this.element = element; + } + + @Override + public E getElement() { + return element; + } + + @Override + public PsiFile getContainingFile() { + return element.getContainingFile(); + } + + @NotNull + @Override + public Project getProject() { + return element.getProject(); + } + + @Override + public VirtualFile getVirtualFile() { + return element.getContainingFile().getVirtualFile(); + } + + @Override + public Segment getRange() { + return element.getTextRange(); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..691ddcd436f6b24ac9cf77819f08af2a796679ae --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java @@ -0,0 +1,278 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.*; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.*; + +/** + * @author abreslav + */ +public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDescriptor { + + private final ResolveSession resolveSession; + + private final Name name; + private final DeclarationDescriptor containingDeclaration; + private final TypeConstructor typeConstructor; + private final ClassMemberDeclarationProvider declarationProvider; + + private final LazyClassMemberScope unsubstitutedMemberScope; + private final JetScope unsubstitutedInnerClassesScope; + private ClassReceiver implicitReceiver; + private JetScope scopeForClassHeaderResolution; + private JetScope scopeForMemberDeclarationResolution; + + private final Modality modality; + private final Visibility visibility; + private final ClassKind kind; + + + public LazyClassDescriptor( + @NotNull ResolveSession resolveSession, + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull Name name, + @NotNull ClassMemberDeclarationProvider memberDeclarationProvider + ) { + this.declarationProvider = memberDeclarationProvider; + this.resolveSession = resolveSession; + this.name = name; + this.containingDeclaration = containingDeclaration; + this.unsubstitutedMemberScope = new LazyClassMemberScope(resolveSession, memberDeclarationProvider, this); + this.unsubstitutedInnerClassesScope = new InnerClassesScopeWrapper(unsubstitutedMemberScope); + + this.typeConstructor = new LazyClassTypeConstructor(); + + JetClassOrObject classOrObject = memberDeclarationProvider.getOwnerClassOrObject(); + this.kind = getClassKind(classOrObject); + Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL; + JetModifierList modifierList = classOrObject.getModifierList(); + this.modality = DescriptorResolver.resolveModalityFromModifiers(modifierList, defaultModality); + this.visibility = DescriptorResolver.resolveVisibilityFromModifiers(modifierList); + } + + @NotNull + private static ClassKind getClassKind(@NotNull JetClassOrObject jetClassOrObject) { + if (jetClassOrObject instanceof JetClass) { + JetClass jetClass = (JetClass) jetClassOrObject; + if (jetClass.isTrait()) return ClassKind.TRAIT; + if (jetClass.hasModifier(JetTokens.ANNOTATION_KEYWORD)) return ClassKind.ANNOTATION_CLASS; + if (jetClass.hasModifier(JetTokens.ENUM_KEYWORD)) return ClassKind.ENUM_CLASS; + return ClassKind.CLASS; + } + if (jetClassOrObject instanceof JetObjectDeclaration) { + return ClassKind.OBJECT; + } + throw new IllegalArgumentException("Unknown class or object kind: " + jetClassOrObject); + } + + @Override + protected JetScope getScopeForMemberLookup() { + return unsubstitutedMemberScope; + } + + @NotNull + @Override + public JetScope getUnsubstitutedInnerClassesScope() { + return unsubstitutedInnerClassesScope; + } + + public JetScope getScopeForMemberDeclarationResolution() { + if (scopeForMemberDeclarationResolution == null) { + WritableScopeImpl scope = new WritableScopeImpl(getScopeForClassHeaderResolution(), this, RedeclarationHandler.DO_NOTHING) + .setDebugName("Member Declaration Resolution"); + + scope.changeLockLevel(WritableScope.LockLevel.READING); + scopeForMemberDeclarationResolution = scope; + } + return scopeForMemberDeclarationResolution; + } + + @NotNull + public JetScope getScopeForClassHeaderResolution() { + if (scopeForClassHeaderResolution == null) { + WritableScopeImpl scope = new WritableScopeImpl(resolveSession.getResolutionScope(declarationProvider.getOwnerClassOrObject()), this, RedeclarationHandler.DO_NOTHING) + .setDebugName("Class Header Resolution"); + for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) { + scope.addClassifierDescriptor(typeParameterDescriptor); + } + scope.changeLockLevel(WritableScope.LockLevel.READING); + scopeForClassHeaderResolution = scope; + } + return scopeForClassHeaderResolution; + } + + @NotNull + @Override + public Set getConstructors() { + return unsubstitutedMemberScope.getConstructors(); + } + + @Override + public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { + return unsubstitutedMemberScope.getPrimaryConstructor(); + } + + @NotNull + @Override + public DeclarationDescriptor getOriginal() { + return this; + } + + @NotNull + @Override + public DeclarationDescriptor getContainingDeclaration() { + return containingDeclaration; + } + + @NotNull + @Override + public TypeConstructor getTypeConstructor() { + return typeConstructor; + } + + @Override + public JetType getClassObjectType() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public boolean isClassObjectAValue() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public ClassDescriptor getClassObjectDescriptor() { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public ClassKind getKind() { + return kind; + } + + @NotNull + @Override + public Modality getModality() { + return modality; + } + + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + implicitReceiver = new ClassReceiver(this); + } + return implicitReceiver; + } + + @Override + public List getAnnotations() { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public Name getName() { + return name; + } + + @Override + public String toString() { + return "lazy class " + getName().toString(); + } + + private class LazyClassTypeConstructor implements TypeConstructor { + private Collection supertypes = null; + private List parameters = null; + + @NotNull + @Override + public List getParameters() { + if (parameters == null) { + JetClassOrObject declaration = declarationProvider.getOwnerClassOrObject(); + if (declaration instanceof JetClass) { + JetClass jetClass = (JetClass) declaration; + + List typeParameters = jetClass.getTypeParameters(); + parameters = new ArrayList(typeParameters.size()); + + for (int i = 0; i < typeParameters.size(); i++) { + parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i)); + } + } + else { + // It is an object declaration, no type parameters + parameters = Collections.emptyList(); + } + } + return parameters; + } + + @NotNull + @Override + public Collection getSupertypes() { + if (supertypes == null) { + JetClassOrObject declaration = declarationProvider.getOwnerClassOrObject(); + this.supertypes = resolveSession.getDescriptorResolver() + .resolveSupertypes(getScopeForClassHeaderResolution(), + declaration, + resolveSession.getTrace()); + } + return supertypes; + } + + @Override + public boolean isSealed() { + return !getModality().isOverridable(); + } + + @Override + public ClassifierDescriptor getDeclarationDescriptor() { + return LazyClassDescriptor.this; + } + + @Override + public List getAnnotations() { + return Collections.emptyList(); // TODO + } + + @Override + public String toString() { + return LazyClassDescriptor.this.getName().toString(); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java new file mode 100644 index 0000000000000000000000000000000000000000..cdc8e4eb42e6bb2a620e37afe2319bb83dc5808f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java @@ -0,0 +1,82 @@ +/* +* Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; + +import java.util.Set; + +/** +* @author abreslav +*/ +public class LazyClassMemberScope extends AbstractLazyMemberScope { + + public LazyClassMemberScope( + @NotNull ResolveSession resolveSession, + @NotNull ClassMemberDeclarationProvider declarationProvider, + @NotNull LazyClassDescriptor thisClass + ) { + super(resolveSession, declarationProvider, thisClass); + } + + @NotNull + @Override + protected JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration) { + return thisDescriptor.getScopeForMemberDeclarationResolution(); + } + + @Override + protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set result) { + JetClassOrObject owner = declarationProvider.getOwnerClassOrObject(); + //throw new UnsupportedOperationException(); // TODO + System.err.println("getNonDeclaredFunctions() should generate fake overrides for a class"); + } + + @Override + protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set result) { + System.err.println("getNonDeclaredProperties() should generate fake overrides for a class"); + throw new UnsupportedOperationException(); // TODO + } + + @Override + public NamespaceDescriptor getNamespace(@NotNull Name name) { + return null; + } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + return thisDescriptor.getImplicitReceiver(); + } + + @NotNull + public Set getConstructors() { + throw new UnsupportedOperationException(); // TODO + } + + @Nullable + public ConstructorDescriptor getPrimaryConstructor() { + throw new UnsupportedOperationException(); // TODO + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyDescriptorFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyDescriptorFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..fa3096812c43a6c0f49132810994d7e2f2d37b16 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyDescriptorFactory.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; + +/** + * @author abreslav + */ +public class LazyDescriptorFactory { + + @NotNull + public ClassDescriptor createLazyClassDescriptor() { + return null; + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..57ca156042b965f890fd72b1d23a8f8fa72473e3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageDescriptor.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2012 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.lazy; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.AbstractNamespaceDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptorParent; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; + +import java.util.Collections; + +/** + * @author abreslav + */ +public class LazyPackageDescriptor extends AbstractNamespaceDescriptorImpl implements NamespaceDescriptor { + private final LazyPackageMemberScope memberScope; + + public LazyPackageDescriptor( + @NotNull NamespaceDescriptorParent containingDeclaration, + @NotNull Name name, + @NotNull ResolveSession resolveSession, + @NotNull DeclarationProvider declarationProvider + ) { + super(containingDeclaration, Collections.emptyList(), name); + this.memberScope = new LazyPackageMemberScope(resolveSession, declarationProvider, this); + } + + @NotNull + @Override + public JetScope getMemberScope() { + return memberScope; + } + + @NotNull + @Override + public FqName getQualifiedName() { + return DescriptorUtils.getFQName(this).toSafe(); + } + + @Override + public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { + throw new UnsupportedOperationException(); // TODO + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageMemberScope.java new file mode 100644 index 0000000000000000000000000000000000000000..0efbd11badbaa9af03aeda77ea71a3a4e8c9116b --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyPackageMemberScope.java @@ -0,0 +1,86 @@ +/* +* Copyright 2010-2012 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.lazy; + +import com.google.common.collect.Maps; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; + +import java.util.Map; +import java.util.Set; + +/** +* @author abreslav +*/ +public class LazyPackageMemberScope extends AbstractLazyMemberScope { + + private final Map packageDescriptors = Maps.newHashMap(); + + public LazyPackageMemberScope(@NotNull ResolveSession resolveSession, + @NotNull DeclarationProvider declarationProvider, + @NotNull NamespaceDescriptor thisPackage) { + super(resolveSession, declarationProvider, thisPackage); + } + + @Override + public NamespaceDescriptor getNamespace(@NotNull Name name) { + NamespaceDescriptor known = packageDescriptors.get(name); + if (known != null) return known; + if (allDescriptorsComputed) return null; + + if (!declarationProvider.isPackageDeclared(name)) return null; + + DeclarationProvider packageMemberDeclarationProvider = resolveSession.getDeclarationProviderFactory().getPackageMemberDeclarationProvider( + DescriptorUtils.getFQName(thisDescriptor).child(name).toSafe()); + assert packageMemberDeclarationProvider != null : "Package is declared, but declaration provider is not found: " + name; + NamespaceDescriptor namespaceDescriptor = new LazyPackageDescriptor(thisDescriptor, name, resolveSession, packageMemberDeclarationProvider); + + packageDescriptors.put(name, namespaceDescriptor); + + return namespaceDescriptor; + } + + @NotNull + @Override + protected JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration) { + return resolveSession.getScopeProvider().getFileScopeForDeclarationResolution((JetFile) declaration.getContainingFile()); + } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + return ReceiverDescriptor.NO_RECEIVER; + } + + @Override + protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set result) { + // No extra functions + } + + @Override + protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set result) { + // No extra properties + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyResolveINjectorGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyResolveINjectorGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..e389651354b97f42d27712d9fc734e5583d30d3a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyResolveINjectorGenerator.java @@ -0,0 +1,7 @@ +package org.jetbrains.jet.lang.resolve.lazy; + +/** + * @author abreslav + */ +public class LazyResolveINjectorGenerator { +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyTypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyTypeParameterDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..6bc25199322948b7f384b327b297c9baeebe0ecf --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyTypeParameterDescriptor.java @@ -0,0 +1,286 @@ +/* + * Copyright 2010-2012 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.lazy; + +import com.google.common.collect.Sets; +import com.intellij.psi.SmartPsiElementPointer; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; +import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.util.lazy.LazyValue; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author abreslav + */ +public class LazyTypeParameterDescriptor implements TypeParameterDescriptor { + private final ResolveSession resolveSession; + + private final SmartPsiElementPointer jetTypeParameterSmartPsiElementPointer; + private final Variance variance; + private final int index; + private final LazyClassDescriptor containingDeclaration; + private final Name name; + + private TypeConstructor typeConstructor; + private JetType defaultType; + + private Set upperBounds; + private JetType upperBoundsAsType; + + private Set classObjectBounds; + private JetType classObjectBoundsAsType; + + public LazyTypeParameterDescriptor( + @NotNull ResolveSession resolveSession, + @NotNull LazyClassDescriptor containingDeclaration, + @NotNull JetTypeParameter jetTypeParameter, + int index) { + this.resolveSession = resolveSession; + // TODO: different smart pointer implementations in IDE and compiler + this.jetTypeParameterSmartPsiElementPointer = new IdentitySmartPointer(jetTypeParameter); + this.variance = jetTypeParameter.getVariance(); + this.containingDeclaration = containingDeclaration; + this.index = index; + this.name = jetTypeParameter.getNameAsName(); + } + + @Override + public boolean isReified() { + return false; + } + + @Override + public Variance getVariance() { + return variance; + } + + @NotNull + @Override + public Set getUpperBounds() { + if (upperBounds == null) { + upperBounds = Sets.newLinkedHashSet(); + + JetTypeParameter jetTypeParameter = getElement(); + + resolveUpperBoundsFromWhereClause(upperBounds, false); + + JetTypeReference extendsBound = jetTypeParameter.getExtendsBound(); + if (extendsBound != null) { + upperBounds.add(resolveBoundType(extendsBound)); + } + + if (upperBounds.isEmpty()) { + upperBounds.add(JetStandardClasses.getDefaultBound()); + } + } + return upperBounds; + } + + private JetTypeParameter resolveUpperBoundsFromWhereClause(Set upperBounds, boolean forClassObject) { + JetTypeParameter jetTypeParameter = getElement(); + + JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(jetTypeParameter, JetClassOrObject.class); + if (classOrObject instanceof JetClass) { + JetClass jetClass = (JetClass) classOrObject; + for (JetTypeConstraint jetTypeConstraint : jetClass.getTypeConstaints()) { + if (jetTypeConstraint.isClassObjectContraint() == forClassObject) continue; + + JetSimpleNameExpression constrainedParameterName = jetTypeConstraint.getSubjectTypeParameterName(); + if (constrainedParameterName != null) { + if (name.equals(constrainedParameterName.getReferencedNameAsName())) { + + JetTypeReference boundTypeReference = jetTypeConstraint.getBoundTypeReference(); + if (boundTypeReference != null) { + upperBounds.add(resolveBoundType(boundTypeReference)); + } + } + } + } + } + return jetTypeParameter; + } + + private JetTypeParameter getElement() { + JetTypeParameter jetTypeParameter = jetTypeParameterSmartPsiElementPointer.getElement(); + if (jetTypeParameter == null) { + throw new IllegalStateException("Psi element not found for type parameter: " + this); + } + return jetTypeParameter; + } + + private JetType resolveBoundType(@NotNull JetTypeReference boundTypeReference) { + return resolveSession.getTypeResolver() + .resolveType(containingDeclaration.getScopeForClassHeaderResolution(), boundTypeReference, + resolveSession.getTrace(), false); + } + + @NotNull + @Override + public JetType getUpperBoundsAsType() { + if (upperBoundsAsType == null) { + Set upperBounds = getUpperBounds(); + assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName(); + upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); + if (upperBoundsAsType == null) { + upperBoundsAsType = JetStandardClasses.getNothingType(); + } + } + return upperBoundsAsType; + } + + @NotNull + @Override + public Set getLowerBounds() { + return Collections.singleton(getLowerBoundsAsType()); + } + + @NotNull + @Override + public JetType getLowerBoundsAsType() { + return JetStandardClasses.getNothingType(); + } + + @NotNull + @Override + public TypeConstructor getTypeConstructor() { + if (typeConstructor == null) { + typeConstructor = new TypeConstructor() { + @NotNull + @Override + public Collection getSupertypes() { + return LazyTypeParameterDescriptor.this.getUpperBounds(); + } + + @NotNull + @Override + public List getParameters() { + return Collections.emptyList(); + } + + @Override + public boolean isSealed() { + return false; + } + + @Override + public ClassifierDescriptor getDeclarationDescriptor() { + return LazyTypeParameterDescriptor.this; + } + + @Override + public List getAnnotations() { + return LazyTypeParameterDescriptor.this.getAnnotations(); + } + + @Override + public String toString() { + return getName().toString(); + } + }; + } + return typeConstructor; + } + + @NotNull + @Override + public JetType getDefaultType() { + if (defaultType == null) { + defaultType = new JetTypeImpl(getTypeConstructor(), new LazyScopeAdapter(new LazyValue() { + @Override + protected JetScope compute() { + return getUpperBoundsAsType().getMemberScope(); + } + })); + } + return defaultType; + } + + @Override + public JetType getClassObjectType() { + return null; + } + + @Override + public boolean isClassObjectAValue() { + return false; + } + + @NotNull + @Override + public DeclarationDescriptor getOriginal() { + return this; + } + + @Override + public DeclarationDescriptor getContainingDeclaration() { + return containingDeclaration; + } + + @NotNull + @Override + @Deprecated + public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) { + throw new UnsupportedOperationException("Don't call substitute() on type parameters"); + } + + @Override + public R accept(DeclarationDescriptorVisitor visitor, D data) { + return visitor.visitTypeParameterDescriptor(this, data); + } + + @Override + public void acceptVoid(DeclarationDescriptorVisitor visitor) { + visitor.visitTypeParameterDescriptor(this, null); + } + + @Override + public int getIndex() { + return index; + } + + @Override + public List getAnnotations() { + return Collections.emptyList(); // TODO + } + + @NotNull + @Override + public Name getName() { + return name; + } + + @Override + public String toString() { + return getName().toString(); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java new file mode 100644 index 0000000000000000000000000000000000000000..61fc828cf006c073b903bfbb15baa99c758dacab --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -0,0 +1,201 @@ +/* + * Copyright 2010-2012 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.lazy; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.di.InjectorForLazyResolve; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author abreslav + */ +public class ResolveSession { + private final ModuleDescriptor module; + private final LazyPackageDescriptor rootPackage; + private final ScopeProvider scopeProvider; + + private final BindingTrace trace = new BindingTraceContext(); + private final DeclarationProviderFactory declarationProviderFactory; + + private final Map packageDescriptors = Maps.newHashMap(); + private final InjectorForLazyResolve injector; + + public ResolveSession( + @NotNull Project project, + @NotNull ModuleDescriptor rootDescriptor, + @NotNull DeclarationProviderFactory declarationProviderFactory + ) { + this.injector = new InjectorForLazyResolve(project); + this.module = rootDescriptor; + DeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(FqName.ROOT); + assert provider != null : "No declaration provider for root package in " + rootDescriptor; + this.rootPackage = new LazyPackageDescriptor(rootDescriptor, JetPsiUtil.ROOT_NAMESPACE_NAME, this, provider); + rootDescriptor.setRootNs(rootPackage); + + this.scopeProvider = new ScopeProvider(this); + this.declarationProviderFactory = declarationProviderFactory; + } + + @NotNull + public DescriptorResolver getDescriptorResolver() { + return injector.getDescriptorResolver(); + } + + public TypeResolver getTypeResolver() { + return injector.getTypeResolver(); + } + + @Nullable + public NamespaceDescriptor getPackageDescriptor(@NotNull Name shortName) { + return rootPackage.getMemberScope().getNamespace(shortName); + //NamespaceDescriptor namespaceDescriptor = packageDescriptors.get(shortName); + //if (namespaceDescriptor == null) { + // DeclarationProvider declarationProvider = declarationProviderFactory.getPackageMemberDeclarationProvider( + // FqName.topLevel(shortName)); + // if (declarationProvider == null) return null; + // + // namespaceDescriptor = new LazyPackageDescriptor(module.getRootNs(), shortName, this, declarationProvider); + // + // packageDescriptors.put(shortName, namespaceDescriptor); + //} + //return namespaceDescriptor; + } + + @Nullable + public NamespaceDescriptor getPackageDescriptorByFqName(FqName fqName) { + List names = fqName.pathSegments(); + NamespaceDescriptor current = getPackageDescriptor(names.get(0)); + if (current == null) return null; + for (Name name : names.subList(1, names.size())) { + current = current.getMemberScope().getNamespace(name); + if (current == null) return null; + } + return current; + } + + @NotNull + public ClassDescriptor getClassDescriptor(JetClassOrObject classOrObject) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + public ScopeProvider getScopeProvider() { + return scopeProvider; + } + + public Collection getDescriptorsForDeclarations(Collection declarationsOrFiles) { + final List descriptors = Lists.newArrayList(); + for (PsiElement declarationOrFile : declarationsOrFiles) { + declarationOrFile.accept(new JetVisitorVoid() { + @Override + public void visitJetFile(JetFile file) { + JetNamespaceHeader header = file.getNamespaceHeader(); + if (header == null) { + throw new UnsupportedOperationException("Lazy resolve is not supported for scripts"); + } + NamespaceDescriptor packageDescriptor = getPackageDescriptorByFqName(new FqName(header.getQualifiedName())); + if (packageDescriptor == null) { + throw new IllegalStateException("Package descriptor not found for: " + header.getQualifiedName()); + } + JetScope packageMemberScope = packageDescriptor.getMemberScope(); + for (JetDeclaration declaration : file.getDeclarations()) { + collectDescriptors(packageMemberScope, declaration); + } + } + + @Override + public void visitDeclaration(JetDeclaration dcl) { + JetScope scope = scopeProvider.getResolutionScopeForDeclaration(dcl); + collectDescriptors(scope, dcl); + } + + private void collectDescriptors(JetScope outerScope, JetDeclaration declaration) { + if (declaration instanceof JetClass) { + JetClass jetClass = (JetClass) declaration; + descriptors.add(outerScope.getClassifier(jetClass.getNameAsSafeName())); + } + else if (declaration instanceof JetFunction) { + JetFunction jetFunction = (JetFunction) declaration; + Set functionDescriptors = outerScope.getFunctions(jetFunction.getNameAsSafeName()); + descriptors.addAll(functionDescriptors); + } + else if (declaration instanceof JetProperty) { + JetProperty jetProperty = (JetProperty) declaration; + Set functionDescriptors = outerScope.getProperties(jetProperty.getNameAsSafeName()); + descriptors.addAll(functionDescriptors); + } + else if (declaration instanceof JetObjectDeclaration) { + JetObjectDeclaration jetObjectDeclaration = (JetObjectDeclaration) declaration; + descriptors.addAll(outerScope.getProperties(jetObjectDeclaration.getNameAsSafeName())); + descriptors.add(outerScope.getObjectDescriptor(jetObjectDeclaration.getNameAsSafeName())); + } + } + }); + } + return descriptors; + } + + @NotNull + public BindingContext getBindingContext() { + return trace.getBindingContext(); + } + + @NotNull + /*package*/ BindingTrace getTrace() { + return trace; + } + + @NotNull + public DeclarationProviderFactory getDeclarationProviderFactory() { + return declarationProviderFactory; + } + + @NotNull + public JetScope getResolutionScope(PsiElement element) { + PsiElement parent = element.getParent(); + if (parent instanceof JetFile) { + JetFile file = (JetFile) parent; + return getScopeProvider().getFileScopeForDeclarationResolution(file); + } + + if (parent instanceof JetClassBody) { + JetClassBody classBody = (JetClassBody) parent; + JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classBody, JetClassOrObject.class); + ClassDescriptor classDescriptor = getClassDescriptor(classOrObject); + assert classDescriptor instanceof LazyClassDescriptor : "Trying to resolve a member of a non-lazily loaded class: " + element; + return ((LazyClassDescriptor) classDescriptor).getScopeForMemberDeclarationResolution(); + } + + throw new IllegalArgumentException("Unsupported PSI element: " + element); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ScopeProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ScopeProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..778beca49b78f7a59cd97cb5857707b25779a4fb --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ScopeProvider.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2012 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.lazy; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamespaceHeader; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.*; + +/** +* @author abreslav +*/ +public class ScopeProvider { + + private final ResolveSession resolveSession; + + public ScopeProvider(@NotNull ResolveSession resolveSession) { + this.resolveSession = resolveSession; + } + + // This scope does not contain imported functions + @NotNull + public JetScope getFileScopeForDeclarationResolution(JetFile file) { + // package + // + imported classes + JetNamespaceHeader header = file.getNamespaceHeader(); + if (header == null) { + throw new IllegalArgumentException("Scripts are not supported: " + file.getName()); + } + + FqName fqName = new FqName(header.getQualifiedName()); + NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(fqName); + + if (packageDescriptor == null) { + throw new IllegalStateException("Package not found: " + fqName + " maybe the file is not in scope of this resolve session: " + file.getName()); + } + + WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, packageDescriptor, RedeclarationHandler.DO_NOTHING); + writableScope.importScope(packageDescriptor.getMemberScope()); + + writableScope.changeLockLevel(WritableScope.LockLevel.READING); + // TODO: Cache + return writableScope; + } + + @NotNull + public JetScope getScopeForClassMemberResolution(@NotNull JetClassOrObject classOrObject) { + // TODO: cache + ClassDescriptor classDescriptor = resolveSession.getClassDescriptor(classOrObject); + JetScope memberScope = classDescriptor.getDefaultType().getMemberScope(); + JetScope outerScope = getResolutionScopeForDeclaration((JetDeclaration) classOrObject); + + WritableScope typeParametersScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.DO_NOTHING); + for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) { + typeParametersScope.addClassifierDescriptor(typeParameterDescriptor); + } + + return new ChainedScope(classDescriptor, memberScope, typeParametersScope, outerScope); + } + + public JetScope getScopeForClassSupertypeResolution(JetClassOrObject declaration) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + public JetScope getResolutionScopeForDeclaration(@NotNull JetDeclaration jetDeclaration) { + PsiElement immediateParent = jetDeclaration.getParent(); + if (immediateParent instanceof JetFile) { + return getFileScopeForDeclarationResolution((JetFile) immediateParent); + } + + JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(jetDeclaration, JetDeclaration.class); + if (parentDeclaration instanceof JetClassOrObject) { + JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration; + return getScopeForClassMemberResolution(classOrObject); + } + else { + throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration); + } + } + + public ClassDescriptor buildLazyClassDescriptor(DeclarationDescriptor declaration, Name name, JetScope outerScope) { + throw new UnsupportedOperationException(); // TODO + } + + public NamespaceDescriptor buildLazyPackageDescriptor(DeclarationDescriptor declaration, + Name name) { + throw new UnsupportedOperationException(); // TODO + } +} diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/BasicLazyResolveTest.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/BasicLazyResolveTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f50271456c3df552e62a2cb8fe6f303a76f74b1d --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/BasicLazyResolveTest.java @@ -0,0 +1,232 @@ +package org.jetbrains.jet.lang.resolve.lazy;/* + * Copyright 2010-2012 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. + */ + +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.CompileCompilerDependenciesTest; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.junit.After; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +/** + * @author abreslav + */ +public class BasicLazyResolveTest { + + private static final Name FOO = Name.identifier("foo"); + + private final Disposable rootDisposable = new Disposable() { + @Override + public void dispose() { + } + }; + + @After + public void tearDown() throws Exception { + Disposer.dispose(rootDisposable); + } + + @Test + public void test() { + JetCoreEnvironment jetCoreEnvironment = + new JetCoreEnvironment(rootDisposable, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true)); + + ModuleDescriptor root = new ModuleDescriptor(Name.special("")); + + Project project = jetCoreEnvironment.getProject(); + final JetClass jetClass = JetPsiFactory.createClass(project, "package p; class C {fun f() {}}"); + final JetClass genericJetClass = JetPsiFactory.createClass(project, "package p; open class G {fun f(): T {}}"); + final JetClass genericJetClass2 = JetPsiFactory.createClass(project, "package p; class G2 : G {}"); + final JetNamedFunction fooFunction1 = JetPsiFactory.createFunction(project, "package p; fun foo() {}"); + final JetNamedFunction fooFunction2 = JetPsiFactory.createFunction(project, "package p; fun foo(a: C) {}"); + + ResolveSession session = new ResolveSession(project, root, new DeclarationProviderFactory() { + @Override + public DeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName) { + if (packageFqName.equals(FqName.ROOT)) { + return new DeclarationProvider() { + @Override + public List getAllDeclarations() { + return Collections.emptyList(); + } + + @NotNull + @Override + public List getFunctionDeclarations(@NotNull Name name) { + return Collections.emptyList(); + } + + @NotNull + @Override + public List getPropertyDeclarations(@NotNull Name name) { + return Collections.emptyList(); + } + + @Override + public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { + return null; + } + + @Override + public boolean isPackageDeclared(@NotNull Name name) { + return name.equals(Name.identifier("p")); + } + }; + } + if (!packageFqName.equals(FqName.topLevel(Name.identifier("p")))) return null; + return new DeclarationProvider() { + @Override + public List getAllDeclarations() { + return Arrays.asList(jetClass, genericJetClass, genericJetClass2, fooFunction1, fooFunction2); + } + + @NotNull + @Override + public List getFunctionDeclarations(@NotNull Name name) { + if (!FOO.equals(name)) return Collections.emptyList(); + return Arrays.asList(fooFunction1, fooFunction2); + } + + @NotNull + @Override + public List getPropertyDeclarations(@NotNull Name name) { + return Collections.emptyList(); + } + + @Override + public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { + if (name.equals(Name.identifier("C"))) return jetClass; + if (name.equals(Name.identifier("G"))) return genericJetClass; + if (name.equals(Name.identifier("G2"))) return genericJetClass2; + return null; + } + + @Override + public boolean isPackageDeclared(@NotNull Name name) { + return false; + } + }; + } + + @NotNull + @Override + public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassOrObject jetClassOrObject) { + final JetClass jetClass = (JetClass) jetClassOrObject; + return new ClassMemberDeclarationProvider() { + @NotNull + @Override + public JetClassOrObject getOwnerClassOrObject() { + return jetClass; + } + + @Override + public List getAllDeclarations() { + return jetClass.getDeclarations(); + } + + private List filter(List list, Class t) { + //noinspection unchecked + return (List) Lists.newArrayList(Collections2.filter(list, Predicates.instanceOf(t))); + } + + @NotNull + @Override + public List getFunctionDeclarations(@NotNull Name name) { + return filter(jetClass.getDeclarations(), JetNamedFunction.class); + } + + @NotNull + @Override + public List getPropertyDeclarations(@NotNull Name name) { + return filter(jetClass.getDeclarations(), JetProperty.class); + } + + @Override + public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { + return null; + } + + @Override + public boolean isPackageDeclared(@NotNull Name name) { + return false; + } + }; + } + }); + + NamespaceDescriptor packageDescriptor = session.getPackageDescriptor(Name.identifier("p")); + assertNotNull(packageDescriptor); + assertEquals(Name.identifier("p"), packageDescriptor.getName()); + assertNull(packageDescriptor.getMemberScope().getNamespace(FOO)); + + ClassifierDescriptor classifier = packageDescriptor.getMemberScope().getClassifier(Name.identifier("C")); + assertTrue(ClassDescriptor.class.isInstance(classifier)); + ClassDescriptor classDescriptor = (ClassDescriptor) classifier; + assertNotNull(classifier); + assertEquals(classifier.getContainingDeclaration(), packageDescriptor); + assertEquals(Name.identifier("C"), classifier.getName()); + assertEquals(Visibilities.INTERNAL, classDescriptor.getVisibility()); + TypeConstructor typeConstructor = classifier.getTypeConstructor(); + assertTrue(typeConstructor.isSealed()); + assertTrue(typeConstructor.getParameters().isEmpty()); + assertEquals("[Any]", typeConstructor.getSupertypes().toString()); + + List fooFunctions = Lists.newArrayList(packageDescriptor.getMemberScope().getFunctions(FOO)); + assertEquals(2, fooFunctions.size()); + FunctionDescriptor foo1 = fooFunctions.get(0); + assertEquals(FOO, foo1.getName()); + assertEquals(0, foo1.getValueParameters().size()); + assertEquals(packageDescriptor, foo1.getContainingDeclaration()); + + FunctionDescriptor foo2 = fooFunctions.get(1); + assertEquals(FOO, foo2.getName()); + assertEquals(1, foo2.getValueParameters().size()); + assertEquals(classDescriptor, foo2.getValueParameters().get(0).getType().getConstructor().getDeclarationDescriptor()); + assertEquals(packageDescriptor, foo2.getContainingDeclaration()); + + ClassifierDescriptor genericClassifier2 = packageDescriptor.getMemberScope().getClassifier(Name.identifier("G2")); + assertNotNull(genericClassifier2); + assertEquals(1, genericClassifier2.getTypeConstructor().getSupertypes().size()); + assertEquals("G", genericClassifier2.getTypeConstructor().getSupertypes().iterator().next().toString()); + + ClassifierDescriptor genericClassifier = packageDescriptor.getMemberScope().getClassifier(Name.identifier("G")); + assertNotNull(genericClassifier); + assertEquals(1, genericClassifier.getTypeConstructor().getParameters().size()); + TypeParameterDescriptor typeParameterDescriptor_T = genericClassifier.getTypeConstructor().getParameters().get(0); + assertEquals(JetStandardClasses.getNullableAnyType(), + typeParameterDescriptor_T.getUpperBoundsAsType()); + assertEquals("G", genericClassifier.getDefaultType().toString()); + assertEquals(typeParameterDescriptor_T.getDefaultType(), genericClassifier.getDefaultType().getMemberScope().getFunctions(Name.identifier("f")).iterator().next().getReturnType()); + } +} \ No newline at end of file diff --git a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java index 9e0b9e3426c47853332b3b07381e506a48a9e1ff..bfc0a601f44d7d95fd6151b92244d76327b0d2ed 100644 --- a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java @@ -17,13 +17,7 @@ package org.jetbrains.jet.di; import com.intellij.openapi.project.Project; -import org.jetbrains.jet.codegen.ClassBuilderFactory; -import org.jetbrains.jet.codegen.ClassBuilderMode; -import org.jetbrains.jet.codegen.ClassCodegen; -import org.jetbrains.jet.codegen.ClassFileFactory; -import org.jetbrains.jet.codegen.GenerationState; -import org.jetbrains.jet.codegen.JetTypeMapper; -import org.jetbrains.jet.codegen.ScriptCodegen; +import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; @@ -31,7 +25,6 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.java.*; -import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolverDummyImpl; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; @@ -54,6 +47,16 @@ public class AllInjectorsGenerator { generateInjectorForJavaSemanticServices(); generateInjectorForJvmCodegen(); generateInjectorForJetTypeMapper(); + generateInjectorForLazyResolve(); + } + + private static void generateInjectorForLazyResolve() throws IOException { + DependencyInjectorGenerator generator = new DependencyInjectorGenerator(false); + generator.addParameter(Project.class); + generator.addPublicField(DescriptorResolver.class); + generator.addPublicField(ExpressionTypingServices.class); + generator.addPublicField(TypeResolver.class); + generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForLazyResolve"); } private static void generateInjectorForTopDownAnalyzerBasic() throws IOException {