From d1409116f350b0beb1d3a53497d1d438798a9827 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 7 Feb 2012 20:05:58 +0400 Subject: [PATCH] - KT-1147 Can't see local variable in completion - Disable class level keywords from method parameters list - Reorganize completion tests to separate methods --- .../lang/descriptors/DescriptorsUtils.java | 3 +- .../jet/lang/psi/JetSimpleNameExpression.java | 13 ++- .../JetKeywordCompletionContributor.java | 2 +- .../completion/basic/BeforeDotInCall.kt | 19 ++++ .../completion/basic/InMiddleOfNamespace.kt | 9 ++ .../keywords/InMethodParametersList.kt | 55 +++++++++++ .../completion/ExpectedCompletionUtils.java | 21 ++++- .../completion/ExtensionsCompletionTest.java | 60 +++++++----- .../completion/JetBasicCompletionTest.java | 75 +++++++++++---- .../jet/completion/JetCompletionTestBase.java | 68 ++++++-------- .../completion/KeywordsCompletionTest.java | 93 +++++++++++++++---- .../handlers/JavaCompletionHandlerTest.java | 2 + 12 files changed, 309 insertions(+), 111 deletions(-) create mode 100644 idea/testData/completion/basic/BeforeDotInCall.kt create mode 100644 idea/testData/completion/basic/InMiddleOfNamespace.kt create mode 100644 idea/testData/completion/keywords/InMethodParametersList.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java index dd4081398c2..f28f1ec954c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java @@ -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"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java index 133e8581b4c..4561715a993 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java @@ -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; diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index 0e6b5eb5570..7a06187bc76 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -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 diff --git a/idea/testData/completion/basic/BeforeDotInCall.kt b/idea/testData/completion/basic/BeforeDotInCall.kt new file mode 100644 index 00000000000..faafd3e035c --- /dev/null +++ b/idea/testData/completion/basic/BeforeDotInCall.kt @@ -0,0 +1,19 @@ +package testing + +fun testTop() { + +} + +class TestSample() { + fun main(args : Array) { + val testVar = "" + test.testFun() + } + + fun testFun() { + + } +} + +// TIME: 2 +// EXIST: testVar, testFun, testTop \ No newline at end of file diff --git a/idea/testData/completion/basic/InMiddleOfNamespace.kt b/idea/testData/completion/basic/InMiddleOfNamespace.kt new file mode 100644 index 00000000000..020ba806ac0 --- /dev/null +++ b/idea/testData/completion/basic/InMiddleOfNamespace.kt @@ -0,0 +1,9 @@ +package testdata.kotlin.data + +class TestSample() { + fun main(args : Array) { + testdata.kotlin.data.TestSample() + } +} + +// EXIST: kotlin \ No newline at end of file diff --git a/idea/testData/completion/keywords/InMethodParametersList.kt b/idea/testData/completion/keywords/InMethodParametersList.kt new file mode 100644 index 00000000000..cd762862b7f --- /dev/null +++ b/idea/testData/completion/keywords/InMethodParametersList.kt @@ -0,0 +1,55 @@ +package TestData + +class TestSample() { + fun test() { + } +} + +// 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 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java index b89c61f11ad..52fb79372c3 100644 --- a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java +++ b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java @@ -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 result = new ArrayList(); @@ -88,7 +100,6 @@ public class ExpectedCompletionUtils { private static List fileNonEmptyLines(String fileText) { ArrayList result = new ArrayList(); - 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; diff --git a/idea/tests/org/jetbrains/jet/completion/ExtensionsCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/ExtensionsCompletionTest.java index 5484200d560..bf05a1f8621 100644 --- a/idea/tests/org/jetbrains/jet/completion/ExtensionsCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/ExtensionsCompletionTest.java @@ -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; } } diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 4bb6dd31b89..b22ea0075d6 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -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; } } diff --git a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java index 24639142147..ab2eecf8ce7 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java +++ b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java @@ -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); } } diff --git a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java index cc45d46b28b..7761deffec8 100644 --- a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java @@ -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; } } diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/JavaCompletionHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/JavaCompletionHandlerTest.java index 6849817f3fb..3be6a4378a8 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/JavaCompletionHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/JavaCompletionHandlerTest.java @@ -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); }