Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 35.4% 92 / 0 / 260
Functions: -% 0 / 1 / 1
Branches: 38.0% 70 / 0 / 184

OMCompiler/Compiler/Script/ReverseLookup.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package ReverseLookup
37 import Absyn;
38
39 protected
40 import AbsynUtil;
41 import BaseAvlTree;
42 import Dump;
43 import ExecStat;
44 import JSON;
45 import ProgramUtil;
46 import Util;
47
48 uniontype PathEntry
49 record ENTRY
50 PathTree.Tree tree;
51 Boolean shadowed;
52 end ENTRY;
53 end PathEntry;
54
55 encapsulated package PathTree
56 import BaseAvlTree;
57 import ReverseLookup.PathEntry;
58 extends BaseAvlTree;
59
60 redeclare type Key = String;
61 redeclare type Value = PathEntry;
62
63 redeclare function extends keyStr
64 algorithm
65 outString := inKey;
66 end keyStr;
67
68 redeclare function extends valueStr
69 algorithm
70 outString := "";
71 end valueStr;
72
73 redeclare function extends keyCompare
74 algorithm
75 42 outResult := stringCompare(inKey1, inKey2);
76 end keyCompare;
77 end PathTree;
78
79 uniontype Paths
80 record PATHS
81 PathTree.Tree tree;
82 list<String> relativePath;
83 list<String> currentPath;
84 end PATHS;
85
86 function currentPathStr
87 input Paths paths;
88 output String str = stringDelimitList(listReverse(paths.currentPath), ".");
89 end currentPathStr;
90 end Paths;
91
92 uniontype Match
93 record MATCH
94 Absyn.ComponentRef name;
95 String scope;
96 SourceInfo info;
97 end MATCH;
98 end Match;
99
100 type Matches = list<Match>;
101
102 public
103 function lookup
104 input Absyn.Path path;
105 input Absyn.Path scope;
106 input Absyn.Program program;
107 input Boolean exactMatch;
108 input Boolean prettyPrint;
109 output String result;
110 protected
111 PathTree.Tree tree;
112 Matches matches;
113 Paths paths;
114 Absyn.Class cls;
115 Option<Absyn.Path> opt_path;
116 Absyn.Path relative_path;
117 list<list<Match>> grouped_matches;
118 algorithm
119 2 ExecStat.execStatReset();
120
121
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if AbsynUtil.pathEqual(scope, Absyn.Path.IDENT("AllLoadedClasses")) then
122 1 tree := addPath(path, PathTree.new());
123 1 paths := Paths.PATHS(tree, AbsynUtil.pathToStringList(path), {});
124 1 matches := lookupInProgram(program, paths, exactMatch);
125 else
126 1 opt_path := AbsynUtil.pathStripSamePrefix(path, scope);
127 1 relative_path := Util.getOptionOrDefault(opt_path, path);
128 1 tree := addPath(relative_path, PathTree.new());
129 1 paths := Paths.PATHS(tree, AbsynUtil.pathToStringList(relative_path), {});
130
131 try
132 1 cls := ProgramUtil.getPathedClassInProgram(scope, program);
133 1 matches := lookupInClass(cls, paths, exactMatch, {});
134 else
135 matches := {};
136 end try;
137 end if;
138
139 2 grouped_matches := groupMatches(matches);
140 2 result := serializeMatches(grouped_matches, prettyPrint);
141 2 ExecStat.execStat("ReverseLookup.lookup(" + AbsynUtil.pathString(path) + ")");
142 end lookup;
143
144 protected
145 function addPath
146 input Absyn.Path path;
147 input output PathTree.Tree tree;
148 protected
149 Option<PathEntry> opt_entry;
150 PathEntry entry;
151 algorithm
152 tree := match path
153 4 case Absyn.Path.IDENT() then PathTree.add(tree, path.name, PathEntry.ENTRY(PathTree.new(), false), conflictFunc = PathTree.addConflictKeep);
154 case Absyn.Path.QUALIFIED()
155 algorithm
156 2 opt_entry := PathTree.getOpt(tree, path.name);
157
158
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if isSome(opt_entry) then
159 ✗ entry := Util.getOption(opt_entry);
160 ✗ entry.tree := addPath(path.path, entry.tree);
161 else
162 2 entry := PathEntry.ENTRY(addPath(path.path, PathTree.new()), false);
163 end if;
164 2 then
165 PathTree.add(tree, path.name, entry, conflictFunc = PathTree.addConflictReplace);
166
167 ✗ case Absyn.Path.FULLYQUALIFIED() then addPath(path.path, tree);
168 end match;
169 end addPath;
170
171 function lookupPath
172 input Absyn.Path path;
173 input PathTree.Tree paths;
174 input Boolean exactMatch;
175 input Boolean fullyQualified = false;
176 output Boolean found;
177 protected
178 PathEntry entry;
179 algorithm
180 found := matchcontinue path
181 case Absyn.Path.IDENT()
182 algorithm
183 7 entry := PathTree.get(paths, path.name);
184
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
5 then
185 (fullyQualified or not entry.shadowed) and PathTree.isEmpty(entry.tree);
186
187 case Absyn.Path.QUALIFIED()
188 algorithm
189 11 entry := PathTree.get(paths, path.name);
190
191
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 3 times.
11 if entry.shadowed and not fullyQualified then
192 found := false;
193 elseif PathTree.isEmpty(entry.tree) and not exactMatch then
194 // A prefix of the path matches.
195 found := true;
196 else
197 8 found := lookupPath(path.path, entry.tree, exactMatch, fullyQualified);
198 end if;
199 then
200 found;
201
202 1 case Absyn.Path.FULLYQUALIFIED() then lookupPath(path.path, paths, exactMatch, true);
203 else false;
204 end matchcontinue;
205 end lookupPath;
206
207 function matchPath
208 input Absyn.Path path;
209 input Paths paths;
210 input Boolean exactMatch;
211 input SourceInfo info;
212 input output Matches matches;
213 algorithm
214
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
10 if lookupPath(path, paths.tree, exactMatch) then
215 5 matches := Match.MATCH(AbsynUtil.pathToCref(path), Paths.currentPathStr(paths), info) :: matches;
216 end if;
217 end matchPath;
218
219 function lookupCref
220 input Absyn.ComponentRef cref;
221 input PathTree.Tree paths;
222 input Boolean exactMatch;
223 input Boolean fullyQualified = false;
224 output Boolean found;
225 protected
226 PathEntry entry;
227 algorithm
228 found := matchcontinue cref
229 case Absyn.ComponentRef.CREF_IDENT()
230 algorithm
231 ✗ entry := PathTree.get(paths, cref.name);
232 ✗ then
233 (fullyQualified or not entry.shadowed) and PathTree.isEmpty(entry.tree);
234
235 case Absyn.ComponentRef.CREF_QUAL()
236 algorithm
237 ✗ entry := PathTree.get(paths, cref.name);
238
239 ✗ if entry.shadowed and not fullyQualified then
240 found := false;
241 elseif PathTree.isEmpty(entry.tree) and not exactMatch then
242 // A prefix of the path matches.
243 found := true;
244 else
245 ✗ found := lookupCref(cref.componentRef, entry.tree, exactMatch, fullyQualified);
246 end if;
247 then
248 found;
249
250 ✗ case Absyn.ComponentRef.CREF_FULLYQUALIFIED() then lookupCref(cref.componentRef, paths, exactMatch, true);
251 else false;
252 end matchcontinue;
253 end lookupCref;
254
255 function matchCref
256 input Absyn.ComponentRef cref;
257 input Paths paths;
258 input Boolean exactMatch;
259 input SourceInfo info;
260 input output Matches matches;
261 algorithm
262 ✗ if lookupCref(cref, paths.tree, exactMatch) then
263 ✗ matches := Match.MATCH(cref, Paths.currentPathStr(paths), info) :: matches;
264 end if;
265 end matchCref;
266
267 function shadowLocalNames
268 input Absyn.Class cls;
269 input output Paths paths;
270 algorithm
271
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 17 times.
32 for part in AbsynUtil.getClassPartsInClass(cls) loop
272
2/2
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 15 times.
36 for item in AbsynUtil.getElementItemsInClass(cls) loop
273 21 paths := shadowLocalNamesInElementItem(item, paths);
274 end for;
275 end for;
276 end shadowLocalNames;
277
278 function shadowLocalNamesInElementItem
279 input Absyn.ElementItem item;
280 input output Paths paths;
281 protected
282 Absyn.ElementSpec spec;
283 algorithm
284 paths := match item
285 case Absyn.ElementItem.ELEMENTITEM(element = Absyn.Element.ELEMENT(specification = spec))
286 21 then shadowLocalNamesInElementSpec(spec, paths);
287 else paths;
288 end match;
289 end shadowLocalNamesInElementItem;
290
291 function shadowLocalNamesInElementSpec
292 input Absyn.ElementSpec spec;
293 input output Paths paths;
294 algorithm
295 paths := match spec
296 case Absyn.ElementSpec.CLASSDEF()
297 13 then shadowLocalName(AbsynUtil.className(spec.class_), paths);
298
299 case Absyn.ElementSpec.COMPONENTS()
300 algorithm
301
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for comp in spec.components loop
302 5 paths := shadowLocalName(AbsynUtil.componentName(comp), paths);
303 end for;
304 then
305 paths;
306
307 else paths;
308 end match;
309 end shadowLocalNamesInElementSpec;
310
311 function shadowLocalName
312 input String name;
313 input output Paths paths;
314 protected
315 PathEntry entry;
316 algorithm
317
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1 time.
18 if PathTree.hasKey(paths.tree, name) then
318 1 entry := PathTree.get(paths.tree, name);
319
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if not entry.shadowed then
321 1 entry.shadowed := true;
322 1 paths.tree := PathTree.update(paths.tree, name, entry);
323 end if;
324 //paths.tree := PathTree.update(paths.tree, name, PathTree.add(PathTree.new(), "$shadowed", PathTree.new()));
325 end if;
326 end shadowLocalName;
327
328 function lookupInProgram
329 input Absyn.Program program;
330 input Paths paths;
331 input Boolean exactMatch;
332 output Matches matches = {};
333 algorithm
334
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for cls in program.classes loop
335 3 matches := lookupInClass(cls, paths, exactMatch, matches);
336 end for;
337 end lookupInProgram;
338
339 function lookupInClass
340 input Absyn.Class cls;
341 input Paths paths;
342 input Boolean exactMatch;
343 input output Matches matches;
344 protected
345 list<String> relative_path = paths.relativePath;
346 Paths local_paths;
347 algorithm
348 17 local_paths := shadowLocalNames(cls, paths);
349
350
6/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 8 times.
17 if not listEmpty(relative_path) and cls.name == listHead(relative_path) then
351 4 relative_path := listRest(relative_path);
352
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 local_paths.relativePath := relative_path;
353
354
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if not listEmpty(relative_path) then
355 2 local_paths.tree := addPath(AbsynUtil.stringListPath(relative_path), local_paths.tree);
356 end if;
357 end if;
358
359 17 matches := lookupInClassDef(cls.body, cls.name, local_paths, exactMatch, cls.info, matches);
360 end lookupInClass;
361
362 function lookupInClassDef
363 input Absyn.ClassDef cdef;
364 input String name;
365 input Paths paths;
366 input Boolean exactMatch;
367 input SourceInfo info;
368 input output Matches matches;
369 protected
370 Paths local_paths = paths;
371 algorithm
372 matches := match cdef
373 case Absyn.ClassDef.PARTS()
374 algorithm
375 30 local_paths.currentPath := name :: local_paths.currentPath;
376
377
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 for part in cdef.classParts loop
378 15 matches := lookupInClassPart(part, local_paths, exactMatch, info, matches);
379 end for;
380
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 for ann in cdef.ann loop
382 ✗ matches := lookupInAnnotation(ann, local_paths, exactMatch, matches);
383 end for;
384 then
385 matches;
386
387 case Absyn.ClassDef.DERIVED()
388 algorithm
389 2 matches := lookupInTypeSpec(cdef.typeSpec, paths, exactMatch, info, matches);
390
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for arg in cdef.arguments loop
392 ✗ matches := lookupInElementArg(arg, paths, exactMatch, matches);
393 end for;
394 2 then
395 lookupInCommentOpt(cdef.comment, paths, exactMatch, matches);
396
397 case Absyn.ClassDef.ENUMERATION()
398 algorithm
399 ✗ matches := lookupInEnumDef(cdef.enumLiterals, paths, exactMatch, matches);
400 ✗ then
401 lookupInCommentOpt(cdef.comment, paths, exactMatch, matches);
402
403 case Absyn.ClassDef.OVERLOAD()
404 ✗ then lookupInCommentOpt(cdef.comment, paths, exactMatch, matches);
405
406 case Absyn.ClassDef.CLASS_EXTENDS()
407 algorithm
408 ✗ local_paths.currentPath := name :: local_paths.currentPath;
409
410 ✗ for arg in cdef.modifications loop
411 ✗ matches := lookupInElementArg(arg, local_paths, exactMatch, matches);
412 end for;
413
414 ✗ for part in cdef.parts loop
415 ✗ matches := lookupInClassPart(part, local_paths, exactMatch, info, matches);
416 end for;
417
418 ✗ for ann in cdef.ann loop
419 ✗ matches := lookupInAnnotation(ann, local_paths, exactMatch, matches);
420 end for;
421 then
422 matches;
423
424 case Absyn.ClassDef.PDER()
425 algorithm
426 ✗ matches := matchPath(cdef.functionName, paths, exactMatch, info, matches);
427 ✗ then
428 lookupInCommentOpt(cdef.comment, paths, exactMatch, matches);
429
430 else matches;
431 end match;
432 end lookupInClassDef;
433
434 function lookupInClassPart
435 input Absyn.ClassPart part;
436 input Paths paths;
437 input Boolean exactMatch;
438 input SourceInfo info;
439 input output Matches matches;
440 algorithm
441 matches := match part
442 case Absyn.ClassPart.PUBLIC()
443 algorithm
444
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 15 times.
36 for e in part.contents loop
445 21 matches := lookupInElementItem(e, paths, exactMatch, matches);
446 end for;
447 then
448 matches;
449
450 case Absyn.ClassPart.PROTECTED()
451 algorithm
452 ✗ for e in part.contents loop
453 ✗ matches := lookupInElementItem(e, paths, exactMatch, matches);
454 end for;
455 then
456 matches;
457
458 case Absyn.ClassPart.EQUATIONS()
459 algorithm
460 ✗ for e in part.contents loop
461 ✗ matches := lookupInEquationItem(e, paths, exactMatch, matches);
462 end for;
463 then
464 matches;
465
466 case Absyn.ClassPart.INITIALEQUATIONS()
467 algorithm
468 ✗ for e in part.contents loop
469 ✗ matches := lookupInEquationItem(e, paths, exactMatch, matches);
470 end for;
471 then
472 matches;
473
474 case Absyn.ClassPart.ALGORITHMS()
475 algorithm
476 ✗ for alg in part.contents loop
477 ✗ matches := lookupInAlgorithmItem(alg, paths, exactMatch, matches);
478 end for;
479 then
480 matches;
481
482 case Absyn.ClassPart.INITIALALGORITHMS()
483 algorithm
484 ✗ for alg in part.contents loop
485 ✗ matches := lookupInAlgorithmItem(alg, paths, exactMatch, matches);
486 end for;
487 then
488 matches;
489
490 case Absyn.ClassPart.EXTERNAL()
491 algorithm
492 ✗ matches := lookupInExternalDecl(part.externalDecl, paths, exactMatch, info, matches);
493
494 ✗ if isSome(part.annotation_) then
495 ✗ matches := lookupInAnnotation(Util.getOption(part.annotation_), paths, exactMatch, matches);
496 end if;
497 then
498 matches;
499
500 else matches;
501 end match;
502 end lookupInClassPart;
503
504 function lookupInEnumDef
505 input Absyn.EnumDef enumDef;
506 input Paths paths;
507 input Boolean exactMatch;
508 input output Matches matches;
509 algorithm
510 matches := match enumDef
511 case Absyn.EnumDef.ENUMLITERALS()
512 algorithm
513 ✗ for lit in enumDef.enumLiterals loop
514 ✗ matches := lookupInCommentOpt(lit.comment, paths, exactMatch, matches);
515 end for;
516 then
517 matches;
518
519 else matches;
520 end match;
521 end lookupInEnumDef;
522
523 function lookupInCommentOpt
524 input Option<Absyn.Comment> cmt;
525 input Paths paths;
526 input Boolean exactMatch;
527 input output Matches matches;
528 algorithm
529
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if isSome(cmt) then
530 ✗ matches := lookupInComment(Util.getOption(cmt), paths, exactMatch, matches);
531 end if;
532 end lookupInCommentOpt;
533
534 function lookupInComment
535 input Absyn.Comment cmt;
536 input Paths paths;
537 input Boolean exactMatch;
538 input output Matches matches;
539 algorithm
540 ✗ if isSome(cmt.annotation_) then
541 ✗ matches := lookupInAnnotation(Util.getOption(cmt.annotation_), paths, exactMatch, matches);
542 end if;
543 end lookupInComment;
544
545 function lookupInAnnotation
546 input Absyn.Annotation ann;
547 input Paths paths;
548 input Boolean exactMatch;
549 input output Matches matches;
550 algorithm
551 ✗ for arg in ann.elementArgs loop
552 ✗ matches := lookupInElementArg(arg, paths, exactMatch, matches);
553 end for;
554 end lookupInAnnotation;
555
556 function lookupInElementArg
557 input Absyn.ElementArg arg;
558 input Paths paths;
559 input Boolean exactMatch;
560 input output Matches matches;
561 algorithm
562 matches := match arg
563 case Absyn.ElementArg.MODIFICATION()
564 algorithm
565 ✗ if isSome(arg.modification) then
566 ✗ matches := lookupInModification(Util.getOption(arg.modification), paths, exactMatch, matches);
567 end if;
568 then
569 matches;
570
571 case Absyn.ElementArg.REDECLARATION()
572 algorithm
573 ✗ matches := lookupInElementSpec(arg.elementSpec, paths, exactMatch, arg.info, matches);
574
575 ✗ if isSome(arg.constrainClass) then
576 ✗ matches := lookupInConstrainClass(Util.getOption(arg.constrainClass), paths, exactMatch, arg.info, matches);
577 end if;
578 then
579 matches;
580
581 else matches;
582 end match;
583 end lookupInElementArg;
584
585 function lookupInModification
586 input Absyn.Modification mod;
587 input Paths paths;
588 input Boolean exactMatch;
589 input output Matches matches;
590 algorithm
591 ✗ for arg in mod.elementArgLst loop
592 ✗ matches := lookupInElementArg(arg, paths, exactMatch, matches);
593 end for;
594
595 ✗ matches := lookupInEqMod(mod.eqMod, paths, exactMatch, matches);
596 end lookupInModification;
597
598 function lookupInEqMod
599 input Absyn.EqMod eqMod;
600 input Paths paths;
601 input Boolean exactMatch;
602 input output Matches matches;
603 algorithm
604 matches := match eqMod
605 case Absyn.EqMod.EQMOD()
606 ✗ then lookupInExp(eqMod.exp, paths, exactMatch, eqMod.info, matches);
607 else matches;
608 end match;
609 end lookupInEqMod;
610
611 function lookupInExp
612 input Absyn.Exp exp;
613 input Paths paths;
614 input Boolean exactMatch;
615 input SourceInfo info;
616 input output Matches matches;
617 algorithm
618 matches := match exp
619 ✗ case Absyn.Exp.CREF() then matchCref(exp.componentRef, paths, exactMatch, info, matches);
620 case Absyn.Exp.BINARY()
621 algorithm
622 ✗ matches := lookupInExp(exp.exp1, paths, exactMatch, info, matches);
623 ✗ then
624 lookupInExp(exp.exp2, paths, exactMatch, info, matches);
625
626 case Absyn.Exp.UNARY()
627 ✗ then lookupInExp(exp.exp, paths, exactMatch, info, matches);
628
629 case Absyn.Exp.LBINARY()
630 algorithm
631 ✗ matches := lookupInExp(exp.exp1, paths, exactMatch, info, matches);
632 ✗ then
633 lookupInExp(exp.exp2, paths, exactMatch, info, matches);
634
635 case Absyn.Exp.LUNARY()
636 ✗ then lookupInExp(exp.exp, paths, exactMatch, info, matches);
637
638 case Absyn.Exp.IFEXP()
639 algorithm
640 ✗ matches := lookupInExp(exp.ifExp, paths, exactMatch, info, matches);
641 ✗ matches := lookupInExp(exp.trueBranch, paths, exactMatch, info, matches);
642 ✗ matches := lookupInExp(exp.elseBranch, paths, exactMatch, info, matches);
643
644 ✗ for branch in exp.elseIfBranch loop
645 ✗ matches := lookupInExp(Util.tuple21(branch), paths, exactMatch, info, matches);
646 ✗ matches := lookupInExp(Util.tuple22(branch), paths, exactMatch, info, matches);
647 end for;
648 then
649 matches;
650
651 case Absyn.Exp.CALL()
652 algorithm
653 ✗ matches := matchCref(exp.function_, paths, exactMatch, info, matches);
654 ✗ then
655 lookupInFunctionArgs(exp.functionArgs, paths, exactMatch, info, matches);
656
657 case Absyn.Exp.PARTEVALFUNCTION()
658 algorithm
659 ✗ matches := matchCref(exp.function_, paths, exactMatch, info, matches);
660 ✗ then
661 lookupInFunctionArgs(exp.functionArgs, paths, exactMatch, info, matches);
662
663 case Absyn.Exp.ARRAY()
664 algorithm
665 ✗ for e in exp.arrayExp loop
666 ✗ matches := lookupInExp(e, paths, exactMatch, info, matches);
667 end for;
668 then
669 matches;
670
671 case Absyn.Exp.MATRIX()
672 algorithm
673 ✗ for row in exp.matrix loop
674 ✗ for e in row loop
675 ✗ matches := lookupInExp(e, paths, exactMatch, info, matches);
676 end for;
677 end for;
678 then
679 matches;
680
681 case Absyn.Exp.RANGE()
682 algorithm
683 ✗ matches := lookupInExp(exp.start, paths, exactMatch, info, matches);
684
685 ✗ if isSome(exp.step) then
686 ✗ matches := lookupInExp(Util.getOption(exp.step), paths, exactMatch, info, matches);
687 end if;
688
689 ✗ then
690 lookupInExp(exp.stop, paths, exactMatch, info, matches);
691
692 case Absyn.Exp.TUPLE()
693 algorithm
694 ✗ for e in exp.expressions loop
695 ✗ matches := lookupInExp(e, paths, exactMatch, info, matches);
696 end for;
697 then
698 matches;
699
700 case Absyn.Exp.EXPRESSIONCOMMENT()
701 ✗ then lookupInExp(exp.exp, paths, exactMatch, info, matches);
702
703 case Absyn.Exp.SUBSCRIPTED_EXP()
704 algorithm
705 ✗ matches := lookupInExp(exp.exp, paths, exactMatch, info, matches);
706 ✗ then
707 lookupInSubscripts(exp.subscripts, paths, exactMatch, info, matches);
708
709 else matches;
710 end match;
711 end lookupInExp;
712
713 function lookupInCref
714 input Absyn.ComponentRef cref;
715 input Paths paths;
716 input Boolean exactMatch;
717 input SourceInfo info;
718 input output Matches matches;
719 algorithm
720 ✗ matches := matchCref(cref, paths, exactMatch, info, matches);
721 ✗ matches := lookupInCrefSubs(cref, paths, exactMatch, info, matches);
722 end lookupInCref;
723
724 function lookupInCrefSubs
725 input Absyn.ComponentRef cref;
726 input Paths paths;
727 input Boolean exactMatch;
728 input SourceInfo info;
729 input output Matches matches;
730 algorithm
731 matches := match cref
732 case Absyn.ComponentRef.CREF_IDENT()
733 ✗ then lookupInSubscripts(cref.subscripts, paths, exactMatch, info, matches);
734
735 case Absyn.ComponentRef.CREF_QUAL()
736 algorithm
737 ✗ matches := lookupInSubscripts(cref.subscripts, paths, exactMatch, info, matches);
738 ✗ then
739 lookupInCrefSubs(cref.componentRef, paths, exactMatch, info, matches);
740
741 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
742 ✗ then lookupInCrefSubs(cref.componentRef, paths, exactMatch, info, matches);
743
744 else matches;
745 end match;
746 end lookupInCrefSubs;
747
748 function lookupInSubscripts
749 input list<Absyn.Subscript> subs;
750 input Paths paths;
751 input Boolean exactMatch;
752 input SourceInfo info;
753 input output Matches matches;
754 algorithm
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 for sub in subs loop
756 ✗ matches := lookupInSubscript(sub, paths, exactMatch, info, matches);
757 end for;
758 end lookupInSubscripts;
759
760 function lookupInSubscript
761 input Absyn.Subscript sub;
762 input Paths paths;
763 input Boolean exactMatch;
764 input SourceInfo info;
765 input output Matches matches;
766 algorithm
767 matches := match sub
768 ✗ case Absyn.Subscript.SUBSCRIPT() then lookupInExp(sub.subscript, paths, exactMatch, info, matches);
769 else matches;
770 end match;
771 end lookupInSubscript;
772
773 function lookupInFunctionArgs
774 input Absyn.FunctionArgs args;
775 input Paths paths;
776 input Boolean exactMatch;
777 input SourceInfo info;
778 input output Matches matches;
779 algorithm
780 matches := match args
781 case Absyn.FunctionArgs.FUNCTIONARGS()
782 algorithm
783 ✗ for arg in args.args loop
784 ✗ matches := lookupInExp(arg, paths, exactMatch, info, matches);
785 end for;
786
787 ✗ for named_arg in args.argNames loop
788 ✗ matches := lookupInExp(named_arg.argValue, paths, exactMatch, info, matches);
789 end for;
790 then
791 matches;
792
793 case Absyn.FunctionArgs.FOR_ITER_FARG()
794 algorithm
795 ✗ matches := lookupInExp(args.exp, paths, exactMatch, info, matches);
796 ✗ matches := lookupInForIterators(args.iterators, paths, exactMatch, info, matches);
797 then
798 matches;
799
800 end match;
801 end lookupInFunctionArgs;
802
803 function lookupInForIterators
804 input Absyn.ForIterators iterators;
805 input Paths paths;
806 input Boolean exactMatch;
807 input SourceInfo info;
808 input output Matches matches;
809 algorithm
810 ✗ for i in iterators loop
811 ✗ if isSome(i.range) then
812 ✗ matches := lookupInExp(Util.getOption(i.range), paths, exactMatch, info, matches);
813 end if;
814 end for;
815 end lookupInForIterators;
816
817 function lookupInElementItem
818 input Absyn.ElementItem item;
819 input Paths paths;
820 input Boolean exactMatch;
821 input output Matches matches;
822 algorithm
823 matches := match item
824 21 case Absyn.ElementItem.ELEMENTITEM() then lookupInElement(item.element, paths, exactMatch, matches);
825 else matches;
826 end match;
827 end lookupInElementItem;
828
829 function lookupInElement
830 input Absyn.Element element;
831 input Paths paths;
832 input Boolean exactMatch;
833 input output Matches matches;
834 algorithm
835 matches := match element
836 case Absyn.Element.ELEMENT()
837 algorithm
838 21 matches := lookupInElementSpec(element.specification, paths, exactMatch, element.info, matches);
839
840
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if isSome(element.constrainClass) then
841 ✗ matches := lookupInConstrainClass(Util.getOption(element.constrainClass), paths, exactMatch, element.info, matches);
842 end if;
843 then
844 matches;
845
846 else matches;
847 end match;
848 end lookupInElement;
849
850 function lookupInElementSpec
851 input Absyn.ElementSpec spec;
852 input Paths paths;
853 input Boolean exactMatch;
854 input SourceInfo info;
855 input output Matches matches;
856 algorithm
857 matches := match spec
858 13 case Absyn.ElementSpec.CLASSDEF() then lookupInClass(spec.class_, paths, exactMatch, matches);
859 case Absyn.ElementSpec.EXTENDS()
860 algorithm
861 3 matches := matchPath(spec.path, paths, exactMatch, info, matches);
862
863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 for arg in spec.elementArg loop
864 ✗ matches := lookupInElementArg(arg, paths, exactMatch, matches);
865 end for;
866
867
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if isSome(spec.annotationOpt) then
868 ✗ matches := lookupInAnnotation(Util.getOption(spec.annotationOpt), paths, exactMatch, matches);
869 end if;
870 then
871 matches;
872
873 case Absyn.ElementSpec.IMPORT()
874 algorithm
875 ✗ matches := lookupInImport(spec.import_, paths, exactMatch, info, matches);
876 then
877 matches;
878
879 case Absyn.ElementSpec.COMPONENTS()
880 algorithm
881 5 matches := lookupInTypeSpec(spec.typeSpec, paths, exactMatch, info, matches);
882
883
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for c in spec.components loop
884 5 matches := lookupInComponentItem(c, paths, exactMatch, info, matches);
885 end for;
886 then
887 matches;
888
889 end match;
890 end lookupInElementSpec;
891
892 function lookupInConstrainClass
893 input Absyn.ConstrainClass constrainClass;
894 input Paths paths;
895 input Boolean exactMatch;
896 input SourceInfo info;
897 input output Matches matches;
898 algorithm
899 ✗ matches := lookupInElementSpec(constrainClass.elementSpec, paths, exactMatch, info, matches);
900 end lookupInConstrainClass;
901
902 function lookupInImport
903 input Absyn.Import imp;
904 input Paths paths;
905 input Boolean exactMatch;
906 input SourceInfo info;
907 input output Matches matches;
908 algorithm
909 matches := match imp
910 case Absyn.Import.NAMED_IMPORT()
911 ✗ then matchPath(imp.path, paths, exactMatch, info, matches);
912
913 case Absyn.Import.QUAL_IMPORT()
914 ✗ then matchPath(imp.path, paths, exactMatch, info, matches);
915
916 case Absyn.Import.UNQUAL_IMPORT()
917 ✗ then matchPath(imp.path, paths, exactMatch, info, matches);
918
919 case Absyn.Import.GROUP_IMPORT()
920 ✗ then matchPath(imp.prefix, paths, exactMatch, info, matches);
921 end match;
922 end lookupInImport;
923
924 function lookupInComponentItem
925 input Absyn.ComponentItem item;
926 input Paths paths;
927 input Boolean exactMatch;
928 input SourceInfo info;
929 input output Matches matches;
930 algorithm
931 5 matches := lookupInComponent(item.component, paths, exactMatch, info, matches);
932
933
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if isSome(item.condition) then
934 ✗ matches := lookupInExp(Util.getOption(item.condition), paths, exactMatch, info, matches);
935 end if;
936 end lookupInComponentItem;
937
938 function lookupInComponent
939 input Absyn.Component component;
940 input Paths paths;
941 input Boolean exactMatch;
942 input SourceInfo info;
943 input output Matches matches;
944 algorithm
945 5 matches := lookupInSubscripts(component.arrayDim, paths, exactMatch, info, matches);
946
947
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if isSome(component.modification) then
948 ✗ matches := lookupInModification(Util.getOption(component.modification), paths, exactMatch, matches);
949 end if;
950 end lookupInComponent;
951
952 function lookupInTypeSpec
953 input Absyn.TypeSpec typeSpec;
954 input Paths paths;
955 input Boolean exactMatch;
956 input SourceInfo info;
957 input output Matches matches;
958 algorithm
959 matches := match typeSpec
960 case Absyn.TypeSpec.TPATH()
961 algorithm
962 7 matches := matchPath(typeSpec.path, paths, exactMatch, info, matches);
963
964
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if isSome(typeSpec.arrayDim) then
965 ✗ matches := lookupInSubscripts(Util.getOption(typeSpec.arrayDim), paths, exactMatch, info, matches);
966 end if;
967 then
968 matches;
969
970 else matches;
971 end match;
972 end lookupInTypeSpec;
973
974 function lookupInEquationItems
975 input list<Absyn.EquationItem> items;
976 input Paths paths;
977 input Boolean exactMatch;
978 input output Matches matches;
979 algorithm
980 ✗ for item in items loop
981 ✗ matches := lookupInEquationItem(item, paths, exactMatch, matches);
982 end for;
983 end lookupInEquationItems;
984
985 function lookupInEquationItem
986 input Absyn.EquationItem item;
987 input Paths paths;
988 input Boolean exactMatch;
989 input output Matches matches;
990 algorithm
991 matches := match item
992 case Absyn.EquationItem.EQUATIONITEM()
993 algorithm
994 ✗ matches := lookupInEquation(item.equation_, paths, exactMatch, item.info, matches);
995 ✗ then
996 lookupInCommentOpt(item.comment, paths, exactMatch, matches);
997
998 else matches;
999 end match;
1000 end lookupInEquationItem;
1001
1002 function lookupInEquation
1003 input Absyn.Equation eq;
1004 input Paths paths;
1005 input Boolean exactMatch;
1006 input SourceInfo info;
1007 input output Matches matches;
1008 algorithm
1009 () := match eq
1010 case Absyn.Equation.EQ_IF()
1011 algorithm
1012 ✗ matches := lookupInExp(eq.ifExp, paths, exactMatch, info, matches);
1013 ✗ matches := lookupInEquationItems(eq.equationTrueItems, paths, exactMatch, matches);
1014
1015 ✗ for branch in eq.elseIfBranches loop
1016 ✗ matches := lookupInExp(Util.tuple21(branch), paths, exactMatch, info, matches);
1017 ✗ matches := lookupInEquationItems(Util.tuple22(branch), paths, exactMatch, matches);
1018 end for;
1019
1020 ✗ matches := lookupInEquationItems(eq.equationElseItems, paths, exactMatch, matches);
1021 then
1022 ();
1023
1024 case Absyn.Equation.EQ_EQUALS()
1025 algorithm
1026 ✗ matches := lookupInExp(eq.leftSide, paths, exactMatch, info, matches);
1027 ✗ matches := lookupInExp(eq.rightSide, paths, exactMatch, info, matches);
1028 then
1029 ();
1030
1031 case Absyn.Equation.EQ_PDE()
1032 algorithm
1033 ✗ matches := lookupInExp(eq.leftSide, paths, exactMatch, info, matches);
1034 ✗ matches := lookupInExp(eq.rightSide, paths, exactMatch, info, matches);
1035 then
1036 ();
1037
1038 case Absyn.Equation.EQ_CONNECT()
1039 algorithm
1040 ✗ matches := lookupInCref(eq.connector1, paths, exactMatch, info, matches);
1041 ✗ matches := lookupInCref(eq.connector2, paths, exactMatch, info, matches);
1042 then
1043 ();
1044
1045 case Absyn.Equation.EQ_FOR()
1046 algorithm
1047 ✗ matches := lookupInForIterators(eq.iterators, paths, exactMatch, info, matches);
1048 ✗ matches := lookupInEquationItems(eq.forEquations, paths, exactMatch, matches);
1049 then
1050 ();
1051
1052 case Absyn.Equation.EQ_WHEN_E()
1053 algorithm
1054 ✗ matches := lookupInExp(eq.whenExp, paths, exactMatch, info, matches);
1055 ✗ matches := lookupInEquationItems(eq.whenEquations, paths, exactMatch, matches);
1056
1057 ✗ for branch in eq.elseWhenEquations loop
1058 ✗ matches := lookupInExp(Util.tuple21(branch), paths, exactMatch, info, matches);
1059 ✗ matches := lookupInEquationItems(Util.tuple22(branch), paths, exactMatch, matches);
1060 end for;
1061 then
1062 ();
1063
1064 case Absyn.Equation.EQ_NORETCALL()
1065 algorithm
1066 ✗ matches := lookupInCref(eq.functionName, paths, exactMatch, info, matches);
1067 ✗ matches := lookupInFunctionArgs(eq.functionArgs, paths, exactMatch, info, matches);
1068 then
1069 ();
1070
1071 else ();
1072 end match;
1073 end lookupInEquation;
1074
1075 function lookupInAlgorithmItems
1076 input list<Absyn.AlgorithmItem> items;
1077 input Paths paths;
1078 input Boolean exactMatch;
1079 input output Matches matches;
1080 algorithm
1081 ✗ for item in items loop
1082 ✗ matches := lookupInAlgorithmItem(item, paths, exactMatch, matches);
1083 end for;
1084 end lookupInAlgorithmItems;
1085
1086 function lookupInAlgorithmItem
1087 input Absyn.AlgorithmItem item;
1088 input Paths paths;
1089 input Boolean exactMatch;
1090 input output Matches matches;
1091 algorithm
1092 matches := match item
1093 case Absyn.AlgorithmItem.ALGORITHMITEM()
1094 algorithm
1095 ✗ matches := lookupInAlgorithm(item.algorithm_, paths, exactMatch, item.info, matches);
1096 ✗ matches := lookupInCommentOpt(item.comment, paths, exactMatch, matches);
1097 then
1098 matches;
1099
1100 else matches;
1101 end match;
1102 end lookupInAlgorithmItem;
1103
1104 function lookupInAlgorithm
1105 input Absyn.Algorithm alg;
1106 input Paths paths;
1107 input Boolean exactMatch;
1108 input SourceInfo info;
1109 input output Matches matches;
1110 algorithm
1111 () := match alg
1112 case Absyn.Algorithm.ALG_ASSIGN()
1113 algorithm
1114 ✗ matches := lookupInExp(alg.assignComponent, paths, exactMatch, info, matches);
1115 ✗ matches := lookupInExp(alg.value, paths, exactMatch, info, matches);
1116 then
1117 ();
1118
1119 case Absyn.Algorithm.ALG_IF()
1120 algorithm
1121 ✗ matches := lookupInExp(alg.ifExp, paths, exactMatch, info, matches);
1122 ✗ matches := lookupInAlgorithmItems(alg.trueBranch, paths, exactMatch, matches);
1123
1124 ✗ for branch in alg.elseIfAlgorithmBranch loop
1125 ✗ matches := lookupInExp(Util.tuple21(branch), paths, exactMatch, info, matches);
1126 ✗ matches := lookupInAlgorithmItems(Util.tuple22(branch), paths, exactMatch, matches);
1127 end for;
1128
1129 ✗ matches := lookupInAlgorithmItems(alg.elseBranch, paths, exactMatch, matches);
1130 then
1131 ();
1132
1133 case Absyn.Algorithm.ALG_FOR()
1134 algorithm
1135 ✗ matches := lookupInForIterators(alg.iterators, paths, exactMatch, info, matches);
1136 ✗ matches := lookupInAlgorithmItems(alg.forBody, paths, exactMatch, matches);
1137 then
1138 ();
1139
1140 case Absyn.Algorithm.ALG_PARFOR()
1141 algorithm
1142 ✗ matches := lookupInForIterators(alg.iterators, paths, exactMatch, info, matches);
1143 ✗ matches := lookupInAlgorithmItems(alg.parforBody, paths, exactMatch, matches);
1144 then
1145 ();
1146
1147 case Absyn.Algorithm.ALG_WHILE()
1148 algorithm
1149 ✗ matches := lookupInExp(alg.boolExpr, paths, exactMatch, info, matches);
1150 ✗ matches := lookupInAlgorithmItems(alg.whileBody, paths, exactMatch, matches);
1151 then
1152 ();
1153
1154 case Absyn.Algorithm.ALG_WHEN_A()
1155 algorithm
1156 ✗ matches := lookupInExp(alg.boolExpr, paths, exactMatch, info, matches);
1157 ✗ matches := lookupInAlgorithmItems(alg.whenBody, paths, exactMatch, matches);
1158
1159 ✗ for branch in alg.elseWhenAlgorithmBranch loop
1160 ✗ matches := lookupInExp(Util.tuple21(branch), paths, exactMatch, info, matches);
1161 ✗ matches := lookupInAlgorithmItems(Util.tuple22(branch), paths, exactMatch, matches);
1162 end for;
1163 then
1164 ();
1165
1166 case Absyn.Algorithm.ALG_NORETCALL()
1167 algorithm
1168 ✗ matches := lookupInCref(alg.functionCall, paths, exactMatch, info, matches);
1169 ✗ matches := lookupInFunctionArgs(alg.functionArgs, paths, exactMatch, info, matches);
1170 then
1171 ();
1172
1173 else ();
1174 end match;
1175 end lookupInAlgorithm;
1176
1177 function lookupInExternalDecl
1178 input Absyn.ExternalDecl extDecl;
1179 input Paths paths;
1180 input Boolean exactMatch;
1181 input SourceInfo info;
1182 input output Matches matches;
1183 algorithm
1184 ✗ for arg in extDecl.args loop
1185 ✗ matches := lookupInExp(arg, paths, exactMatch, info, matches);
1186 end for;
1187
1188 ✗ if isSome(extDecl.annotation_) then
1189 ✗ matches := lookupInAnnotation(Util.getOption(extDecl.annotation_), paths, exactMatch, matches);
1190 end if;
1191 end lookupInExternalDecl;
1192
1193 function serializeMatches
1194 input list<Matches> groupedMatches;
1195 input Boolean prettyPrint;
1196 output String str;
1197 protected
1198 list<JSON> json_groups = {}, json_elems;
1199 JSON json_group, json_elem;
1200 Match first_match;
1201 algorithm
1202
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for group in groupedMatches loop
1203 4 first_match := listHead(group);
1204 4 json_group := JSON.addPair("filename", JSON.makeString(first_match.info.fileName), JSON.emptyListObject());
1205
1206 json_elems := {};
1207
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 for m in group loop
1208 5 json_elem := JSON.dumpJSONSourceInfo(m.info, dumpFilename = false);
1209 5 json_elem := JSON.addPair("name", JSON.makeString(Dump.printComponentRefStr(m.name)), json_elem);
1210 5 json_elem := JSON.addPair("class", JSON.makeString(m.scope), json_elem);
1211 json_elems := json_elem :: json_elems;
1212 end for;
1213
1214 4 json_group := JSON.addPair("matches", JSON.makeArray(json_elems), json_group);
1215 json_groups := json_group :: json_groups;
1216 end for;
1217
1218 2 str := JSON.toString(JSON.makeArray(json_groups), prettyPrint);
1219 end serializeMatches;
1220
1221 function groupMatches
1222 "Sorts matches into groups based on filename."
1223 input Matches matches;
1224 output list<Matches> outMatches;
1225 protected
1226 UnorderedMap<String, Matches> grouped_matches;
1227
1228 function add_match
1229 input Option<Matches> oldMatches;
1230 input Match newMatch;
1231 output Matches outMatches;
1232 algorithm
1233
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 time.
5 if isSome(oldMatches) then
1234 1 SOME(outMatches) := oldMatches;
1235 outMatches := newMatch :: outMatches;
1236 else
1237 outMatches := {newMatch};
1238 end if;
1239 end add_match;
1240 algorithm
1241 2 grouped_matches := UnorderedMap.new<Matches>(stringHashDjb2, stringEq);
1242
1243
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 for m in matches loop
1244 5 UnorderedMap.addUpdate(m.info.fileName, function add_match(newMatch = m), grouped_matches);
1245 end for;
1246
1247 2 outMatches := UnorderedMap.valueList(grouped_matches);
1248
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 outMatches := listReverse(MetaModelica.Dangerous.listReverseInPlace(l) for l in outMatches);
1249 end groupMatches;
1250
1251 annotation(__OpenModelica_Interface="backend_tools");
1252 end ReverseLookup;
1253