1 package de.fhdw.wtf.tooling;
2
3 import java.io.IOException;
4 import java.net.URI;
5 import java.nio.charset.Charset;
6 import java.nio.charset.StandardCharsets;
7 import java.nio.file.Files;
8 import java.nio.file.Paths;
9 import java.util.ArrayList;
10 import java.util.Collection;
11 import java.util.concurrent.ExecutionException;
12
13 import de.fhdw.wtf.common.ast.Model;
14 import de.fhdw.wtf.common.exception.editor.CheckException;
15 import de.fhdw.wtf.common.exception.editor.EditorMarkable;
16 import de.fhdw.wtf.common.exception.editor.EditorMarker;
17 import de.fhdw.wtf.common.exception.editor.GeneralCheckException;
18 import de.fhdw.wtf.common.exception.editor.MarkableCheckException;
19 import de.fhdw.wtf.common.exception.editor.MultipleCheckExceptions;
20 import de.fhdw.wtf.common.exception.parser.AbstractParserException;
21 import de.fhdw.wtf.common.exception.parser.NoValidTokenStreamException;
22 import de.fhdw.wtf.common.exception.referencer.ReferencerException;
23 import de.fhdw.wtf.common.exception.referencer.ReferencingNotSuccessfulException;
24 import de.fhdw.wtf.common.exception.walker.CyclicDependencyException;
25 import de.fhdw.wtf.common.exception.walker.CyclicPartDefinitionException;
26 import de.fhdw.wtf.common.exception.walker.TaskException;
27 import de.fhdw.wtf.common.stream.FilteredTokenStream;
28 import de.fhdw.wtf.common.stream.SimpleScannerInput;
29 import de.fhdw.wtf.common.task.DependencyTask;
30 import de.fhdw.wtf.common.task.GroupDependencyTask;
31 import de.fhdw.wtf.common.task.TaskExecutorFixed;
32 import de.fhdw.wtf.common.task.result.ExceptionalTaskResult;
33 import de.fhdw.wtf.common.task.result.OKTaskResult;
34 import de.fhdw.wtf.common.task.result.TaskResult;
35 import de.fhdw.wtf.common.task.result.visitor.TaskResultVisitor;
36 import de.fhdw.wtf.common.token.Position;
37 import de.fhdw.wtf.dsl.scanner.modelScanner.ModelDslScanner;
38 import de.fhdw.wtf.parser.Parser;
39 import de.fhdw.wtf.walker.tasks.AbstractOperationsCheck;
40 import de.fhdw.wtf.walker.tasks.AnalyzeInheritanceTreesTask;
41 import de.fhdw.wtf.walker.tasks.BaseTypeInheritanceCheck;
42 import de.fhdw.wtf.walker.tasks.ConstructorReferencer;
43 import de.fhdw.wtf.walker.tasks.CyclicInheritanceCheck;
44 import de.fhdw.wtf.walker.tasks.DoubleAttributenameCheck;
45 import de.fhdw.wtf.walker.tasks.DoubleGroupcomponentCheck;
46 import de.fhdw.wtf.walker.tasks.InvalidAttributeModifierCheck;
47 import de.fhdw.wtf.walker.tasks.OverloadingCheck;
48 import de.fhdw.wtf.walker.tasks.ProductCheck;
49 import de.fhdw.wtf.walker.tasks.PrototypesTask;
50 import de.fhdw.wtf.walker.tasks.ReferencedConstructorsCheck;
51 import de.fhdw.wtf.walker.tasks.SubtypesFillTask;
52 import de.fhdw.wtf.walker.tasks.SupertypesCleanInheritanceTask;
53 import de.fhdw.wtf.walker.tasks.SupertypesFillTask;
54 import de.fhdw.wtf.walker.tasks.SymmetricCheck;
55 import de.fhdw.wtf.walker.tasks.TypeReferencer;
56 import de.fhdw.wtf.walker.walker.SimpleWalkerTask;
57
58 public abstract class SyntaxCheckAbstract {
59
60 private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
61
62
63
64
65
66
67
68
69
70
71
72
73 public Model getModelFromFile(final URI uri) throws MultipleCheckExceptions, CyclicDependencyException,
74 InterruptedException, CyclicPartDefinitionException, ExecutionException {
75 try {
76 final String fileContent = readFile(uri, DEFAULT_CHARSET);
77 return this.getModelFromString(fileContent);
78 } catch (final IOException e) {
79 e.printStackTrace();
80 return null;
81 }
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95 public Model getModelFromString(final String wtfFileContent) throws MultipleCheckExceptions,
96 CyclicDependencyException, InterruptedException, CyclicPartDefinitionException, ExecutionException {
97 final FilteredTokenStream output = this.scanString(wtfFileContent);
98 Model result;
99 result = this.parseStream(output);
100 this.checkModelGeneral(result);
101 return result;
102 }
103
104
105
106
107
108
109 public void checkModelGeneral(final Model model) throws MultipleCheckExceptions, CyclicDependencyException,
110 InterruptedException, ExecutionException, CyclicPartDefinitionException {
111 final MultipleCheckExceptions exceptions = new MultipleCheckExceptions();
112 final TaskExecutorFixed taskmanager = TaskExecutorFixed.create();
113
114 final GroupDependencyTask firstCheckers = GroupDependencyTask.create(taskmanager);
115 final DependencyTask doubleGroupcomponent = DoubleGroupcomponentCheck.create(model, taskmanager);
116 final DependencyTask abstractOperationsCheck = AbstractOperationsCheck.create(model, taskmanager);
117 final DependencyTask productCheck = ProductCheck.create(model, taskmanager);
118 final DependencyTask symmetricCheck = SymmetricCheck.create(model, taskmanager);
119 firstCheckers.addMembers(doubleGroupcomponent, abstractOperationsCheck, productCheck, symmetricCheck);
120
121 final TypeReferencer typeReferencer = TypeReferencer.create(model, taskmanager);
122 typeReferencer.addDependency(firstCheckers);
123
124 final GroupDependencyTask inheritanceChecker = GroupDependencyTask.create(taskmanager);
125 final DependencyTask cyclicInheritance = CyclicInheritanceCheck.create(model, taskmanager);
126 final DependencyTask baseTypeInheritanceCheck = BaseTypeInheritanceCheck.create(model, taskmanager);
127 inheritanceChecker.addMembers(cyclicInheritance, baseTypeInheritanceCheck);
128 inheritanceChecker.addDependency(typeReferencer);
129
130 final GroupDependencyTask checkersAfterReferencing = GroupDependencyTask.create(taskmanager);
131 final SimpleWalkerTask invalidAttributeModifierCheck = InvalidAttributeModifierCheck.create(model, taskmanager);
132 final DependencyTask doubleAttributenameCheck = DoubleAttributenameCheck.create(model, taskmanager);
133 checkersAfterReferencing.addMembers(invalidAttributeModifierCheck, doubleAttributenameCheck);
134 checkersAfterReferencing.addDependency(inheritanceChecker);
135
136 final GroupDependencyTask completers = GroupDependencyTask.create(taskmanager);
137 final DependencyTask prototypesTask = PrototypesTask.create(model, taskmanager);
138 final DependencyTask subtypesFillTask = SubtypesFillTask.create(model, taskmanager);
139 final SupertypesFillTask supertypesFillTask = SupertypesFillTask.create(model, taskmanager);
140 final DependencyTask supertypesCleanInheritanceTask =
141 SupertypesCleanInheritanceTask.create(model, taskmanager, supertypesFillTask);
142 prototypesTask.addDependency(subtypesFillTask);
143 supertypesFillTask.addDependency(prototypesTask);
144 supertypesCleanInheritanceTask.addDependency(supertypesFillTask);
145 completers.addMembers(subtypesFillTask, prototypesTask, supertypesFillTask, supertypesCleanInheritanceTask);
146 completers.addDependency(checkersAfterReferencing);
147 final SimpleWalkerTask overloadingCheck = OverloadingCheck.create(model, taskmanager);
148 overloadingCheck.addDependency(completers);
149
150 final ConstructorReferencer constructorReferencer = ConstructorReferencer.create(model, taskmanager);
151 constructorReferencer.addDependency(overloadingCheck);
152
153 final DependencyTask analyzeInheritanceTreesTask = AnalyzeInheritanceTreesTask.create(model, taskmanager);
154 analyzeInheritanceTreesTask.addDependency(constructorReferencer);
155
156 final DependencyTask referencedConstructorsCheck = ReferencedConstructorsCheck.create(model, taskmanager);
157 referencedConstructorsCheck.addDependency(analyzeInheritanceTreesTask);
158
159 taskmanager.startAllKnownTasks();
160 final Collection<TaskResult> results = taskmanager.getResultsAndShutdown();
161
162 final Collection<Exception> occuredExceptions = new ArrayList<>();
163 for (final TaskResult current : results) {
164 current.accept(new TaskResultVisitor() {
165
166 @Override
167 public void handleOkTaskResult(final OKTaskResult result) {
168
169 }
170
171 @Override
172 public void handleExceptionalTaskResult(final ExceptionalTaskResult result) {
173 occuredExceptions.add(result.getError());
174 }
175 });
176 }
177 if (!occuredExceptions.isEmpty()) {
178 for (final Exception occuredException : occuredExceptions) {
179 if (occuredException instanceof ReferencingNotSuccessfulException) {
180 for (final TaskException e : typeReferencer.getExceptions()) {
181 if (e instanceof ReferencerException) {
182 exceptions.add(new MarkableCheckException(((ReferencerException) e).getPosStart(),
183 ((ReferencerException) e).getPosEnd(), e, EditorMarker.REFERENCER_MARKER));
184 }
185 }
186 } else if (occuredException instanceof EditorMarkable) {
187 final EditorMarkable e = (EditorMarkable) occuredException;
188 exceptions.add(new MarkableCheckException(e.getStartPosition(), e.getEndPos(), occuredException, e
189 .getMarker()));
190 } else {
191 exceptions.add(new GeneralCheckException(occuredException));
192 }
193 }
194
195 throw exceptions;
196 }
197 }
198
199 private Model parseStream(final FilteredTokenStream output) throws MultipleCheckExceptions {
200 Model result;
201 final Parser parser = Parser.create(output);
202 try {
203 result = parser.parse();
204 return result;
205 } catch (final NoValidTokenStreamException e) {
206
207 final Collection<CheckException> excList = new ArrayList<>();
208 for (final AbstractParserException parserException : parser.getExceptions()) {
209 final int positionInLine =
210 parserException.getToken().getPosition().getPosition() + parserException.getToken().getLength();
211 final int columnNumber =
212 parserException.getToken().getPosition().getPosition() + parserException.getToken().getLength();
213 final int lineNumber = parserException.getToken().getPosition().getLineNumber();
214 final Position startPos = parserException.getToken().getPosition();
215 final Position endPos =
216 Position.create(
217 parserException.getToken().getPosition().getFilePath(),
218 lineNumber,
219 columnNumber,
220 positionInLine);
221 final MarkableCheckException markableException =
222 new MarkableCheckException(startPos, endPos, parserException, EditorMarker.PARSER_MARKER);
223 excList.add(markableException);
224 }
225 throw new MultipleCheckExceptions(excList);
226 }
227 }
228
229 private FilteredTokenStream scanString(final String fileContent) {
230 final FilteredTokenStream output = FilteredTokenStream.create();
231 final ModelDslScanner scanner = ModelDslScanner.create();
232 final SimpleScannerInput input = new SimpleScannerInput(fileContent);
233 scanner.scan(input, output);
234 return output;
235 }
236
237 private static String readFile(final URI uri, final Charset encoding) throws IOException {
238 final byte[] encoded = Files.readAllBytes(Paths.get(uri.getPath()));
239 return new String(encoded, encoding);
240 }
241
242 }