Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-10-04 14:54:05 +04:00
21 changed files with 203 additions and 32 deletions
@@ -123,6 +123,8 @@ public interface Errors {
DiagnosticWithParameterFactory<JetNamedDeclaration, JetClass> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticWithParameterFactory.create(ERROR, "Non final member in a final class", DiagnosticParameters.CLASS);
DiagnosticWithParameterFactory<JetNamedDeclaration, JetType> PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Public member should specify a type", DiagnosticParameters.TYPE);
SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning
SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here");
SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = SimpleDiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor");
@@ -481,17 +481,7 @@ public class ClassDescriptorResolver {
JetType type = getVariableType(scopeWithTypeParameters, property, true);
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
boolean hasBody = hasBody(property);
Modality defaultModality = getDefaultModality(containingDeclaration, hasBody);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
@@ -513,6 +503,21 @@ public class ClassDescriptorResolver {
return propertyDescriptor;
}
/*package*/ static boolean hasBody(JetProperty property) {
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
return hasBody;
}
@NotNull
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, boolean allowDeferred) {
// TODO : receiver?
@@ -137,6 +137,29 @@ public class DeclarationsChecker {
checkPropertyAbstractness(property, propertyDescriptor, classDescriptor);
checkPropertyInitializer(property, propertyDescriptor, classDescriptor);
checkAccessors(property, propertyDescriptor);
checkDeclaredTypeInPublicMember(property, propertyDescriptor);
}
private void checkDeclaredTypeInPublicMember(JetNamedDeclaration member, CallableMemberDescriptor memberDescriptor) {
PsiElement nameIdentifier = member.getNameIdentifier();
boolean hasDeferredType;
if (member instanceof JetProperty) {
hasDeferredType = ((JetProperty) member).getPropertyTypeRef() == null && ClassDescriptorResolver.hasBody((JetProperty) member);
}
else {
assert member instanceof JetFunction;
JetFunction function = (JetFunction) member;
hasDeferredType = function.getReturnTypeRef() == null && function.getBodyExpression() != null && !function.hasBlockBody();
}
if ((memberDescriptor.getVisibility() == Visibility.PUBLIC || memberDescriptor.getVisibility() == Visibility.PROTECTED) &&
hasDeferredType && nameIdentifier != null) {
JetType returnType = memberDescriptor.getReturnType();
if (returnType instanceof DeferredType) {
returnType = ((DeferredType) returnType).getActualType();
}
context.getTrace().report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member, nameIdentifier, returnType));
}
}
private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {
@@ -232,6 +255,7 @@ public class DeclarationsChecker {
JetModifierList modifierList = function.getModifierList();
ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;
boolean hasAbstractModifier = abstractNode != null;
checkDeclaredTypeInPublicMember(function, functionDescriptor);
if (containingDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
@@ -0,0 +1,92 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author svtk
*/
public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
private JetType type;
public AddReturnTypeFix(@NotNull JetNamedDeclaration element, JetType type) {
super(element);
this.type = type;
}
@NotNull
@Override
public String getText() {
return "Add return type declaration";
}
@NotNull
@Override
public String getFamilyName() {
return "Add return type declaration";
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement newElement;
if (element instanceof JetProperty) {
newElement = addPropertyType(project, (JetProperty) element, type);
}
else {
assert element instanceof JetFunction;
newElement = addFunctionType(project, (JetFunction) element, type);
}
ImportClassHelper.perform(type, element, newElement);
}
@Override
public boolean startInWriteAction() {
return true;
}
public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) {
JetProperty newProperty = (JetProperty) property.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
PsiElement nameIdentifier = newProperty.getNameIdentifier();
addTypeReference(newProperty, typeReference, colon, nameIdentifier);
return newProperty;
}
public static JetFunction addFunctionType(Project project, JetFunction function, JetType type) {
JetFunction newFunction = (JetFunction) function.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
JetParameterList valueParameterList = newFunction.getValueParameterList();
addTypeReference(newFunction, typeReference, colon, valueParameterList);
return newFunction;
}
private static void addTypeReference(JetNamedDeclaration element, JetTypeReference typeReference, Pair<PsiElement, PsiElement> colon, PsiElement anchor) {
assert anchor != null;
element.addAfter(typeReference, anchor);
element.addRangeAfter(colon.getFirst(), colon.getSecond(), anchor);
}
public static JetIntentionActionFactory<JetNamedDeclaration> createFactory() {
return new JetIntentionActionFactory<JetNamedDeclaration>() {
@Override
public JetIntentionAction<JetNamedDeclaration> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetNamedDeclaration;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE);
JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE);
return new AddReturnTypeFix((JetNamedDeclaration) diagnostic.getPsiElement(), type);
}
};
}
}
@@ -103,5 +103,7 @@ public class QuickFixes {
add(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
add(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
add(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
add(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
}
}
@@ -2,7 +2,6 @@ package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
@@ -97,7 +96,7 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
newElement.deleteChildRange(nextSibling, initializer);
if (newElement.getPropertyTypeRef() == null && type != null) {
newElement = addPropertyType(project, newElement, type);
newElement = AddReturnTypeFix.addPropertyType(project, newElement, type);
needImport = true;
}
}
@@ -108,17 +107,6 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
}
}
public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) {
JetProperty newProperty = (JetProperty) property.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
PsiElement nameIdentifier = newProperty.getNameIdentifier();
assert nameIdentifier != null;
newProperty.addAfter(typeReference, nameIdentifier);
newProperty.addRangeAfter(colon.getFirst(), colon.getSecond(), nameIdentifier);
return newProperty;
}
public static JetIntentionActionFactory<JetProperty> createFactory() {
return new JetIntentionActionFactory<JetProperty>() {
@Override
@@ -164,3 +164,8 @@ fun f(): Int {
}
fun f(): Int = if (1 < 2) 1 else returnNothing()
public fun <!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>f<!>() = 1
class B() {
protected fun <!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>f<!>() = "ss"
}
@@ -25,4 +25,5 @@ class Test() {
<!UNRESOLVED_REFERENCE!>$b<!> = <!UNRESOLVED_REFERENCE!>$a<!>
a = <!UNRESOLVED_REFERENCE!>$b<!>
}
public val <!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>i<!> = 1
}
+1 -1
View File
@@ -3,7 +3,7 @@ class Outer() {
val outer: Outer get() = this@Outer
}
public val x = Inner()
public val x : Inner = Inner()
}
fun box() : String {
@@ -1,5 +1,5 @@
open class Base() {
public val plain = 239
val plain = 239
public val read : Int
get() = 239
@@ -1,5 +1,5 @@
class Outer() {
public val s = "xyzzy"
val s = "xyzzy"
open class InnerBase(public val name: String) {
}
@@ -7,7 +7,7 @@ class Outer() {
class InnerDerived(): InnerBase(s) {
}
public val x = InnerDerived()
val x = InnerDerived()
}
fun box() : String {
@@ -0,0 +1,6 @@
// "Add return type declaration" "true"
namespace a
class A() {
protected fun <caret>foo() : Int = 1
}
@@ -0,0 +1,6 @@
// "Add return type declaration" "true"
namespace a
class A() {
public fun <caret>foo() : String = "a"
}
@@ -0,0 +1,6 @@
// "Add return type declaration" "true"
namespace a
import java.util.List
public val <caret>l : List<Int>? = java.util.Collections.emptyList<Int>()
@@ -0,0 +1,6 @@
// "Add return type declaration" "false"
namespace a
class A() {
internal protected fun <caret>foo() = 1
}
@@ -0,0 +1,6 @@
// "Add return type declaration" "true"
namespace a
class A() {
protected fun <caret>foo() = 1
}
@@ -0,0 +1,6 @@
// "Add return type declaration" "false"
namespace a
class A() {
public fun <caret>foo()
}
@@ -0,0 +1,6 @@
// "Add return type declaration" "true"
namespace a
class A() {
public fun <caret>foo() = "a"
}
@@ -0,0 +1,4 @@
// "Add return type declaration" "true"
namespace a
public val <caret>l = java.util.Collections.emptyList<Int>()
@@ -34,7 +34,7 @@ public class PropertyGenTest extends CodegenTestCase {
}
public void testPublicVar() throws Exception {
loadText("class PublicVar() { public var foo = 0; }");
loadText("class PublicVar() { public var foo : Int = 0; }");
final Class aClass = loadImplementationClass(generateClassesInFile(), "PublicVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setFoo");
@@ -44,7 +44,7 @@ public class PropertyGenTest extends CodegenTestCase {
}
public void testAccessorsInInterface() {
loadText("class AccessorsInInterface() { public var foo = 0; }");
loadText("class AccessorsInInterface() { public var foo : Int = 0; }");
final Class aClass = loadClass("AccessorsInInterface", generateClassesInFile());
assertNotNull(findMethodByName(aClass, "getFoo"));
assertNotNull(findMethodByName(aClass, "setFoo"));
@@ -108,7 +108,7 @@ public class PropertyGenTest extends CodegenTestCase {
}
public void testInitializersForNamespaceProperties() throws Exception {
loadText("public val x = System.currentTimeMillis()");
loadText("val x = System.currentTimeMillis()");
final Method method = generateFunction("getX");
assertIsCurrentTime((Long) method.invoke(null));
}
@@ -136,7 +136,7 @@ public class PropertyGenTest extends CodegenTestCase {
}
public void testKt160() throws Exception {
loadText("public val s = java.lang.Double.toString(1.0)");
loadText("internal val s = java.lang.Double.toString(1.0)");
final Method method = generateFunction("getS");
assertEquals(method.invoke(null), "1.0");
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.jet.JetTestCaseBase;
/**
@@ -21,5 +22,10 @@ public class TypeAdditionFixTests extends LightQuickFixTestCase {
protected String getTestDataPath() {
return JetTestCaseBase.getTestDataPathBase();
}
@Override
protected Sdk getProjectJDK() {
return JetTestCaseBase.jdkFromIdeaHome();
}
}