diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatter.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatter.java new file mode 100644 index 000000000..8ea829704 --- /dev/null +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatter.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2020 itemis AG (http://www.itemis.eu) and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.xtext.formatting2.internal; + +import org.eclipse.xtext.formatting2.AbstractJavaFormatter; +import org.eclipse.xtext.formatting2.IFormattableDocument; +import org.eclipse.xtext.formatting2.internal.formattertestlanguage.IDList; +import org.eclipse.xtext.formatting2.internal.services.FormatterTestLanguageGrammarAccess; + +import com.google.inject.Inject; + +/** + * @author Arne Deutsch - Initial contribution and API + */ +public class JavaFormatter extends AbstractJavaFormatter { + + @Inject + FormatterTestLanguageGrammarAccess grammar; + + protected void format(IDList list, IFormattableDocument doc) { + doc.prepend(regionFor(list).keyword("idlist"), it -> it.noSpace()); + regionFor(list).ruleCallsTo(grammar.getIDRule()).forEach(region -> doc.prepend(region, it -> it.oneSpace())); + } + +} diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTest.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTest.java new file mode 100644 index 000000000..cd472fdca --- /dev/null +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2020 itemis AG (http://www.itemis.com) and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.xtext.formatting2.internal; + +import org.eclipse.xtext.formatting2.internal.tests.FormatterTestLanguageInjectorProvider; +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.XtextRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.inject.Inject; + +/** + * @author Arne Deutsch - Initial contribution and API + */ +@RunWith(XtextRunner.class) +@InjectWith(FormatterTestLanguageInjectorProvider.class) +public class JavaFormatterTest { + + @Inject + private JavaFormatterTestHelper helper; + + @Test + public void javaFormatterWorks() { + helper.assertFormatted(" idlist a b c", "idlist a b c"); + } + +} diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTestHelper.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTestHelper.java new file mode 100644 index 000000000..4083b5416 --- /dev/null +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/JavaFormatterTestHelper.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2020 itemis AG (http://www.itemis.eu) and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.xtext.formatting2.internal; + +import org.eclipse.xtext.formatting2.IFormatter2; +import org.eclipse.xtext.testing.formatter.FormatterTestHelper; +import org.eclipse.xtext.testing.formatter.FormatterTestRequest; + +import com.google.inject.Inject; + +/** + * @author Arne Deutsch - Initial contribution and API + */ +public class JavaFormatterTestHelper extends FormatterTestHelper { + + @Inject + private JavaFormatter formatter; + + public void assertFormatted(String original, String expectation) { + assertFormatted(r -> r.setToBeFormatted(original).setExpectation(expectation)); + } + + @Override + protected IFormatter2 createFormatter(FormatterTestRequest request) { + return formatter; + } + +} diff --git a/org.eclipse.xtext/META-INF/MANIFEST.MF b/org.eclipse.xtext/META-INF/MANIFEST.MF index 1c3e412d7..e10c099fd 100644 --- a/org.eclipse.xtext/META-INF/MANIFEST.MF +++ b/org.eclipse.xtext/META-INF/MANIFEST.MF @@ -32,20 +32,7 @@ Export-Package: org.eclipse.xtext, org.eclipse.xtend.core", org.eclipse.xtext.formatting, org.eclipse.xtext.formatting.impl, - org.eclipse.xtext.formatting2; - x-friends:="org.eclipse.xtext.generator, - org.eclipse.xtext.ide, - org.eclipse.xtext.ide.tests, - org.eclipse.xtext.purexbase, - org.eclipse.xtext.testing, - org.eclipse.xtext.testlanguages, - org.eclipse.xtext.tests, - org.eclipse.xtext.xbase, - org.eclipse.xtend.core, - org.eclipse.xtend.ide, - org.eclipse.xtext.xtext.generator, - org.eclipse.xtext.junit4, - org.eclipse.xtext.ui", + org.eclipse.xtext.formatting2, org.eclipse.xtext.formatting2.debug;x-friends:="org.eclipse.xtext.ide, org.eclipse.xtext.eclipse.tests, org.eclipse.xtext.ide.tests, @@ -54,17 +41,7 @@ Export-Package: org.eclipse.xtext, org.eclipse.xtext.tests", org.eclipse.xtext.formatting2.internal;x-friends:="org.eclipse.xtext.tests, org.eclipse.xtend.core", - org.eclipse.xtext.formatting2.regionaccess;x-friends:="org.eclipse.xtext.ide, - org.eclipse.xtext.ide.tests, - org.eclipse.xtext.purexbase, - org.eclipse.xtext.xbase, - org.eclipse.xtend.core, - org.eclipse.xtend.ide, - org.eclipse.xtend.core, - org.eclipse.xtext.junit4, - org.eclipse.xtext.testing, - org.eclipse.xtext.tests, - org.eclipse.xtext.ui", + org.eclipse.xtext.formatting2.regionaccess, org.eclipse.xtext.formatting2.regionaccess.internal;x-friends:="org.eclipse.xtext.ide, org.eclipse.xtend.core, org.eclipse.xtend.ide, diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/AbstractJavaFormatter.java b/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/AbstractJavaFormatter.java new file mode 100644 index 000000000..38405b3a0 --- /dev/null +++ b/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/AbstractJavaFormatter.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2020 itemis AG (http://www.itemis.eu) and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.xtext.formatting2; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.formatting2.regionaccess.IEObjectRegion; +import org.eclipse.xtext.formatting2.regionaccess.IHiddenRegion; +import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegion; +import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegionFinder; +import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegionsFinder; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.util.PolymorphicDispatcher; + +import com.google.common.annotations.Beta; + +/** + *
+ * This is an abstract base class for language-specific formatters, intended to be extended with a java class. + *
+ *+ * It is working very much like {@link AbstractFormatter2} but does support additional methods to simplify java + * formatter code. + *
+ *+ * the "_format" methods are called by reflection. The name is important as well as there are exactly two arguments + * whereas the first one is of the element type you like to format and the second one of type + * {@link IFormattableDocument}. The methods should be protected. + *
+ *+ * Example code for a java formatter: + * + *
+ * import static org.xtext.example.mydsl.myDsl.MyDslPackage.Literals.*; + * + * public class MyDslFormatter2 extends AbstractJavaFormatter { + * protected void _format(Model model, IFormattableDocument doc) { + * for (Parent parent : model.getParents()) + * doc.format(parent); + * } + * + * protected void _format(Parent parent, IFormattableDocument doc) { + * doc.prepend(regionFor(parent).keyword("parent"), it -> it.noSpace()); + * doc.append(regionFor(parent).keyword("parent"), it -> it.oneSpace()); + * doc.append(regionFor(parent).feature(PARENT__NAME), it -> it.oneSpace()); + * doc.prepend(regionFor(parent).keyword("{"), it -> it.oneSpace()); + * doc.append(regionFor(parent).keyword("{"), it -> it.newLine()); + * doc.interior(regionFor(parent).keyword("{"), regionFor(parent).keyword("}"), it -> it.indent()); + * doc.append(regionFor(parent).keyword("}"), it -> it.setNewLines(1, 1, 2)); + * for (Child child : parent.getChildren()) + * doc.format(child); + * } + * + * protected void _format(Child child, IFormattableDocument doc) { + * doc.append(regionFor(child).keyword("child"), it -> it.oneSpace()); + * doc.append(regionFor(child).feature(CHILD__NAME), it -> it.newLine()); + * } + * } + *+ * + *
+ * This is suitable for the following grammar: + * + *
+ * grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals + * + * generate myDsl "http://www.xtext.org/example/mydsl/MyDsl" + * + * Model: parents+=Parent*; + * Parent: 'parent' name=ID '!' ('{' children+=Child* '}')?; + * Child: 'child' name=ID; + *+ * + */ +@Beta +public abstract class AbstractJavaFormatter extends AbstractFormatter2 { + + private PolymorphicDispatcher