diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java index e05beea88c9..2d4c059a84f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -9,6 +9,8 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; /** + * Stores a number of semantic services. Should be created once for each kotlin project. + * * @author abreslav */ public class JetSemanticServices { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java index faf32b925fd..fca01a74182 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java @@ -10,6 +10,9 @@ import java.util.Collections; import java.util.List; /** + * Type reference element. + * Underlying token is {@link org.jetbrains.jet.JetNodeTypes#TYPE_REFERENCE} + * * @author max */ public class JetTypeReference extends JetElement { @@ -36,6 +39,15 @@ public class JetTypeReference extends JetElement { return findChildByClass(JetTypeElement.class); } + /** + * Will return not null for type references with internal user type. + * There could be other JetTypeReferences, see parsing of in {@link org.jetbrains.jet.lang.parsing.JetParsing} + */ + @Nullable + public JetUserType getUserType() { + return findChildByClass(JetUserType.class); + } + public List getAnnotations() { List answer = null; for (JetAnnotation annotation : getAttributeAnnotations()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 5a14b835dad..2061bf240d5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -41,11 +41,15 @@ public interface BindingContext { WritableSlice> INDEXED_LVALUE_SET = Slices.createSimpleSlice(); WritableSlice AUTOCAST = Slices.createSimpleSlice(); + + /** A scope where type of expression has been resolved */ WritableSlice RESOLUTION_SCOPE = Slices.createSimpleSlice(); WritableSlice VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice(); WritableSlice AUTO_CREATED_IT = Slices.createSimpleSetSlice(); WritableSlice VARIABLE_ASSIGNMENT = Slices.createSimpleSlice(); + + /** Was type of current expression has been already resolved */ WritableSlice PROCESSED = Slices.createSimpleSetSlice(); WritableSlice STATEMENT = Slices.createRemovableSetSlice(); WritableSlice DELEGATED = Slices.createRemovableSetSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 654135be994..f3694bf4ec4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -49,11 +49,20 @@ public class TypeResolver { JetTypeElement typeElement = typeReference.getTypeElement(); JetType type = resolveTypeElement(scope, annotations, typeElement, false); trace.record(BindingContext.TYPE, typeReference, type); + + final JetUserType jetUserType = typeReference.getUserType(); + if (jetUserType != null) { + final JetSimpleNameExpression referenceExpression = jetUserType.getReferenceExpression(); + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, scope); + } + return type; } @NotNull - private JetType resolveTypeElement(final JetScope scope, final List annotations, JetTypeElement typeElement, final boolean nullable) { + private JetType resolveTypeElement(final JetScope scope, final List annotations, + JetTypeElement typeElement, final boolean nullable) { + final JetType[] result = new JetType[1]; if (typeElement != null) { typeElement.accept(new JetVisitorVoid() { @@ -70,6 +79,7 @@ public class TypeResolver { resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments()); return; } + if (classifierDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor; diff --git a/idea/testData/completion/basic/ExtendClassName.kt b/idea/testData/completion/basic/ExtendClassName.kt new file mode 100644 index 00000000000..47daf28eff9 --- /dev/null +++ b/idea/testData/completion/basic/ExtendClassName.kt @@ -0,0 +1,13 @@ +open class MySecondClass() { +} + +open class MyFirstClass { + +} + +class A() : My { + public fun test() { + } +} + +// EXIST: MySecondClass, MyFirstClass \ No newline at end of file diff --git a/idea/testData/completion/basic/VariableClassName.kt b/idea/testData/completion/basic/VariableClassName.kt new file mode 100644 index 00000000000..0296a23af4c --- /dev/null +++ b/idea/testData/completion/basic/VariableClassName.kt @@ -0,0 +1,10 @@ +open class MyClass() { +} + +class A() : My { + public fun test() { + val a : MyC + } +} + +// EXIST: MyClass \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java new file mode 100644 index 00000000000..00d91a18421 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java @@ -0,0 +1,58 @@ +package org.jetbrains.jet.completion; + +import junit.framework.TestSuite; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetTestCaseBuilder; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; + +/** + * @author Nikolay.Krasko + */ +public class JetBasicCompletion extends JetCompletionTestBase { + private final String myPath; + private final String myName; + + public JetBasicCompletion(@NotNull String path, @NotNull String name) { + myPath = path; + myName = name; + + // Set name explicitly because otherwise there will be "TestCase.fName cannot be null" + setName("testCompletionExecute"); + } + + public void testCompletionExecute() { + doTest(); + } + + @Override + protected String getTestDataPath() { + return new File(PluginTestCaseBase.getTestDataPathBase(), myPath).getPath() + + File.separator; + } + + @NotNull + @Override + public String getName() { + return "test" + myName; + } + + @NotNull + public static TestSuite suite() { + TestSuite suite = new TestSuite(); + + JetTestCaseBuilder.appendTestsInDirectory( + PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/", false, + JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { + + @NotNull + @Override + public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name) { + return new JetBasicCompletion(dataPath, name); + } + }, suite); + + return suite; + } +} diff --git a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java index f214d6e0043..1df0d5ef2cf 100644 --- a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java @@ -22,10 +22,10 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { myName = name; // Set name explicitly because otherwise there will be "TestCase.fName cannot be null" - setName("testComletionExecute"); + setName("testCompletionExecute"); } - public void testComletionExecute() { + public void testCompletionExecute() { doTest(); }