Extract ConstructorResolver class from JavaDescriptorResolver
This commit is contained in:
+10
-131
@@ -42,6 +42,7 @@ import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSign
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ClassResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ConstructorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.PropertiesResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
|
||||
@@ -69,7 +70,8 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorResolver.*;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValueOfMethod;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValuesMethod;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
|
||||
|
||||
/**
|
||||
@@ -125,6 +127,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver;
|
||||
private PropertiesResolver propertiesResolver = new PropertiesResolver(this);
|
||||
private final ClassResolver classResolver = new ClassResolver(this);
|
||||
private final ConstructorResolver constructorResolver = new ConstructorResolver(this);
|
||||
|
||||
@Inject
|
||||
public void setProject(Project project) {
|
||||
@@ -196,142 +199,16 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
|
||||
@NotNull
|
||||
public Collection<ConstructorDescriptor> resolveConstructors(@NotNull ResolverClassData classData) {
|
||||
Collection<ConstructorDescriptor> constructors = Lists.newArrayList();
|
||||
|
||||
PsiClass psiClass = classData.getPsiClass();
|
||||
|
||||
ClassDescriptorFromJvmBytecode containingClass = classData.getClassDescriptor();
|
||||
assert psiClass != null;
|
||||
TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver(
|
||||
containingClass, "class " + psiClass.getQualifiedName());
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = containingClass.getTypeConstructor().getParameters();
|
||||
|
||||
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
||||
|
||||
boolean isStatic = psiClass.hasModifierProperty(PsiModifier.STATIC);
|
||||
if (containingClass.getKind() == ClassKind.OBJECT || containingClass.getKind() == ClassKind.CLASS_OBJECT) {
|
||||
constructors.add(createPrimaryConstructorForObject(containingClass));
|
||||
}
|
||||
else if (psiConstructors.length == 0) {
|
||||
if (trace.get(BindingContext.CONSTRUCTOR, psiClass) != null) {
|
||||
constructors.add(trace.get(BindingContext.CONSTRUCTOR, psiClass));
|
||||
}
|
||||
else {
|
||||
// We need to create default constructors for classes and abstract classes.
|
||||
// Example:
|
||||
// class Kotlin() : Java() {}
|
||||
// abstract public class Java {}
|
||||
if (!psiClass.isInterface()) {
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
containingClass,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
constructorDescriptor.initialize(typeParameters, Collections.<ValueParameterDescriptor>emptyList(), containingClass
|
||||
.getVisibility(), isStatic);
|
||||
constructors.add(constructorDescriptor);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
if (psiClass.isAnnotationType()) {
|
||||
// A constructor for an annotation type takes all the "methods" in the @interface as parameters
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
containingClass,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||
PsiMethod[] methods = psiClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
PsiMethod method = methods[i];
|
||||
if (method instanceof PsiAnnotationMethod) {
|
||||
PsiAnnotationMethod annotationMethod = (PsiAnnotationMethod) method;
|
||||
assert annotationMethod.getParameterList().getParameters().length == 0;
|
||||
|
||||
PsiType returnType = annotationMethod.getReturnType();
|
||||
|
||||
// We take the following heuristical convention:
|
||||
// if the last method of the @interface is an array, we convert it into a vararg
|
||||
JetType varargElementType = null;
|
||||
if (i == methods.length - 1 && (returnType instanceof PsiArrayType)) {
|
||||
varargElementType = semanticServices.getTypeTransformer().transformToType(((PsiArrayType) returnType).getComponentType(), resolverForTypeParameters);
|
||||
}
|
||||
|
||||
assert returnType != null;
|
||||
valueParameters.add(new ValueParameterDescriptorImpl(
|
||||
constructorDescriptor,
|
||||
i,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Name.identifier(method.getName()),
|
||||
false,
|
||||
semanticServices.getTypeTransformer().transformToType(returnType, resolverForTypeParameters),
|
||||
annotationMethod.getDefaultValue() != null,
|
||||
varargElementType));
|
||||
}
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(typeParameters, valueParameters, containingClass.getVisibility(), isStatic);
|
||||
constructors.add(constructorDescriptor);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PsiMethod psiConstructor : psiConstructors) {
|
||||
ConstructorDescriptor constructor = resolveConstructor(psiClass, classData, isStatic, psiConstructor);
|
||||
if (constructor != null) {
|
||||
constructors.add(constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ConstructorDescriptor constructor : constructors) {
|
||||
((ConstructorDescriptorImpl) constructor).setReturnType(containingClass.getDefaultType());
|
||||
}
|
||||
|
||||
return constructors;
|
||||
return constructorResolver.resolveConstructors(classData);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ConstructorDescriptor resolveConstructor(PsiClass psiClass, ResolverClassData classData, boolean aStatic, PsiMethod psiConstructor) {
|
||||
PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor);
|
||||
|
||||
//noinspection deprecation
|
||||
if (constructor.getJetConstructor().hidden()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (trace.get(BindingContext.CONSTRUCTOR, psiConstructor) != null) {
|
||||
return trace.get(BindingContext.CONSTRUCTOR, psiConstructor);
|
||||
}
|
||||
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
classData.getClassDescriptor(),
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
false);
|
||||
|
||||
String context = "constructor of class " + psiClass.getQualifiedName();
|
||||
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(
|
||||
constructorDescriptor, constructor.getParameters(),
|
||||
TypeVariableResolvers.classTypeVariableResolver(classData.getClassDescriptor(), context));
|
||||
|
||||
if (valueParameterDescriptors.receiverType != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||
new AlternativeMethodSignatureData(constructor, valueParameterDescriptors, null, Collections.<TypeParameterDescriptor>emptyList());
|
||||
if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) {
|
||||
valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters();
|
||||
}
|
||||
else if (alternativeMethodSignatureData.hasErrors()) {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, constructorDescriptor, alternativeMethodSignatureData.getError());
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(classData.getClassDescriptor().getTypeConstructor().getParameters(),
|
||||
valueParameterDescriptors.descriptors,
|
||||
resolveVisibility(psiConstructor, constructor.getJetConstructor()), aStatic);
|
||||
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
||||
return constructorDescriptor;
|
||||
return constructorResolver.resolveConstructor(psiClass, classData, aStatic, psiConstructor);
|
||||
}
|
||||
|
||||
public static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||
@@ -945,8 +822,10 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
}
|
||||
}
|
||||
|
||||
private ValueParameterDescriptors resolveParameterDescriptors(DeclarationDescriptor containingDeclaration,
|
||||
List<PsiParameterWrapper> parameters, TypeVariableResolver typeVariableResolver) {
|
||||
public ValueParameterDescriptors resolveParameterDescriptors(
|
||||
DeclarationDescriptor containingDeclaration,
|
||||
List<PsiParameterWrapper> parameters, TypeVariableResolver typeVariableResolver
|
||||
) {
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
JetType receiverType = null;
|
||||
int indexDelta = 0;
|
||||
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.resolver;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
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.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolvers;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorResolver {
|
||||
private final JavaDescriptorResolver javaDescriptorResolver;
|
||||
|
||||
public ConstructorResolver(JavaDescriptorResolver javaDescriptorResolver) {
|
||||
this.javaDescriptorResolver = javaDescriptorResolver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<ConstructorDescriptor> resolveConstructors(@NotNull JavaDescriptorResolveData.ResolverClassData classData) {
|
||||
Collection<ConstructorDescriptor> constructors = Lists.newArrayList();
|
||||
|
||||
PsiClass psiClass = classData.getPsiClass();
|
||||
|
||||
ClassDescriptorFromJvmBytecode containingClass = classData.getClassDescriptor();
|
||||
assert psiClass != null;
|
||||
TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver(
|
||||
containingClass, "class " + psiClass.getQualifiedName());
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = containingClass.getTypeConstructor().getParameters();
|
||||
|
||||
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
||||
|
||||
boolean isStatic = psiClass.hasModifierProperty(PsiModifier.STATIC);
|
||||
if (containingClass.getKind() == ClassKind.OBJECT || containingClass.getKind() == ClassKind.CLASS_OBJECT) {
|
||||
constructors.add(DescriptorResolver.createPrimaryConstructorForObject(containingClass));
|
||||
}
|
||||
else if (psiConstructors.length == 0) {
|
||||
if (javaDescriptorResolver.getTrace().get(BindingContext.CONSTRUCTOR, psiClass) != null) {
|
||||
constructors.add(javaDescriptorResolver.getTrace().get(BindingContext.CONSTRUCTOR, psiClass));
|
||||
}
|
||||
else {
|
||||
// We need to create default constructors for classes and abstract classes.
|
||||
// Example:
|
||||
// class Kotlin() : Java() {}
|
||||
// abstract public class Java {}
|
||||
if (!psiClass.isInterface()) {
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
containingClass,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
constructorDescriptor.initialize(typeParameters, Collections.<ValueParameterDescriptor>emptyList(), containingClass
|
||||
.getVisibility(), isStatic);
|
||||
constructors.add(constructorDescriptor);
|
||||
javaDescriptorResolver.getTrace().record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
if (psiClass.isAnnotationType()) {
|
||||
// A constructor for an annotation type takes all the "methods" in the @interface as parameters
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
containingClass,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||
PsiMethod[] methods = psiClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
PsiMethod method = methods[i];
|
||||
if (method instanceof PsiAnnotationMethod) {
|
||||
PsiAnnotationMethod annotationMethod = (PsiAnnotationMethod) method;
|
||||
assert annotationMethod.getParameterList().getParameters().length == 0;
|
||||
|
||||
PsiType returnType = annotationMethod.getReturnType();
|
||||
|
||||
// We take the following heuristical convention:
|
||||
// if the last method of the @interface is an array, we convert it into a vararg
|
||||
JetType varargElementType = null;
|
||||
if (i == methods.length - 1 && (returnType instanceof PsiArrayType)) {
|
||||
varargElementType = javaDescriptorResolver.getSemanticServices().getTypeTransformer()
|
||||
.transformToType(((PsiArrayType) returnType).getComponentType(), resolverForTypeParameters);
|
||||
}
|
||||
|
||||
assert returnType != null;
|
||||
valueParameters.add(new ValueParameterDescriptorImpl(
|
||||
constructorDescriptor,
|
||||
i,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Name.identifier(method.getName()),
|
||||
false,
|
||||
javaDescriptorResolver.getSemanticServices().getTypeTransformer()
|
||||
.transformToType(returnType, resolverForTypeParameters),
|
||||
annotationMethod.getDefaultValue() != null,
|
||||
varargElementType));
|
||||
}
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(typeParameters, valueParameters, containingClass.getVisibility(), isStatic);
|
||||
constructors.add(constructorDescriptor);
|
||||
javaDescriptorResolver.getTrace().record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PsiMethod psiConstructor : psiConstructors) {
|
||||
ConstructorDescriptor constructor = resolveConstructor(psiClass, classData, isStatic, psiConstructor);
|
||||
if (constructor != null) {
|
||||
constructors.add(constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ConstructorDescriptor constructor : constructors) {
|
||||
((ConstructorDescriptorImpl) constructor).setReturnType(containingClass.getDefaultType());
|
||||
}
|
||||
|
||||
return constructors;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ConstructorDescriptor resolveConstructor(
|
||||
PsiClass psiClass,
|
||||
JavaDescriptorResolveData.ResolverClassData classData,
|
||||
boolean aStatic,
|
||||
PsiMethod psiConstructor
|
||||
) {
|
||||
PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor);
|
||||
|
||||
//noinspection deprecation
|
||||
if (constructor.getJetConstructor().hidden()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (javaDescriptorResolver.getTrace().get(BindingContext.CONSTRUCTOR, psiConstructor) != null) {
|
||||
return javaDescriptorResolver.getTrace().get(BindingContext.CONSTRUCTOR, psiConstructor);
|
||||
}
|
||||
|
||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||
classData.getClassDescriptor(),
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
false);
|
||||
|
||||
String context = "constructor of class " + psiClass.getQualifiedName();
|
||||
JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = javaDescriptorResolver.resolveParameterDescriptors(
|
||||
constructorDescriptor, constructor.getParameters(),
|
||||
TypeVariableResolvers.classTypeVariableResolver(classData.getClassDescriptor(), context));
|
||||
|
||||
if (valueParameterDescriptors.getReceiverType() != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||
new AlternativeMethodSignatureData(constructor, valueParameterDescriptors, null,
|
||||
Collections.<TypeParameterDescriptor>emptyList());
|
||||
if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) {
|
||||
valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters();
|
||||
}
|
||||
else if (alternativeMethodSignatureData.hasErrors()) {
|
||||
javaDescriptorResolver.getTrace().record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, constructorDescriptor,
|
||||
alternativeMethodSignatureData.getError());
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(classData.getClassDescriptor().getTypeConstructor().getParameters(),
|
||||
valueParameterDescriptors.getDescriptors(),
|
||||
JavaDescriptorResolver.resolveVisibility(psiConstructor, constructor.getJetConstructor()),
|
||||
aStatic);
|
||||
javaDescriptorResolver.getTrace().record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
||||
return constructorDescriptor;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user