Refactored completion tests to support more flexible input file format

This commit is contained in:
Valentin Kipyatkov
2013-11-27 17:12:12 +04:00
parent 912fb904b8
commit 29f7318f4f
19 changed files with 110 additions and 81 deletions
@@ -3,9 +3,9 @@ class Test {
} }
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: String~(jet) // EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException // EXIST: IllegalStateException
// EXIST: StringBuilder // EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer // EXIST_JAVA_ONLY: StringBuffer
// ABSENT: HTMLStyleElement // ABSENT: HTMLStyleElement
// ABSENT: Statement@Statement~(java.sql) // ABSENT: Statement
@@ -3,9 +3,9 @@ class Test {
} }
// INVOCATION_COUNT: 2 // INVOCATION_COUNT: 2
// EXIST: String~(jet) // EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException // EXIST: IllegalStateException
// EXIST: StringBuilder // EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer // EXIST_JAVA_ONLY: StringBuffer
// EXIST_JS_ONLY: HTMLStyleElement // EXIST_JS_ONLY: HTMLStyleElement
// EXIST_JAVA_ONLY: Statement@Statement~(java.sql) // EXIST_JAVA_ONLY: { lookupString:"Statement", tailText:" (java.sql)" }
@@ -13,7 +13,7 @@ class StrMore {
} }
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: String~(jet) // EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: StrSome // EXIST: StrSome
// EXIST: StrMore // EXIST: StrMore
// EXIST: StrInFun // EXIST: StrInFun
@@ -4,4 +4,4 @@ fun some() {
tes<caret> tes<caret>
} }
// EXIST: test@test(a: jet.Int) // EXIST: { lookupString:"test", itemText:"test(a: jet.Int)" }
@@ -5,10 +5,11 @@ class SomeClass {
} }
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: SomeClass, SomeInternal // EXIST: SomeClass
// EXIST: String~(jet) // EXIST: SomeInternal
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException // EXIST: IllegalStateException
// EXIST: StringBuilder // EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer // EXIST_JAVA_ONLY: StringBuffer
// ABSENT: HTMLStyleElement // ABSENT: HTMLStyleElement
// ABSENT: Statement@Statement~(java.sql) // ABSENT: Statement
@@ -5,10 +5,11 @@ class SomeClass {
} }
// INVOCATION_COUNT: 2 // INVOCATION_COUNT: 2
// EXIST: SomeClass, SomeInternal // EXIST: SomeClass
// EXIST: String~(jet) // EXIST: SomeInternal
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException // EXIST: IllegalStateException
// EXIST: StringBuilder // EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer // EXIST_JAVA_ONLY: StringBuffer
// EXIST_JS_ONLY: HTMLStyleElement // EXIST_JS_ONLY: HTMLStyleElement
// EXIST_JAVA_ONLY: Statement@Statement~(java.sql) // EXIST_JAVA_ONLY: { lookupString:"Statement", tailText:" (java.sql)" }
@@ -5,5 +5,5 @@ fun firstFun() {
} }
// INVOCATION_COUNT: 0 // INVOCATION_COUNT: 0
// EXIST: Int~(jet) // EXIST: { lookupString:"Int", tailText:" (jet)" }
// ABSENT: Int~(jet.runtime.SharedVar) // ABSENT: { lookupString:"Int", tailText:" (jet.runtime.SharedVar)" }
@@ -4,10 +4,10 @@ fun main(args: Array<String>) {
// INVOCATION_COUNT: 2 // INVOCATION_COUNT: 2
// WITH_ORDER: 1 // WITH_ORDER: 1
// EXIST: Array~(jet) // EXIST: { lookupString:"Array", tailText:" (jet)" }
// EXIST_JAVA_ONLY: Array~(java.sql) // EXIST_JAVA_ONLY: { lookupString:"Array", tailText:" (java.sql)" }
// EXIST_JAVA_ONLY: ArrayList~<E> (java.util) // EXIST_JAVA_ONLY: { lookupString:"ArrayList", tailText:"<E> (java.util)" }
// EXIST_JS_ONLY: ArrayList~(java.util) // EXIST_JS_ONLY: { lookupString:"ArrayList", tailText:" (java.util)" }
@@ -3,6 +3,6 @@ fun some(a: Double<caret>) {
// INVOCATION_COUNT: 2 // INVOCATION_COUNT: 2
// WITH_ORDER: 1 // WITH_ORDER: 1
// EXIST: Double~(jet) // EXIST: { lookupString:"Double", tailText:" (jet)" }
// EXIST_JAVA_ONLY: Double~(java.lang) // EXIST_JAVA_ONLY: { lookupString:"Double", tailText:" (java.lang)" }
// EXIST: DoubleArray~(jet) // EXIST: { lookupString:"DoubleArray", tailText:" (jet)" }
@@ -1,4 +1,4 @@
fun some(a : Statement<caret>) fun some(a : Statement<caret>)
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: Statement@Statement~(java.sql) // EXIST: { lookupString:"Statement", tailText:" (java.sql)" }
@@ -8,5 +8,5 @@ fun firstFun() {
} }
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: toLinkedList@toLinkedList()~for jet.Iterable<T> in kotlin // EXIST: { lookupString:"toLinkedList", itemText:"toLinkedList()", tailText:" for jet.Iterable<T> in kotlin" }
// NUMBER: 1 // NUMBER: 1
@@ -1,5 +1,5 @@
val x = LineIterator<caret> val x = LineIterator<caret>
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: LineIterator~(kotlin.io) // EXIST: { lookupString:"LineIterator", tailText:" (kotlin.io)" }
// NUMBER: 1 // NUMBER: 1
@@ -3,5 +3,5 @@ import java.io.InputStreamReader
val x = InputStreamReader<caret> val x = InputStreamReader<caret>
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: InputStreamReader~(java.io) // EXIST: { lookupString:"InputStreamReader", tailText:" (java.io)" }
// NUMBER: 1 // NUMBER: 1
@@ -6,6 +6,6 @@ fun firstFun() {
} }
// INVOCATION_COUNT: 1 // INVOCATION_COUNT: 1
// EXIST: PropertyMetadata@PropertyMetadata~(jet) // EXIST: { lookupString:"PropertyMetadata", itemText:"PropertyMetadata", tailText:" (jet)" }
// EXIST: PropertyMetadataImpl@PropertyMetadataImpl~(jet) // EXIST: { lookupString:"PropertyMetadataImpl", itemText:"PropertyMetadataImpl", tailText:" (jet)" }
// NUMBER: 2 // NUMBER: 2
@@ -2,4 +2,4 @@ class Foo
var a : Foo = <caret> var a : Foo = <caret>
// EXIST: Foo@Foo() // EXIST: { lookupString:"Foo", itemText:"Foo()" }
@@ -4,4 +4,4 @@ fun foo(p : Any){
var a : Foo<String> = <caret> var a : Foo<String> = <caret>
} }
// EXIST: Foo@Foo<jet.String>() // EXIST: { lookupString:"Foo", itemText:"Foo<jet.String>()" }
@@ -4,4 +4,4 @@ fun foo(p : Any){
var a : Foo? = <caret> var a : Foo? = <caret>
} }
// EXIST: Foo@Foo() // EXIST: { lookupString:"Foo", itemText:"Foo()" }
@@ -24,4 +24,4 @@ fun f3() : String{}
// EXIST: f1 // EXIST: f1
// EXIST: f2 // EXIST: f2
// ABSENT: f3 // ABSENT: f3
// EXIST: Foo@Foo() // EXIST: { lookupString:"Foo", itemText:"Foo()" }
@@ -19,6 +19,10 @@ package org.jetbrains.jet.completion;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
@@ -29,11 +33,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.InTextDirectivesUtils; import org.jetbrains.jet.InTextDirectivesUtils;
import org.jetbrains.jet.plugin.project.TargetPlatform; import org.jetbrains.jet.plugin.project.TargetPlatform;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* Extract a number of statements about completion from the given text. Those statements * Extract a number of statements about completion from the given text. Those statements
@@ -44,52 +44,57 @@ public class ExpectedCompletionUtils {
} }
public static class CompletionProposal { public static class CompletionProposal {
public static final Pattern PATTERN = Pattern.compile("([^~@]*)(@([^~]*))?(~(.*))?"); public static final String LOOKUP_STRING = "lookupString";
public static final int LOOKUP_STRING_GROUP_INDEX = 1; public static final String PRESENTATION_ITEM_TEXT = "itemText";
public static final int PRESENTABLE_STRING_GROUP_INDEX = 3; public static final String PRESENTATION_TYPE_TEXT = "typeText";
public static final int TAIL_TEXT_STRING_GROUP_INDEX = 5; public static final String PRESENTATION_TAIL_TEXT = "tailText";
public static final Set<String> validKeys = new HashSet<String>(
Arrays.asList(LOOKUP_STRING, PRESENTATION_ITEM_TEXT, PRESENTATION_TYPE_TEXT, PRESENTATION_TAIL_TEXT)
);
public static final String TAIL_FLAG = "~"; private final Map<String, String> map;
public static final String PRESENTABLE_FLAG = "@";
private final String lookupString; public CompletionProposal(@NotNull String lookupString) {
private final String presenterText; map = new HashMap<String, String>();
private final String tailString; map.put(LOOKUP_STRING, lookupString);
public CompletionProposal(@NotNull String lookupString, @Nullable String presenterText, @Nullable String tailString) {
this.lookupString = lookupString;
this.presenterText = presenterText != null ? presenterText.trim() : null;
this.tailString = tailString != null ? tailString.trim() : null;
} }
public boolean isSuitable(CompletionProposal proposal) { public CompletionProposal(@NotNull Map<String, String> map) {
if (proposal.tailString != null) { this.map = map;
if (!proposal.tailString.equals(tailString)) { for (String key : map.keySet()) {
if (!validKeys.contains(key)){
throw new RuntimeException("Invalid key '" + key + "'");
}
}
}
public CompletionProposal(@NotNull JsonObject json) {
map = new HashMap<String, String>();
for (Map.Entry<String, JsonElement> entry : json.entrySet()) {
String key = entry.getKey();
if (!validKeys.contains(key)) {
throw new RuntimeException("Invalid json property '" + key + "'");
}
map.put(key, entry.getValue().getAsString());
}
}
public boolean matches(CompletionProposal expectedProposal) {
for (Map.Entry<String, String> entry : expectedProposal.map.entrySet()) {
if (!entry.getValue().equals(map.get(entry.getKey()))) {
return false; return false;
} }
} }
return true;
if (proposal.presenterText != null) {
if (!proposal.presenterText.equals(presenterText)) {
return false;
}
}
return lookupString.equals(proposal.lookupString);
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder result = new StringBuilder(lookupString); JsonObject jsonObject = new JsonObject();
if (presenterText != null) { for (Map.Entry<String, String> entry : map.entrySet()) {
result.append(PRESENTABLE_FLAG).append(presenterText); jsonObject.addProperty(entry.getKey(), entry.getValue());
} }
return jsonObject.toString();
if (tailString != null) {
result.append(TAIL_FLAG).append(tailString);
}
return result.toString();
} }
} }
@@ -168,12 +173,17 @@ public class ExpectedCompletionUtils {
public static CompletionProposal[] processProposalAssertions(String fileText, String... prefixes) { public static CompletionProposal[] processProposalAssertions(String fileText, String... prefixes) {
Collection<CompletionProposal> proposals = new ArrayList<CompletionProposal>(); Collection<CompletionProposal> proposals = new ArrayList<CompletionProposal>();
for (String proposalStr : InTextDirectivesUtils.findListWithPrefixes(fileText, prefixes)) { for (String proposalStr : InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, prefixes)) {
Matcher matcher = CompletionProposal.PATTERN.matcher(proposalStr); if (proposalStr.startsWith("{")){
matcher.find(); JsonParser parser = new JsonParser();
proposals.add(new CompletionProposal(matcher.group(CompletionProposal.LOOKUP_STRING_GROUP_INDEX), JsonElement json = parser.parse(proposalStr);
matcher.group(CompletionProposal.PRESENTABLE_STRING_GROUP_INDEX), proposals.add(new CompletionProposal((JsonObject) json));
matcher.group(CompletionProposal.TAIL_TEXT_STRING_GROUP_INDEX))); }
else{
for(String item : proposalStr.split(",")){
proposals.add(new CompletionProposal(item.trim()));
}
}
} }
return ArrayUtil.toObjectArray(proposals, CompletionProposal.class); return ArrayUtil.toObjectArray(proposals, CompletionProposal.class);
@@ -225,7 +235,7 @@ public class ExpectedCompletionUtils {
for (int index = 0; index < itemsInformation.size(); index++) { for (int index = 0; index < itemsInformation.size(); index++) {
CompletionProposal proposal = itemsInformation.get(index); CompletionProposal proposal = itemsInformation.get(index);
if (proposal.isSuitable(expectedProposal)) { if (proposal.matches(expectedProposal)) {
isFound = true; isFound = true;
Assert.assertTrue("Invalid order of existent elements in " + allItemsString, Assert.assertTrue("Invalid order of existent elements in " + allItemsString,
@@ -236,7 +246,14 @@ public class ExpectedCompletionUtils {
} }
} }
Assert.assertTrue("Expected '" + expectedProposal + "' not found in " + allItemsString, isFound); if (!isFound) {
if (allItemsString.isEmpty()) {
Assert.fail("Completion is empty but " + expectedProposal + " is expected");
}
else {
Assert.fail("Expected " + expectedProposal + " not found in:\n" + allItemsString);
}
}
} }
} }
@@ -259,7 +276,7 @@ public class ExpectedCompletionUtils {
for (CompletionProposal unexpectedProposal : unexpected) { for (CompletionProposal unexpectedProposal : unexpected) {
for (CompletionProposal proposal : itemsInformation) { for (CompletionProposal proposal : itemsInformation) {
Assert.assertFalse("Unexpected '" + unexpectedProposal + "' presented in " + allItemsString, Assert.assertFalse("Unexpected '" + unexpectedProposal + "' presented in " + allItemsString,
proposal.isSuitable(unexpectedProposal)); proposal.matches(unexpectedProposal));
} }
} }
} }
@@ -271,8 +288,18 @@ public class ExpectedCompletionUtils {
if (items != null) { if (items != null) {
for (LookupElement item : items) { for (LookupElement item : items) {
item.renderElement(presentation); item.renderElement(presentation);
result.add(new ExpectedCompletionUtils.CompletionProposal(item.getLookupString(), presentation.getItemText(), Map<String, String> map = new HashMap<String, String>();
presentation.getTailText())); map.put(CompletionProposal.LOOKUP_STRING, item.getLookupString());
if (presentation.getItemText() != null){
map.put(CompletionProposal.PRESENTATION_ITEM_TEXT, presentation.getItemText());
}
if (presentation.getTypeText() != null){
map.put(CompletionProposal.PRESENTATION_TYPE_TEXT, presentation.getTypeText());
}
if (presentation.getTailText() != null){
map.put(CompletionProposal.PRESENTATION_TAIL_TEXT, presentation.getTailText());
}
result.add(new ExpectedCompletionUtils.CompletionProposal(map));
} }
} }