/*******************************************************************************
* 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.structure.StructureElementKind.VAR;
import org.junit.Test;
import melnorme.lang.tooling.ElementAttributes;
import melnorme.lang.tooling.ast.ParserErrorTypes;
import melnorme.lang.tooling.ast.SourceRange;
import melnorme.lang.tooling.common.ParserError;
import melnorme.lang.tooling.structure.AbstractStructureParser_Test;
import melnorme.lang.tooling.structure.StructureElement;
import melnorme.lang.tooling.structure.StructureElementKind;
import melnorme.utilbox.collections.Indexable;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.StringUtil;
import melnorme.utilbox.status.Severity;
public class RustParseDescribeParser_Test extends AbstractStructureParser_Test {
public static String NO_TYPE = "\"\" ";
@Override
protected RustParseDescribeParser createStructureParser() {
return new RustParseDescribeParser(null, source);
}
public static String elemString(String kind, String name, String attribs, String type, String... children) {
return
kind + "{" + quoteString(name) + "{ @0 @14 } { @0 @5 }" + type + attribs +
StringUtil.collToString(children, "\n")
+ "}"
;
}
public StructureElement elem(String name, StructureElementKind elementKind,
ElementAttributes elementAttributes, String type, Indexable<StructureElement> children) {
return elem(name, srAt(0, 14), srAt(0, 5), elementKind, elementAttributes, type, children);
}
protected void testParseDescribe(String describeOutputContent, Indexable<ParserError> parserProblems,
StructureElement... expectedElements)
throws CommonException {
String describeOutput = "RUST_PARSE_DESCRIBE 0.1 { \n" + describeOutputContent + "\n}";
testParseStructure(describeOutput, parserProblems, expectedElements);
}
protected void testParseDescribe(String describeOutputContent, StructureElement... expectedElements)
throws CommonException {
testParseDescribe("MESSAGES {} " + describeOutputContent, list(), expectedElements);
}
@Test
public void test() throws Exception { test$(); }
public void test$() throws Exception {
testParseDescribe("",
array());
testParseDescribe(
"Function" + "{ func{ @0 @14 } { @0 @5 } {} {} }",
array(
elem("func", srAt(0, 14), srAt(0, 5), StructureElementKind.FUNCTION, null, null, list())
)
);
/* ----------------- test use aggregation ----------------- */
testParseDescribe(
"Use" + "{" + quoteString("foo::blah") + "{ @1 @10 } { @0 @5 } {} {} }" +
"Use" + "{" + quoteString("use") + "{ @10 @20 } { @11 @14 } {} {} }",
array(
elem("use declarations", srAt(1, 20), srAt(1, 1), StructureElementKind.USE_GROUP, null, null, list(
elem("foo::blah", srAt(1, 10), srAt(0, 5), StructureElementKind.USE, null, null, list()),
elem("use", srAt(10, 20), srAt(11, 14), StructureElementKind.USE, null, null, list())
))
)
);
testParseDescribe(
"Use" + "{" + quoteString("foo::blah") + "{ @1 @10 } { @0 @5 } {} {} }" +
"Use" + "{" + quoteString("use") + "{ @10 @20 } { @11 @14 } {} {} }" +
elemString("Var", "var", "{}", "{}"),
array(
elem("use declarations", srAt(1, 20), srAt(1, 1), StructureElementKind.USE_GROUP, null, null, list(
elem("foo::blah", srAt(1, 10), srAt(0, 5), StructureElementKind.USE, null, null, list()),
elem("use", srAt(10, 20), srAt(11, 14), StructureElementKind.USE, null, null, list())
)),
elem("var" , StructureElementKind.VAR, null, null, list())
)
);
/* ----------------- test kinds ----------------- */
testParseDescribe(
elemString("Var", "var", "{}", "{}") +
elemString("Function", "function", "{}", "{}") +
elemString("Struct", "struct", "{}", "{}") +
elemString("Impl", "impl", "{}", "{}") +
elemString("Trait", "trait", "{}", "{}") +
elemString("Enum", "enum", "{}", "{}") +
elemString("EnumVariant", "enum_vrt", "{}", "{}") +
elemString("TypeAlias", "ty_alias", "{}", "{}") +
elemString("ExternCrate", "ec", "{}", "{}") +
elemString("Mod", "mod", "{}", "{}") +
elemString("Use", "use", "{}", "{}"),
array(
elem("var" , StructureElementKind.VAR, null, null, list()),
elem("function" , StructureElementKind.FUNCTION, null, null, list()),
elem("struct" , StructureElementKind.STRUCT, null, null, list()),
elem("impl" , StructureElementKind.IMPL, null, null, list()),
elem("trait" , StructureElementKind.TRAIT, null, null, list()),
elem("enum" , StructureElementKind.ENUM, null, null, list()),
elem("enum_vrt" , StructureElementKind.ENUM_VARIANT, null, null, list()),
elem("ty_alias" , StructureElementKind.TYPE_ALIAS, null, null, list()),
elem("ec" , StructureElementKind.EXTERN_CRATE, null, null, list()),
elem("mod" , StructureElementKind.MOD, null, null, list()),
elem("use declarations", srAt(0, 14), srAt(0, 0), StructureElementKind.USE_GROUP, null, null, list(
elem("use", StructureElementKind.USE, null, null, list())
))
)
);
// Test invalid element kind
verifyThrows(() -> {
testParseDescribe(elemString("XXX", "func", "{}", "{}"), array());
}, null, "Unknown element kind `XXX`");
/* ----------------- test SourceRange ----------------- */
source = DEFAULT_SOURCE;
testParseDescribe(
"Var { var1 { @0 @10 } { @1 @14} {} {} }" +
"Var { var2 { @5 } { @0 } {} {} }" +
"Var { var3 { 0:0 0:0 } { 0:3 0:5 } {} {} }" +
"Var { var4 { 1:0 1:10 } { 1:5 3:5 } {} {} }",
array(
elem("var1", srAt(0, 10), srAt(1,14), VAR, null, null, list()),
elem("var2", srAt(5, 5) , srAt(0, 0), VAR, null, null, list()),
elem("var3", srAt(pos(0, 0), pos(0, 0)), srAt(pos(0, 3), pos(0, 5)), VAR, null, null, list()),
elem("var4", srAt(pos(1, 0), pos(1, 10)), srAt(pos(1, 5), pos(3, 5)), VAR, null, null, list())
)
);
verifyThrows(() -> {
testParseDescribe("Var { var1 { } { } {} {} }", array());
}, null, "Empty source range");
/* ----------------- test attrib ----------------- */
testParseDescribe(
elemString("Function", "func", "{pub}", NO_TYPE),
array(
elem("func", StructureElementKind.FUNCTION, attPub(), null, list())
)
);
verifyThrows(() -> {
testParseDescribe(elemString("Function", "func", "{xx zzz}", NO_TYPE), array());
}, null, "Unknown protection `xx`");
verifyThrows(() -> {
testParseDescribe(elemString("Function", "func", "{pub zzz}", NO_TYPE), array());
}, null, "Unknown attribute");
/* ----------------- test type ----------------- */
testParseDescribe(
elemString("Function", "func", "{}", "\"(u32) -> &str\""),
array(
elem("func", StructureElementKind.FUNCTION, null, "(u32) -> &str", list())
)
);
verifyThrows(() -> {
testParseDescribe(elemString("Function", "func", "{}", "{blah}"), array());
}, null, "Unknown element type");
/* ----------------- test children ----------------- */
testParseDescribe(
elemString("Struct", "struct", "{}", NO_TYPE,
elemString("Var", "var1", "{}", NO_TYPE),
elemString("Var", "var2", "{}", NO_TYPE)
) +
elemString("Impl", "impl", "{}", "{}",
elemString("Function", "function", "{}", NO_TYPE)
),
array(
elem("struct", StructureElementKind.STRUCT, null, null, list(
elem("var1", StructureElementKind.VAR, null, null, list()),
elem("var2", StructureElementKind.VAR, null, null, list())
)),
elem("impl", StructureElementKind.IMPL, null, null, list(
elem("function", StructureElementKind.FUNCTION, null, null, list())
))
)
);
}
@Test
public void test_Messages() throws Exception { test_Messages$(); }
public void test_Messages$() throws Exception {
testParseDescribe(
"MESSAGES { }",
list(),
array()
);
testParseDescribe(
"MESSAGES { "
+ "{ ERROR { @1 @12} "+quoteString("BLAH BLAH") + "}"
+" }",
list(msg(Severity.ERROR, srAt(1, 12), "BLAH BLAH")),
array()
);
testParseDescribe(
"MESSAGES { "
+ "{ WARNING { @1 @12} "+quoteString("BLAH BLAH") + "}"
+ "{ INFO { 0:0 1:0 } "+quoteString("This is a warning.") + "}"
+" }" +
"Function" + "{ func{ @0 @14 } { @0 @5 } {} {} }",
list(
msg(Severity.WARNING, srAt(1, 12), "BLAH BLAH"),
msg(Severity.INFO, srAt(1, pos(1, 10)), "This is a warning.")
),
array(
elem("func", srAt(0, 14), srAt(0, 5), StructureElementKind.FUNCTION, null, null, list())
)
);
verifyThrows(() -> {
testParseDescribe("MESSAGES { "
+ "{ ERROR_XXX { @1 @12} "+quoteString("BLAH BLAH") + "}"
+" }", list(), array());
}, null, "Invalid message severity `ERROR_XXX`");
}
protected ParserError msg(Severity severity, SourceRange sourceRange, String errorMessage) {
return new ParserError(ParserErrorTypes.GENERIC_ERROR, severity, sourceRange, errorMessage, null);
}
}