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
// EXIST: String~(jet)
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException
// EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer
// ABSENT: HTMLStyleElement
// ABSENT: Statement@Statement~(java.sql)
// ABSENT: Statement
@@ -3,9 +3,9 @@ class Test {
}
// INVOCATION_COUNT: 2
// EXIST: String~(jet)
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException
// EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer
// 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
// EXIST: String~(jet)
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: StrSome
// EXIST: StrMore
// EXIST: StrInFun
@@ -4,4 +4,4 @@ fun some() {
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
// EXIST: SomeClass, SomeInternal
// EXIST: String~(jet)
// EXIST: SomeClass
// EXIST: SomeInternal
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException
// EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer
// ABSENT: HTMLStyleElement
// ABSENT: Statement@Statement~(java.sql)
// ABSENT: Statement
@@ -5,10 +5,11 @@ class SomeClass {
}
// INVOCATION_COUNT: 2
// EXIST: SomeClass, SomeInternal
// EXIST: String~(jet)
// EXIST: SomeClass
// EXIST: SomeInternal
// EXIST: { lookupString:"String", tailText:" (jet)" }
// EXIST: IllegalStateException
// EXIST: StringBuilder
// EXIST_JAVA_ONLY: StringBuffer
// 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
// EXIST: Int~(jet)
// ABSENT: Int~(jet.runtime.SharedVar)
// EXIST: { lookupString:"Int", tailText:" (jet)" }
// ABSENT: { lookupString:"Int", tailText:" (jet.runtime.SharedVar)" }
@@ -4,10 +4,10 @@ fun main(args: Array<String>) {
// INVOCATION_COUNT: 2
// WITH_ORDER: 1
// EXIST: Array~(jet)
// EXIST_JAVA_ONLY: Array~(java.sql)
// EXIST_JAVA_ONLY: ArrayList~<E> (java.util)
// EXIST_JS_ONLY: ArrayList~(java.util)
// EXIST: { lookupString:"Array", tailText:" (jet)" }
// EXIST_JAVA_ONLY: { lookupString:"Array", tailText:" (java.sql)" }
// EXIST_JAVA_ONLY: { lookupString:"ArrayList", tailText:"<E> (java.util)" }
// EXIST_JS_ONLY: { lookupString:"ArrayList", tailText:" (java.util)" }
@@ -3,6 +3,6 @@ fun some(a: Double<caret>) {
// INVOCATION_COUNT: 2
// WITH_ORDER: 1
// EXIST: Double~(jet)
// EXIST_JAVA_ONLY: Double~(java.lang)
// EXIST: DoubleArray~(jet)
// EXIST: { lookupString:"Double", tailText:" (jet)" }
// EXIST_JAVA_ONLY: { lookupString:"Double", tailText:" (java.lang)" }
// EXIST: { lookupString:"DoubleArray", tailText:" (jet)" }
@@ -1,4 +1,4 @@
fun some(a : Statement<caret>)
// INVOCATION_COUNT: 1
// EXIST: Statement@Statement~(java.sql)
// EXIST: { lookupString:"Statement", tailText:" (java.sql)" }
@@ -8,5 +8,5 @@ fun firstFun() {
}
// 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
@@ -1,5 +1,5 @@
val x = LineIterator<caret>
// INVOCATION_COUNT: 1
// EXIST: LineIterator~(kotlin.io)
// EXIST: { lookupString:"LineIterator", tailText:" (kotlin.io)" }
// NUMBER: 1
@@ -3,5 +3,5 @@ import java.io.InputStreamReader
val x = InputStreamReader<caret>
// INVOCATION_COUNT: 1
// EXIST: InputStreamReader~(java.io)
// EXIST: { lookupString:"InputStreamReader", tailText:" (java.io)" }
// NUMBER: 1
@@ -6,6 +6,6 @@ fun firstFun() {
}
// INVOCATION_COUNT: 1
// EXIST: PropertyMetadata@PropertyMetadata~(jet)
// EXIST: PropertyMetadataImpl@PropertyMetadataImpl~(jet)
// EXIST: { lookupString:"PropertyMetadata", itemText:"PropertyMetadata", tailText:" (jet)" }
// EXIST: { lookupString:"PropertyMetadataImpl", itemText:"PropertyMetadataImpl", tailText:" (jet)" }
// NUMBER: 2
@@ -2,4 +2,4 @@ class Foo
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>
}
// EXIST: Foo@Foo<jet.String>()
// EXIST: { lookupString:"Foo", itemText:"Foo<jet.String>()" }
@@ -4,4 +4,4 @@ fun foo(p : Any){
var a : Foo? = <caret>
}
// EXIST: Foo@Foo()
// EXIST: { lookupString:"Foo", itemText:"Foo()" }
@@ -24,4 +24,4 @@ fun f3() : String{}
// EXIST: f1
// EXIST: f2
// 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.collect.Collections2;
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.LookupElementPresentation;
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.plugin.project.TargetPlatform;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
/**
* 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 final Pattern PATTERN = Pattern.compile("([^~@]*)(@([^~]*))?(~(.*))?");
public static final int LOOKUP_STRING_GROUP_INDEX = 1;
public static final int PRESENTABLE_STRING_GROUP_INDEX = 3;
public static final int TAIL_TEXT_STRING_GROUP_INDEX = 5;
public static final String LOOKUP_STRING = "lookupString";
public static final String PRESENTATION_ITEM_TEXT = "itemText";
public static final String PRESENTATION_TYPE_TEXT = "typeText";
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 = "~";
public static final String PRESENTABLE_FLAG = "@";
private final Map<String, String> map;
private final String lookupString;
private final String presenterText;
private final String tailString;
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 CompletionProposal(@NotNull String lookupString) {
map = new HashMap<String, String>();
map.put(LOOKUP_STRING, lookupString);
}
public boolean isSuitable(CompletionProposal proposal) {
if (proposal.tailString != null) {
if (!proposal.tailString.equals(tailString)) {
public CompletionProposal(@NotNull Map<String, String> map) {
this.map = map;
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;
}
}
if (proposal.presenterText != null) {
if (!proposal.presenterText.equals(presenterText)) {
return false;
}
}
return lookupString.equals(proposal.lookupString);
return true;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder(lookupString);
if (presenterText != null) {
result.append(PRESENTABLE_FLAG).append(presenterText);
JsonObject jsonObject = new JsonObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
jsonObject.addProperty(entry.getKey(), entry.getValue());
}
if (tailString != null) {
result.append(TAIL_FLAG).append(tailString);
}
return result.toString();
return jsonObject.toString();
}
}
@@ -168,12 +173,17 @@ public class ExpectedCompletionUtils {
public static CompletionProposal[] processProposalAssertions(String fileText, String... prefixes) {
Collection<CompletionProposal> proposals = new ArrayList<CompletionProposal>();
for (String proposalStr : InTextDirectivesUtils.findListWithPrefixes(fileText, prefixes)) {
Matcher matcher = CompletionProposal.PATTERN.matcher(proposalStr);
matcher.find();
proposals.add(new CompletionProposal(matcher.group(CompletionProposal.LOOKUP_STRING_GROUP_INDEX),
matcher.group(CompletionProposal.PRESENTABLE_STRING_GROUP_INDEX),
matcher.group(CompletionProposal.TAIL_TEXT_STRING_GROUP_INDEX)));
for (String proposalStr : InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, prefixes)) {
if (proposalStr.startsWith("{")){
JsonParser parser = new JsonParser();
JsonElement json = parser.parse(proposalStr);
proposals.add(new CompletionProposal((JsonObject) json));
}
else{
for(String item : proposalStr.split(",")){
proposals.add(new CompletionProposal(item.trim()));
}
}
}
return ArrayUtil.toObjectArray(proposals, CompletionProposal.class);
@@ -225,7 +235,7 @@ public class ExpectedCompletionUtils {
for (int index = 0; index < itemsInformation.size(); index++) {
CompletionProposal proposal = itemsInformation.get(index);
if (proposal.isSuitable(expectedProposal)) {
if (proposal.matches(expectedProposal)) {
isFound = true;
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 proposal : itemsInformation) {
Assert.assertFalse("Unexpected '" + unexpectedProposal + "' presented in " + allItemsString,
proposal.isSuitable(unexpectedProposal));
proposal.matches(unexpectedProposal));
}
}
}
@@ -271,8 +288,18 @@ public class ExpectedCompletionUtils {
if (items != null) {
for (LookupElement item : items) {
item.renderElement(presentation);
result.add(new ExpectedCompletionUtils.CompletionProposal(item.getLookupString(), presentation.getItemText(),
presentation.getTailText()));
Map<String, String> map = new HashMap<String, String>();
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));
}
}