aboutsummaryrefslogtreecommitdiffstats
path: root/language/src/main
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-11-15 23:45:25 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-11-15 23:45:25 +0100
commita136840664ff6190821f276c7a081152bd391dc2 (patch)
treea2c1eeb471964b7e89fd467dad257040d81f9586 /language/src/main
parentchore(lang): fix Sonar issue (diff)
downloadrefinery-a136840664ff6190821f276c7a081152bd391dc2.tar.gz
refinery-a136840664ff6190821f276c7a081152bd391dc2.tar.zst
refinery-a136840664ff6190821f276c7a081152bd391dc2.zip
feat(lang): basic formatting
Adds support for formatting some elements without any indentation. Mostly for testing model serialization with some human-readable formatting instead of just space-separating the tokens. Finishing the formatter to support all language constructs might be a bit more difficult due to our Prolog-like indentation rules.
Diffstat (limited to 'language/src/main')
-rw-r--r--language/src/main/java/tools/refinery/language/GenerateProblem.mwe23
-rw-r--r--language/src/main/java/tools/refinery/language/Problem.xtext9
-rw-r--r--language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java183
3 files changed, 191 insertions, 4 deletions
diff --git a/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2 b/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2
index 58620d6a..0d934b68 100644
--- a/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2
+++ b/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2
@@ -39,6 +39,9 @@ Workflow {
39 serializer = { 39 serializer = {
40 generateStub = false 40 generateStub = false
41 } 41 }
42 formatter = {
43 generateStub = true
44 }
42 validator = { 45 validator = {
43 generateDeprecationValidation = true 46 generateDeprecationValidation = true
44 } 47 }
diff --git a/language/src/main/java/tools/refinery/language/Problem.xtext b/language/src/main/java/tools/refinery/language/Problem.xtext
index 26773047..c94d40ab 100644
--- a/language/src/main/java/tools/refinery/language/Problem.xtext
+++ b/language/src/main/java/tools/refinery/language/Problem.xtext
@@ -8,7 +8,8 @@ Problem:
8 statements+=Statement*; 8 statements+=Statement*;
9 9
10Statement: 10Statement:
11 ClassDeclaration | EnumDeclaration | PredicateDefinition | RuleDefinition | Assertion | NodeValueAssertion | ScopeDeclaration | 11 ClassDeclaration | EnumDeclaration | PredicateDefinition | RuleDefinition | Assertion | NodeValueAssertion |
12 ScopeDeclaration |
12 IndividualDeclaration; 13 IndividualDeclaration;
13 14
14ClassDeclaration: 15ClassDeclaration:
@@ -67,7 +68,7 @@ Literal:
67 68
68ValueLiteral: 69ValueLiteral:
69 atom=Atom 70 atom=Atom
70 (refinement?=":"|"=") 71 (refinement?=":" | "=")
71 values+=LogicConstant ("|" values+=LogicConstant)*; 72 values+=LogicConstant ("|" values+=LogicConstant)*;
72 73
73NegativeLiteral: 74NegativeLiteral:
@@ -78,7 +79,7 @@ ActionLiteral:
78 79
79ValueActionLiteral: 80ValueActionLiteral:
80 atom=Atom 81 atom=Atom
81 (refinement?=":"|"=") 82 (refinement?=":" | "=")
82 value=LogicValue; 83 value=LogicValue;
83 84
84DeleteActionLiteral: 85DeleteActionLiteral:
@@ -86,7 +87,7 @@ DeleteActionLiteral:
86 87
87NewActionLiteral: 88NewActionLiteral:
88 "new" variable=NewVariable; 89 "new" variable=NewVariable;
89 90
90NewVariable: 91NewVariable:
91 name=Identifier; 92 name=Identifier;
92 93
diff --git a/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java b/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
new file mode 100644
index 00000000..903347f7
--- /dev/null
+++ b/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
@@ -0,0 +1,183 @@
1/*
2 * generated by Xtext 2.26.0.M2
3 */
4package tools.refinery.language.formatting2;
5
6import org.eclipse.emf.ecore.EObject;
7import org.eclipse.xtext.formatting2.AbstractJavaFormatter;
8import org.eclipse.xtext.formatting2.IFormattableDocument;
9import org.eclipse.xtext.formatting2.IHiddenRegionFormatter;
10import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegionsFinder;
11import org.eclipse.xtext.formatting2.regionaccess.ISequentialRegion;
12import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
13
14import tools.refinery.language.model.problem.Assertion;
15import tools.refinery.language.model.problem.Atom;
16import tools.refinery.language.model.problem.ClassDeclaration;
17import tools.refinery.language.model.problem.Conjunction;
18import tools.refinery.language.model.problem.IndividualDeclaration;
19import tools.refinery.language.model.problem.NegativeLiteral;
20import tools.refinery.language.model.problem.Parameter;
21import tools.refinery.language.model.problem.PredicateDefinition;
22import tools.refinery.language.model.problem.Problem;
23import tools.refinery.language.model.problem.ProblemPackage;
24
25public class ProblemFormatter extends AbstractJavaFormatter {
26
27 protected void format(Problem problem, IFormattableDocument doc) {
28 doc.prepend(problem, this::noSpace);
29 var region = regionFor(problem);
30 doc.append(region.keyword("problem"), this::oneSpace);
31 doc.prepend(region.keyword("."), this::noSpace);
32 appendNewLines(doc, region.keyword("."), this::twoNewLines);
33 for (var statement : problem.getStatements()) {
34 doc.format(statement);
35 }
36 }
37
38 protected void format(Assertion assertion, IFormattableDocument doc) {
39 surroundNewLines(doc, assertion, this::singleNewLine);
40 var region = regionFor(assertion);
41 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__DEFAULT), this::oneSpace);
42 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__VALUE), this::noSpace);
43 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__RELATION), this::noSpace);
44 formatParenthesizedList(region, doc);
45 doc.prepend(region.keyword(":"), this::noSpace);
46 doc.append(region.keyword(":"), this::oneSpace);
47 doc.prepend(region.keyword("."), this::noSpace);
48 for (var argument : assertion.getArguments()) {
49 doc.format(argument);
50 }
51 }
52
53 protected void format(ClassDeclaration classDeclaration, IFormattableDocument doc) {
54 surroundNewLines(doc, classDeclaration, this::twoNewLines);
55 var region = regionFor(classDeclaration);
56 doc.append(region.feature(ProblemPackage.Literals.CLASS_DECLARATION__ABSTRACT), this::oneSpace);
57 doc.append(region.keyword("class"), this::oneSpace);
58 doc.surround(region.keyword("extends"), this::oneSpace);
59 formatList(region, ",", doc);
60 doc.prepend(region.keyword("{"), this::oneSpace);
61 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2));
62 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2));
63 doc.prepend(region.keyword("."), this::noSpace);
64 for (var referenceDeclaration : classDeclaration.getReferenceDeclarations()) {
65 doc.format(referenceDeclaration);
66 }
67 }
68
69 protected void format(PredicateDefinition predicateDefinition, IFormattableDocument doc) {
70 surroundNewLines(doc, predicateDefinition, this::twoNewLines);
71 var region = regionFor(predicateDefinition);
72 doc.append(region.feature(ProblemPackage.Literals.PREDICATE_DEFINITION__KIND), this::oneSpace);
73 doc.append(region.keyword("pred"), this::oneSpace);
74 doc.append(region.feature(ProblemPackage.Literals.NAMED_ELEMENT__NAME), this::noSpace);
75 formatParenthesizedList(region, doc);
76 doc.surround(region.keyword("<->"), this::oneSpace);
77 formatList(region, ";", doc);
78 doc.prepend(region.keyword("."), this::noSpace);
79 for (var parameter : predicateDefinition.getParameters()) {
80 doc.format(parameter);
81 }
82 for (var body : predicateDefinition.getBodies()) {
83 doc.format(body);
84 }
85 }
86
87 protected void format(Parameter parameter, IFormattableDocument doc) {
88 doc.append(regionFor(parameter).feature(ProblemPackage.Literals.PARAMETER__PARAMETER_TYPE), this::oneSpace);
89 }
90
91 protected void format(Conjunction conjunction, IFormattableDocument doc) {
92 var region = regionFor(conjunction);
93 formatList(region, ",", doc);
94 for (var literal : conjunction.getLiterals()) {
95 doc.format(literal);
96 }
97 }
98
99 protected void format(NegativeLiteral literal, IFormattableDocument doc) {
100 var region = regionFor(literal);
101 doc.append(region.keyword("!"), this::noSpace);
102 doc.format(literal.getAtom());
103 }
104
105 protected void format(Atom atom, IFormattableDocument doc) {
106 var region = regionFor(atom);
107 doc.append(region.feature(ProblemPackage.Literals.ATOM__RELATION), this::noSpace);
108 doc.append(region.feature(ProblemPackage.Literals.ATOM__TRANSITIVE_CLOSURE), this::noSpace);
109 formatParenthesizedList(region, doc);
110 for (var argument : atom.getArguments()) {
111 doc.format(argument);
112 }
113 }
114
115 protected void format(IndividualDeclaration individualDeclaration, IFormattableDocument doc) {
116 surroundNewLines(doc, individualDeclaration, this::singleNewLine);
117 var region = regionFor(individualDeclaration);
118 doc.append(region.keyword("indiv"), this::oneSpace);
119 formatList(region, ",", doc);
120 doc.prepend(region.keyword("."), this::noSpace);
121 }
122
123 protected void formatParenthesizedList(ISemanticRegionsFinder region, IFormattableDocument doc) {
124 doc.append(region.keyword("("), this::noSpace);
125 doc.prepend(region.keyword(")"), this::noSpace);
126 formatList(region, ",", doc);
127 }
128
129 protected void formatList(ISemanticRegionsFinder region, String separator, IFormattableDocument doc) {
130 for (var comma : region.keywords(separator)) {
131 doc.prepend(comma, this::noSpace);
132 doc.append(comma, this::oneSpace);
133 }
134 }
135
136 protected void singleNewLine(IHiddenRegionFormatter it) {
137 it.setNewLines(1, 1, 2);
138 }
139
140 protected void twoNewLines(IHiddenRegionFormatter it) {
141 it.highPriority();
142 it.setNewLines(2);
143 }
144
145 protected void surroundNewLines(IFormattableDocument doc, EObject eObject,
146 Procedure1<? super IHiddenRegionFormatter> init) {
147 var region = doc.getRequest().getTextRegionAccess().regionForEObject(eObject);
148 preprendNewLines(doc, region, init);
149 appendNewLines(doc, region, init);
150 }
151
152 protected void preprendNewLines(IFormattableDocument doc, ISequentialRegion region,
153 Procedure1<? super IHiddenRegionFormatter> init) {
154 if (region == null) {
155 return;
156 }
157 var previousHiddenRegion = region.getPreviousHiddenRegion();
158 if (previousHiddenRegion == null) {
159 return;
160 }
161 if (previousHiddenRegion.getPreviousSequentialRegion() == null) {
162 doc.set(previousHiddenRegion, it -> it.setNewLines(0));
163 } else {
164 doc.set(previousHiddenRegion, init);
165 }
166 }
167
168 protected void appendNewLines(IFormattableDocument doc, ISequentialRegion region,
169 Procedure1<? super IHiddenRegionFormatter> init) {
170 if (region == null) {
171 return;
172 }
173 var nextHiddenRegion = region.getNextHiddenRegion();
174 if (nextHiddenRegion == null) {
175 return;
176 }
177 if (nextHiddenRegion.getNextSequentialRegion() == null) {
178 doc.set(nextHiddenRegion, it -> it.setNewLines(1));
179 } else {
180 doc.set(nextHiddenRegion, init);
181 }
182 }
183}