/*******************************************************************************
* Copyright (c) 2010 Martin Schnabel <mb0@mb0.org>.
* 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
******************************************************************************/
package org.axdt.as3.formatting;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import org.axdt.as3.As3StandaloneSetup;
import org.eclipse.emf.common.util.URI;
import org.eclipse.xtext.formatting.IFormatter;
import org.eclipse.xtext.formatting.INodeModelStreamer;
import org.eclipse.xtext.junit.AbstractXtextTests;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.parser.IParser;
import org.eclipse.xtext.parsetree.reconstr.ITokenStream;
import org.eclipse.xtext.parsetree.reconstr.impl.TokenStringBuffer;
import org.eclipse.xtext.resource.SaveOptions;
import org.eclipse.xtext.resource.SaveOptions.Builder;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
public class As3FormatterTest extends AbstractXtextTests {
@Override
protected void setUp() throws Exception {
super.setUp();
with(As3StandaloneSetup.class);
}
public String formatEObject(String input) throws Exception {
XtextResourceSet resourceSet = get(XtextResourceSet.class);
XtextResource resource = (XtextResource) resourceSet.createResource(URI.createURI("dummy:/Test1.as"));
resource.reparse(input);
ByteArrayOutputStream formatted = new ByteArrayOutputStream();
Builder options = SaveOptions.newBuilder();
options.format();
options.noValidation();
resource.doSave(formatted, options.getOptions().toOptionsMap());
return formatted.toString();
}
public String formatNodeModel(String input, boolean preserve) throws Exception {
IParser parser = getParser();
IParseResult parseResult = parser.parse(new StringReader(input));
IFormatter formatter = getInjector().getInstance(IFormatter.class);
TokenStringBuffer buf = new TokenStringBuffer();
ITokenStream fmt = formatter.createFormatterStream("", buf, preserve);
INodeModelStreamer nodeModelStreamer = getInjector().getInstance(INodeModelStreamer.class);
nodeModelStreamer.feedTokenStream(fmt, parseResult.getRootNode(), 0, input.length());
return buf.toString();
}
public void assertFormat(String expected, String toformat) throws Exception {
assertEquals(expected, formatNodeModel(toformat, false));
}
public void assertFormatPreserve(String expected, String toformat) throws Exception {
assertEquals(expected, formatNodeModel(toformat, true));
}
public void assertFormatDefault(String expected, String toformat) throws Exception {
String formatEObject = formatEObject(toformat);
assertEquals(expected, formatEObject);
}
public void testIgnoreLineBreaksProblem() throws Exception {
assertFormat("1++;\n\n2++;", "\n\n1++\n\n2++\n\n");
}
public void testIgnoreLineBreaksProblemDefault() throws Exception {
assertFormatDefault("1++;\n2++;", "\n\n1++\n\n2++\n\n");
}
public void testIgnoreLineBreaksProblemPreserve() throws Exception {
assertFormatPreserve("\n\n1++;\n\n2++;", "\n\n1++\n\n2++\n\n");
}
public void testIgnoreLineBreaks() throws Exception {
assertFormat("a();\nb();", "a();b();");
assertFormat("a();\nb();", "a();\nb();");
assertFormat("a();\n\nb();", "a();\n\n\nb();");
assertFormatDefault("a();\nb();", "a();b();");
assertFormatDefault("a();\nb();", "a();\nb();");
assertFormatDefault("a();\nb();", "a();\n\n\nb();");
}
public void testExpressions() throws Exception {
assertFormatDefault("1 + 1;", " 1+ 1 ; ");
assertFormatPreserve(" 1+ 1 ;", " 1+ 1 ; ");
assertFormatDefault("a.b.c++;", " a . b . c ++ ; ");
assertFormatDefault("new T(a, b);", "new T ( a , b ) ; ");
assertFormatDefault("a.b(c, d);", "a.b(c,d);");
assertFormatDefault("function(a:*, c:*):void {\n\ta++;\n};", "function(a:*,c:*):void{a++;};");
}
public void testMetadata() throws Exception {
assertFormatDefault("[Meta]\nclass A {\n}","[Meta]class A{}");
assertFormatPreserve("[Meta]class A{}","[Meta]class A{}");
assertFormat("[Meta(foo = \"bar\")]\nclass A {\n}","[Meta(foo=\"bar\")]class A{}");
}
public void testBlockStatement() throws Exception {
assertFormatDefault("{\n\t1++;\n\t2++;\n}", "{1++;\n2++;}");
assertFormatDefault("{\n\t1++;\n\t2++;\n}", "{1++;2++;}");
}
public void testIfElse() throws Exception {
assertFormatDefault("if (true) {\n} else {\n}", "if(true){}else{}");
}
public void testShortIfElse() throws Exception {
assertFormatDefault("if (true) 1++;\nelse 2++;", "if(true)1++;else 2++;");
assertFormatDefault("if (true) 1++;\nelse 2++;", "if(true)\n\t1++;else\n\t2++;");
// there is no easy way to add indentation so better use a block
assertFormat("if (true) 1++;\nelse 2++;", "if(true)\n\t1++;else\n\t2++;");
}
public void testInitializers() throws Exception {
// initializers can have breaks
assertFormat("[\n\t1,\n\t2,\n\t3\n];", "[\n1,\n2,\n3\n];");
assertFormat("{\n\t'a':1,\n\t'b':2,\n\t'c':3\n};", "{\n'a':1,\n'b':2,\n'c':3\n};");
// the trade off are bounding spaces
assertFormat("[ 1, 2, 3 ];", "[1,2,3];");
assertFormat("{ 'a':1, 'b':2, 'c':3 };", "{'a':1,'b':2,'c':3};");
}
public void testStatements() throws Exception {
assertFormatDefault("if (true) {\n}", "if(true){}");
assertFormatDefault("if (true) {\n\t1 + 1;\n}", "if(true){1+1;}");
assertFormatDefault("if (true) 1++;\nelse 2++;", "if(true)1++;else 2++;");
assertFormatDefault("while (true) c++;", "while(true)c++;");
assertFormatDefault("while (true) {\n\t1++;\n\t2++;\n}", "while(true){1++;2++;}");
assertFormatDefault("do {\n\t1++;\n\t2++;\n} while (true);", "do{1++;2++;}while(true);");
assertFormatDefault("for (a in b) c(a);", "for(a in b)c(a);");
assertFormatDefault("for each (a in b) c(a);", "for each(a in b)c(a);");
assertFormatDefault("var i:* = 0;", "var i:* =0;");
assertFormatDefault("var i:* = 0;", "var i:*=0;");
}
public void testEndComment() throws Exception {
assertFormat("1++;\n//comment", "1++;//comment");
assertFormat("1++;\n//comment", "1++;\n//comment");
assertFormatPreserve("1++;//comment", "1++;//comment");
assertFormatPreserve("1++; //comment", "1++; //comment");
assertFormatDefault("1++;\n//comment", "1++;\n\n//comment");
assertFormatDefault("1++;\n//comment", "1++;//comment");
assertFormatDefault("1++;\n//comment\n2++;", "1++;//comment\n2++;");
}
public void testCommentInBlock() throws Exception {
// this seems a bit strange because of the comment indention fix
assertFormat("class A {\n\t1++;\n\t//comment\n}","class A{1++;//comment\n}");
assertFormat("class A {\n\t//comment\n\t1++;\n}","class A{\n//comment\n1++;}");
assertFormat("class A {\t//comment\n\t1++;\n}","class A{//comment\n1++;}");
assertFormatDefault("class A {\n\t1++;\n\t//comment\n}","class A{1++;//comment\n}");
assertFormat("class A {//comment\n}","class A{//comment\n}");
}
public void testComments() throws Exception {
assertFormat("a++;\n/* ml comment */\na++;", "a++;/* ml comment */a++;");
assertFormatDefault("a++;\n/* ml comment */\na++;", "a++;\n/* ml comment */\na++;");
assertFormatDefault("a++;\n/* ml comment */\na++;", "a++;\n\n\n/* ml comment */\n\n\na++;");
assertFormat("a++;\n\n/* ml comment */\n\na++;", "a++;\n\n\n/* ml comment */\n\n\na++;");
assertFormatDefault("a++;\n/** doc comment */\na++;", "a++;/** doc comment */a++;");
assertFormat("a++;\n\n/** doc comment */\na++;", "a++;\n\n\n/** doc comment */\n\n\na++;");
}
public void testImportDirective() throws Exception {
assertFormatDefault("import a.b.c;\nimport c.b.a;","import a.b.c;\nimport c.b.a;");
}
public void testClassDirective() throws Exception {
assertFormat("public class a {\n}", "public class a{}");
assertFormatDefault("public class a {\n}", "public class a{}");
assertFormatDefault("package {\n\tpublic class a {\n\t}\n}", "package{public class a{}}");
assertFormatDefault("class a {\n\tpublic function a() {\n\t\tsuper();\n\t}\n}", "class a{public function a(){super();}}");
assertFormat("package {\n\tpublic class a {\n\t}\n}", "package{public class a{}}");
assertFormat("package {\n\n\timport a.b;\n\timport foo.bar;\n\n\tpublic class a {\n\n\t}\n}",
"package{\n\n\n\nimport a.b;import foo.bar;\n\n\n\npublic class a{\n\n\n\n}}");
assertFormatDefault("package {\n\timport a.b;\n\timport foo.bar;\n\tpublic class a {\n\t}\n}",
"package{import a.b;import foo.bar;public class a{}}");
assertFormatDefault("package {\n\n\timport a.b;\n\timport foo.bar;\n\tpublic class a {\n\n\t}\n}",
"package{\n\n\n\nimport a.b;import foo.bar;\n\n\n\npublic class a{\n\n\n\n}}");
}
public void testDirectives() throws Exception {
assertFormatDefault("var a:b = new b();\na.c();\na.d[a.f()]..foo();", "var a:b=new b();a.c();a.d[a.f()]..foo();");
assertFormat("package\n{\n\n\timport a.b;\n\timport foo.bar;\n\n\tpublic class a\n\t{\n\n\t}\n}", "package\n\n\n\n{\n\n\n\nimport a.b;import foo.bar;\n\n\n\npublic class a\n\n\n\n{\n\n\n\n}}");
assertFormat("interface a {\n\tfunction b():c;\n}", "interface a{function b():c;}");
}
}