/*******************************************************************************
* Copyright (c) 2014 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package com.github.rustdt.tooling.ops;
import static melnorme.lang.tooling.CompletionProposalKind.Function;
import static melnorme.lang.tooling.CompletionProposalKind.Let;
import static melnorme.lang.tooling.CompletionProposalKind.Struct;
import static melnorme.lang.tooling.CompletionProposalKind.Trait;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import static melnorme.utilbox.core.CoreUtil.listFrom;
import java.util.List;
import org.junit.Test;
import melnorme.lang.tests.CommonToolingTest;
import melnorme.lang.tooling.ElementAttributes;
import melnorme.lang.tooling.ToolCompletionProposal;
import melnorme.lang.tooling.ToolingMessages;
import melnorme.lang.tooling.ast.SourceRange;
import melnorme.lang.tooling.common.SourceLineColumnRange;
import melnorme.lang.tooling.toolchain.ops.OperationSoftFailure;
import melnorme.lang.tooling.toolchain.ops.SourceLocation;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.MiscUtil;
public class RacerOutputParserTest extends CommonToolingTest {
protected static final String NL = "\n";
protected static final String DESC2 = "pub trait BufRead : Read {";
protected static final String DESC1 = "pub struct BufReader<R> {";
protected RacerCompletionOutputParser createTestsParser(int offset) {
return new RacerCompletionOutputParser(offset) {
@Override
protected void handleInvalidMatchKindString(String matchKindString) throws CommonException {
}
};
}
protected SourceRange sr(int offset, int length) {
return new SourceRange(offset, length);
}
protected static ElementAttributes att() {
return new ElementAttributes(null);
}
@Test
public void test() throws Exception { test$(); }
public void test$() throws Exception {
int offset = 10;
RacerCompletionOutputParser buildParser = createTestsParser(offset);
testParseOutput(buildParser, "", listFrom()); // Empty
testParseOutput(buildParser,
"PREFIX 1,1,\n" +
"MATCH BufReader;BufReader;32;11;/RustProject/src/xpto.rs;Struct;"+DESC1+NL+
"MATCH BufRead;BufRead;519;10;/RustProject/src/xpto2.rs;Trait;"+DESC2+NL
,
listFrom(
new ToolCompletionProposal(offset, 0, "BufReader", "BufReader", Struct, att(), null, "xpto.rs", DESC1),
new ToolCompletionProposal(offset, 0, "BufRead", "BufRead", Trait, att(), null, "xpto2.rs", DESC2)
)
);
testParseOutput(buildParser,
"PREFIX 4,6,pr\n" +
"MATCH BufReader;BufReader;32;11;relativeDir/src/xpto.rs;Let;"+DESC1+NL+
"END\n"
,
listFrom(
new ToolCompletionProposal(offset-2, 2, "BufReader", "BufReader", Let, att(), null, "xpto.rs", DESC1)
)
);
testParseOutput(buildParser,
"PREFIX 1,1,\n" +
"MATCH stdin;stdin();122;7;/rustc-nightly/src/libstd/io/stdio.rs;Function;pub fn stdin() -> Stdin {"+NL+
"MATCH repeat;repeat(${1:byte: u8});75;7;/rustc-nightly/src/libstd/io/util.rs;Function;"
+"pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }" +NL+
"MATCH copy;copy(${1:r: &mut R}, ${2:w: &mut W});31;7;/rustc-nightly/src/libstd/io/util.rs;Function;"
+"pub fn copy<R: Read, W: Write>(r: &mut R, w: &mut W) -> io::Result<u64> {" +NL
,
listFrom(
new ToolCompletionProposal(offset, 0, "stdin", "stdin()", Function, att(), null, "stdio.rs",
"pub fn stdin() -> Stdin {",
"stdin()", new ArrayList2<SourceRange>()),
new ToolCompletionProposal(offset, 0, "repeat", "repeat(byte: u8)", Function, att(), null, "util.rs",
"pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }",
"repeat(byte)", ArrayList2.create(sr(7, 4))),
new ToolCompletionProposal(offset, 0, "copy", "copy(r: &mut R, w: &mut W)", Function, att(),
null, "util.rs",
"pub fn copy<R: Read, W: Write>(r: &mut R, w: &mut W) -> io::Result<u64> {",
"copy(r, w)", ArrayList2.create(sr(5, 1), sr(8, 1)))
)
);
// Test error case
testParseOutput(buildParser,
"PREFIX 1,1,\n" +
"MATCH xxx;xxx(;122;7;/rustc-nightly/src/libstd/io/stdio.rs;Function;pub fn stdin() -> Stdin {\n"+
"MATCH xxx2;xxx2(${;122;7;/rustc-nightly/src/libstd/io/stdio.rs;Function;pub fn stdin() -> Stdin {\n"
,
listFrom(
new ToolCompletionProposal(offset, 0, "xxx", "xxx()", Function, att(), null, "stdio.rs",
"pub fn stdin() -> Stdin {",
"xxx()", new ArrayList2<SourceRange>()),
new ToolCompletionProposal(offset, 0, "xxx2", "xxx2()", Function, att(), null, "stdio.rs",
"pub fn stdin() -> Stdin {",
"xxx2(__)", ArrayList2.create(sr(5, 2)))
)
);
// Commented out, to be fully removed
// testMultiLineDesc(offset, buildParser);
}
protected void testParseOutput(RacerCompletionOutputParser parser, String output, List<?> expected) {
try {
ArrayList2<ToolCompletionProposal> proposals = parser.parseOutput(output);
assertAreEqualLists(proposals, expected);
} catch(CommonException | OperationSoftFailure e) {
assertFail();
}
}
protected static final String DESC_LINE2 = " where K: AsRef<OsStr>, V: AsRef<OsStr>";
protected void testMultiLineDesc(int offset, RacerCompletionOutputParser buildParser)
throws CommonException {
// Test multi-line description
testParseOutput(buildParser,
"PREFIX 1,1,\n" +
"MATCH xxx;xxx(;122;7;/rustc-nightly/src/libstd/io/stdio.rs;Function;pub fn stdin() -> Stdin {"+NL+
DESC_LINE2 +NL+
"MATCH xxx2;xxx2(${;122;7;/rustc-nightly/src/libstd/io/stdio.rs;Function;pub fn xxx2() -> Stdin {"+NL+
DESC_LINE2 +NL+
DESC_LINE2
,
listFrom(
new ToolCompletionProposal(offset, 0, "xxx", "xxx()", Function, att(), null, "stdio.rs",
"pub fn stdin() -> Stdin {" +NL+ DESC_LINE2,
"xxx()", new ArrayList2<SourceRange>()),
new ToolCompletionProposal(offset, 0, "xxx2", "xxx2()", Function, att(), null, "stdio.rs",
"pub fn xxx2() -> Stdin {" +NL+ DESC_LINE2 +NL+ DESC_LINE2,
"xxx2(__)", ArrayList2.create(sr(5, 2)))
)
);
}
@Test
public void parseMatchLine() throws Exception { parseMatchLine$(); }
public void parseMatchLine$() throws Exception {
RacerCompletionOutputParser buildParser = createTestsParser(0);
testParseResolvedMatch(buildParser, "", null, ToolingMessages.FIND_DEFINITION_NoTargetFound);
String LOC_ROOT = MiscUtil.OS_IS_WINDOWS ? "C:\\" : "/";
testParseResolvedMatch(buildParser,
"MATCH other,19,3,"+LOC_ROOT+"RustProj/src/main.rs,Function,fn other(foo: i32) {",
new SourceLocation(loc(LOC_ROOT+"/RustProj/src/main.rs"), new SourceLineColumnRange(19, 4)),
null);
testParseResolvedMatch(buildParser, "MATCH other,as", null, "Invalid integer: `as`");
}
protected void testParseResolvedMatch(RacerCompletionOutputParser buildParser, String input,
SourceLocation expected, String expectedException) {
try {
SourceLocation result = buildParser.parseResolvedMatch(input);
assertAreEqual(result, expected);
assertTrue(expectedException == null);
} catch(CommonException e) {
assertNotNull(expectedException);
assertTrue(e.getMessage().contains(expectedException));
}
}
}