// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.google.collide.client.code.autocomplete;
import static org.waveprotocol.wave.client.common.util.SignalEvent.KeySignalType.INPUT;
import com.google.collide.client.code.autocomplete.AutocompleteProposals.ProposalWithContext;
import com.google.collide.client.documentparser.DocumentParser;
import com.google.collide.client.util.IncrementalScheduler;
import com.google.collide.client.util.PathUtil;
import com.google.collide.codemirror2.CodeMirror2;
import com.google.collide.codemirror2.Parser;
import com.google.collide.codemirror2.State;
import com.google.collide.codemirror2.Stream;
import com.google.collide.codemirror2.SyntaxType;
import com.google.collide.codemirror2.Token;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.json.shared.JsonStringSet;
import com.google.collide.shared.document.Document;
import com.google.collide.shared.util.JsonCollections;
/**
* A set of common test utilities and mock implementations.
*
* <p>This code was moved from TestSetupHelper.
*/
public class TestUtils {
public static final SignalEventEssence CTRL_SPACE = new SignalEventEssence(
' ', true, false, false, false, INPUT);
public static final SignalEventEssence CTRL_SHIFT_SPACE = new SignalEventEssence(
' ', true, false, true, false, INPUT);
/**
* Implementation that publishes its content.
*/
public static class MockStream implements Stream {
/**
* Flag that indicates "at the end of line".
*
* <p>This flag is toggled each time {@link #isEnd} is called. That way the
* first invocation of {@link #isEnd} always returns {@code false} and
* second invocation returns {@code true}.
*
* <p>Described behavior allows {@link MockParser} implementations to push
* tokens. To determine what tokens to push, {@link #getText} can be used.
*/
boolean toggle = true;
private final String text;
public MockStream(String text) {
this.text = text;
}
public String getText() {
return text;
}
/**
* @see #toggle
*/
@Override
public boolean isEnd() {
toggle = !toggle;
return toggle;
}
}
/**
* Implementation that "collects" schedule requests.
*/
public static class MockIncrementalScheduler implements IncrementalScheduler {
public final JsonArray<Task> requests = JsonCollections.createArray();
@Override
public void schedule(Task worker) {
requests.add(worker);
}
@Override
public void cancel() {
requests.clear();
}
@Override
public void pause() {}
@Override
public void resume() {}
@Override
public boolean isPaused() {
return false;
}
@Override
public boolean isBusy() {
return !requests.isEmpty();
}
@Override
public void teardown() {}
}
private static class MockState implements State {
@Override
public State copy(Parser codeMirrorParser) {
return createMockState();
}
}
/**
* Mock {@link Parser} implementation.
*/
public static class MockParser implements Parser {
private final SyntaxType type;
public MockParser(SyntaxType type) {
this.type = type;
}
@Override
public boolean hasSmartIndent() {
return false;
}
@Override
public SyntaxType getSyntaxType() {
return type;
}
@Override
public int indent(State stateBefore, String textAfter) {
return 0;
}
@Override
public State defaultState() {
return createMockState();
}
@Override
public void parseNext(Stream stream, State parserState, JsonArray<Token> tokens) {
}
@Override
public Stream createStream(String text) {
return new MockStream(text);
}
@Override
public String getName(State state) {
return type.getName();
}
}
public static <T extends AutocompleteProposal> JsonStringSet createNameSet(
JsonArray<T> proposals) {
JsonStringSet result = JsonCollections.createStringSet();
for (int i = 0; i < proposals.size(); i++) {
result.add(proposals.get(i).name);
}
return result;
}
public static JsonStringSet createNameSet(AutocompleteProposals proposals) {
JsonStringSet result = JsonCollections.createStringSet();
for (int i = 0; i < proposals.size(); i++) {
result.add(proposals.get(i).name);
}
return result;
}
public static AbstractTrie<String> createStringTrie(String... items) {
AbstractTrie<String> result = new AbstractTrie<String>();
for (String item : items) {
result.put(item, item);
}
return result;
}
public static <T extends AutocompleteProposal> String joinNames(JsonArray<T> proposals) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < proposals.size(); i++) {
if (i > 0) {
result.append(",");
}
result.append(proposals.get(i).name);
}
return result.toString();
}
public static <T extends AutocompleteProposal> T findProposalByName(
JsonArray<T> proposals, String name) {
for (int i = 0; i < proposals.size(); i++) {
if (proposals.get(i).getName().equals(name)) {
return proposals.get(i);
}
}
return null;
}
public static State createMockState() {
return new MockState();
}
public static DocumentParser createDocumentParser(PathUtil path) {
return createDocumentParser(
path, false, new MockIncrementalScheduler(), Document.createEmpty());
}
public static DocumentParser createDocumentParser(PathUtil path, boolean setupRealParser,
IncrementalScheduler scheduler, Document document) {
Parser parser = setupRealParser ? CodeMirror2.getParser(path)
: new MockParser(SyntaxType.syntaxTypeByFilePath(path));
return DocumentParser.create(document, parser, scheduler);
}
/**
* Selects and returns proposal with given name.
*
* @return {@code null} if proposal with specified name is not found
*/
public static ProposalWithContext selectProposalByName(
AutocompleteProposals proposals, String name) {
for (int i = 0, n = proposals.size(); i < n; i++) {
AutocompleteProposal proposal = proposals.get(i);
if (proposal.getName().equals(name)) {
return proposals.select(i);
}
}
return null;
}
}