Delete KotlinSignature and corresponding code

This commit is contained in:
Alexander Udalov
2015-11-13 22:51:00 +03:00
parent d472154ea7
commit fa34ebac4a
14 changed files with 29 additions and 1091 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.load.java.components;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
@@ -24,35 +23,23 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.load.java.JavaBindingContext;
import org.jetbrains.kotlin.load.java.structure.JavaConstructor;
import org.jetbrains.kotlin.load.java.structure.JavaField;
import org.jetbrains.kotlin.load.java.structure.JavaMember;
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.AlternativeFieldSignatureData;
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.AlternativeMethodSignatureData;
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.SignaturesPropagationData;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Collections;
import java.util.List;
public class TraceBasedExternalSignatureResolver implements ExternalSignatureResolver {
@NotNull private final BindingTrace trace;
@NotNull private final Project project;
private final BindingTrace trace;
public TraceBasedExternalSignatureResolver(
@NotNull Project project,
@NotNull BindingTrace trace
) {
this.project = project;
public TraceBasedExternalSignatureResolver(@NotNull BindingTrace trace) {
this.trace = trace;
}
@Override
@NotNull
public PropagatedMethodSignature resolvePropagatedSignature(
public AlternativeMethodSignature resolvePropagatedSignature(
@NotNull JavaMethod method,
@NotNull ClassDescriptor owner,
@NotNull KotlinType returnType,
@@ -62,60 +49,10 @@ public class TraceBasedExternalSignatureResolver implements ExternalSignatureRes
) {
SignaturesPropagationData data =
new SignaturesPropagationData(owner, returnType, receiverType, valueParameters, typeParameters, method);
return new PropagatedMethodSignature(data.getModifiedReturnType(), data.getModifiedReceiverType(),
data.getModifiedValueParameters(), data.getModifiedTypeParameters(), data.getSignatureErrors(),
data.getModifiedHasStableParameterNames(), data.getSuperFunctions());
}
@Override
@NotNull
public AlternativeMethodSignature resolveAlternativeMethodSignature(
@NotNull JavaMember methodOrConstructor,
boolean hasSuperMethods,
@Nullable KotlinType returnType,
@Nullable KotlinType receiverType,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> typeParameters,
boolean hasStableParameterNames
) {
assert methodOrConstructor instanceof JavaMethod || methodOrConstructor instanceof JavaConstructor :
"Not a method or a constructor: " + methodOrConstructor.getName();
AlternativeMethodSignatureData data = new AlternativeMethodSignatureData(
methodOrConstructor, receiverType, project, valueParameters, returnType, typeParameters, hasSuperMethods
return new AlternativeMethodSignature(
data.getModifiedReturnType(), data.getModifiedReceiverType(), data.getModifiedValueParameters(),
data.getModifiedTypeParameters(), data.getSignatureErrors(), data.getModifiedHasStableParameterNames()
);
if (data.isAnnotated() && !data.hasErrors()) {
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) {
return new AlternativeMethodSignature(returnType, receiverType, valueParameters,
typeParameters, Collections.<String>emptyList(), hasStableParameterNames);
}
return new AlternativeMethodSignature(data.getReturnType(), receiverType, data.getValueParameters(), data.getTypeParameters(),
Collections.<String>emptyList(), true);
}
List<String> error = data.hasErrors() ? Collections.singletonList(data.getError()) : Collections.<String>emptyList();
return new AlternativeMethodSignature(returnType, receiverType, valueParameters, typeParameters, error, hasStableParameterNames);
}
@Override
@NotNull
public AlternativeFieldSignature resolveAlternativeFieldSignature(
@NotNull JavaField field,
@NotNull KotlinType returnType,
boolean isVar
) {
AlternativeFieldSignatureData data = new AlternativeFieldSignatureData(field, returnType, project, isVar);
if (data.isAnnotated() && !data.hasErrors()) {
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) {
return new AlternativeFieldSignature(returnType, null);
}
return new AlternativeFieldSignature(data.getReturnType(), null);
}
String error = data.hasErrors() ? data.getError() : null;
return new AlternativeFieldSignature(returnType, error);
}
@Override
@@ -1,89 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.ComparatorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.load.java.structure.JavaField;
import org.jetbrains.kotlin.psi.KtProperty;
import org.jetbrains.kotlin.psi.KtPsiFactoryKt;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.HashMap;
public class AlternativeFieldSignatureData extends ElementAlternativeSignatureData {
private KotlinType altReturnType;
public AlternativeFieldSignatureData(
@NotNull JavaField field,
@NotNull KotlinType originalReturnType,
@NotNull Project project,
boolean isVar
) {
String signature = SignaturesUtil.getKotlinSignature(field);
if (signature == null) {
setAnnotated(false);
return;
}
setAnnotated(true);
KtProperty altPropertyDeclaration = KtPsiFactoryKt.KtPsiFactory(project).createProperty(signature);
try {
checkForSyntaxErrors(altPropertyDeclaration);
checkFieldAnnotation(altPropertyDeclaration, field, isVar);
altReturnType = computeReturnType(originalReturnType, altPropertyDeclaration.getTypeReference(),
new HashMap<TypeParameterDescriptor, TypeParameterDescriptorImpl>());
}
catch (AlternativeSignatureMismatchException e) {
setError(e.getMessage());
}
}
@NotNull
public KotlinType getReturnType() {
checkForErrors();
return altReturnType;
}
private static void checkFieldAnnotation(@NotNull KtProperty altProperty, @NotNull JavaField field, boolean isVar) {
if (!ComparatorUtil.equalsNullable(field.getName().asString(), altProperty.getName())) {
throw new AlternativeSignatureMismatchException("Field name mismatch, original: %s, alternative: %s",
field.getName().asString(), altProperty.getName());
}
if (altProperty.getTypeReference() == null) {
throw new AlternativeSignatureMismatchException("Field annotation for shouldn't have type reference");
}
if (altProperty.getGetter() != null || altProperty.getSetter() != null) {
throw new AlternativeSignatureMismatchException("Field annotation for shouldn't have getters and setters");
}
if (altProperty.isVar() != isVar) {
throw new AlternativeSignatureMismatchException("Wrong mutability in annotation for field");
}
if (altProperty.hasInitializer()) {
throw new AlternativeSignatureMismatchException("Default value is not expected in annotation for field");
}
}
}
@@ -1,317 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiNamedElement;
import com.intellij.util.containers.ComparatorUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.load.java.structure.JavaMember;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.load.java.components.TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT;
import static org.jetbrains.kotlin.load.java.components.TypeUsage.UPPER_BOUND;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
public class AlternativeMethodSignatureData extends ElementAlternativeSignatureData {
private final KtNamedFunction altFunDeclaration;
private List<ValueParameterDescriptor> altValueParameters;
private KotlinType altReturnType;
private List<TypeParameterDescriptor> altTypeParameters;
private Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters;
public AlternativeMethodSignatureData(
@NotNull JavaMember methodOrConstructor,
@Nullable KotlinType receiverType,
@NotNull Project project,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable KotlinType originalReturnType,
@NotNull List<TypeParameterDescriptor> methodTypeParameters,
boolean hasSuperMethods
) {
String signature = SignaturesUtil.getKotlinSignature(methodOrConstructor);
if (signature == null) {
setAnnotated(false);
altFunDeclaration = null;
return;
}
if (receiverType != null) {
throw new UnsupportedOperationException("Alternative annotations for extension functions are not supported yet");
}
setAnnotated(true);
altFunDeclaration = KtPsiFactoryKt.KtPsiFactory(project).createFunction(signature);
originalToAltTypeParameters = JavaResolverUtils.recreateTypeParametersAndReturnMapping(methodTypeParameters, null);
try {
checkForSyntaxErrors(altFunDeclaration);
checkEqualFunctionNames(altFunDeclaration, methodOrConstructor);
computeTypeParameters(methodTypeParameters);
computeValueParameters(valueParameters);
if (originalReturnType != null) {
altReturnType = computeReturnType(originalReturnType, altFunDeclaration.getTypeReference(), originalToAltTypeParameters);
}
if (hasSuperMethods) {
checkParameterAndReturnTypesForOverridingMethods(valueParameters, methodTypeParameters, originalReturnType);
}
}
catch (AlternativeSignatureMismatchException e) {
setError(e.getMessage());
}
}
public static List<ValueParameterDescriptor> updateNames(
List<ValueParameterDescriptor> originalValueParameters,
List<ValueParameterDescriptor> altValueParameters
) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(originalValueParameters.size());
for (int i = 0; i < originalValueParameters.size(); i++) {
ValueParameterDescriptor originalValueParameter = originalValueParameters.get(i);
ValueParameterDescriptor altValueParameter = altValueParameters.get(i);
result.add(originalValueParameter.copy(originalValueParameter.getContainingDeclaration(), altValueParameter.getName()));
}
return result;
}
private void checkParameterAndReturnTypesForOverridingMethods(
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> methodTypeParameters,
@Nullable KotlinType returnType
) {
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return;
TypeSubstitutor substitutor = JavaResolverUtils.createSubstitutorForTypeParameters(originalToAltTypeParameters);
for (ValueParameterDescriptor parameter : valueParameters) {
int index = parameter.getIndex();
ValueParameterDescriptor altParameter = altValueParameters.get(index);
KotlinType substituted = substitutor.substitute(parameter.getType(), Variance.INVARIANT);
assert substituted != null;
if (!TypeUtils.equalTypes(substituted, altParameter.getType())) {
throw new AlternativeSignatureMismatchException(
"Parameter type changed for method which overrides another: " + altParameter.getType()
+ ", was: " + parameter.getType());
}
}
// don't check receiver
for (TypeParameterDescriptor parameter : methodTypeParameters) {
int index = parameter.getIndex();
KotlinType upperBoundsAsType = TypeIntersector.getUpperBoundsAsType(parameter);
KotlinType substituted = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT);
assert substituted != null;
KotlinType altUpperBoundsAsType = TypeIntersector.getUpperBoundsAsType(altTypeParameters.get(index));
if (!TypeUtils.equalTypes(substituted, altUpperBoundsAsType)) {
throw new AlternativeSignatureMismatchException(
"Type parameter's upper bound changed for method which overrides another: "
+ altUpperBoundsAsType + ", was: " + upperBoundsAsType
);
}
}
if (returnType != null) {
KotlinType substitutedReturnType = substitutor.substitute(returnType, Variance.INVARIANT);
assert substitutedReturnType != null;
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(altReturnType, substitutedReturnType)) {
throw new AlternativeSignatureMismatchException(
"Return type is changed to not subtype for method which overrides another: " + altReturnType + ", was: " + returnType);
}
}
}
@NotNull
public List<ValueParameterDescriptor> getValueParameters() {
checkForErrors();
return altValueParameters;
}
@Nullable
public KotlinType getReturnType() {
checkForErrors();
return altReturnType;
}
@NotNull
public List<TypeParameterDescriptor> getTypeParameters() {
checkForErrors();
return altTypeParameters;
}
private void computeValueParameters(@NotNull List<ValueParameterDescriptor> parameterDescriptors) {
if (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>(parameterDescriptors.size());
for (int i = 0; i < parameterDescriptors.size(); i++) {
ValueParameterDescriptor originalParameterDescriptor = parameterDescriptors.get(i);
KtParameter annotationValueParameter = altFunDeclaration.getValueParameters().get(i);
//noinspection ConstantConditions
KtTypeElement alternativeTypeElement = annotationValueParameter.getTypeReference().getTypeElement();
assert alternativeTypeElement != null;
KotlinType alternativeType;
KotlinType alternativeVarargElementType;
KotlinType 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 = TypeTransformingVisitor.computeType(alternativeTypeElement, originalParameterDescriptor.getType(), originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT);
alternativeVarargElementType = null;
}
else {
if (!annotationValueParameter.isVarArg()) {
throw new AlternativeSignatureMismatchException("Parameter in method signature is vararg, but in alternative signature it is not");
}
alternativeVarargElementType = TypeTransformingVisitor.computeType(alternativeTypeElement, originalParamVarargElementType,
originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT);
alternativeType = getBuiltIns(originalParameterDescriptor).getArrayType(Variance.OUT_VARIANCE, alternativeVarargElementType);
}
Name altName = annotationValueParameter.getNameAsName();
altParamDescriptors.add(new ValueParameterDescriptorImpl(
originalParameterDescriptor.getContainingDeclaration(),
null,
originalParameterDescriptor.getIndex(),
originalParameterDescriptor.getAnnotations(),
altName != null ? altName : originalParameterDescriptor.getName(),
alternativeType,
originalParameterDescriptor.declaresDefaultValue(),
originalParameterDescriptor.isCrossinline(),
originalParameterDescriptor.isNoinline(),
alternativeVarargElementType,
SourceElement.NO_SOURCE
));
}
altValueParameters = altParamDescriptors;
}
private void computeTypeParameters(List<TypeParameterDescriptor> typeParameters) {
if (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>(typeParameters.size());
for (int i = 0; i < typeParameters.size(); i++) {
TypeParameterDescriptor originalTypeParamDescriptor = typeParameters.get(i);
TypeParameterDescriptorImpl altParamDescriptor = originalToAltTypeParameters.get(originalTypeParamDescriptor);
KtTypeParameter altTypeParameter = altFunDeclaration.getTypeParameters().get(i);
List<KotlinType> originalUpperBounds = originalTypeParamDescriptor.getUpperBounds();
List<KtTypeReference> altUpperBounds = getUpperBounds(altFunDeclaration, altTypeParameter);
if (altUpperBounds.size() != originalUpperBounds.size()) {
if (altUpperBounds.isEmpty()
&& originalUpperBounds.size() == 1
&& TypeUtilsKt.isDefaultBound(originalUpperBounds.iterator().next())) {
// Only default bound => no error
}
else {
throw new AlternativeSignatureMismatchException("Upper bound number mismatch for %s. Expected %d, but found %d",
originalTypeParamDescriptor.getName(),
originalUpperBounds.size(),
altUpperBounds.size());
}
}
if (altUpperBounds.isEmpty()) {
altParamDescriptor.addDefaultUpperBound();
}
else {
int upperBoundIndex = 0;
for (KotlinType upperBound : originalUpperBounds) {
KtTypeElement altTypeElement = altUpperBounds.get(upperBoundIndex).getTypeElement();
assert altTypeElement != null;
altParamDescriptor.addUpperBound(TypeTransformingVisitor.computeType(altTypeElement, upperBound,
originalToAltTypeParameters, UPPER_BOUND));
upperBoundIndex++;
}
}
altParamDescriptor.setInitialized();
altTypeParameters.add(altParamDescriptor);
}
}
@NotNull
private static List<KtTypeReference> getUpperBounds(@NotNull KtFunction function, @NotNull KtTypeParameter jetTypeParameter) {
List<KtTypeReference> result = new ArrayList<KtTypeReference>();
ContainerUtil.addIfNotNull(result, jetTypeParameter.getExtendsBound());
Name name = jetTypeParameter.getNameAsName();
if (name == null) return result;
for (KtTypeConstraint constraint : function.getTypeConstraints()) {
KtSimpleNameExpression parameterName = constraint.getSubjectTypeParameterName();
assert parameterName != null : "No parameter name in constraint " + constraint.getText();
if (name.equals(parameterName.getReferencedNameAsName())) {
result.add(constraint.getBoundTypeReference());
}
}
return result;
}
private static void checkEqualFunctionNames(@NotNull PsiNamedElement namedElement, @NotNull JavaMember methodOrConstructor) {
if (!ComparatorUtil.equalsNullable(methodOrConstructor.getName().asString(), namedElement.getName())) {
throw new AlternativeSignatureMismatchException("Function names mismatch, original: %s, alternative: %s",
methodOrConstructor.getName().asString(), namedElement.getName());
}
}
}
@@ -1,27 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
class AlternativeSignatureMismatchException extends RuntimeException {
AlternativeSignatureMismatchException(String format, Object... params) {
this(String.format(format, params));
}
AlternativeSignatureMismatchException(String message) {
super(message);
}
}
@@ -1,109 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.psi.KtTypeElement;
import org.jetbrains.kotlin.psi.KtTypeReference;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.load.java.components.TypeUsage.MEMBER_SIGNATURE_COVARIANT;
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;
}
protected static void checkForSyntaxErrors(PsiElement namedElement) {
List<PsiErrorElement> syntaxErrors = AnalyzingUtils.getSyntaxErrorRanges(namedElement);
if (!syntaxErrors.isEmpty()) {
int errorOffset = syntaxErrors.get(0).getTextOffset();
String syntaxErrorDescription = syntaxErrors.get(0).getErrorDescription();
if (syntaxErrors.size() == 1) {
throw new AlternativeSignatureMismatchException("Alternative signature has syntax error at %d: %s",
errorOffset, syntaxErrorDescription);
}
else {
throw new AlternativeSignatureMismatchException("Alternative signature has %d syntax errors, first is at %d: %s",
syntaxErrors.size(), errorOffset, syntaxErrorDescription);
}
}
}
protected static KotlinType computeReturnType(
@NotNull KotlinType originalType,
@Nullable KtTypeReference altReturnTypeReference,
@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters) {
if (altReturnTypeReference == null) {
if (KotlinBuiltIns.isUnit(originalType)) {
return originalType;
}
else {
throw new AlternativeSignatureMismatchException(
"Return type in alternative signature is missing, while in real signature it is '%s'",
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(originalType));
}
}
KtTypeElement typeElement = altReturnTypeReference.getTypeElement();
assert (typeElement != null);
return TypeTransformingVisitor.computeType(typeElement, originalType, originalToAltTypeParameters, MEMBER_SIGNATURE_COVARIANT);
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation;
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument;
import org.jetbrains.kotlin.load.java.structure.JavaLiteralAnnotationArgument;
import org.jetbrains.kotlin.load.java.structure.JavaMember;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.*;
public class SignaturesUtil {
private SignaturesUtil() {
}
@Nullable
public static String getKotlinSignature(@NotNull JavaMember member) {
JavaAnnotation newAnnotation = member.findAnnotation(KOTLIN_SIGNATURE);
if (newAnnotation != null) return extractKotlinSignatureArgument(newAnnotation);
JavaAnnotation oldAnnotation = member.findAnnotation(OLD_KOTLIN_SIGNATURE);
if (oldAnnotation != null) return extractKotlinSignatureArgument(oldAnnotation);
return null;
}
@Nullable
private static String extractKotlinSignatureArgument(@NotNull JavaAnnotation annotation) {
JavaAnnotationArgument argument = annotation.findArgument(DEFAULT_ANNOTATION_MEMBER_NAME);
if (argument instanceof JavaLiteralAnnotationArgument) {
Object value = ((JavaLiteralAnnotationArgument) argument).getValue();
if (value instanceof String) {
return StringUtil.unescapeStringCharacters((String) value);
}
}
return null;
}
}
@@ -1,235 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.jvm.kotlinSignature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.load.java.components.TypeUsage;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.TypeResolver;
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.types.*;
import java.util.*;
import static org.jetbrains.kotlin.load.java.components.TypeUsage.TYPE_ARGUMENT;
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
public class TypeTransformingVisitor extends KtVisitor<KotlinType, Void> {
private final KotlinType originalType;
private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters;
private final TypeUsage typeUsage;
private TypeTransformingVisitor(
KotlinType originalType,
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters,
TypeUsage typeUsage
) {
this.originalType = originalType;
this.typeUsage = typeUsage;
this.originalToAltTypeParameters = Collections.unmodifiableMap(originalToAltTypeParameters);
}
@NotNull
public static KotlinType computeType(
@NotNull KtTypeElement alternativeTypeElement,
@NotNull KotlinType originalType,
@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters,
@NotNull TypeUsage typeUsage
) {
KotlinType computedType = alternativeTypeElement.accept(new TypeTransformingVisitor(originalType, originalToAltTypeParameters, typeUsage), null);
assert (computedType != null);
return computedType;
}
@Override
public KotlinType visitNullableType(@NotNull KtNullableType nullableType, Void aVoid) {
if (!TypeUtils.isNullableType(originalType) && typeUsage != TYPE_ARGUMENT) {
throw new AlternativeSignatureMismatchException("Auto type '%s' is not-null, while type in alternative signature is nullable: '%s'",
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(originalType), nullableType.getText());
}
KtTypeElement innerType = nullableType.getInnerType();
assert innerType != null : "Syntax error: " + nullableType.getText();
return TypeUtils.makeNullable(computeType(innerType, originalType, originalToAltTypeParameters, typeUsage));
}
@Override
public KotlinType visitFunctionType(@NotNull KtFunctionType type, Void data) {
KotlinBuiltIns builtIns = JvmPlatform.INSTANCE$.getBuiltIns();
return visitCommonType(type.getReceiverTypeReference() == null
? builtIns.getFunction(type.getParameters().size())
: builtIns.getExtensionFunction(type.getParameters().size()), type);
}
@Override
public KotlinType visitUserType(@NotNull KtUserType type, Void data) {
KtUserType qualifier = type.getQualifier();
//noinspection ConstantConditions
String shortName = type.getReferenceExpression().getReferencedName();
String longName = (qualifier == null ? "" : qualifier.getText() + ".") + shortName;
return visitCommonType(longName, type);
}
private KotlinType visitCommonType(@NotNull ClassDescriptor classDescriptor, @NotNull KtTypeElement type) {
return visitCommonType(DescriptorUtils.getFqNameSafe(classDescriptor).asString(), type);
}
@NotNull
private KotlinType visitCommonType(@NotNull String qualifiedName, @NotNull KtTypeElement type) {
if (originalType.isError()) {
return originalType;
}
TypeConstructor originalTypeConstructor = originalType.getConstructor();
ClassifierDescriptor declarationDescriptor = originalTypeConstructor.getDeclarationDescriptor();
assert declarationDescriptor != null;
FqNameUnsafe originalClassFqName = DescriptorUtils.getFqName(declarationDescriptor);
ClassDescriptor classFromLibrary = getAutoTypeAnalogWithinBuiltins(originalClassFqName, qualifiedName);
if (!isSameName(qualifiedName, originalClassFqName.asString()) && classFromLibrary == null) {
throw new AlternativeSignatureMismatchException("Alternative signature type mismatch, expected: %s, actual: %s",
qualifiedName, originalClassFqName);
}
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();
}
List<TypeProjection> arguments = originalType.getArguments();
if (arguments.size() != type.getTypeArgumentsAsTypes().size()) {
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return originalType;
throw new AlternativeSignatureMismatchException("'%s' type in method signature has %d type arguments, while '%s' in alternative signature has %d of them",
DescriptorRenderer.FQ_NAMES_IN_TYPES.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++) {
altArguments.add(getAltArgument(type, typeConstructor, i, arguments.get(i)));
}
MemberScope memberScope;
if (typeConstructorClassifier instanceof TypeParameterDescriptor) {
memberScope = typeConstructorClassifier.getDefaultType().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 KotlinTypeImpl.create(originalType.getAnnotations(), typeConstructor, false, altArguments, memberScope);
}
@NotNull
private TypeProjection getAltArgument(
@NotNull KtTypeElement type,
@NotNull TypeConstructor typeConstructor,
int i,
@NotNull TypeProjection originalArgument
) {
KtTypeReference typeReference = type.getTypeArgumentsAsTypes().get(i); // process both function type and user type
if (typeReference == null) {
// star projection
assert type instanceof KtUserType
&& ((KtUserType) type).getTypeArguments().get(i).getProjectionKind() == KtProjectionKind.STAR;
return originalArgument;
}
KtTypeElement argumentAlternativeTypeElement = typeReference.getTypeElement();
assert argumentAlternativeTypeElement != null;
TypeParameterDescriptor parameter = typeConstructor.getParameters().get(i);
KotlinType alternativeArgumentType = computeType(argumentAlternativeTypeElement, originalArgument.getType(), originalToAltTypeParameters, TYPE_ARGUMENT);
Variance projectionKind = originalArgument.getProjectionKind();
Variance altProjectionKind;
if (type instanceof KtUserType) {
KtTypeProjection typeProjection = ((KtUserType) type).getTypeArguments().get(i);
altProjectionKind = TypeResolver.resolveProjectionKind(typeProjection.getProjectionKind());
if (altProjectionKind != projectionKind && projectionKind != Variance.INVARIANT && !JavaDescriptorResolverKt.getPLATFORM_TYPES()) {
throw new AlternativeSignatureMismatchException("Projection kind mismatch, actual: %s, in alternative signature: %s",
projectionKind, altProjectionKind);
}
if (altProjectionKind != INVARIANT && parameter.getVariance() != INVARIANT) {
if (altProjectionKind == parameter.getVariance()) {
altProjectionKind = projectionKind;
}
else {
throw new AlternativeSignatureMismatchException("Projection kind '%s' is conflicting with variance of %s",
altProjectionKind, DescriptorUtils.getFqName(typeConstructor.getDeclarationDescriptor()));
}
}
}
else {
altProjectionKind = projectionKind;
}
return new TypeProjectionImpl(altProjectionKind, alternativeArgumentType);
}
@Nullable
private static ClassDescriptor getAutoTypeAnalogWithinBuiltins(
@NotNull FqNameUnsafe originalClassFqName,
@NotNull String qualifiedName
) {
ClassId javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(originalClassFqName);
if (javaClassId == null) return null;
Collection<ClassDescriptor> descriptors = JavaToKotlinClassMap.INSTANCE.mapPlatformClass(javaClassId.asSingleFqName());
for (ClassDescriptor descriptor : descriptors) {
String fqName = DescriptorUtils.getFqName(descriptor).asString();
if (isSameName(qualifiedName, fqName)) {
return descriptor;
}
}
return null;
}
@Override
public KotlinType visitSelfType(@NotNull KtSelfType 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);
}
}