- KT-1147 Can't see local variable in completion

- Disable class level keywords from method parameters list
- Reorganize completion tests to separate methods
This commit is contained in:
Nikolay Krasko
2012-02-07 20:05:58 +04:00
parent adfce7e22d
commit d1409116f3
12 changed files with 309 additions and 111 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.util.QualifiedNamesUtil;
/**
* @author Nikolay Krasko
@@ -28,7 +29,7 @@ public final class DescriptorsUtils {
public static String getFQName(@NotNull NamedFunctionDescriptor functionDescriptor) {
if (functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
final String namespaceFQN = getFQName((NamespaceDescriptor) functionDescriptor.getContainingDeclaration());
return !namespaceFQN.isEmpty() ? namespaceFQN + "." + functionDescriptor.getName() : functionDescriptor.getName();
return QualifiedNamesUtil.combine(namespaceFQN, functionDescriptor.getName());
}
throw new IllegalArgumentException("Currently supported only for top level functions");
@@ -32,7 +32,9 @@ public class JetSimpleNameExpression extends JetReferenceExpression {
PsiElement parent = getParent();
if (parent instanceof JetQualifiedExpression && !isImportDirectiveExpression()) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
return qualifiedExpression.getReceiverExpression();
if (!isFirstPartInQualifiedExpression(qualifiedExpression)) {
return qualifiedExpression.getReceiverExpression();
}
} else if (parent instanceof JetCallExpression) {
//This is in case `a().b()`
JetCallExpression callExpression = (JetCallExpression) parent;
@@ -45,6 +47,15 @@ public class JetSimpleNameExpression extends JetReferenceExpression {
return null;
}
// Check that this is simple name expression is first part in full qualified name: firstPart.otherPart.otherPart.call()
private boolean isFirstPartInQualifiedExpression(JetQualifiedExpression qualifiedExpression) {
if (qualifiedExpression.getParent() instanceof JetQualifiedExpression) {
return isFirstPartInQualifiedExpression((JetQualifiedExpression) qualifiedExpression.getParent());
}
return qualifiedExpression.getFirstChild() == this;
}
public boolean isImportDirectiveExpression() {
PsiElement parent = getParent();
if (parent == null) return false;
@@ -123,7 +123,7 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
public boolean isAcceptable(Object element, PsiElement context) {
//noinspection unchecked
return PsiTreeUtil.getParentOfType(context, JetClassBody.class, true,
JetBlockExpression.class, JetProperty.class) != null;
JetBlockExpression.class, JetProperty.class, JetParameterList.class) != null;
}
@Override
@@ -0,0 +1,19 @@
package testing
fun testTop() {
}
class TestSample() {
fun main(args : Array<String>) {
val testVar = ""
test<caret>.testFun()
}
fun testFun() {
}
}
// TIME: 2
// EXIST: testVar, testFun, testTop
@@ -0,0 +1,9 @@
package testdata.kotlin.data
class TestSample() {
fun main(args : Array<String>) {
testdata.kot<caret>lin.data.TestSample()
}
}
// EXIST: kotlin
@@ -0,0 +1,55 @@
package TestData
class TestSample() {
fun test(<caret>) {
}
}
// ABSENT: abstract
// ABSENT: annotation
// ABSENT: as
// ABSENT: break
// ABSENT: by
// ABSENT: catch
// ABSENT: class
// ABSENT: continue
// ABSENT: do
// ABSENT: else
// ABSENT: enum
// ABSENT: false
// ABSENT: final
// ABSENT: finally
// ABSENT: for
// ABSENT: fun
// ABSENT: get
// ABSENT: if
// ABSENT: import
// ABSENT: in
// ABSENT: inline
// ABSENT: internal
// ABSENT: is
// ABSENT: null
// ABSENT: object
// ABSENT: open
// EXIST: out
// ABSENT: override
// ABSENT: package
// ABSENT: private
// ABSENT: protected
// ABSENT: public
// ABSENT: return
// ABSENT: set
// ABSENT: super
// ABSENT: This
// ABSENT: this
// ABSENT: throw
// ABSENT: trait
// ABSENT: true
// ABSENT: try
// ABSENT: type
// ABSENT: val
// ABSENT: var
// ABSENT: vararg
// ABSENT: when
// ABSENT: where
// ABSENT: while
@@ -20,20 +20,22 @@ public class ExpectedCompletionUtils {
public static final String EXIST_LINE_PREFIX = "// EXIST:";
public static final String ABSENT_LINE_PREFIX = "// ABSENT:";
public static final String NUMBER_LINE_PREFIX = "// NUMBER:";
public static final String EXECUTION_TIME_PREFIX = "// TIME:";
private final String existLinePrefix;
private final String absentLinePrefix;
private final String numberLinePrefix;
private final String executionTimePrefix;
public ExpectedCompletionUtils() {
this(EXIST_LINE_PREFIX, ABSENT_LINE_PREFIX, NUMBER_LINE_PREFIX);
this(EXIST_LINE_PREFIX, ABSENT_LINE_PREFIX, NUMBER_LINE_PREFIX, EXECUTION_TIME_PREFIX);
}
public ExpectedCompletionUtils(String existLinePrefix, String absentLinePrefix, String numberLinePrefix) {
public ExpectedCompletionUtils(String existLinePrefix, String absentLinePrefix, String numberLinePrefix, String execitionTimePrefix) {
this.existLinePrefix = existLinePrefix;
this.absentLinePrefix = absentLinePrefix;
this.numberLinePrefix = numberLinePrefix;
this.executionTimePrefix = execitionTimePrefix;
}
@NotNull
@@ -56,6 +58,16 @@ public class ExpectedCompletionUtils {
return null;
}
@Nullable
public Integer getExecutionTime(String fileText) {
final String[] numberStrings = findListWithPrefix(executionTimePrefix, fileText);
if (numberStrings.length > 0) {
return Integer.parseInt(numberStrings[0]);
}
return null;
}
@NotNull
private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>();
@@ -88,7 +100,6 @@ public class ExpectedCompletionUtils {
private static List<String> fileNonEmptyLines(String fileText) {
ArrayList<String> result = new ArrayList<String>();
try {
BufferedReader reader = new BufferedReader(new StringReader(fileText));
try {
@@ -103,7 +114,7 @@ public class ExpectedCompletionUtils {
reader.close();
}
} catch(IOException e) {
assert false;
throw new AssertionError(e);
}
return result;
@@ -1,9 +1,5 @@
package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
@@ -13,31 +9,45 @@ import java.io.File;
*/
public class ExtensionsCompletionTest extends JetCompletionTestBase {
// public ExtensionsCompletionTest() {
// this("/completion/basic/extensions", "IrrelevantExtension");
// // this("/completion/basic/extensions", "InvalidTypeParameters");
// // this("/completion/basic/extensions", "ExtensionInExtensionThis");
// }
protected ExtensionsCompletionTest(@NotNull String path, @NotNull String name) {
super(path, name);
public void testExtensionInExtendedClass() {
doTest();
}
@NotNull
public static TestSuite suite() {
TestSuite suite = new TestSuite();
public void testExtensionInExtendedClassThis() {
doTest();
}
JetTestCaseBuilder.appendTestsInDirectory(
PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/extensions", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
public void testExtensionInExtension() {
doTest();
}
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new ExtensionsCompletionTest(dataPath, name);
}
}, suite);
public void testExtensionInExtensionThis() {
doTest();
}
return suite;
public void testInvalidTypeParameters() {
doTest();
}
public void testIrrelevantExtension() {
doTest();
}
public void testJavaTypeExtension() {
doTest();
}
public void testKotlinGenericTypeExtension() {
doTest();
}
public void testKotlinTypeExtension() {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/extensions").getPath() +
File.separator;
}
}
@@ -1,9 +1,5 @@
package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
@@ -13,25 +9,66 @@ import java.io.File;
*/
public class JetBasicCompletionTest extends JetCompletionTestBase {
protected JetBasicCompletionTest(@NotNull String path, @NotNull String name) {
super(path, name);
public void testBeforeDotInCall() {
doTest();
}
@NotNull
public static TestSuite suite() {
TestSuite suite = new TestSuite();
public void testExtendClassName() {
doTest();
}
JetTestCaseBuilder.appendTestsInDirectory(
PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
public void testExtendQualifiedClassName() {
doTest();
}
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new JetBasicCompletionTest(dataPath, name);
}
}, suite);
public void testFromImports() {
doTest();
}
return suite;
public void testInCallExpression() {
doTest();
}
public void testInEmptyImport() {
doTest();
}
public void testInImport() {
doTest();
}
// TODO: activate this test
public void todotestInMiddleOfNamespace() {
doTest();
}
public void testJavaClassNames() {
doTest();
}
public void testJavaPackage() {
doTest();
}
public void testNamedObject() {
doTest();
}
public void testOverloadFunctions() {
doTest();
}
public void testSubpackageInFun() {
doTest();
}
public void testVariableClassName() {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/basic").getPath() +
File.separator;
}
}
@@ -7,60 +7,48 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
/**
* @author Nikolay.Krasko
*/
public abstract class JetCompletionTestBase extends LightCompletionTestCase {
private final String myPath;
private final String myName;
protected JetCompletionTestBase(@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() throws Exception {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), myPath).getPath() +
File.separator;
}
@NotNull
@Override
public String getName() {
return "test" + myName;
}
private final ExpectedCompletionUtils completionUtils = new ExpectedCompletionUtils();
private CompletionType type;
protected void doTest() throws Exception {
final String testName = getTestName(false);
@Override
protected abstract String getTestDataPath();
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
protected void doTest() {
try {
final String testName = getTestName(false);
configureByFile(testName + ".kt");
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
final String fileText = getFile().getText();
final ExpectedCompletionUtils completionUtils = new ExpectedCompletionUtils();
configureByFileNoComplete(testName + ".kt");
assertContainsItems(completionUtils.itemsShouldExist(fileText));
assertNotContainItems(completionUtils.itemsShouldAbsent(fileText));
Integer itemsNumber = completionUtils.getExpectedNumber(fileText);
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
final String fileText = getFile().getText();
Integer completionTime = completionUtils.getExecutionTime(fileText);
complete(completionTime == null ? 1 : completionTime);
final String[] expected = completionUtils.itemsShouldExist(fileText);
final String[] unexpected = completionUtils.itemsShouldAbsent(fileText);
Integer itemsNumber = completionUtils.getExpectedNumber(fileText);
assertTrue("Should be some assertions about completion", expected.length != 0 || unexpected.length != 0 || itemsNumber != null);
assertContainsItems(expected);
assertNotContainItems(unexpected);
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
@@ -1,9 +1,5 @@
package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
@@ -15,26 +11,85 @@ import java.io.File;
*/
public class KeywordsCompletionTest extends JetCompletionTestBase {
protected KeywordsCompletionTest(@NotNull String path, @NotNull String name) {
super(path, name);
public void testAfterClassProperty() {
doTest();
}
@NotNull
public static TestSuite suite() {
TestSuite suite = new TestSuite();
public void testAfterDot() {
doTest();
}
JetTestCaseBuilder.appendTestsInDirectory(
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
public void testAfterSpaceAndDot() {
doTest();
}
public void testclassObject() {
doTest();
}
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new KeywordsCompletionTest(dataPath, name);
}
}, suite);
public void testInBlockComment() {
doTest();
}
return suite;
public void testInChar() {
doTest();
}
public void testInClassBeforeFun() {
doTest();
}
public void testInClassProperty() {
doTest();
}
public void testInClassScope() {
doTest();
}
public void testInFunctionScope() {
doTest();
}
public void testInParametersList() {
doTest();
}
public void testInMethodParametersList() {
doTest();
}
public void testInString() {
doTest();
}
public void testInTopProperty() {
doTest();
}
public void testInTopScopeAfterPackage() {
doTest();
}
public void testInTypeScope() {
doTest();
}
public void testLineComment() {
doTest();
}
public void testPropertySetterGetter() {
doTest();
}
public void testTopScope() {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords").getPath() +
File.separator;
}
}
@@ -20,6 +20,8 @@ public class JavaCompletionHandlerTest extends CompletionTestCase {
configureByFiles(null, fileName + ".java", fileName + ".kt");
complete(2);
checkResultByFile(fileName + ".after.java");
} catch (@SuppressWarnings("CaughtExceptionImmediatelyRethrown") AssertionError assertionError) {
throw assertionError;
} catch (Exception e) {
throw new AssertionError(e);
}