/*
* Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan
*
* 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 com.goide.completion;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.TreePrintCondition;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import java.util.List;
public class GoCompletionTest extends GoCompletionTestBase {
public void testPackageWithoutAlias() {
doTestInclude("package foo; import `fmt`; func main(){<caret>}", "fmt");
}
public void testLocalFunction() {
doTestInclude("package foo; func foo() {}; func main() {<caret>}", "foo", "main");
}
public void testLocalType() {
doTestInclude("package foo; type (T struct {}; T2 struct{}); func main(){var i <caret>}", "T", "T2");
}
public void testLocalFunctionInDifferentFiles() {
myFixture.copyFileToProject(getTestName(true) + "_context.go", "importPath/context.go");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(true) + ".go", "importPath/main.go"));
myFixture.completeBasic();
myFixture.checkResultByFile(getTestName(true) + "_after.go");
}
public void testImportVendoringPackages() {
myFixture.addFileToProject("vendor/pack1/pack2/test.go", "package foo");
doCheckResult("package foo; import `pa<caret>`", "package foo; import `pack1/pack2<caret>`");
}
public void testImportVendoringPackagesWithDisabledVendoring() {
disableVendoring();
myFixture.addFileToProject("vendor/pack1/pack2/test.go", "package foo");
doCheckResult("package foo; import `pa<caret>`", "package foo; import `vendor/pack1/pack2<caret>`", Lookup.NORMAL_SELECT_CHAR);
}
public void testImportPackages() {
myFixture.addFileToProject("package1/pack/test.go", "package foo");
myFixture.addFileToProject("package2/pack/test.go", "package bar");
myFixture.configureByText("test.go", "package foo; import `pack<caret>`");
myFixture.completeBasic();
List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertSameElements(lookupElementStrings, "package1/pack", "package2/pack");
}
public void testImportPackagesWithoutClosingQuote() {
myFixture.addFileToProject("package1/pack/test.go", "package foo");
myFixture.addFileToProject("package2/pack/test.go", "package bar");
myFixture.configureByText("test.go", "package foo; import `pack<caret>");
myFixture.completeBasic();
List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertSameElements(lookupElementStrings, "package1/pack", "package2/pack");
}
public void testImportRelativePackages() {
myFixture.addFileToProject("package1/pack/test.go", "package foo");
myFixture.addFileToProject("package2/pack/test.go", "package bar");
myFixture.configureByText("test.go", "package foo; import `./pack<caret>`");
myFixture.completeBasic();
List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertSameElements(lookupElementStrings, "package1", "package2");
}
public void testDoNotCompleteFullPackagesForRelativeImports() {
myFixture.addFileToProject("package1/pack/test.go", "package foo");
myFixture.addFileToProject("package2/pack/test.go", "package bar");
myFixture.configureByText("test.go", "package foo; import `./pack<caret>`");
myFixture.completeBasic();
List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertSameElements(lookupElementStrings, "package1", "package2");
}
public void testDoNotCompleteOwnImportPath() {
myFixture.addFileToProject("package/long/long/path/test.go", "package pack");
PsiFile testFile = myFixture.addFileToProject("package/very/long/path/but/same/package/test.go",
"package pack; import `package/<caret>`");
myFixture.configureFromExistingVirtualFile(testFile.getVirtualFile());
myFixture.completeBasic();
myFixture.checkResult("package pack; import `package/long/long/path`");
}
public void testImportsPriority() {
myFixture.addFileToProject("package/long/but/similar/path/test.go", "package pack");
myFixture.addFileToProject("package/very/long/path/test.go", "package pack");
myFixture.addFileToProject("package/middle/path/test.go", "package pack");
myFixture.addFileToProject("package/short/test.go", "package pack");
PsiFile testFile = myFixture.addFileToProject("package/long/but/similar/test.go", "package pack; import `package/<caret>`");
myFixture.configureFromExistingVirtualFile(testFile.getVirtualFile());
myFixture.completeBasic();
myFixture.assertPreferredCompletionItems(0, "package/long/but/similar/path", "package/short", "package/middle/path",
"package/very/long/path");
}
public void testDoNotHidePopupOnSlash() {
myFixture.addFileToProject("package1/pack/test.go", "package foo");
myFixture.addFileToProject("package2/pack/test.go", "package bar");
myFixture.configureByText("test.go", "package foo; import `<caret>`");
myFixture.completeBasic();
myFixture.type("package1/\n");
myFixture.checkResult("package foo; import `package1/pack<caret>`");
}
public void testLocalVar() {
doTestInclude("package foo; func main(){var i, j int; <caret>}", "i", "j");
}
public void testPackageLocalVar() {
doTestInclude("package foo; var i, j int; func main(){<caret>}", "i", "j");
}
public void testLocalVarExclude() {
doTestExclude("package foo; func main(){{var i, j int;}; <caret>}", "i", "j");
}
public void testParams() {
doTestInclude("package foo; func main(i, j int){<caret>}", "i", "j");
}
public void testConsts() {
doTestInclude("package foo; const i, j; func main(){<caret>}", "i", "j");
}
public void testNoCompletionInsideStrings() {
doTestEquals("package foo; func main(){\"<caret>\"}");
}
public void testNoKeywordCompletionInsideTypeDeclarationList() {
doTestEquals("package foo; type (\n\t<caret>\n)");
}
public void testNoKeywordCompletionInsideConstDeclarationList() {
doTestEquals("package foo; const (\n\t<caret>\n)");
}
public void testNoKeywordCompletionInsideVarDeclarationList() {
doTestEquals("package foo; var (\n\t<caret>\n)");
}
public void testKeywordCompletionInsideVarDeclarationListAfterEquals() {
doTestInclude("package foo; var (\n\ta = <caret>\n)", "map", "func", "struct");
}
public void testNoCompletionInsideComments() {
doTestEquals("package foo; func main(){/*<caret>*/}");
}
public void testStructTypes() {
doTestEquals("package foo; type AA struct {N AA}; func foo(a AA) {a.<caret>}", "N");
}
public void testStructTypes2() {
doTestEquals("package foo; type AA struct {N AA}; func foo(a *AA) {a.<caret>}", "N");
}
public void testStructKeyword() {
doCheckResult("package main; func main() { d := struct { name str<caret> }; _ = d }",
"package main; func main() { d := struct { name struct{} }; _ = d }");
}
public void testStructKeyword2() {
doTestInclude("package main; func main() { d := struct { name <caret> }; _ = d }", "struct");
}
public void testStructKeyword3() {
doCheckResult("package main; func main() { d := str<caret>; _ = d }",
"package main; func main() { d := struct {\n" +
"\t<caret>\n" +
"}{}; _ = d }");
}
public void testImports() {
doCheckResult("package foo; import imp \"\"; func foo(a im<caret>) {}", "package foo; import imp \"\"; func foo(a imp.) {}");
}
public void testImportsForRefs() {
doCheckResult("package foo; import imp \"\"; func foo() {im<caret>.foo}", "package foo; import imp \"\"; func foo() {imp.<caret>foo}");
}
public void testCompleteFieldWithoutColon() {
doCheckResult("package main;func main(){a:=struct{Demo int}{Demo:1};println(a.D<caret>)}",
"package main;func main(){a:=struct{Demo int}{Demo:1};println(a.Demo<caret>)}");
}
public void testCompleteFieldWithoutColonAfterKey() {
doCheckResult("package main; type Test struct { ID string }; func t() { var n Test; _ = &Test{ID: n.I<caret>} }",
"package main; type Test struct { ID string }; func t() { var n Test; _ = &Test{ID: n.ID<caret>} }");
}
public void testTopLevelKeywords() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "const", "func", "import", "type", "var");
}
public void testTopLevelKeywords_2() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "const", "func", "type", "var");
}
public void testBlockKeywords() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "for", "const", "var", "return", "if", "switch", "go", "defer", "select",
"fallthrough", "goto", "main", "struct", "map", "type");
}
public void testBlockKeywordsInsideOneLineFunction() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "for", "const", "var", "return", "if", "switch", "go", "defer", "select",
"fallthrough", "goto", "main", "struct", "map", "type");
}
public void testBlockKeywordsInsideCaseStatement() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "break", "for", "const", "var", "return", "if", "switch", "go", "defer", "select",
"fallthrough", "goto", "main", "struct", "map", "case", "default", "type");
}
public void testAddSpaceAfterKeyword() {
doTestCompletion();
}
public void testTypeKeywords() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "struct", "interface", "chan", "map");
}
public void testExpressionKeywords() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "struct", "map", "main", "func");
}
public void testTypeKeywordsInsideParentheses() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "chan", "map", "interface", "struct");
}
public void testSelectKeywordInsertHandler() {
doTestCompletion();
}
public void testTypeKeywordInsertBraces() {
doTestCompletion();
}
public void testTypeKeywordDoNotInsertBraces() {
doTestCompletion();
}
public void testInterfaceKeywordAsFunctionParameter() {
doTestCompletion();
}
public void testStructKeywordAsFunctionParameter() {
doTestCompletion();
}
public void testForStatementKeywords() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "bar", "break", "const", "continue", "defer", "for", "go", "if", "return",
"fallthrough", "goto", "select", "switch", "var", "struct", "map", "type");
}
public void testForStatementKeywordsInsideFuncLit() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "bar", "const", "defer", "for", "go", "if", "return",
"fallthrough", "goto", "select", "switch", "var", "struct", "map", "type");
}
public void testDoNotCompleteKeywordsInsideConstSpec() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "a");
}
public void testDoNotCompleteKeywordsInsideSelectorExpression() {
myFixture.testCompletionVariants(getTestName(true) + ".go", "FuncA", "FuncB");
}
public void testRangeKeyword_1() {
doTestCompletion();
}
public void testRangeKeyword_2() {
doTestCompletion();
}
public void testRangeKeyword_3() {
doTestCompletion();
}
public void testChanKeyword() {
doTestCompletion();
}
public void testChanKeyword_2() {
doTestCompletion();
}
public void testChanKeyword_3() {
doTestCompletion();
}
public void testMapKeyword() {
doTestCompletion();
}
public void testMapKeyword_2() {
doTestCompletion();
}
public void testMapKeywordInsertHandler() {
doTestCompletion();
}
public void testMapKeywordInsertHandlerDoNotInsertBrackets() {
doTestCompletion();
}
public void testElseKeyword() {
doTestCompletion();
}
public void testElseKeywordRegression() {
doTestEmptyCompletion();
}
public void testIfKeywordAfterElse() {
doTestCompletion();
}
public void testForStatementKeywordsDoNotInsertSpace() {
doTestCompletion();
}
public void testFunctionInDefer() {
doTestCompletion();
}
public void testFunctionAsFunctionArgument() {
doTestCompletion();
}
public void testFunctionAsVariableValue() {
doTestCompletion();
}
public void testFunctionInGo() {
doTestCompletion();
}
public void testPackageKeyword() {
doTestCompletion();
}
public void testPackageKeywordInEmptyFile() {
doTestCompletion();
}
public void testExpressionCaseKeywordCompletion() {
doTestCompletion();
}
public void testExpressionDefaultKeywordCompletion() {
doTestCompletion();
}
public void testTypeCaseKeywordCompletion() {
doTestCompletion();
}
public void testTypeDefaultKeywordCompletion() {
doTestCompletion();
}
public void testMethods() {
doTestEquals("package foo; type T interface{}; func (t T) f() {t.<caret>}", "f");
}
public void testPreventStackOverflow() {
doTestEquals("package foo; type E struct {*E}; func (e E) foo() {}; func main() {e := E{}; e.<caret>}", "foo", "E");
}
public void testNestedStructures() {
doTestEquals("package foo; type E struct {}; type B struct {E}; func (e E) foo() {}; func (b B) bar(){}" +
"func main() {b := B{}; b.<caret>}", "foo", "bar", "E");
}
public void testNestedStructures2() {
doTestEquals("package foo; type E struct {}; type B struct {E}; func (e E) foo() {}; " +
"func main() {b := B{}; b.E.<caret>}", "foo");
}
public void testNestedStructures3() {
doTestEquals("package foo; type E struct {}; type B struct {E}; func (e E) foo() {}; " +
"func main() {B{}.E.<caret>}", "foo");
}
public void testInterfaceTypes() {
doTestInclude("package foo; type E interface {}; type B interface {<caret>}", "E");
}
public void testReceiverCompletion() {
doTestInclude("package foo; type E interface {}; func (e <caret>", "E");
}
public void testInterfaceTypesNoStruct() {
doTestExclude("package foo; type E struct {}; type B interface {<caret>}", "E");
}
public void testOnlyTypesInParameters() {
doTestExclude("package foo; const a int = 1; var b = 2; func main(<caret>) {}", "a", "b", "main");
}
public void testInnerTypes() {
doTestInclude("package foo; func foo() {type innerType struct {}; var i <caret>}", "innerType");
}
public void testChannelType() {
doTestInclude("package foo; func foo() {type T struct {cn *T}; var i T; i.<caret>}", "cn");
}
public void testInterfaceType() {
doTestInclude("package foo; func foo(i interface {Boo() int}) {i.<caret>}", "Boo");
}
public void testInterfaceType2() {
doTestInclude("package foo; type I interface {Boo() int}; func foo(i I) {i.<caret>}", "Boo");
}
public void testLabel() {
doTestInclude("package foo; func main() { goto <caret>; Label1: 1}", "Label1");
}
public void testNoKeywordsInReceiver() {
doTestExclude("package foo; func (a <caret>) main() { }", "map", "chan", "struct", "interface");
}
public void testOnlyLocalTypesInReceiver() {
doTestEquals("package foo; type ( t int; s int; ); func (c <caret>)", "s", "t");
}
public void testNestedBlocks() {
doTestInclude("package main; func main() {def := 1; abc := 0; {<caret>}}", "abc", "def");
}
public void testNoMainAnymore() {
doTestEquals("package foo; func ma<caret> { }");
}
public void testNoChanOrMap() {
doTestEquals("package foo; func ma(f int.<caret>) { }");
}
public void testOnTopLevel() {
doTestEquals("package foo; func ma() { }\n<caret>", "var", "const", "func", "type");
}
public void testPackageBeforeDot() {
doCheckResult("package foo; import imp \"\"; func foo(a im<caret>.SomeType) {}",
"package foo; import imp \"\"; func foo(a imp.<caret>SomeType) {}");
}
public void testNoUnderscore() {
String theSame = "package foo; func foo() {_ := 1; <caret>}";
doCheckResult(theSame, theSame);
}
public void testVarFuncTypeZeroParam() {
doCheckResult("package foo; var abc = func() {}; func main() {ab<caret>}",
"package foo; var abc = func() {}; func main() {abc()<caret>}");
}
public void testVarFuncTypeOneParam() {
doCheckResult("package foo; var abc = func(o int) {}; func main() {ab<caret>}",
"package foo; var abc = func(o int) {}; func main() {abc(<caret>)}");
}
public void testCaseInsensitiveVariable() {
doCheckResult("package main; func test(BBA int){b<caret>}",
"package main; func test(BBA int){BBA<caret>}");
}
public void testArrayType() {
doCheckResult("package main; type custom []string; func main() { _ = custom<caret> }",
"package main; type custom []string; func main() { _ = custom{<caret>} }");
}
public void testMapType() {
doCheckResult("package main; type custom map[string]string; func main() { _ = custom<caret> }",
"package main; type custom map[string]string; func main() { _ = custom{<caret>} }");
}
public void testRanges() {
doTestInclude("package foo; func foo(a int) {for k := range <caret>}", "a");
}
public void testNoDuplicates() {
doTestInclude("package foo; type a struct {<caret>", "a");
List<String> stringList = myFixture.getLookupElementStrings();
assertNotNull(stringList);
assertSize(1, ContainerUtil.filter(stringList, new TreePrintCondition.Include("a")));
}
public void testTypeCastAsVar() {
doTestInclude("package main\n" +
"var fooVar int = 1\n" +
"func main() {\n" +
" for _, v := range (*<caret>) {\n" +
" }\n" +
"}", "fooVar");
}
private static final String TYPE = "package main;\n" +
"type WaitGroup struct {\n" +
" counter int32\n" +
" waiters int32\n" +
" sema *uint32\n" +
"}\n";
public void testStructField() {
myFixture.configureByText("a.go", TYPE + "func main() {WaitGroup{<caret>}};");
myFixture.completeBasic();
myFixture.assertPreferredCompletionItems(0, "counter", "sema", "waiters");
}
public void testAnonymousStructField() {
myFixture.configureByText("a.go", TYPE + "var baz = []*WaitGroup{{<caret>}}");
myFixture.completeBasic();
myFixture.assertPreferredCompletionItems(0, "counter", "sema", "waiters");
}
public void testStructField2() {
doTestInclude(TYPE + "func main() {WaitGroup{foo:bar, <caret>}};", "counter", "waiters", "sema");
}
public void testStructFieldReplace() {
doCheckResult(TYPE + "func main() { WaitGroup{sem<caret>abc} }", TYPE + "func main() { WaitGroup{sema:<caret>} }",
Lookup.REPLACE_SELECT_CHAR);
}
public void testStructFieldFromOtherStruct() {
doCheckResult("package main; type Example struct { ID string }; func main() { a := Example{ID: \"a\"}; _ = []string{a.<caret>} }",
"package main; type Example struct { ID string }; func main() { a := Example{ID: \"a\"}; _ = []string{a.ID<caret>} }",
Lookup.NORMAL_SELECT_CHAR);
}
public void testNoStructFieldAfterColon() {
doTestExclude(TYPE + "func main() {WaitGroup{sema:<caret>}};", "counter", "waiters", "sema");
}
public void testStructConstructions() {
doCheckResult("package main; func main() {WaitGr<caret>}; type WaitGroup struct {sema *uint32}",
"package main; func main() {WaitGroup{<caret>}}; type WaitGroup struct {sema *uint32}");
}
public void testIntConversion() {
doCheckResult("package main; func main() {int<caret>}; type int int",
"package main; func main() {int(<caret>)}; type int int");
}
public void testPreventSOE() {
doTestInclude("package rubex; const ( IGNORECASE = 1; EXTEND = (IGNORECASE << 1); MULTILINE = (EXTEND << 1)); func m() {<caret>}",
"EXTEND");
}
public void testPreventSOE2() {
doTestInclude("package main; import \"fmt\"; var fmt = &fmt.<caret>");
}
@SuppressWarnings("ConstantConditions")
public void testPackageNames() {
myFixture.configureByText("test_test.go", "package myFromTest_test");
myFixture.configureByText("test_file.go", "package myFromFile");
myFixture.configureByText("test.go", "package m<caret>");
myFixture.completeBasic();
assertSameElements(myFixture.getLookupElementStrings(), "myFromTest", "myFromFile", "main");
}
@SuppressWarnings("ConstantConditions")
public void testPackageNamesInTestFile() {
myFixture.configureByText("foo.go", "package foo");
myFixture.configureByText("foo_test.go", "package <caret>");
myFixture.completeBasic();
assertSameElements(myFixture.getLookupElementStrings(), "foo", "foo_test", "main");
}
public void testPointerSpecType() {
myFixture.configureByText("foo.go", "package main; type a struct{};" +
"func main() {q1, q2:=&a{};q<caret>}");
myFixture.completeBasic();
LookupElement first = ArrayUtil.getFirstElement(myFixture.getLookupElements());
assertNotNull(first);
LookupElementPresentation presentation = new LookupElementPresentation();
first.renderElement(presentation);
assertEquals("*main.a", presentation.getTypeText());
}
public void testPackageNamesInEmptyDirectory() {
PsiFile file = myFixture.addFileToProject("my-directory-name/test.go", "package m<caret>");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
myFixture.completeBasic();
List<String> strings = myFixture.getLookupElementStrings();
assertNotNull(strings);
assertSameElements(strings, "my_directory_name", "main");
}
public void testCompleteFromTestsDefinedInCurrentPackage() {
myFixture.addFileToProject("my_test.go", "package mytest; func MyFunction() {}");
myFixture.configureByText("current_test.go", "package mytest; func TestSomething() { MyFunc<caret> }");
myFixture.completeBasic();
myFixture.checkResult("package mytest; func TestSomething() { MyFunction() }");
}
public void testFieldNamesInEmptyStructLiteral() {
String source = "package test; " +
"type A struct { field_in_a string }; " +
"type B struct { A; field_in_b string }; " +
"func Test() B { a := A{}; s := \"\"; return B{<caret>}; }";
doTestInclude(source, "a", "A", "field_in_b");
}
public void testFieldNamesInStructLiteralWithNameValueInitializers() {
String source = "package test; " +
"type A struct { field_in_a string }; " +
"type B struct { A; field_in_b string }; " +
"func Test() B { a := A{}; s := \"\"; return B{ A: A{}, <caret>}; }";
doTestEquals(source, "field_in_b");
}
public void testNoFieldNamesInStructLiteralWithValueInitializers() {
String source = "package test; " +
"type A struct { field_in_a string }; " +
"type B struct { A; field_in_b string }; " +
"func Test() B { a := A{}; s := \"\"; return B{ A{}, <caret>}; }";
myFixture.configureByText("test.go", source);
myFixture.completeBasic();
List<String> variants = myFixture.getLookupElementStrings();
assertNotNull(variants);
assertContainsElements(variants, "s");
assertDoesntContain(variants, "field_in_b");
}
public void testStructFieldValueCompletion() {
String source = "package test; " +
"type A struct { field1 string; field2 string }; " +
"func Test() A { s := \"\"; return A{field1: \"\", field2: <caret>}; }";
doTestInclude(source, "s");
}
public void testDoNotCompleteVariableTwice() {
doCheckResult("package t; func _() {\n err := 1; for { err := 1; return er<caret> } }",
"package t; func _() {\n err := 1; for { err := 1; return err<caret> } }");
}
private void doTestEmptyCompletion() {
myFixture.testCompletionVariants(getTestName(true) + ".go");
}
}