JavaDescriptorResolver: resolve constructors lazily
This speeds up analyze a bit (profiler shown about 10% of time spent in constructor resolver during completion in KDoc).
This commit is contained in:
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.java;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.MutableClassDescriptorLite;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.LazyClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*
|
||||
* @see LazyClassDescriptor
|
||||
*/
|
||||
public class ClassDescriptorFromJvmBytecode extends MutableClassDescriptorLite {
|
||||
@NotNull
|
||||
private final JavaDescriptorResolver javaDescriptorResolver;
|
||||
@NotNull
|
||||
private final JavaDescriptorResolver.ResolverBinaryClassData resolverBinaryClassData;
|
||||
|
||||
|
||||
// lazy
|
||||
private Collection<ConstructorDescriptor> constructors;
|
||||
|
||||
public ClassDescriptorFromJvmBytecode(
|
||||
@NotNull DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind,
|
||||
@NotNull PsiClass psiClass, @NotNull FqName fqName,
|
||||
@NotNull JavaDescriptorResolver javaDescriptorResolver) {
|
||||
super(containingDeclaration, kind);
|
||||
this.javaDescriptorResolver = javaDescriptorResolver;
|
||||
this.resolverBinaryClassData = new JavaDescriptorResolver.ResolverBinaryClassData(psiClass, fqName, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaDescriptorResolver.ResolverBinaryClassData getResolverBinaryClassData() {
|
||||
return resolverBinaryClassData;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<ConstructorDescriptor> getConstructors() {
|
||||
if (constructors == null) {
|
||||
this.constructors = javaDescriptorResolver.resolveConstructors(resolverBinaryClassData);
|
||||
}
|
||||
return constructors;
|
||||
}
|
||||
}
|
||||
+49
-31
@@ -183,9 +183,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
/** Class with instance members */
|
||||
static class ResolverBinaryClassData extends ResolverScopeData {
|
||||
private final MutableClassDescriptorLite classDescriptor;
|
||||
private final ClassDescriptorFromJvmBytecode classDescriptor;
|
||||
|
||||
ResolverBinaryClassData(@NotNull PsiClass psiClass, @NotNull FqName fqName, @NotNull MutableClassDescriptorLite classDescriptor) {
|
||||
ResolverBinaryClassData(@NotNull PsiClass psiClass, @NotNull FqName fqName, @NotNull ClassDescriptorFromJvmBytecode classDescriptor) {
|
||||
super(psiClass, null, fqName, false, classDescriptor);
|
||||
this.classDescriptor = classDescriptor;
|
||||
}
|
||||
@@ -360,7 +360,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
return classData;
|
||||
}
|
||||
|
||||
classData = new ResolverBinaryClassData(psiClass, fqName, new MutableClassDescriptorLite(containingDeclaration, kind));
|
||||
classData = new ClassDescriptorFromJvmBytecode(
|
||||
containingDeclaration, kind, psiClass, fqName, this)
|
||||
.getResolverBinaryClassData();
|
||||
classDescriptorCache.put(fqName, classData);
|
||||
classData.classDescriptor.setName(name);
|
||||
classData.classDescriptor.setAnnotations(resolveAnnotations(psiClass, taskList));
|
||||
@@ -392,17 +394,40 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
initializeTypeParameters(classData.typeParameters, classData.classDescriptor, "class " + psiClass.getQualifiedName());
|
||||
|
||||
TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver(
|
||||
classData.classDescriptor,
|
||||
"class " + psiClass.getQualifiedName());
|
||||
|
||||
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
|
||||
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classData.getTypeParameters()));
|
||||
|
||||
MutableClassDescriptorLite classObject = createClassObjectDescriptor(classData.classDescriptor, psiClass);
|
||||
if (classObject != null) {
|
||||
classData.classDescriptor.getBuilder().setClassObjectDescriptor(classObject);
|
||||
}
|
||||
|
||||
trace.record(BindingContext.CLASS, psiClass, classData.classDescriptor);
|
||||
|
||||
return classData;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<ConstructorDescriptor> resolveConstructors(@NotNull ResolverBinaryClassData classData) {
|
||||
Collection<ConstructorDescriptor> constructors = Lists.newArrayList();
|
||||
|
||||
PsiClass psiClass = classData.psiClass;
|
||||
|
||||
TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver(
|
||||
classData.classDescriptor, "class " + psiClass.getQualifiedName());
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = classData.classDescriptor.getTypeConstructor().getParameters();
|
||||
|
||||
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
||||
|
||||
boolean isStatic = psiClass.hasModifierProperty(PsiModifier.STATIC);
|
||||
if (psiConstructors.length == 0) {
|
||||
if (classData.classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||
// TODO: wrong: class objects do not need visible constructors
|
||||
ConstructorDescriptorImpl constructor = new ConstructorDescriptorImpl(classData.classDescriptor, new ArrayList<AnnotationDescriptor>(0), true);
|
||||
constructor.initialize(new ArrayList<TypeParameterDescriptor>(0), new ArrayList<ValueParameterDescriptor>(0), Visibilities.PUBLIC);
|
||||
constructors.add(constructor);
|
||||
}
|
||||
else if (psiConstructors.length == 0) {
|
||||
// We need to create default constructors for classes and abstract classes.
|
||||
// Example:
|
||||
// class Kotlin() : Java() {}
|
||||
@@ -413,8 +438,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
constructorDescriptor.initialize(typeParameters, Collections.<ValueParameterDescriptor>emptyList(), classData.classDescriptor.getVisibility(), isStatic);
|
||||
constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType());
|
||||
classData.classDescriptor.addConstructor(constructorDescriptor, null);
|
||||
constructors.add(constructorDescriptor);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
if (psiClass.isAnnotationType()) {
|
||||
@@ -454,32 +478,32 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(typeParameters, valueParameters, classData.classDescriptor.getVisibility(), isStatic);
|
||||
constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType());
|
||||
classData.classDescriptor.addConstructor(constructorDescriptor, null);
|
||||
constructors.add(constructorDescriptor);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PsiMethod psiConstructor : psiConstructors) {
|
||||
resolveConstructor(psiClass, classData, isStatic, psiConstructor);
|
||||
ConstructorDescriptor constructor = resolveConstructor(psiClass, classData, isStatic, psiConstructor);
|
||||
if (constructor != null) {
|
||||
constructors.add(constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MutableClassDescriptorLite classObject = createClassObjectDescriptor(classData.classDescriptor, psiClass);
|
||||
if (classObject != null) {
|
||||
classData.classDescriptor.getBuilder().setClassObjectDescriptor(classObject);
|
||||
for (ConstructorDescriptor constructor : constructors) {
|
||||
((ConstructorDescriptorImpl) constructor).setReturnType(classData.classDescriptor.getDefaultType());
|
||||
}
|
||||
|
||||
trace.record(BindingContext.CLASS, psiClass, classData.classDescriptor);
|
||||
|
||||
return classData;
|
||||
return constructors;
|
||||
}
|
||||
|
||||
private void resolveConstructor(PsiClass psiClass, ResolverBinaryClassData classData, boolean aStatic, PsiMethod psiConstructor) {
|
||||
@Nullable
|
||||
private ConstructorDescriptor resolveConstructor(PsiClass psiClass, ResolverBinaryClassData classData, boolean aStatic, PsiMethod psiConstructor) {
|
||||
PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor);
|
||||
|
||||
if (constructor.getJetConstructor().hidden()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
@@ -496,9 +520,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
constructorDescriptor.initialize(classData.classDescriptor.getTypeConstructor().getParameters(),
|
||||
valueParameterDescriptors.descriptors,
|
||||
resolveVisibilityFromPsiModifiers(psiConstructor), aStatic);
|
||||
constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType());
|
||||
classData.classDescriptor.addConstructor(constructorDescriptor, null);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
||||
return constructorDescriptor;
|
||||
}
|
||||
|
||||
static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||
@@ -531,8 +554,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
checkPsiClassIsNotJet(psiClass);
|
||||
|
||||
FqName fqName = new FqName(classObjectPsiClass.getQualifiedName());
|
||||
ResolverBinaryClassData classData = new ResolverBinaryClassData(classObjectPsiClass, fqName,
|
||||
new MutableClassDescriptorLite(containing, ClassKind.OBJECT));
|
||||
ResolverBinaryClassData classData = new ClassDescriptorFromJvmBytecode(
|
||||
containing, ClassKind.OBJECT, classObjectPsiClass, fqName, this)
|
||||
.getResolverBinaryClassData();
|
||||
|
||||
classDescriptorCache.put(fqName, classData);
|
||||
|
||||
@@ -544,12 +568,6 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
classData.classDescriptor.createTypeConstructor();
|
||||
classData.classDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(semanticServices, classData));
|
||||
|
||||
// TODO: wrong: class objects do not need visible constructors
|
||||
ConstructorDescriptorImpl constructor = new ConstructorDescriptorImpl(classData.classDescriptor, new ArrayList<AnnotationDescriptor>(0), true);
|
||||
constructor.setReturnType(classData.classDescriptor.getDefaultType());
|
||||
constructor.initialize(new ArrayList<TypeParameterDescriptor>(0), new ArrayList<ValueParameterDescriptor>(0), Visibilities.PUBLIC);
|
||||
|
||||
classData.classDescriptor.addConstructor(constructor, null);
|
||||
return classData.classDescriptor;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user