Refactoring: use DescriptionRenderer to generate overriding functions / properties.
This commit is contained in:
committed by
Andrey Breslav
parent
5b1f93b42e
commit
97796f9b0f
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.renderer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
@@ -27,6 +26,20 @@ import org.jetbrains.jet.lang.types.JetType;
|
||||
public interface DescriptorRenderer extends Renderer<DeclarationDescriptor> {
|
||||
DescriptorRenderer COMPACT_WITH_MODIFIERS = new DescriptorRendererBuilder().setWithDefinedIn(false).build();
|
||||
|
||||
DescriptorRenderer SOURCE_CODE = new DescriptorRendererBuilder()
|
||||
.setNormalizedVisibilities(true)
|
||||
.setWithDefinedIn(false)
|
||||
.setShortNames(false)
|
||||
.setShowInternalKeyword(false)
|
||||
.setUnitReturnType(false).build();
|
||||
|
||||
DescriptorRenderer SOURCE_CODE_SHORT_NAMES_IN_TYPES = new DescriptorRendererBuilder()
|
||||
.setNormalizedVisibilities(true)
|
||||
.setWithDefinedIn(false)
|
||||
.setShortNames(true)
|
||||
.setShowInternalKeyword(false)
|
||||
.setUnitReturnType(false).build();
|
||||
|
||||
DescriptorRenderer COMPACT = new DescriptorRendererBuilder()
|
||||
.setWithDefinedIn(false)
|
||||
.setModifiers(false).build();
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class DescriptorRendererBuilder {
|
||||
private boolean shortNames = false;
|
||||
@@ -31,6 +30,9 @@ public class DescriptorRendererBuilder {
|
||||
private boolean debugMode = false;
|
||||
private boolean classWithPrimaryConstructor = false;
|
||||
private boolean verbose = false;
|
||||
private boolean unitReturnType = true;
|
||||
private boolean normalizedVisibilities = false;
|
||||
private boolean showInternalKeyword = true;
|
||||
@NotNull
|
||||
private DescriptorRenderer.ValueParametersHandler valueParametersHandler = new DescriptorRenderer.DefaultValueParameterHandler();
|
||||
@NotNull
|
||||
@@ -76,6 +78,21 @@ public class DescriptorRendererBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DescriptorRendererBuilder setUnitReturnType(boolean unitReturnType) {
|
||||
this.unitReturnType = unitReturnType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DescriptorRendererBuilder setNormalizedVisibilities(boolean normalizedVisibilities) {
|
||||
this.normalizedVisibilities = normalizedVisibilities;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DescriptorRendererBuilder setShowInternalKeyword(boolean showInternalKeyword) {
|
||||
this.showInternalKeyword = showInternalKeyword;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DescriptorRendererBuilder setValueParametersHandler(@NotNull DescriptorRenderer.ValueParametersHandler valueParametersHandler) {
|
||||
this.valueParametersHandler = valueParametersHandler;
|
||||
return this;
|
||||
@@ -93,6 +110,8 @@ public class DescriptorRendererBuilder {
|
||||
|
||||
public DescriptorRenderer build() {
|
||||
return new DescriptorRendererImpl(shortNames, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor,
|
||||
verbose, valueParametersHandler, textFormat, excludedAnnotationClasses);
|
||||
verbose, unitReturnType, normalizedVisibilities, showInternalKeyword, valueParametersHandler,
|
||||
textFormat, excludedAnnotationClasses);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
private final boolean debugMode;
|
||||
private final boolean classWithPrimaryConstructor;
|
||||
private final boolean verbose;
|
||||
private final boolean unitReturnType;
|
||||
private final boolean normalizedVisibilities;
|
||||
private final boolean showInternalKeyword;
|
||||
@NotNull
|
||||
private final ValueParametersHandler handler;
|
||||
@NotNull
|
||||
@@ -70,6 +73,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
boolean debugMode,
|
||||
boolean classWithPrimaryConstructor,
|
||||
boolean verbose,
|
||||
boolean unitReturnType,
|
||||
boolean normalizedVisibilities,
|
||||
boolean showInternalKeyword,
|
||||
@NotNull ValueParametersHandler handler,
|
||||
@NotNull TextFormat textFormat,
|
||||
@NotNull Collection<FqName> excludedAnnotationClasses
|
||||
@@ -81,6 +87,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
this.handler = handler;
|
||||
this.classWithPrimaryConstructor = classWithPrimaryConstructor;
|
||||
this.verbose = verbose;
|
||||
this.unitReturnType = unitReturnType;
|
||||
this.normalizedVisibilities = normalizedVisibilities;
|
||||
this.showInternalKeyword = showInternalKeyword;
|
||||
this.debugMode = debugMode;
|
||||
this.textFormat = textFormat;
|
||||
this.excludedAnnotationClasses = Sets.newHashSet(excludedAnnotationClasses);
|
||||
@@ -307,6 +316,10 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
|
||||
private void renderVisibility(@NotNull Visibility visibility, @NotNull StringBuilder builder) {
|
||||
if (!modifiers) return;
|
||||
if (normalizedVisibilities) {
|
||||
visibility = visibility.normalize();
|
||||
}
|
||||
if (!showInternalKeyword && visibility == Visibilities.INTERNAL) return;
|
||||
builder.append(renderKeyword(visibility.toString())).append(" ");
|
||||
}
|
||||
|
||||
@@ -325,19 +338,25 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
|
||||
private void renderModalityForCallable(@NotNull CallableMemberDescriptor callable, @NotNull StringBuilder builder) {
|
||||
if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.getModality() != Modality.FINAL) {
|
||||
if (overridesSomething(callable) && callable.getModality() == Modality.OPEN) return;
|
||||
renderModality(callable.getModality(), builder);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean overridesSomething(CallableMemberDescriptor callable) {
|
||||
return !callable.getOverriddenDescriptors().isEmpty();
|
||||
}
|
||||
|
||||
private void renderOverrideAndMemberKind(@NotNull CallableMemberDescriptor callableMember, @NotNull StringBuilder builder) {
|
||||
if (verbose) {
|
||||
if (!callableMember.getOverriddenDescriptors().isEmpty()) {
|
||||
builder.append("override /*").append(callableMember.getOverriddenDescriptors().size()).append("*/ ");
|
||||
}
|
||||
if (callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ ");
|
||||
if (overridesSomething(callableMember)) {
|
||||
builder.append("override ");
|
||||
if (verbose) {
|
||||
builder.append("/*").append(callableMember.getOverriddenDescriptors().size()).append("*/ ");
|
||||
}
|
||||
}
|
||||
if (verbose && callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ ");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -443,7 +462,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
renderName(function, builder);
|
||||
renderValueParameters(function, builder);
|
||||
JetType returnType = function.getReturnType();
|
||||
builder.append(" : ").append(returnType == null ? "[NULL]" : escape(renderType(returnType)));
|
||||
if (unitReturnType || !KotlinBuiltIns.getInstance().isUnit(returnType)) {
|
||||
builder.append(": ").append(returnType == null ? "[NULL]" : escape(renderType(returnType)));
|
||||
}
|
||||
renderWhereSuffix(function.getTypeParameters(), builder);
|
||||
}
|
||||
|
||||
@@ -531,7 +552,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
}
|
||||
|
||||
renderName(variable, builder);
|
||||
builder.append(" : ").append(escape(renderType(typeToRender)));
|
||||
builder.append(": ").append(escape(renderType(typeToRender)));
|
||||
|
||||
if (verbose && varargElementType != null) {
|
||||
builder.append(" /*").append(escape(renderType(realType))).append("*/");
|
||||
@@ -555,7 +576,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
builder.append(escape(renderType(receiver.getType()))).append(".");
|
||||
}
|
||||
renderName(property, builder);
|
||||
builder.append(" : ").append(escape(renderType(property.getType())));
|
||||
builder.append(": ").append(escape(renderType(property.getType())));
|
||||
|
||||
renderWhereSuffix(property.getTypeParameters(), builder);
|
||||
}
|
||||
@@ -709,4 +730,4 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.codeInsight.OverrideUtil;
|
||||
import org.jetbrains.jet.plugin.codeInsight.FunctionSignatureUtil;
|
||||
import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -112,8 +112,7 @@ public class JetChangeFunctionSignatureAction implements QuestionAction {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(FunctionDescriptor aValue) {
|
||||
return OverrideUtil.createOverridenFunctionSignatureStringFromDescriptor(
|
||||
project,
|
||||
return FunctionSignatureUtil.createFunctionSignatureStringFromDescriptor(
|
||||
aValue,
|
||||
/* shortTypeNames = */ true);
|
||||
}
|
||||
@@ -121,8 +120,7 @@ public class JetChangeFunctionSignatureAction implements QuestionAction {
|
||||
}
|
||||
|
||||
private static void changeSignature(final JetNamedFunction element, final Project project, FunctionDescriptor signature) {
|
||||
final String signatureString = OverrideUtil.createOverridenFunctionSignatureStringFromDescriptor(
|
||||
project,
|
||||
final String signatureString = FunctionSignatureUtil.createFunctionSignatureStringFromDescriptor(
|
||||
signature,
|
||||
/* shortTypeNames = */ false);
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.plugin.codeInsight;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
public class FunctionSignatureUtil {
|
||||
|
||||
private FunctionSignatureUtil() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String createFunctionSignatureStringFromDescriptor(
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
boolean shortTypeNames
|
||||
) {
|
||||
DescriptorRenderer renderer = shortTypeNames ? DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES : DescriptorRenderer.SOURCE_CODE;
|
||||
return renderer.render(descriptor);
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,14 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -118,18 +118,78 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
||||
for (DescriptorClassMember selectedElement : selectedElements) {
|
||||
DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||
overridingMembers.add(OverrideUtil.createOverridenFunctionElementFromDescriptor(file.getProject(),
|
||||
(SimpleFunctionDescriptor) descriptor, /* shortTypeNames = */
|
||||
false));
|
||||
overridingMembers.add(overrideFunction(file.getProject(),
|
||||
(SimpleFunctionDescriptor) descriptor /* shortTypeNames = */
|
||||
));
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
overridingMembers.add(
|
||||
OverrideUtil.createOverridenPropertyElementFromDescriptor(file.getProject(), (PropertyDescriptor) descriptor));
|
||||
overrideProperty(file.getProject(), (PropertyDescriptor) descriptor));
|
||||
}
|
||||
}
|
||||
return overridingMembers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JetElement overrideProperty(@NotNull Project project, @NotNull PropertyDescriptor descriptor) {
|
||||
PropertyDescriptor newDescriptor = (PropertyDescriptor) descriptor.copy(
|
||||
descriptor.getContainingDeclaration(),
|
||||
Modality.OPEN,
|
||||
descriptor.getVisibility(),
|
||||
descriptor.getKind(),
|
||||
/* copyOverrides = */ true);
|
||||
newDescriptor.addOverriddenDescriptor(descriptor);
|
||||
|
||||
StringBuilder bodyBuilder = new StringBuilder();
|
||||
String initializer = CodeInsightUtils.defaultInitializer(descriptor.getType());
|
||||
if (initializer != null) {
|
||||
bodyBuilder.append(" = ").append(initializer);
|
||||
}
|
||||
else {
|
||||
bodyBuilder.append(" = ?");
|
||||
}
|
||||
return JetPsiFactory.createProperty(project, DescriptorRenderer.SOURCE_CODE.render(newDescriptor) + bodyBuilder.toString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JetNamedFunction overrideFunction(@NotNull Project project, @NotNull FunctionDescriptor descriptor) {
|
||||
FunctionDescriptor newDescriptor = descriptor.copy(
|
||||
descriptor.getContainingDeclaration(),
|
||||
Modality.OPEN,
|
||||
descriptor.getVisibility(),
|
||||
descriptor.getKind(),
|
||||
/* copyOverrides = */ true);
|
||||
newDescriptor.addOverriddenDescriptor(descriptor);
|
||||
|
||||
boolean isAbstractFun = descriptor.getModality() == Modality.ABSTRACT;
|
||||
StringBuilder delegationBuilder = new StringBuilder();
|
||||
if (isAbstractFun) {
|
||||
delegationBuilder.append("throw UnsupportedOperationException()");
|
||||
}
|
||||
else {
|
||||
delegationBuilder.append("super<").append(descriptor.getContainingDeclaration().getName());
|
||||
delegationBuilder.append(">.").append(descriptor.getName()).append("(");
|
||||
}
|
||||
boolean first = true;
|
||||
if (!isAbstractFun) {
|
||||
for (ValueParameterDescriptor parameterDescriptor : descriptor.getValueParameters()) {
|
||||
if (!first) {
|
||||
delegationBuilder.append(", ");
|
||||
}
|
||||
first = false;
|
||||
delegationBuilder.append(parameterDescriptor.getName());
|
||||
}
|
||||
delegationBuilder.append(")");
|
||||
}
|
||||
JetType returnType = descriptor.getReturnType();
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
|
||||
boolean returnsNotUnit = returnType != null && !builtIns.getUnitType().equals(returnType);
|
||||
String body = "{" + (returnsNotUnit && !isAbstractFun ? "return " : "") + delegationBuilder.toString() + "}";
|
||||
|
||||
return JetPsiFactory.createFunction(project, DescriptorRenderer.SOURCE_CODE.render(newDescriptor) + body);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<CallableMemberDescriptor> collectMethodsToGenerate(@NotNull JetClassOrObject classOrObject, BindingContext bindingContext) {
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.plugin.codeInsight;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class OverrideUtil {
|
||||
|
||||
private OverrideUtil() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetElement createOverridenPropertyElementFromDescriptor(@NotNull Project project, @NotNull PropertyDescriptor descriptor) {
|
||||
StringBuilder bodyBuilder = new StringBuilder();
|
||||
bodyBuilder.append(displayableVisibility(descriptor)).append("override ");
|
||||
if (descriptor.isVar()) {
|
||||
bodyBuilder.append("var ");
|
||||
}
|
||||
else {
|
||||
bodyBuilder.append("val ");
|
||||
}
|
||||
|
||||
addReceiverParameter(descriptor, bodyBuilder);
|
||||
|
||||
bodyBuilder.append(descriptor.getName()).append(" : ").append(
|
||||
DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getType()));
|
||||
String initializer = CodeInsightUtils.defaultInitializer(descriptor.getType());
|
||||
if (initializer != null) {
|
||||
bodyBuilder.append(" = ").append(initializer);
|
||||
}
|
||||
else {
|
||||
bodyBuilder.append(" = ?");
|
||||
}
|
||||
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
||||
}
|
||||
|
||||
private static String displayableVisibility(MemberDescriptor descriptor) {
|
||||
Visibility visibility = descriptor.getVisibility().normalize();
|
||||
return visibility != Visibilities.INTERNAL ? visibility.toString() + " ": "";
|
||||
}
|
||||
|
||||
private static String renderType(JetType type, boolean shortNames) {
|
||||
if (shortNames) return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type);
|
||||
else return DescriptorRenderer.TEXT.renderType(type);
|
||||
}
|
||||
|
||||
private static void addReceiverParameter(CallableDescriptor descriptor, StringBuilder bodyBuilder) {
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
bodyBuilder.append(receiverParameter.getType()).append(".");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String createOverridenFunctionSignatureStringFromDescriptor(
|
||||
@NotNull Project project,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
boolean shortTypeNames
|
||||
) {
|
||||
JetNamedFunction functionElement = createOverridenFunctionElementFromDescriptor(project, descriptor, shortTypeNames);
|
||||
JetExpression bodyExpression = functionElement.getBodyExpression();
|
||||
assert bodyExpression != null : "createOverridenFunctionElementFromDescriptor should always return function with body.";
|
||||
bodyExpression.replace(JetPsiFactory.createWhiteSpace(project));
|
||||
return functionElement.getText().trim();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetNamedFunction createOverridenFunctionElementFromDescriptor(
|
||||
@NotNull Project project,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
boolean shortNames
|
||||
) {
|
||||
StringBuilder bodyBuilder = new StringBuilder();
|
||||
bodyBuilder.append(displayableVisibility(descriptor));
|
||||
bodyBuilder.append("override fun ");
|
||||
|
||||
List<String> whereRestrictions = new ArrayList<String>();
|
||||
if (!descriptor.getTypeParameters().isEmpty()) {
|
||||
bodyBuilder.append("<");
|
||||
boolean first = true;
|
||||
for (TypeParameterDescriptor param : descriptor.getTypeParameters()) {
|
||||
if (!first) {
|
||||
bodyBuilder.append(", ");
|
||||
}
|
||||
|
||||
bodyBuilder.append(param.getName());
|
||||
Set<JetType> upperBounds = param.getUpperBounds();
|
||||
if (!upperBounds.isEmpty()) {
|
||||
boolean firstUpperBound = true;
|
||||
for (JetType upperBound : upperBounds) {
|
||||
String upperBoundText = ": " + renderType(upperBound, shortNames);
|
||||
if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound)) {
|
||||
if (firstUpperBound) {
|
||||
bodyBuilder.append(upperBoundText);
|
||||
}
|
||||
else {
|
||||
whereRestrictions.add(param.getName() + upperBoundText);
|
||||
}
|
||||
}
|
||||
firstUpperBound = false;
|
||||
}
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
bodyBuilder.append("> ");
|
||||
}
|
||||
|
||||
addReceiverParameter(descriptor, bodyBuilder);
|
||||
|
||||
bodyBuilder.append(descriptor.getName()).append("(");
|
||||
boolean isAbstractFun = descriptor.getModality() == Modality.ABSTRACT;
|
||||
StringBuilder delegationBuilder = new StringBuilder();
|
||||
if (isAbstractFun) {
|
||||
delegationBuilder.append("throw UnsupportedOperationException()");
|
||||
}
|
||||
else {
|
||||
delegationBuilder.append("super<").append(descriptor.getContainingDeclaration().getName());
|
||||
delegationBuilder.append(">.").append(descriptor.getName()).append("(");
|
||||
}
|
||||
boolean first = true;
|
||||
for (ValueParameterDescriptor parameterDescriptor : descriptor.getValueParameters()) {
|
||||
if (!first) {
|
||||
bodyBuilder.append(", ");
|
||||
if (!isAbstractFun) {
|
||||
delegationBuilder.append(", ");
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
bodyBuilder.append(parameterDescriptor.getName());
|
||||
bodyBuilder.append(": ");
|
||||
bodyBuilder.append(renderType(parameterDescriptor.getType(), shortNames));
|
||||
|
||||
if (!isAbstractFun) {
|
||||
delegationBuilder.append(parameterDescriptor.getName());
|
||||
}
|
||||
}
|
||||
bodyBuilder.append(")");
|
||||
if (!isAbstractFun) {
|
||||
delegationBuilder.append(")");
|
||||
}
|
||||
JetType returnType = descriptor.getReturnType();
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
|
||||
boolean returnsNotUnit = returnType != null && !builtIns.getUnitType().equals(returnType);
|
||||
if (returnsNotUnit) {
|
||||
bodyBuilder.append(": ").append(renderType(returnType, shortNames));
|
||||
}
|
||||
if (!whereRestrictions.isEmpty()) {
|
||||
bodyBuilder.append("\n").append("where ").append(StringUtil.join(whereRestrictions, ", "));
|
||||
}
|
||||
bodyBuilder.append("{").append(returnsNotUnit && !isAbstractFun ? "return " : "").append(delegationBuilder.toString()).append("}");
|
||||
|
||||
return JetPsiFactory.createFunction(project, bodyBuilder.toString());
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.actions.JetChangeFunctionSignatureAction;
|
||||
import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil;
|
||||
import org.jetbrains.jet.plugin.codeInsight.OverrideUtil;
|
||||
import org.jetbrains.jet.plugin.codeInsight.FunctionSignatureUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -76,8 +76,8 @@ public class ChangeMemberFunctionSignatureFix extends JetHintAction<JetNamedFunc
|
||||
|
||||
@NotNull
|
||||
private String getFunctionSignatureString(@NotNull FunctionDescriptor functionSignature, boolean shortTypeNames) {
|
||||
return OverrideUtil.createOverridenFunctionSignatureStringFromDescriptor(
|
||||
element.getProject(), functionSignature, shortTypeNames);
|
||||
return FunctionSignatureUtil.createFunctionSignatureStringFromDescriptor(
|
||||
functionSignature, shortTypeNames);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -136,7 +136,7 @@ public class ChangeMemberFunctionSignatureFix extends JetHintAction<JetNamedFunc
|
||||
matchParameters(MATCH_NAMES, superParameters, parameters, newParameters, matched, used);
|
||||
matchParameters(MATCH_TYPES, superParameters, parameters, newParameters, matched, used);
|
||||
|
||||
return FunctionDescriptorUtil.replaceFunctionParameters(
|
||||
FunctionDescriptor newFunction = FunctionDescriptorUtil.replaceFunctionParameters(
|
||||
superFunction.copy(
|
||||
function.getContainingDeclaration(),
|
||||
Modality.OPEN,
|
||||
@@ -144,6 +144,8 @@ public class ChangeMemberFunctionSignatureFix extends JetHintAction<JetNamedFunc
|
||||
CallableMemberDescriptor.Kind.DELEGATION,
|
||||
/* copyOverrides = */ true),
|
||||
newParameters);
|
||||
newFunction.addOverriddenDescriptor(superFunction);
|
||||
return newFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,7 @@ trait Trait {
|
||||
|
||||
class TraitImpl : Trait {
|
||||
|
||||
override fun <A, B: Runnable, E: Map.Entry<A, B>> foo()
|
||||
where B: Cloneable, B: Comparable<B> {
|
||||
override fun <A, B, E: Map.Entry<A, B>> foo() where B: Runnable, B: Cloneable, B: Comparable<B> {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@ fun some() {
|
||||
tes<caret>
|
||||
}
|
||||
|
||||
// EXIST: test@test(a : jet.Int)
|
||||
// EXIST: test@test(a: jet.Int)
|
||||
@@ -14,13 +14,13 @@ fun</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
l : MyList<in T>,</td>
|
||||
l: MyList<in T>,</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
t : T</td>
|
||||
t: T</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
: jet.Unit <b>
|
||||
: jet.Unit <b>
|
||||
where</b>
|
||||
E : java.lang.Cloneable, E : java.io.Closeable</td>
|
||||
</tr>
|
||||
|
||||
@@ -14,9 +14,9 @@ constructor</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
l : MyList<in T>,</td>
|
||||
l: MyList<in T>,</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
t : T</td>
|
||||
t: T</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
|
||||
@@ -12,11 +12,11 @@ fun</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
a : A<T, R></td>
|
||||
a: A<T, R></td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
: A<T, R></td>
|
||||
: A<T, R></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="7" style="white-space:nowrap;">
|
||||
|
||||
@@ -12,11 +12,11 @@ fun</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
a : A<T, R></td>
|
||||
a: A<T, R></td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
: A<T, R></td>
|
||||
: A<T, R></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="7" style="white-space:nowrap;">
|
||||
|
||||
@@ -12,11 +12,11 @@ fun</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
a : A<T, R></td>
|
||||
a: A<T, R></td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
: A<T, R></td>
|
||||
: A<T, R></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="7" style="white-space:nowrap;">
|
||||
|
||||
@@ -14,13 +14,13 @@ fun</b>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
(</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
r : R,</td>
|
||||
r: R,</td>
|
||||
<td align="right" style="white-space:nowrap;font-weight:bold;">
|
||||
list : T</td>
|
||||
list: T</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
)</td>
|
||||
<td style="white-space:nowrap;font-weight:bold;">
|
||||
: jet.Unit</td>
|
||||
: jet.Unit</td>
|
||||
</tr>
|
||||
</table>
|
||||
is not satisfied: inferred type <font color=red>
|
||||
|
||||
@@ -3,7 +3,7 @@ fun test() {
|
||||
MyClass().<warning descr="'fun test2()' is deprecated. Use A instead">test2</warning>()
|
||||
MyClass.<warning descr="'fun test3()' is deprecated. Use A instead">test3</warning>()
|
||||
|
||||
<warning descr="'fun test4(x : jet.Int, y : jet.Int)' is deprecated. Use A instead">test4</warning>(1, 2)
|
||||
<warning descr="'fun test4(x: jet.Int, y: jet.Int)' is deprecated. Use A instead">test4</warning>(1, 2)
|
||||
}
|
||||
|
||||
deprecated("Use A instead") fun test1() { }
|
||||
|
||||
@@ -6,5 +6,5 @@ fun test() {
|
||||
val x1 = MyClass()
|
||||
val x2 = MyClass()
|
||||
|
||||
<warning descr="'fun get(i : MyClass)' is deprecated. Use A instead">x1[x2]</warning>
|
||||
<warning descr="'fun get(i: MyClass)' is deprecated. Use A instead">x1[x2]</warning>
|
||||
}
|
||||
@@ -20,19 +20,19 @@ fun test() {
|
||||
val x1 = MyClass()
|
||||
val x2 = MyClass()
|
||||
|
||||
x1 <warning descr="'fun minus(i : MyClass)' is deprecated. Use A instead">-</warning> x2
|
||||
x1 <warning descr="'fun div(i : MyClass)' is deprecated. Use A instead">/</warning> x2
|
||||
x1 <warning descr="'fun times(i : MyClass)' is deprecated. Use A instead">*</warning> x2
|
||||
x1 <warning descr="'fun minus(i: MyClass)' is deprecated. Use A instead">-</warning> x2
|
||||
x1 <warning descr="'fun div(i: MyClass)' is deprecated. Use A instead">/</warning> x2
|
||||
x1 <warning descr="'fun times(i: MyClass)' is deprecated. Use A instead">*</warning> x2
|
||||
|
||||
<warning descr="'fun not()' is deprecated. Use A instead">!</warning>x1
|
||||
<warning descr="'fun plus()' is deprecated. Use A instead">+</warning>x1
|
||||
|
||||
x1 <warning descr="'fun contains(i : MyClass)' is deprecated. Use A instead">in</warning> x2
|
||||
x1 <warning descr="'fun contains(i : MyClass)' is deprecated. Use A instead">!in</warning> x2
|
||||
x1 <warning descr="'fun contains(i: MyClass)' is deprecated. Use A instead">in</warning> x2
|
||||
x1 <warning descr="'fun contains(i: MyClass)' is deprecated. Use A instead">!in</warning> x2
|
||||
|
||||
x1 <warning descr="'fun plusAssign(i : MyClass)' is deprecated. Use A instead">+=</warning> x2
|
||||
x1 <warning descr="'fun plusAssign(i: MyClass)' is deprecated. Use A instead">+=</warning> x2
|
||||
|
||||
x1 <warning descr="'fun equals(i : jet.Any?)' is deprecated. Use A instead">==</warning> x2
|
||||
x1 <warning descr="'fun equals(i : jet.Any?)' is deprecated. Use A instead">!=</warning> x2
|
||||
x1 <warning descr="'fun compareTo(i : MyClass)' is deprecated. Use A instead">></warning> x2
|
||||
x1 <warning descr="'fun equals(i: jet.Any?)' is deprecated. Use A instead">==</warning> x2
|
||||
x1 <warning descr="'fun equals(i: jet.Any?)' is deprecated. Use A instead">!=</warning> x2
|
||||
x1 <warning descr="'fun compareTo(i: MyClass)' is deprecated. Use A instead">></warning> x2
|
||||
}
|
||||
@@ -11,7 +11,7 @@ fun test() {
|
||||
val x1 = MyClass()
|
||||
val x2 = MyClass()
|
||||
|
||||
for (i in x1<warning descr="'fun rangeTo(i : MyClass)' is deprecated. Use A instead">..</warning>x2) {
|
||||
for (i in x1<warning descr="'fun rangeTo(i: MyClass)' is deprecated. Use A instead">..</warning>x2) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
package testData.libraries
|
||||
|
||||
[[public abstract class ClassWithAbstractAndOpenMembers() {
|
||||
[public abstract val abstractVal : jet.String]
|
||||
[public abstract val abstractVal: jet.String]
|
||||
|
||||
[public abstract var abstractVar : jet.String]
|
||||
[public abstract var abstractVar: jet.String]
|
||||
|
||||
[public open val openVal : jet.String] /* compiled code */
|
||||
[public open val openVal: jet.String] /* compiled code */
|
||||
|
||||
[public open val openValWithGetter : jet.String] /* compiled code */
|
||||
[public open val openValWithGetter: jet.String] /* compiled code */
|
||||
|
||||
[public open var openVar : jet.String] /* compiled code */
|
||||
[public open var openVar: jet.String] /* compiled code */
|
||||
|
||||
[public open var openVarWithGetter : jet.String] /* compiled code */
|
||||
[public open var openVarWithGetter: jet.String] /* compiled code */
|
||||
|
||||
[public abstract fun abstractFun() : jet.Unit]
|
||||
[public abstract fun abstractFun(): jet.Unit]
|
||||
|
||||
[public open fun openFun() : jet.Unit { /* compiled code */ }]
|
||||
}]]
|
||||
[public open fun openFun(): jet.Unit { /* compiled code */ }]
|
||||
}]]
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
package testData.libraries
|
||||
|
||||
[[public final class ClassWithConstructor(a : jet.String, b : jet.Any) {
|
||||
[internal final val a : jet.String] /* compiled code */
|
||||
[[public final class ClassWithConstructor(a: jet.String, b: jet.Any) {
|
||||
[internal final val a: jet.String] /* compiled code */
|
||||
}]]
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
|
||||
package testData.libraries
|
||||
|
||||
[[public final enum class Color(rgb : jet.Int) : jet.Enum<testData.libraries.Color> {
|
||||
[[public final enum class Color(rgb: jet.Int) : jet.Enum<testData.libraries.Color> {
|
||||
public class object {
|
||||
[public final val BLUE : testData.libraries.Color] /* compiled code */
|
||||
[public final val BLUE: testData.libraries.Color] /* compiled code */
|
||||
|
||||
[public final val GREEN : testData.libraries.Color] /* compiled code */
|
||||
[public final val GREEN: testData.libraries.Color] /* compiled code */
|
||||
|
||||
[public final val RED : testData.libraries.Color] /* compiled code */
|
||||
[public final val RED: testData.libraries.Color] /* compiled code */
|
||||
|
||||
public final fun valueOf(value : jet.String) : testData.libraries.Color { /* compiled code */ }
|
||||
public final fun valueOf(value: jet.String): testData.libraries.Color { /* compiled code */ }
|
||||
|
||||
public final fun values() : jet.Array<testData.libraries.Color> { /* compiled code */ }
|
||||
public final fun values(): jet.Array<testData.libraries.Color> { /* compiled code */ }
|
||||
}
|
||||
|
||||
[internal final val rgb : jet.Int] /* compiled code */
|
||||
}]]
|
||||
[internal final val rgb: jet.Int] /* compiled code */
|
||||
}]]
|
||||
@@ -3,34 +3,34 @@
|
||||
|
||||
package testData.libraries
|
||||
|
||||
[public val globalVal : testData.libraries.Pair<jet.Int, jet.String>] /* compiled code */
|
||||
[public val globalVal: testData.libraries.Pair<jet.Int, jet.String>] /* compiled code */
|
||||
|
||||
[public val globalValWithGetter : jet.Long] /* compiled code */
|
||||
[public val globalValWithGetter: jet.Long] /* compiled code */
|
||||
|
||||
[public val jet.Int.exProp : jet.Int] /* compiled code */
|
||||
[public val jet.Int.exProp: jet.Int] /* compiled code */
|
||||
|
||||
[public val jet.String.exProp : jet.String] /* compiled code */
|
||||
[public val jet.String.exProp: jet.String] /* compiled code */
|
||||
|
||||
[public val <T> testData.libraries.Pair<T, T>.exProp : jet.String] /* compiled code */
|
||||
[public val <T> testData.libraries.Pair<T, T>.exProp: jet.String] /* compiled code */
|
||||
|
||||
[public fun <T : jet.CharSequence> funWithTypeParam(t : T) : jet.Unit { /* compiled code */ }]
|
||||
[public fun <T : jet.CharSequence> funWithTypeParam(t: T): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun <T : jet.Number> funWithTypeParam(t : T) : jet.Unit { /* compiled code */ }]
|
||||
[public fun <T : jet.Number> funWithTypeParam(t: T): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun func() : jet.Unit { /* compiled code */ }]
|
||||
[public fun func(): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun func(cs : jet.CharSequence) : jet.Unit { /* compiled code */ }]
|
||||
[public fun func(cs: jet.CharSequence): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun func(a : jet.Int, b : jet.Int) : jet.Unit { /* compiled code */ }]
|
||||
[public fun func(a: jet.Int, b: jet.Int): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun func(a : jet.Int, b : jet.String = /* compiled code */) : jet.Unit { /* compiled code */ }]
|
||||
[public fun func(a: jet.Int, b: jet.String = /* compiled code */): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun func(str : jet.String) : jet.Unit { /* compiled code */ }]
|
||||
[public fun func(str: jet.String): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun main(args : jet.Array<jet.String>) : jet.Unit { /* compiled code */ }]
|
||||
[public fun main(args: jet.Array<jet.String>): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun processDouble(d : jet.Double) : jet.Unit { /* compiled code */ }]
|
||||
[public fun processDouble(d: jet.Double): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun processDouble(d : testData.libraries.Double) : jet.Unit { /* compiled code */ }]
|
||||
[public fun processDouble(d: testData.libraries.Double): jet.Unit { /* compiled code */ }]
|
||||
|
||||
[public fun <T> T.filter(predicate : (T) -> jet.Boolean) : T? { /* compiled code */ }]
|
||||
[public fun <T> T.filter(predicate: (T) -> jet.Boolean): T? { /* compiled code */ }]
|
||||
@@ -4,5 +4,5 @@
|
||||
package testData.libraries
|
||||
|
||||
[[public object NamedObject {
|
||||
[public final val objectMember : jet.Int] /* compiled code */
|
||||
[public final val objectMember: jet.Int] /* compiled code */
|
||||
}]]
|
||||
@@ -5,12 +5,12 @@ package testData.libraries
|
||||
|
||||
[[public final class WithInnerAndObject() {
|
||||
public class object {
|
||||
[internal final fun foo() : jet.Unit { /* compiled code */ }]
|
||||
[internal final fun foo(): jet.Unit { /* compiled code */ }]
|
||||
}
|
||||
|
||||
[[internal final class MyInner() {
|
||||
[internal trait MyInnerInner {
|
||||
[internal abstract fun innerInnerMethod() : jet.Unit]
|
||||
[internal abstract fun innerInnerMethod(): jet.Unit]
|
||||
}]
|
||||
}]]
|
||||
}]]
|
||||
}]]
|
||||
@@ -1,5 +1,5 @@
|
||||
// "Change function signature..." "true"
|
||||
// ERROR: <html>Class 'B' must be declared abstract or implement abstract member<br/><b>abstract</b> <b>fun</b> f(a: jet.String): jet.Unit <i>defined in</i> A</html>
|
||||
// ERROR: <html>Class 'B' must be declared abstract or implement abstract member<br/><b>internal</b> <b>abstract</b> <b>fun</b> f(a: jet.String): jet.Unit <i>defined in</i> A</html>
|
||||
trait A {
|
||||
fun f(a: Int)
|
||||
fun f(a: String)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// "Change function signature..." "true"
|
||||
// ERROR: <html>Class 'B' must be declared abstract or implement abstract member<br/><b>abstract</b> <b>fun</b> f(a: jet.String): jet.Unit <i>defined in</i> A</html>
|
||||
// ERROR: <html>Class 'B' must be declared abstract or implement abstract member<br/><b>internal</b> <b>abstract</b> <b>fun</b> f(a: jet.String): jet.Unit <i>defined in</i> A</html>
|
||||
trait A {
|
||||
fun f(a: Int)
|
||||
fun f(a: String)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// "Change 'B.foo' function return type to 'Int'" "false"
|
||||
// "Change 'B.foo' function return type to 'Long'" "false"
|
||||
// "Remove explicitly specified return type in 'B.foo' function" "false"
|
||||
// ERROR: <html>Return type is 'jet.String', which is not a subtype of overridden<br/><b>internal</b> <b>abstract</b> <b>fun</b> foo() : jet.Int <i>defined in</i> A</html>
|
||||
// ERROR: <html>Return type is 'jet.String', which is not a subtype of overridden<br/><b>internal</b> <b>abstract</b> <b>fun</b> foo(): jet.Int <i>defined in</i> A</html>
|
||||
abstract class A {
|
||||
abstract fun foo() : Int;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user