Fields alternative signature processing with refactoring of AlternativeSignatureData
Refactoring details: - Move and rename AlternativeSignatureData to kotlinSignature.AlternativeMethodSignatureData - Extract TypeTransforming visitor - Extract AlternativeSignatureMistmatchException - Move errors, return type, and syntax processing to base class
This commit is contained in:
+16
-1
@@ -27,8 +27,10 @@ import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverScopeData;
|
||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeFieldSignatureData;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiFieldWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -114,7 +116,6 @@ public final class JavaDescriptorPropertiesResolver {
|
||||
}
|
||||
|
||||
DeclarationDescriptor realOwner = getRealOwner(owner, scopeData, characteristicMember.getMember().isStatic());
|
||||
|
||||
boolean isEnumEntry = DescriptorUtils.isEnumClassObject(realOwner);
|
||||
boolean isPropertyForNamedObject = members.field != null && JvmAbi.INSTANCE_FIELD.equals(members.field.getMember().getName());
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||
@@ -182,6 +183,20 @@ public final class JavaDescriptorPropertiesResolver {
|
||||
JetType propertyType = getPropertyType(members, characteristicMember, typeVariableResolverForPropertyInternals);
|
||||
JetType receiverType = getReceiverType(characteristicMember, typeVariableResolverForPropertyInternals);
|
||||
|
||||
|
||||
if (characteristicMember.isField()) {
|
||||
AlternativeFieldSignatureData signatureData =
|
||||
new AlternativeFieldSignatureData((PsiFieldWrapper) characteristicMember.getMember(), propertyType);
|
||||
if (!signatureData.hasErrors()) {
|
||||
if (signatureData.isAnnotated()) {
|
||||
propertyType = signatureData.getReturnType();
|
||||
}
|
||||
}
|
||||
else {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, propertyDescriptor, signatureData.getError());
|
||||
}
|
||||
}
|
||||
|
||||
propertyDescriptor.setType(
|
||||
propertyType,
|
||||
typeParameters,
|
||||
|
||||
+27
-16
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags;
|
||||
@@ -428,13 +429,13 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
AlternativeSignatureData alternativeSignatureData =
|
||||
new AlternativeSignatureData(constructor, valueParameterDescriptors, null, Collections.<TypeParameterDescriptor>emptyList());
|
||||
if (!alternativeSignatureData.isNone() && alternativeSignatureData.getError() == null) {
|
||||
valueParameterDescriptors = alternativeSignatureData.getValueParameters();
|
||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||
new AlternativeMethodSignatureData(constructor, valueParameterDescriptors, null, Collections.<TypeParameterDescriptor>emptyList());
|
||||
if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) {
|
||||
valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters();
|
||||
}
|
||||
else if (alternativeSignatureData.getError() != null) {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, constructorDescriptor, alternativeSignatureData.getError());
|
||||
else if (alternativeMethodSignatureData.hasErrors()) {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, constructorDescriptor, alternativeMethodSignatureData.getError());
|
||||
}
|
||||
|
||||
constructorDescriptor.initialize(classData.getClassDescriptor().getTypeConstructor().getParameters(),
|
||||
@@ -808,14 +809,24 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
return psiClassFinder.findPsiClass(packageFQN.child(Name.identifier(JvmAbi.PACKAGE_CLASS)), PsiClassFinder.RuntimeClassesHandleMode.IGNORE);
|
||||
}
|
||||
|
||||
static class ValueParameterDescriptors {
|
||||
public static class ValueParameterDescriptors {
|
||||
final JetType receiverType;
|
||||
final List<ValueParameterDescriptor> descriptors;
|
||||
|
||||
ValueParameterDescriptors(@Nullable JetType receiverType, List<ValueParameterDescriptor> descriptors) {
|
||||
public ValueParameterDescriptors(@Nullable JetType receiverType, @NotNull List<ValueParameterDescriptor> descriptors) {
|
||||
this.receiverType = receiverType;
|
||||
this.descriptors = descriptors;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType getReceiverType() {
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ValueParameterDescriptor> getDescriptors() {
|
||||
return descriptors;
|
||||
}
|
||||
}
|
||||
|
||||
private enum JvmMethodParameterKind {
|
||||
@@ -1120,15 +1131,15 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
|
||||
JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver);
|
||||
|
||||
// TODO consider better place for this check
|
||||
AlternativeSignatureData alternativeSignatureData =
|
||||
new AlternativeSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters);
|
||||
if (!alternativeSignatureData.isNone() && alternativeSignatureData.getError() == null) {
|
||||
valueParameterDescriptors = alternativeSignatureData.getValueParameters();
|
||||
returnType = alternativeSignatureData.getReturnType();
|
||||
methodTypeParameters = alternativeSignatureData.getTypeParameters();
|
||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||
new AlternativeMethodSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters);
|
||||
if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) {
|
||||
valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters();
|
||||
returnType = alternativeMethodSignatureData.getReturnType();
|
||||
methodTypeParameters = alternativeMethodSignatureData.getTypeParameters();
|
||||
}
|
||||
else if (alternativeSignatureData.getError() != null) {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, functionDescriptorImpl, alternativeSignatureData.getError());
|
||||
else if (alternativeMethodSignatureData.hasErrors()) {
|
||||
trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, functionDescriptorImpl, alternativeMethodSignatureData.getError());
|
||||
}
|
||||
|
||||
functionDescriptorImpl.initialize(
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.kotlinSignature;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiFieldWrapper;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class AlternativeFieldSignatureData extends ElementAlternativeSignatureData {
|
||||
private final PsiFieldWrapper field;
|
||||
|
||||
private JetType altReturnType;
|
||||
|
||||
public AlternativeFieldSignatureData(@NotNull PsiFieldWrapper field, @NotNull JetType originalReturnType) {
|
||||
String signature = field.getSignatureAnnotation().signature();
|
||||
JetProperty altPropertyDeclaration;
|
||||
if (signature.isEmpty()) {
|
||||
setAnnotated(false);
|
||||
this.field = null;
|
||||
return;
|
||||
}
|
||||
|
||||
setAnnotated(true);
|
||||
this.field = field;
|
||||
Project project = field.getPsiMember().getProject();
|
||||
altPropertyDeclaration = JetPsiFactory.createProperty(project, signature);
|
||||
|
||||
try {
|
||||
checkForSyntaxErrors(altPropertyDeclaration);
|
||||
altReturnType = computeReturnType(originalReturnType, altPropertyDeclaration.getTypeRef(),
|
||||
new HashMap<TypeParameterDescriptor, TypeParameterDescriptorImpl>());
|
||||
}
|
||||
catch (AlternativeSignatureMismatchException e) {
|
||||
setError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType getReturnType() {
|
||||
checkForErrors();
|
||||
return altReturnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return field.getPsiField().getText();
|
||||
}
|
||||
}
|
||||
+109
-275
@@ -14,43 +14,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
package org.jetbrains.jet.lang.resolve.java.kotlinSignature;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ComparatorUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Evgeny Gerashchenko
|
||||
* @since 6/5/12
|
||||
*/
|
||||
class AlternativeSignatureData {
|
||||
public class AlternativeMethodSignatureData extends ElementAlternativeSignatureData {
|
||||
private final JetNamedFunction altFunDeclaration;
|
||||
private final PsiMethodWrapper method;
|
||||
|
||||
private final boolean none;
|
||||
private String error;
|
||||
|
||||
private JavaDescriptorResolver.ValueParameterDescriptors altValueParameters;
|
||||
private JetType altReturnType;
|
||||
private List<TypeParameterDescriptor> altTypeParameters;
|
||||
@@ -58,56 +56,49 @@ class AlternativeSignatureData {
|
||||
private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters =
|
||||
new HashMap<TypeParameterDescriptor, TypeParameterDescriptorImpl>();
|
||||
|
||||
AlternativeSignatureData(
|
||||
public AlternativeMethodSignatureData(
|
||||
@NotNull PsiMethodWrapper method,
|
||||
@NotNull JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors,
|
||||
@Nullable JetType returnType,
|
||||
@NotNull List<TypeParameterDescriptor> methodTypeParameters) {
|
||||
@Nullable JetType originalReturnType,
|
||||
@NotNull List<TypeParameterDescriptor> methodTypeParameters
|
||||
) {
|
||||
String signature = method.getSignatureAnnotation().signature();
|
||||
if (signature.isEmpty()) {
|
||||
none = true;
|
||||
setAnnotated(false);
|
||||
altFunDeclaration = null;
|
||||
this.method = null;
|
||||
return;
|
||||
}
|
||||
|
||||
none = false;
|
||||
setAnnotated(true);
|
||||
this.method = method;
|
||||
Project project = method.getPsiMethod().getProject();
|
||||
altFunDeclaration = JetPsiFactory.createFunction(project, signature);
|
||||
|
||||
for (TypeParameterDescriptor tp : methodTypeParameters) {
|
||||
originalToAltTypeParameters.put(tp, TypeParameterDescriptorImpl
|
||||
.createForFurtherModification(tp.getContainingDeclaration(), tp.getAnnotations(),
|
||||
tp.isReified(), tp.getVariance(), tp.getName(), tp.getIndex()));
|
||||
for (TypeParameterDescriptor typeParameter : methodTypeParameters) {
|
||||
originalToAltTypeParameters.put(typeParameter,
|
||||
TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
typeParameter.getContainingDeclaration(),
|
||||
typeParameter.getAnnotations(),
|
||||
typeParameter.isReified(),
|
||||
typeParameter.getVariance(),
|
||||
typeParameter.getName(),
|
||||
typeParameter.getIndex()));
|
||||
}
|
||||
|
||||
try {
|
||||
checkForSyntaxErrors();
|
||||
checkForSyntaxErrors(altFunDeclaration);
|
||||
checkEqualFunctionNames(altFunDeclaration, method);
|
||||
|
||||
computeTypeParameters(methodTypeParameters);
|
||||
computeValueParameters(valueParameterDescriptors);
|
||||
if (returnType != null) {
|
||||
computeReturnType(returnType);
|
||||
|
||||
if (originalReturnType != null) {
|
||||
altReturnType = computeReturnType(originalReturnType, altFunDeclaration.getReturnTypeRef(), originalToAltTypeParameters);
|
||||
}
|
||||
}
|
||||
catch (AlternativeSignatureMismatchException e) {
|
||||
error = e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNone() {
|
||||
return none;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
private void checkForErrors() {
|
||||
if (none || error != null) {
|
||||
throw new IllegalStateException("Trying to read result while there is none");
|
||||
setError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,86 +120,85 @@ class AlternativeSignatureData {
|
||||
return altTypeParameters;
|
||||
}
|
||||
|
||||
private JetType computeType(JetTypeElement alternativeTypeElement, JetType autoType) {
|
||||
//noinspection NullableProblems
|
||||
return alternativeTypeElement.accept(new TypeTransformingVisitor(autoType), null);
|
||||
}
|
||||
|
||||
private void computeReturnType(@NotNull JetType autoType) {
|
||||
JetTypeReference altReturnTypeRef = altFunDeclaration.getReturnTypeRef();
|
||||
if (altReturnTypeRef == null) {
|
||||
if (JetStandardClasses.isUnit(autoType)) {
|
||||
altReturnType = autoType;
|
||||
}
|
||||
else {
|
||||
fail("Return type in alternative signature is missing, while in real signature it is '%s'",
|
||||
DescriptorRenderer.TEXT.renderType(autoType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
altReturnType = computeType(altReturnTypeRef.getTypeElement(), autoType);
|
||||
}
|
||||
}
|
||||
|
||||
private void computeValueParameters(JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors) {
|
||||
List<ValueParameterDescriptor> parameterDescriptors = valueParameterDescriptors.descriptors;
|
||||
List<ValueParameterDescriptor> parameterDescriptors = valueParameterDescriptors.getDescriptors();
|
||||
|
||||
if (parameterDescriptors.size() != altFunDeclaration.getValueParameters().size()) {
|
||||
fail("Method signature has %d value parameters, but alternative signature has %d",
|
||||
parameterDescriptors.size(), altFunDeclaration.getValueParameters().size());
|
||||
throw new AlternativeSignatureMismatchException("Method signature has %d value parameters, but alternative signature has %d",
|
||||
parameterDescriptors.size(), altFunDeclaration.getValueParameters().size());
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> altParamDescriptors = new ArrayList<ValueParameterDescriptor>();
|
||||
for (int i = 0, size = parameterDescriptors.size(); i < size; i++) {
|
||||
ValueParameterDescriptor pd = parameterDescriptors.get(i);
|
||||
JetParameter valueParameter = altFunDeclaration.getValueParameters().get(i);
|
||||
ValueParameterDescriptor originalParameterDescriptor = parameterDescriptors.get(i);
|
||||
JetParameter annotationValueParameter = altFunDeclaration.getValueParameters().get(i);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetTypeElement alternativeTypeElement = valueParameter.getTypeReference().getTypeElement();
|
||||
JetTypeElement alternativeTypeElement = annotationValueParameter.getTypeReference().getTypeElement();
|
||||
assert alternativeTypeElement != null;
|
||||
|
||||
JetType alternativeType;
|
||||
JetType alternativeVarargElementType;
|
||||
if (pd.getVarargElementType() == null) {
|
||||
if (valueParameter.isVarArg()) {
|
||||
fail("Parameter in method signature is not vararg, but in alternative signature it is vararg");
|
||||
|
||||
JetType originalParamVarargElementType = originalParameterDescriptor.getVarargElementType();
|
||||
if (originalParamVarargElementType == null) {
|
||||
if (annotationValueParameter.isVarArg()) {
|
||||
throw new AlternativeSignatureMismatchException("Parameter in method signature is not vararg, but in alternative signature it is vararg");
|
||||
}
|
||||
alternativeType = computeType(alternativeTypeElement, pd.getType());
|
||||
|
||||
alternativeType = TypeTransformingVisitor.computeType(alternativeTypeElement, originalParameterDescriptor.getType(), originalToAltTypeParameters);
|
||||
alternativeVarargElementType = null;
|
||||
}
|
||||
else {
|
||||
if (!valueParameter.isVarArg()) {
|
||||
fail("Parameter in method signature is vararg, but in alternative signature it is not");
|
||||
if (!annotationValueParameter.isVarArg()) {
|
||||
throw new AlternativeSignatureMismatchException("Parameter in method signature is vararg, but in alternative signature it is not");
|
||||
}
|
||||
alternativeVarargElementType = computeType(alternativeTypeElement, pd.getVarargElementType());
|
||||
|
||||
alternativeVarargElementType = TypeTransformingVisitor.computeType(alternativeTypeElement, originalParamVarargElementType,
|
||||
originalToAltTypeParameters);
|
||||
alternativeType = JetStandardLibrary.getInstance().getArrayType(alternativeVarargElementType);
|
||||
}
|
||||
altParamDescriptors.add(new ValueParameterDescriptorImpl(pd.getContainingDeclaration(), pd.getIndex(), pd.getAnnotations(),
|
||||
pd.getName(), pd.isVar(), alternativeType, pd.declaresDefaultValue(),
|
||||
alternativeVarargElementType));
|
||||
|
||||
altParamDescriptors.add(new ValueParameterDescriptorImpl(
|
||||
originalParameterDescriptor.getContainingDeclaration(),
|
||||
originalParameterDescriptor.getIndex(),
|
||||
originalParameterDescriptor.getAnnotations(),
|
||||
originalParameterDescriptor.getName(),
|
||||
originalParameterDescriptor.isVar(),
|
||||
alternativeType,
|
||||
originalParameterDescriptor.declaresDefaultValue(),
|
||||
alternativeVarargElementType));
|
||||
}
|
||||
if (valueParameterDescriptors.receiverType != null) {
|
||||
|
||||
if (valueParameterDescriptors.getReceiverType() != null) {
|
||||
throw new UnsupportedOperationException("Alternative annotations for extension functions are not supported yet");
|
||||
}
|
||||
|
||||
altValueParameters = new JavaDescriptorResolver.ValueParameterDescriptors(null, altParamDescriptors);
|
||||
}
|
||||
|
||||
private void computeTypeParameters(List<TypeParameterDescriptor> typeParameters) {
|
||||
|
||||
if (typeParameters.size() != altFunDeclaration.getTypeParameters().size()) {
|
||||
fail("Method signature has %d type parameters, but alternative signature has %d",
|
||||
typeParameters.size(), altFunDeclaration.getTypeParameters().size());
|
||||
throw new AlternativeSignatureMismatchException("Method signature has %d type parameters, but alternative signature has %d",
|
||||
typeParameters.size(), altFunDeclaration.getTypeParameters().size());
|
||||
}
|
||||
|
||||
altTypeParameters = new ArrayList<TypeParameterDescriptor>();
|
||||
|
||||
for (int i = 0, size = typeParameters.size(); i < size; i++) {
|
||||
TypeParameterDescriptor pd = typeParameters.get(i);
|
||||
TypeParameterDescriptorImpl altParamDescriptor = originalToAltTypeParameters.get(pd);
|
||||
TypeParameterDescriptor originalTypeParamDescriptor = typeParameters.get(i);
|
||||
|
||||
TypeParameterDescriptorImpl altParamDescriptor = originalToAltTypeParameters.get(originalTypeParamDescriptor);
|
||||
JetTypeParameter altTypeParameter = altFunDeclaration.getTypeParameters().get(i);
|
||||
|
||||
int upperBoundIndex = 0;
|
||||
for (JetType upperBound : pd.getUpperBounds()) {
|
||||
for (JetType upperBound : originalTypeParamDescriptor.getUpperBounds()) {
|
||||
JetTypeElement altTypeElement;
|
||||
JetTypeParameter parameter = altFunDeclaration.getTypeParameters().get(i);
|
||||
|
||||
if (upperBoundIndex == 0) {
|
||||
JetTypeReference extendsBound = parameter.getExtendsBound();
|
||||
JetTypeReference extendsBound = altTypeParameter.getExtendsBound();
|
||||
if (extendsBound == null) { // default upper bound
|
||||
assert pd.getUpperBounds().size() == 1;
|
||||
assert originalTypeParamDescriptor.getUpperBounds().size() == 1;
|
||||
altParamDescriptor.addDefaultUpperBound();
|
||||
break;
|
||||
}
|
||||
@@ -218,18 +208,24 @@ class AlternativeSignatureData {
|
||||
}
|
||||
else {
|
||||
JetTypeConstraint constraint =
|
||||
findTypeParameterConstraint(altFunDeclaration, pd.getName(), upperBoundIndex);
|
||||
findTypeParameterConstraint(altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex);
|
||||
if (constraint == null) {
|
||||
fail("Upper bound #%d for type parameter %s is missing", upperBoundIndex, pd.getName());
|
||||
throw new AlternativeSignatureMismatchException("Upper bound #%d for type parameter %s is missing",
|
||||
upperBoundIndex, originalTypeParamDescriptor.getName());
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
altTypeElement = constraint.getBoundTypeReference().getTypeElement();
|
||||
}
|
||||
altParamDescriptor.addUpperBound(computeType(altTypeElement, upperBound));
|
||||
|
||||
assert (altTypeElement != null);
|
||||
|
||||
altParamDescriptor.addUpperBound(TypeTransformingVisitor.computeType(altTypeElement, upperBound,
|
||||
originalToAltTypeParameters));
|
||||
upperBoundIndex++;
|
||||
}
|
||||
if (findTypeParameterConstraint(altFunDeclaration, pd.getName(), upperBoundIndex) != null) {
|
||||
fail("Extra upper bound #%d for type parameter %s", upperBoundIndex, pd.getName());
|
||||
|
||||
if (findTypeParameterConstraint(altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex) != null) {
|
||||
throw new AlternativeSignatureMismatchException("Extra upper bound #%d for type parameter %s", upperBoundIndex, originalTypeParamDescriptor.getName());
|
||||
}
|
||||
|
||||
altParamDescriptor.setInitialized();
|
||||
@@ -237,9 +233,21 @@ class AlternativeSignatureData {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
String paramsString = StringUtil.join(method.getPsiMethod().getSignature(PsiSubstitutor.EMPTY).getParameterTypes(),
|
||||
new Function<PsiType, String>() {
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getPresentableText();
|
||||
}
|
||||
}, ", ");
|
||||
|
||||
return String.format("%s(%s)", altFunDeclaration.getName(), paramsString);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetTypeConstraint findTypeParameterConstraint(@NotNull JetFunction function, @NotNull Name typeParameterName,
|
||||
int index) {
|
||||
private static JetTypeConstraint findTypeParameterConstraint(@NotNull JetFunction function, @NotNull Name typeParameterName, int index) {
|
||||
if (index != 0) {
|
||||
int currentIndex = 0;
|
||||
for (JetTypeConstraint constraint : function.getTypeConstraints()) {
|
||||
@@ -256,184 +264,10 @@ class AlternativeSignatureData {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkForSyntaxErrors() {
|
||||
List<PsiErrorElement> syntaxErrors = AnalyzingUtils.getSyntaxErrorRanges(altFunDeclaration);
|
||||
if (!syntaxErrors.isEmpty()) {
|
||||
String textSignature = String.format("%s(%s)", method.getName(),
|
||||
StringUtil.join(method.getPsiMethod().getSignature(PsiSubstitutor.EMPTY).getParameterTypes(),
|
||||
new Function<PsiType, String>() {
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getPresentableText();
|
||||
}
|
||||
}, ", "));
|
||||
int errorOffset = syntaxErrors.get(0).getTextOffset();
|
||||
String syntaxErrorDescription = syntaxErrors.get(0).getErrorDescription();
|
||||
|
||||
if (syntaxErrors.size() == 1) {
|
||||
fail("Alternative signature for %s has syntax error at %d: %s",
|
||||
textSignature, errorOffset, syntaxErrorDescription);
|
||||
}
|
||||
else {
|
||||
fail("Alternative signature for %s has %d syntax errors, first is at %d: %s",
|
||||
textSignature, syntaxErrors.size(), errorOffset, syntaxErrorDescription);
|
||||
}
|
||||
private static void checkEqualFunctionNames(PsiNamedElement namedElement, PsiMethodWrapper method) {
|
||||
if (!ComparatorUtil.equalsNullable(method.getName(), namedElement.getName())) {
|
||||
throw new AlternativeSignatureMismatchException("Function names mismatch, original: %s, alternative: %s",
|
||||
method.getName(), namedElement.getName());
|
||||
}
|
||||
|
||||
if (!ComparatorUtil.equalsNullable(method.getName(), altFunDeclaration.getName())) {
|
||||
fail("Function names mismatch, original: %s, alternative: %s", method.getName(), altFunDeclaration.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void fail(String format, Object... params) {
|
||||
throw new AlternativeSignatureMismatchException(String.format(format, params));
|
||||
}
|
||||
|
||||
private static class AlternativeSignatureMismatchException extends RuntimeException {
|
||||
private AlternativeSignatureMismatchException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
|
||||
private final JetType autoType;
|
||||
|
||||
public TypeTransformingVisitor(JetType autoType) {
|
||||
this.autoType = autoType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitNullableType(JetNullableType nullableType, Void data) {
|
||||
if (!autoType.isNullable()) {
|
||||
fail("Auto type '%s' is not-null, while type in alternative signature is nullable: '%s'",
|
||||
DescriptorRenderer.TEXT.renderType(autoType), nullableType.getText());
|
||||
}
|
||||
return TypeUtils.makeNullable(computeType(nullableType.getInnerType(), autoType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitFunctionType(JetFunctionType type, Void data) {
|
||||
return visitCommonType(type.getReceiverTypeRef() == null
|
||||
? JetStandardClasses.getFunction(type.getParameters().size())
|
||||
: JetStandardClasses.getReceiverFunction(type.getParameters().size()), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTupleType(JetTupleType type, Void data) {
|
||||
return visitCommonType(JetStandardClasses.getTuple(type.getComponentTypeRefs().size()), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitUserType(JetUserType type, Void data) {
|
||||
JetUserType qualifier = type.getQualifier();
|
||||
//noinspection ConstantConditions
|
||||
String shortName = type.getReferenceExpression().getReferencedName();
|
||||
String longName = (qualifier == null ? "" : qualifier.getText() + ".") + shortName;
|
||||
if (JetStandardClasses.UNIT_ALIAS.getName().equals(longName)) {
|
||||
return visitCommonType(JetStandardClasses.getTuple(0), type);
|
||||
}
|
||||
return visitCommonType(longName, type);
|
||||
}
|
||||
|
||||
private JetType visitCommonType(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeElement type) {
|
||||
return visitCommonType(DescriptorUtils.getFQName(classDescriptor).toSafe().getFqName(), type);
|
||||
}
|
||||
|
||||
private JetType visitCommonType(@NotNull String qualifiedName, @NotNull JetTypeElement type) {
|
||||
TypeConstructor originalTypeConstructor = autoType.getConstructor();
|
||||
ClassifierDescriptor declarationDescriptor = originalTypeConstructor.getDeclarationDescriptor();
|
||||
assert declarationDescriptor != null;
|
||||
String fqName = DescriptorUtils.getFQName(declarationDescriptor).toSafe().getFqName();
|
||||
ClassDescriptor classFromLibrary = getAutoTypeAnalogWithinBuiltins(qualifiedName);
|
||||
if (!isSameName(qualifiedName, fqName) && classFromLibrary == null) {
|
||||
fail("Alternative signature type mismatch, expected: %s, actual: %s", qualifiedName, fqName);
|
||||
}
|
||||
|
||||
List<TypeProjection> arguments = autoType.getArguments();
|
||||
|
||||
if (arguments.size() != type.getTypeArgumentsAsTypes().size()) {
|
||||
fail("'%s' type in method signature has %d type arguments, while '%s' in alternative signature has %d of them",
|
||||
DescriptorRenderer.TEXT.renderType(autoType), arguments.size(), type.getText(),
|
||||
type.getTypeArgumentsAsTypes().size());
|
||||
}
|
||||
|
||||
List<TypeProjection> altArguments = new ArrayList<TypeProjection>();
|
||||
for (int i = 0, size = arguments.size(); i < size; i++) {
|
||||
JetTypeElement argumentAlternativeTypeElement = type.getTypeArgumentsAsTypes().get(i).getTypeElement();
|
||||
TypeProjection argument = arguments.get(i);
|
||||
JetType alternativeType =
|
||||
computeType(argumentAlternativeTypeElement, argument.getType());
|
||||
Variance variance = argument.getProjectionKind();
|
||||
if (type instanceof JetUserType) {
|
||||
JetTypeProjection typeProjection = ((JetUserType) type).getTypeArguments().get(i);
|
||||
Variance altVariance = Variance.INVARIANT;
|
||||
switch (typeProjection.getProjectionKind()) {
|
||||
case IN:
|
||||
altVariance = Variance.IN_VARIANCE;
|
||||
break;
|
||||
case OUT:
|
||||
altVariance = Variance.OUT_VARIANCE;
|
||||
break;
|
||||
case STAR:
|
||||
fail("Star projection is not available in alternative signatures");
|
||||
default:
|
||||
}
|
||||
if (altVariance != variance && variance != Variance.INVARIANT) {
|
||||
fail("Variance mismatch, actual: %s, in alternative signature: %s", variance, altVariance);
|
||||
}
|
||||
}
|
||||
altArguments.add(new TypeProjection(variance, alternativeType));
|
||||
}
|
||||
|
||||
TypeConstructor typeConstructor;
|
||||
if (classFromLibrary != null) {
|
||||
typeConstructor = classFromLibrary.getTypeConstructor();
|
||||
}
|
||||
else {
|
||||
typeConstructor = originalTypeConstructor;
|
||||
}
|
||||
ClassifierDescriptor typeConstructorClassifier = typeConstructor.getDeclarationDescriptor();
|
||||
if (typeConstructorClassifier instanceof TypeParameterDescriptor
|
||||
&& originalToAltTypeParameters.containsKey(typeConstructorClassifier)) {
|
||||
typeConstructor = originalToAltTypeParameters.get(typeConstructorClassifier).getTypeConstructor();
|
||||
}
|
||||
JetScope memberScope;
|
||||
if (typeConstructorClassifier instanceof TypeParameterDescriptor) {
|
||||
memberScope = ((TypeParameterDescriptor) typeConstructorClassifier).getUpperBoundsAsType().getMemberScope();
|
||||
}
|
||||
else if (typeConstructorClassifier instanceof ClassDescriptor) {
|
||||
memberScope = ((ClassDescriptor) typeConstructorClassifier).getMemberScope(altArguments);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("Unexpected class of type constructor classifier "
|
||||
+ (typeConstructorClassifier == null ? "null" : typeConstructorClassifier.getClass().getName()));
|
||||
}
|
||||
return new JetTypeImpl(autoType.getAnnotations(), typeConstructor, false,
|
||||
altArguments, memberScope);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getAutoTypeAnalogWithinBuiltins(String qualifiedName) {
|
||||
Type javaAnalog = KotlinToJavaTypesMap.getInstance().getJavaAnalog(autoType);
|
||||
if (javaAnalog == null || javaAnalog.getSort() != Type.OBJECT) return null;
|
||||
Collection<ClassDescriptor> descriptors =
|
||||
JavaToKotlinClassMap.getInstance().mapPlatformClass(JvmClassName.byType(javaAnalog).getFqName());
|
||||
for (ClassDescriptor descriptor : descriptors) {
|
||||
String fqName = DescriptorUtils.getFQName(descriptor).getFqName();
|
||||
if (isSameName(qualifiedName, fqName)) {
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitSelfType(JetSelfType type, Void data) {
|
||||
throw new UnsupportedOperationException("Self-types are not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSameName(String qualifiedName, String fullyQualifiedName) {
|
||||
return fullyQualifiedName.equals(qualifiedName) || fullyQualifiedName.endsWith("." + qualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.kotlinSignature;
|
||||
|
||||
class AlternativeSignatureMismatchException extends RuntimeException {
|
||||
AlternativeSignatureMismatchException(String format, Object... params) {
|
||||
this(String.format(format, params));
|
||||
}
|
||||
|
||||
AlternativeSignatureMismatchException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.kotlinSignature;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeElement;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class ElementAlternativeSignatureData {
|
||||
private String error;
|
||||
private boolean isAnnotated;
|
||||
|
||||
public final boolean hasErrors() {
|
||||
return error != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final String getError() {
|
||||
if (error == null) {
|
||||
throw new IllegalStateException("There are no errors");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
protected final void setError(@Nullable String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public boolean isAnnotated() {
|
||||
return this.isAnnotated;
|
||||
}
|
||||
|
||||
protected final void checkForErrors() {
|
||||
if (!isAnnotated() || hasErrors()) {
|
||||
throw new IllegalStateException("Trying to read result while there is none");
|
||||
}
|
||||
}
|
||||
|
||||
protected final void setAnnotated(boolean isAnnotated) {
|
||||
this.isAnnotated = isAnnotated;
|
||||
}
|
||||
|
||||
public abstract String getSignature();
|
||||
|
||||
protected void checkForSyntaxErrors(PsiElement namedElement) {
|
||||
List<PsiErrorElement> syntaxErrors = AnalyzingUtils.getSyntaxErrorRanges(namedElement);
|
||||
|
||||
if (!syntaxErrors.isEmpty()) {
|
||||
String textSignature = getSignature();
|
||||
|
||||
int errorOffset = syntaxErrors.get(0).getTextOffset();
|
||||
String syntaxErrorDescription = syntaxErrors.get(0).getErrorDescription();
|
||||
|
||||
if (syntaxErrors.size() == 1) {
|
||||
throw new AlternativeSignatureMismatchException("Alternative signature for %s has syntax error at %d: %s",
|
||||
textSignature, errorOffset, syntaxErrorDescription);
|
||||
}
|
||||
else {
|
||||
throw new AlternativeSignatureMismatchException("Alternative signature for %s has %d syntax errors, first is at %d: %s",
|
||||
textSignature, syntaxErrors.size(), errorOffset, syntaxErrorDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static JetType computeReturnType(
|
||||
@NotNull JetType originalType,
|
||||
@Nullable JetTypeReference altReturnTypeReference,
|
||||
@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters) {
|
||||
if (altReturnTypeReference == null) {
|
||||
if (JetStandardClasses.isUnit(originalType)) {
|
||||
return originalType;
|
||||
}
|
||||
else {
|
||||
throw new AlternativeSignatureMismatchException(
|
||||
"Return type in alternative signature is missing, while in real signature it is '%s'",
|
||||
DescriptorRenderer.TEXT.renderType(originalType));
|
||||
}
|
||||
}
|
||||
|
||||
JetTypeElement typeElement = altReturnTypeReference.getTypeElement();
|
||||
assert (typeElement != null);
|
||||
|
||||
return TypeTransformingVisitor.computeType(typeElement, originalType, originalToAltTypeParameters);
|
||||
}
|
||||
}
|
||||
+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.kotlinSignature;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.KotlinToJavaTypesMap;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
|
||||
private final JetType originalType;
|
||||
private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters;
|
||||
|
||||
private TypeTransformingVisitor(
|
||||
JetType originalType,
|
||||
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters
|
||||
) {
|
||||
this.originalType = originalType;
|
||||
this.originalToAltTypeParameters = Collections.unmodifiableMap(originalToAltTypeParameters);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetType computeType(
|
||||
@NotNull JetTypeElement alternativeTypeElement,
|
||||
@NotNull JetType originalType,
|
||||
@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters
|
||||
) {
|
||||
JetType computedType = alternativeTypeElement.accept(new TypeTransformingVisitor(originalType, originalToAltTypeParameters), null);
|
||||
assert (computedType != null);
|
||||
return computedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitNullableType(JetNullableType nullableType, Void aVoid) {
|
||||
if (!originalType.isNullable()) {
|
||||
throw new AlternativeSignatureMismatchException("Auto type '%s' is not-null, while type in alternative signature is nullable: '%s'",
|
||||
DescriptorRenderer.TEXT.renderType(originalType), nullableType.getText());
|
||||
}
|
||||
return TypeUtils.makeNullable(computeType(nullableType.getInnerType(), originalType, originalToAltTypeParameters));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitFunctionType(JetFunctionType type, Void data) {
|
||||
return visitCommonType(type.getReceiverTypeRef() == null
|
||||
? JetStandardClasses.getFunction(type.getParameters().size())
|
||||
: JetStandardClasses.getReceiverFunction(type.getParameters().size()), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTupleType(JetTupleType type, Void data) {
|
||||
return visitCommonType(JetStandardClasses.getTuple(type.getComponentTypeRefs().size()), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitUserType(JetUserType type, Void data) {
|
||||
JetUserType qualifier = type.getQualifier();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
String shortName = type.getReferenceExpression().getReferencedName();
|
||||
String longName = (qualifier == null ? "" : qualifier.getText() + ".") + shortName;
|
||||
|
||||
if (JetStandardClasses.UNIT_ALIAS.getName().equals(longName)) {
|
||||
return visitCommonType(JetStandardClasses.getTuple(0), type);
|
||||
}
|
||||
|
||||
return visitCommonType(longName, type);
|
||||
}
|
||||
|
||||
private JetType visitCommonType(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeElement type) {
|
||||
return visitCommonType(DescriptorUtils.getFQName(classDescriptor).toSafe().getFqName(), type);
|
||||
}
|
||||
|
||||
private JetType visitCommonType(@NotNull String qualifiedName, @NotNull JetTypeElement type) {
|
||||
TypeConstructor originalTypeConstructor = originalType.getConstructor();
|
||||
ClassifierDescriptor declarationDescriptor = originalTypeConstructor.getDeclarationDescriptor();
|
||||
assert declarationDescriptor != null;
|
||||
String fqName = DescriptorUtils.getFQName(declarationDescriptor).toSafe().getFqName();
|
||||
ClassDescriptor classFromLibrary = getAutoTypeAnalogWithinBuiltins(qualifiedName);
|
||||
if (!isSameName(qualifiedName, fqName) && classFromLibrary == null) {
|
||||
throw new AlternativeSignatureMismatchException("Alternative signature type mismatch, expected: %s, actual: %s", qualifiedName, fqName);
|
||||
}
|
||||
|
||||
List<TypeProjection> arguments = originalType.getArguments();
|
||||
|
||||
if (arguments.size() != type.getTypeArgumentsAsTypes().size()) {
|
||||
throw new AlternativeSignatureMismatchException("'%s' type in method signature has %d type arguments, while '%s' in alternative signature has %d of them",
|
||||
DescriptorRenderer.TEXT.renderType(originalType), arguments.size(), type.getText(),
|
||||
type.getTypeArgumentsAsTypes().size());
|
||||
}
|
||||
|
||||
List<TypeProjection> altArguments = new ArrayList<TypeProjection>();
|
||||
for (int i = 0, size = arguments.size(); i < size; i++) {
|
||||
JetTypeElement argumentAlternativeTypeElement = type.getTypeArgumentsAsTypes().get(i).getTypeElement();
|
||||
assert argumentAlternativeTypeElement != null;
|
||||
|
||||
TypeProjection argument = arguments.get(i);
|
||||
JetType alternativeType = computeType(argumentAlternativeTypeElement, argument.getType(), originalToAltTypeParameters);
|
||||
Variance variance = argument.getProjectionKind();
|
||||
if (type instanceof JetUserType) {
|
||||
JetTypeProjection typeProjection = ((JetUserType) type).getTypeArguments().get(i);
|
||||
Variance altVariance = Variance.INVARIANT;
|
||||
switch (typeProjection.getProjectionKind()) {
|
||||
case IN:
|
||||
altVariance = Variance.IN_VARIANCE;
|
||||
break;
|
||||
case OUT:
|
||||
altVariance = Variance.OUT_VARIANCE;
|
||||
break;
|
||||
case STAR:
|
||||
throw new AlternativeSignatureMismatchException("Star projection is not available in alternative signatures");
|
||||
default:
|
||||
}
|
||||
if (altVariance != variance && variance != Variance.INVARIANT) {
|
||||
throw new AlternativeSignatureMismatchException("Variance mismatch, actual: %s, in alternative signature: %s", variance, altVariance);
|
||||
}
|
||||
}
|
||||
altArguments.add(new TypeProjection(variance, alternativeType));
|
||||
}
|
||||
|
||||
TypeConstructor typeConstructor;
|
||||
if (classFromLibrary != null) {
|
||||
typeConstructor = classFromLibrary.getTypeConstructor();
|
||||
}
|
||||
else {
|
||||
typeConstructor = originalTypeConstructor;
|
||||
}
|
||||
ClassifierDescriptor typeConstructorClassifier = typeConstructor.getDeclarationDescriptor();
|
||||
if (typeConstructorClassifier instanceof TypeParameterDescriptor && originalToAltTypeParameters.containsKey(typeConstructorClassifier)) {
|
||||
typeConstructor = originalToAltTypeParameters.get(typeConstructorClassifier).getTypeConstructor();
|
||||
}
|
||||
JetScope memberScope;
|
||||
if (typeConstructorClassifier instanceof TypeParameterDescriptor) {
|
||||
memberScope = ((TypeParameterDescriptor) typeConstructorClassifier).getUpperBoundsAsType().getMemberScope();
|
||||
}
|
||||
else if (typeConstructorClassifier instanceof ClassDescriptor) {
|
||||
memberScope = ((ClassDescriptor) typeConstructorClassifier).getMemberScope(altArguments);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("Unexpected class of type constructor classifier "
|
||||
+ (typeConstructorClassifier == null ? "null" : typeConstructorClassifier.getClass().getName()));
|
||||
}
|
||||
return new JetTypeImpl(originalType.getAnnotations(), typeConstructor, false,
|
||||
altArguments, memberScope);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getAutoTypeAnalogWithinBuiltins(String qualifiedName) {
|
||||
Type javaAnalog = KotlinToJavaTypesMap.getInstance().getJavaAnalog(originalType);
|
||||
if (javaAnalog == null || javaAnalog.getSort() != Type.OBJECT) return null;
|
||||
Collection<ClassDescriptor> descriptors =
|
||||
JavaToKotlinClassMap.getInstance().mapPlatformClass(JvmClassName.byType(javaAnalog).getFqName());
|
||||
for (ClassDescriptor descriptor : descriptors) {
|
||||
String fqName = DescriptorUtils.getFQName(descriptor).getFqName();
|
||||
if (isSameName(qualifiedName, fqName)) {
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitSelfType(JetSelfType type, Void data) {
|
||||
throw new UnsupportedOperationException("Self-types are not supported yet");
|
||||
}
|
||||
|
||||
private static boolean isSameName(String qualifiedName, String fullyQualifiedName) {
|
||||
return fullyQualifiedName.equals(qualifiedName) || fullyQualifiedName.endsWith("." + qualifiedName);
|
||||
}
|
||||
}
|
||||
+10
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.KotlinSignatureAnnotation;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
@@ -41,4 +42,13 @@ public class PsiFieldWrapper extends PsiMemberWrapper {
|
||||
public boolean isAbstract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private KotlinSignatureAnnotation signatureAnnotation;
|
||||
@NotNull
|
||||
public KotlinSignatureAnnotation getSignatureAnnotation() {
|
||||
if (signatureAnnotation == null) {
|
||||
signatureAnnotation = KotlinSignatureAnnotation.get(getPsiMember());
|
||||
}
|
||||
return signatureAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user