In progress: [Issue 13] Implement a formatter
* Fixed line wrap for normal and public imports
* Added tests to verify correct formatting
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/TestSourceReader.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/CommentReader.java
similarity index 70%
rename from com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/TestSourceReader.java
rename to com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/CommentReader.java
index ba99394..793dee2 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/TestSourceReader.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/CommentReader.java
@@ -1,9 +1,8 @@
/*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2012 Google Inc.
*
- * 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
+ * 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
*/
@@ -12,6 +11,7 @@
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static java.io.File.separator;
+import static java.util.Collections.emptyList;
import java.io.*;
import java.util.*;
@@ -21,32 +21,26 @@
import com.google.eclipse.protobuf.junit.util.MultiLineTextBuilder;
/**
+ * Reads the comments of test methods.
+ *
* @author alruiz@google.com (Alex Ruiz)
*/
-class TestSourceReader {
+public class CommentReader {
private static final String COMMENT_START = "//";
- private final Map<String, List<String>> comments = newHashMap();
- private final CommentProcessor processor = new CommentProcessor();
-
+ private final Map<String, List<String>> commentsByMethod = newHashMap();
private boolean initialized;
private final Object lock = new Object();
- String commentsIn(FrameworkMethod method) {
+ public List<String> commentsIn(FrameworkMethod method) {
synchronized (lock) {
ensureCommentsAreRead(method.getMethod().getDeclaringClass());
- List<String> allComments = comments.get(method.getName());
- if (allComments == null || allComments.isEmpty()) {
- return null;
+ List<String> comments = commentsByMethod.get(method.getName());
+ if (comments != null) {
+ return comments;
}
- for (String comment : allComments) {
- Object processed = processor.processComment(comment);
- if (processed instanceof String) {
- return (String) processed;
- }
- }
- return null;
+ return emptyList();
}
}
@@ -64,7 +58,7 @@
String classFile = fqn + ".java";
File file = new File("src" + separator + classFile);
Scanner scanner = null;
- List<String> allComments = newArrayList();
+ List<String> comments = newArrayList();
MultiLineTextBuilder comment = new MultiLineTextBuilder();
try {
scanner = new Scanner(new FileInputStream(file));
@@ -81,14 +75,14 @@
line = line.trim();
String testName = testName(line);
if (line.length() == 0 || testName != null) {
- if (!allComments.contains(comment)) {
- allComments.add(comment.toString());
+ if (!comments.contains(comment)) {
+ comments.add(comment.toString());
}
comment = new MultiLineTextBuilder();
}
if (testName != null) {
- comments.put(testName, allComments);
- allComments = newArrayList();
+ commentsByMethod.put(testName, comments);
+ comments = newArrayList();
}
}
} catch (IOException e) {
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
index bb407d3..55e1df1 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
@@ -34,13 +34,21 @@
import com.google.inject.*;
/**
- * Rule that performs configuration of a standalone Xtext environment.
+ * JUnit <code>{@link MethodRule}</code> that:
+ * <ol>
+ * <li>Performs configuration of a standalone Xtext environment</li>
+ * <li>Creates an <code>{@link XtextResource}</code> from method-level comments</li>
+ * <li>Creates .proto files in the file system based on method-level comments (if the comment starts with
+ * "// Create file" followed by the name of the file to create)</li>
+ * <li>Finds model objects and nodes in the created <code>{@link XtextResource}</code> (from #2)</li>
+ * </ol>
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class XtextRule implements MethodRule {
private final Injector injector;
- private final TestSourceReader reader;
+ private final CommentProcessor processor;
+ private final CommentReader reader;
private Protobuf root;
private XtextResource resource;
@@ -60,13 +68,14 @@
private XtextRule(Injector injector) {
this.injector = injector;
- reader = new TestSourceReader();
+ processor = new CommentProcessor();
+ reader = new CommentReader();
}
@Override public Statement apply(Statement base, FrameworkMethod method, Object target) {
injector.injectMembers(target);
root = null;
- String comments = reader.commentsIn(method);
+ String comments = commentsIn(method);
if (!isEmpty(comments)) {
parseText(comments);
finder = new Finder(resource.getParseResult().getRootNode(), comments);
@@ -74,8 +83,14 @@
return base;
}
- public Injector injector() {
- return injector;
+ private String commentsIn(FrameworkMethod method) {
+ for (String comment : reader.commentsIn(method)) {
+ Object processed = processor.processComment(comment);
+ if (processed instanceof String) {
+ return (String) processed;
+ }
+ }
+ return null;
}
public void parseText(String text) {
@@ -130,6 +145,10 @@
return injector.getInstance(type);
}
+ public Injector injector() {
+ return injector;
+ }
+
public XtextResource resource() {
return resource;
}
@@ -150,7 +169,7 @@
return finder.find(text, count, type, asList(options));
}
- public ILeafNode find(String text) {
+ public ILeafNode findNode(String text) {
return finder.find(text);
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isCommentOrString_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isCommentOrString_Test.java
index 5b8c9e9..90e5aea 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isCommentOrString_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isCommentOrString_Test.java
@@ -34,7 +34,7 @@
// // This is a test.
// message Person {}
@Test public void should_return_true_if_node_belongs_to_single_line_comment() {
- ILeafNode commentNode = xtext.find("// This is a test.");
+ ILeafNode commentNode = xtext.findNode("// This is a test.");
assertTrue(nodes.isCommentOrString(commentNode));
}
@@ -43,7 +43,7 @@
// /* This is a test. */
// message Person {}
@Test public void should_return_true_if_node_belongs_to_multiple_line_comment() {
- ILeafNode commentNode = xtext.find("/* This is a test. */");
+ ILeafNode commentNode = xtext.findNode("/* This is a test. */");
assertTrue(nodes.isCommentOrString(commentNode));
}
@@ -53,7 +53,7 @@
// optional string name = 1 [default = 'Alex'];
// }
@Test public void should_return_true_if_node_belongs_to_string() {
- ILeafNode node = xtext.find("'Alex'");
+ ILeafNode node = xtext.findNode("'Alex'");
assertTrue(nodes.isCommentOrString(node));
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isComment_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isComment_Test.java
index 5092e10..fb21453 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isComment_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isComment_Test.java
@@ -34,7 +34,7 @@
// // This is a test.
// message Person {}
@Test public void should_return_true_if_node_belongs_to_single_line_comment() {
- ILeafNode commentNode = xtext.find("// This is a test.");
+ ILeafNode commentNode = xtext.findNode("// This is a test.");
assertTrue(nodes.isComment(commentNode));
}
@@ -43,7 +43,7 @@
// /* This is a test. */
// message Person {}
@Test public void should_return_true_if_node_belongs_to_multiple_line_comment() {
- ILeafNode commentNode = xtext.find("/* This is a test. */");
+ ILeafNode commentNode = xtext.findNode("/* This is a test. */");
assertTrue(nodes.isComment(commentNode));
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isMultipleLineComment_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isMultipleLineComment_Test.java
index 805f589..35ad0f6 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isMultipleLineComment_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isMultipleLineComment_Test.java
@@ -34,7 +34,7 @@
// /* This is a test. */
// message Person {}
@Test public void should_return_true_if_node_belongs_to_multiple_line_comment() {
- ILeafNode commentNode = xtext.find("/* This is a test. */");
+ ILeafNode commentNode = xtext.findNode("/* This is a test. */");
assertTrue(nodes.isMultipleLineComment(commentNode));
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isSingleLineComment_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isSingleLineComment_Test.java
index b0dae01..56680a0 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isSingleLineComment_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isSingleLineComment_Test.java
@@ -34,7 +34,7 @@
// // This is a test.
// message Person {}
@Test public void should_return_true_if_node_belongs_to_single_line_comment() {
- ILeafNode commentNode = xtext.find("// This is a test.");
+ ILeafNode commentNode = xtext.findNode("// This is a test.");
assertTrue(nodes.isSingleLineComment(commentNode));
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isString_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isString_Test.java
index 309a29d..f322859 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isString_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_isString_Test.java
@@ -35,7 +35,7 @@
// optional string name = 1 [default = 'Alex'];
// }
@Test public void should_return_true_if_node_belongs_to_string() {
- ILeafNode node = xtext.find("'Alex'");
+ ILeafNode node = xtext.findNode("'Alex'");
assertTrue(nodes.isString(node));
}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/editor/Formatter_Test.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/editor/Formatter_Test.java
new file mode 100644
index 0000000..2628aae
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/editor/Formatter_Test.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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 com.google.eclipse.protobuf.ui.editor;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.formatting.ProtobufFormatter;
+import com.google.eclipse.protobuf.ui.junit.core.CommentReaderRule;
+import com.google.eclipse.protobuf.ui.swtbot.*;
+
+/**
+ * Tests for <code>{@link ProtobufFormatter}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Formatter_Test {
+ private static SWTWorkbenchBot robot;
+ private static FileFactory fileFactory;
+
+ public @Rule CommentReaderRule commentReader = new CommentReaderRule();
+
+ @BeforeClass public static void setUpOnce() throws Exception {
+ robot = new SWTWorkbenchBot();
+ Workbench workbench = new Workbench(robot);
+ workbench.initialize();
+ ProjectFactory projectFactory = new ProjectFactory(robot);
+ projectFactory.createGeneralProject("FormatterTest");
+ fileFactory = new FileFactory(robot);
+ SWTBotEclipseEditor editor = fileFactory.createFile("dummy.proto");
+ editor.setText("syntax = 'proto2';");
+ editor.saveAndClose();
+ }
+
+ // import 'dummy.proto';import 'google/protobuf/descriptor.proto';
+
+ // import 'dummy.proto';
+ // import 'google/protobuf/descriptor.proto';
+ @Test public void should_add_line_wrap_after_normal_import() throws Exception {
+ SWTBotEclipseEditor editor = fileFactory.createFile("formatNormalImport.proto");
+ Comments comments = commentsAbove();
+ editor.setText(comments.beforeFormatting);
+ formatAndSave(editor);
+ assertThat(editor.getText(), equalTo(comments.expected));
+ }
+
+ // import public 'dummy.proto';import 'google/protobuf/descriptor.proto';
+
+ // import public 'dummy.proto';
+ // import 'google/protobuf/descriptor.proto';
+ @Test public void should_add_line_wrap_after_public_import() throws Exception {
+ SWTBotEclipseEditor editor = fileFactory.createFile("formatPublicImport.proto");
+ Comments comments = commentsAbove();
+ editor.setText(comments.beforeFormatting);
+ formatAndSave(editor);
+ assertThat(editor.getText(), equalTo(comments.expected));
+ }
+
+ private Comments commentsAbove() {
+ return new Comments(commentReader.commentsInCurrentTestMethod());
+ }
+
+ private void formatAndSave(SWTBotEclipseEditor editor) {
+ editor.pressShortcut(SWT.MOD1 | SWT.SHIFT, 'F');
+ editor.save();
+ }
+
+ @After public void tearDown() {
+ robot.saveAllEditors();
+ robot.closeAllEditors();
+ }
+
+ private static class Comments {
+ String beforeFormatting;
+ String expected;
+
+ Comments(List<String> comments) {
+ beforeFormatting = comments.get(0);
+ expected = comments.get(1);
+ }
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/junit/core/CommentReaderRule.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/junit/core/CommentReaderRule.java
new file mode 100644
index 0000000..6907091
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/junit/core/CommentReaderRule.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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 com.google.eclipse.protobuf.ui.junit.core;
+
+import java.util.List;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.*;
+
+import com.google.eclipse.protobuf.junit.core.CommentReader;
+
+/**
+ * JUnit <code>{@link MethodRule}</code> that keeps a registry of comments per method.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class CommentReaderRule implements MethodRule {
+ private final CommentReader reader = new CommentReader();
+
+ private List<String> comments;
+
+ @Override public Statement apply(Statement base, FrameworkMethod method, Object target) {
+ comments = reader.commentsIn(method);
+ return base;
+ }
+
+ public List<String> commentsInCurrentTestMethod() {
+ return comments;
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/FileFactory.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/FileFactory.java
new file mode 100644
index 0000000..5332925
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/FileFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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 com.google.eclipse.protobuf.ui.swtbot;
+
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class FileFactory {
+
+ private final SWTWorkbenchBot robot;
+
+ public FileFactory(SWTWorkbenchBot robot) {
+ this.robot = robot;
+ }
+
+ public SWTBotEclipseEditor createFile(String name) {
+ robot.menu("File").menu("New").menu("File").click();
+ SWTBotShell shell = robot.shell("New File");
+ shell.activate();
+ robot.textWithLabel("File name:").setText(name);
+ robot.button("Finish").click();
+ return robot.editorByTitle(name).toTextEditor();
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/ProjectFactory.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/ProjectFactory.java
new file mode 100644
index 0000000..87eb6af
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/ProjectFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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 com.google.eclipse.protobuf.ui.swtbot;
+
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProjectFactory {
+ private final SWTWorkbenchBot robot;
+
+ public ProjectFactory(SWTWorkbenchBot robot) {
+ this.robot = robot;
+ }
+
+ public void createGeneralProject(String name) {
+ robot.menu("File").menu("New").menu("Project...").click();
+ SWTBotShell shell = robot.shell("New Project");
+ shell.activate();
+ robot.tree().expandNode("General").select("Project");
+ robot.button("Next >").click();
+ robot.textWithLabel("Project name:").setText(name);
+ robot.button("Finish").click();
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/Workbench.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/Workbench.java
new file mode 100644
index 0000000..50bdc11
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/swtbot/Workbench.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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 com.google.eclipse.protobuf.ui.swtbot;
+
+import static com.google.eclipse.protobuf.ui.util.Workspaces.workspaceRoot;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.*;
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public final class Workbench {
+ private static final NullProgressMonitor NULL_MONITOR = new NullProgressMonitor();
+
+ private final SWTWorkbenchBot robot;
+
+ public Workbench(SWTWorkbenchBot robot) {
+ this.robot = robot;
+ }
+
+ public void initialize() throws CoreException {
+ robot.closeAllShells();
+ closeWelcomeView();
+ deleteAllProjects();
+ }
+
+ private void closeWelcomeView() {
+ try {
+ robot.viewByTitle("Welcome").close();
+ } catch (WidgetNotFoundException ignored) {}
+ }
+
+ private void deleteAllProjects() throws CoreException {
+ for (IProject project : workspaceRoot().getProjects()) {
+ project.delete(true, true, NULL_MONITOR);
+ }
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
index acb0c4b..30cf32f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
@@ -17,7 +17,9 @@
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess;
/**
- * This class provides custom formatting.
+ * Provides custom formatting.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
*
* @see <a href="http://www.eclipse.org/Xtext/documentation/2_0_0/105-formatting.php">Xtext Formatting</a>
*/
@@ -26,9 +28,10 @@
ProtobufGrammarAccess g = (ProtobufGrammarAccess) getGrammarAccess();
c.setLinewrap(0, 1, 2).before(g.getSL_COMMENTRule());
c.setLinewrap(1).after(g.getPackageRule());
+ c.setLinewrap(1).after(g.getNormalImportRule());
+ c.setLinewrap(1).after(g.getPublicImportRule());
c.setLinewrap(1).after(g.getNativeOptionRule());
c.setLinewrap(1).after(g.getCustomOptionRule());
- c.setLinewrap(1).after(g.getImportRule());
c.setLinewrap(1).after(g.getGroupRule());
c.setLinewrap(1).after(g.getMessageFieldRule());
c.setLinewrap(1).after(g.getEnumRule());