Skip to content

Commit b901aca

Browse files
committed
Refactor IncarnationContext and related classes to use StableElementKey for mappings and reduce complexity
1 parent 55f64f6 commit b901aca

18 files changed

Lines changed: 486 additions & 629 deletions

‎ref-code-adaptation/README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ assignments are rewritten only inside that owning Java type.
119119
superclasses, modifiers, and type-reference printing. Runtime Java reflection
120120
is not used by the adapter.
121121
- `ManualIncarnationContextBuilder` is the non-mutating context builder for `useConcretization=false`.
122+
- `IncarnationContext` owns one immutable stable-key mapping. MontiCore symbols
123+
are retained only as mapped-element payload for AST operations; symbol object
124+
identity is not used for incarnation lookup.
122125
- `AdaptationConflictDetector` validates manual mappings before Java output is written.
123126
- `JavaTypeUpdateService` fills Java-expressible gaps only after
124127
cdconcretization, such as missing fields, methods, types, enum constants,

‎ref-code-adaptation/src/main/java/de/monticore/codeAdaption/AdaptedCodeMerger.java‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import de.monticore.cdbasis._ast.ASTCDCompilationUnit;
44
import de.monticore.codeAdaption.handler.multiIncarnation.IncarnationContext;
5+
import de.monticore.codeAdaption.handler.multiIncarnation.StableElementKey;
56
import de.monticore.codeAdaption.utils.AdapterUtils;
67
import de.monticore.codeAdaption.utils.CDModelIndex;
78
import de.monticore.codeAdaption.utils.visitors.JavaAstElemCollector;
@@ -12,7 +13,6 @@
1213
import de.monticore.java.javadsl._ast.ASTOrdinaryCompilationUnit;
1314
import de.monticore.java.javadsl._ast.ASTTypeDeclaration;
1415
import de.monticore.java.javadsl._visitor.JavaDSLTraverser;
15-
import de.monticore.symboltable.ISymbol;
1616
import java.io.IOException;
1717
import java.util.ArrayList;
1818
import java.util.Comparator;
@@ -41,7 +41,8 @@ Set<ASTOrdinaryCompilationUnit> mergeAdaptedCode(
4141
Set<ASTOrdinaryCompilationUnit> filterCodeForMapping(
4242
Set<ASTOrdinaryCompilationUnit> javaFiles,
4343
CodeValidator validator,
44-
IncarnationContext context) {
44+
IncarnationContext context,
45+
CDModelIndex referenceIndex) {
4546
validator.initializeTypeMatcher(javaFiles);
4647
Set<ASTOrdinaryCompilationUnit> result = new LinkedHashSet<>();
4748
for (ASTOrdinaryCompilationUnit unit : javaFiles) {
@@ -54,10 +55,10 @@ Set<ASTOrdinaryCompilationUnit> filterCodeForMapping(
5455
.map(Optional::get)
5556
.flatMap(matching -> matching.getReferences().stream())
5657
.anyMatch(
57-
reference -> {
58-
List<ISymbol> incarnations = context.getIncarnations(reference);
59-
return incarnations != null && !incarnations.isEmpty();
60-
});
58+
reference -> StableElementKey.fromSymbol(reference, referenceIndex)
59+
.map(context::getIncarnations)
60+
.filter(incarnations -> !incarnations.isEmpty())
61+
.isPresent());
6162
boolean ignoredTopLevel =
6263
collector.getAllTypeDeclarations().stream()
6364
.map(validator::getMatchedType)

‎ref-code-adaptation/src/main/java/de/monticore/codeAdaption/CodeAdapter.java‎

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ private void adaptInternal(
183183
Set<ASTOrdinaryCompilationUnit> mappingCode = cloneUnits(refCode);
184184
mappingCode = codeMerger.splitCompilationUnitsByType(mappingCode);
185185
mappingCode =
186-
codeMerger.filterCodeForMapping(mappingCode, validators.get(mapping), ctx);
186+
codeMerger.filterCodeForMapping(
187+
mappingCode, validators.get(mapping), ctx, referenceIndex);
187188

188189
for (AdaptationPass pass :
189190
buildAdaptationPasses(
@@ -222,7 +223,7 @@ private void adaptInternal(
222223
checkers.get(mapping),
223224
updater,
224225
validators.get(mapping),
225-
createSelector(pass.typeSelection(), ctx),
226+
createSelector(pass.typeSelection(), ctx, referenceIndex, conIndex),
226227
Map.of(mapping, ctx),
227228
ctx,
228229
mapping,
@@ -309,39 +310,45 @@ private static List<AdaptationPass> buildAdaptationPasses(
309310
validator.getMatchedType(type),
310311
context,
311312
relevantTypes,
313+
referenceIndex,
312314
useCommonParentForMultipleIncarnations);
313315
for (var field : collector.getAllFieldDeclarations(type)) {
314316
addRelevantTypeReferences(
315317
validator.getMatchedField(type, field),
316318
context,
317319
relevantTypes,
320+
referenceIndex,
318321
useCommonParentForMultipleIncarnations);
319322
}
320323
for (var supertype : collector.getAllFSuperTypeDeclarations(type)) {
321324
addRelevantTypeReferences(
322325
validator.getMatchedSupertype(type, supertype),
323326
context,
324327
relevantTypes,
328+
referenceIndex,
325329
useCommonParentForMultipleIncarnations);
326330
}
327331
for (var method : collector.getAllMethodDeclarations(type)) {
328332
addRelevantTypeReferences(
329333
validator.getMatchedMethod(type, method),
330334
context,
331335
relevantTypes,
336+
referenceIndex,
332337
useCommonParentForMultipleIncarnations);
333338
for (var parameter : collector.getAllParameters(type, method)) {
334339
addRelevantTypeReferences(
335340
validator.getMatchedParameter(type, method, parameter),
336341
context,
337342
relevantTypes,
343+
referenceIndex,
338344
useCommonParentForMultipleIncarnations);
339345
}
340346
for (var local : collector.getAllLocVariables(type, method)) {
341347
addRelevantTypeReferences(
342348
validator.getMatchedLocalVariable(type, method, local),
343349
context,
344350
relevantTypes,
351+
referenceIndex,
345352
useCommonParentForMultipleIncarnations);
346353
}
347354
}
@@ -355,7 +362,7 @@ private static List<AdaptationPass> buildAdaptationPasses(
355362
Map<ISymbol, ISymbol> selection = Map.of();
356363
defaultUnits.add(unit);
357364
defaultOutputTypeNames.addAll(
358-
expectedOutputTypeNames(unit, validator, context, selection));
365+
expectedOutputTypeNames(unit, validator, context, selection, referenceIndex));
359366
} else {
360367
for (Map<ISymbol, ISymbol> selection :
361368
buildCompleteTypeSelections(
@@ -368,7 +375,7 @@ private static List<AdaptationPass> buildAdaptationPasses(
368375
new AdaptationPass(
369376
Set.of(unit),
370377
selection,
371-
expectedOutputTypeNames(unit, validator, context, selection)));
378+
expectedOutputTypeNames(unit, validator, context, selection, referenceIndex)));
372379
}
373380
}
374381
}
@@ -393,6 +400,7 @@ private static void addRelevantTypeReferences(
393400
Optional<de.monticore.codeAdaption.matcher.CodeMatching> matching,
394401
IncarnationContext context,
395402
Map<StableElementKey, ISymbol> relevantTypes,
403+
CDModelIndex referenceIndex,
396404
boolean useCommonParentForMultipleIncarnations) {
397405
if (matching.isEmpty() || !matching.get().mustBePerform()) {
398406
return;
@@ -401,24 +409,29 @@ private static void addRelevantTypeReferences(
401409
if (!(reference instanceof de.monticore.cdbasis._symboltable.CDTypeSymbol)) {
402410
continue;
403411
}
404-
List<ISymbol> incarnations = context.getIncarnations(reference);
405-
if (incarnations == null
406-
|| incarnations.size() < 2
412+
List<IncarnationContext.MappedElement> incarnations =
413+
StableElementKey.fromSymbol(reference, referenceIndex)
414+
.map(context::getIncarnations)
415+
.orElseGet(List::of);
416+
if (incarnations.size() < 2
407417
|| (useCommonParentForMultipleIncarnations
408418
&& isExactGroupingSet(context, incarnations))) {
409419
continue;
410420
}
411-
context.getStableKey(reference).ifPresent(key -> relevantTypes.put(key, reference));
421+
StableElementKey.fromSymbol(reference, referenceIndex)
422+
.ifPresent(key -> relevantTypes.put(key, reference));
412423
}
413424
}
414425

415426
private static boolean isExactGroupingSet(
416-
IncarnationContext context, List<ISymbol> incarnations) {
427+
IncarnationContext context, List<IncarnationContext.MappedElement> incarnations) {
417428
Set<String> incarnationNames =
418-
incarnations.stream().map(ISymbol::getName).collect(java.util.stream.Collectors.toSet());
429+
incarnations.stream()
430+
.map(element -> element.key().getName())
431+
.collect(java.util.stream.Collectors.toSet());
419432
Set<String> derivedGroupings =
420433
incarnationNames.stream()
421-
.map(context::findGroupingTypeForImplementer)
434+
.map(name -> groupingName(context, name))
422435
.flatMap(Optional::stream)
423436
.collect(java.util.stream.Collectors.toSet());
424437
if (derivedGroupings.size() == 1) {
@@ -428,8 +441,7 @@ private static boolean isExactGroupingSet(
428441
.allMatch(
429442
incarnation ->
430443
grouping.equals(incarnation)
431-
|| context
432-
.findGroupingTypeForImplementer(incarnation)
444+
|| groupingName(context, incarnation)
433445
.filter(grouping::equals)
434446
.isPresent());
435447
if (everyIncarnationBelongsToGrouping) {
@@ -443,7 +455,7 @@ private static boolean isExactGroupingSet(
443455
if (possibleGrouping.equals(incarnation)) {
444456
continue;
445457
}
446-
Optional<String> grouping = context.findGroupingTypeForImplementer(incarnation);
458+
Optional<String> grouping = groupingName(context, incarnation);
447459
foundImplementer |= grouping.isPresent();
448460
if (grouping.isEmpty() || !possibleGrouping.equals(grouping.get())) {
449461
exact = false;
@@ -461,7 +473,8 @@ private static Set<String> expectedOutputTypeNames(
461473
ASTOrdinaryCompilationUnit unit,
462474
CodeValidator validator,
463475
IncarnationContext context,
464-
Map<ISymbol, ISymbol> selection) {
476+
Map<ISymbol, ISymbol> selection,
477+
CDModelIndex referenceIndex) {
465478
Set<String> result = new LinkedHashSet<>();
466479
for (var type : unit.getTypeDeclarationList()) {
467480
Optional<CodeMatching> matching = validator.getMatchedType(type);
@@ -472,7 +485,8 @@ private static Set<String> expectedOutputTypeNames(
472485
boolean resolved = false;
473486
List<ISymbol> concreteReferences = new ArrayList<>();
474487
for (ISymbol reference : matching.get().getReferences()) {
475-
ISymbol selected = selectedIncarnation(reference, selection, context);
488+
ISymbol selected =
489+
selectedIncarnation(reference, selection, context, referenceIndex);
476490
concreteReferences.add(selected == null ? reference : selected);
477491
resolved |= selected != null;
478492
}
@@ -493,26 +507,35 @@ private static Set<String> expectedOutputTypeNames(
493507
private static ISymbol selectedIncarnation(
494508
ISymbol reference,
495509
Map<ISymbol, ISymbol> selection,
496-
IncarnationContext context) {
510+
IncarnationContext context,
511+
CDModelIndex referenceIndex) {
497512
ISymbol selected = selection.get(reference);
513+
Optional<StableElementKey> referenceKey =
514+
StableElementKey.fromSymbol(reference, referenceIndex);
498515
if (selected == null) {
499-
Optional<StableElementKey> referenceKey = context.getStableKey(reference);
500516
selected =
501517
selection.entrySet().stream()
502-
.filter(entry -> referenceKey.equals(context.getStableKey(entry.getKey())))
518+
.filter(
519+
entry ->
520+
referenceKey.equals(
521+
StableElementKey.fromSymbol(entry.getKey(), referenceIndex)))
503522
.map(Map.Entry::getValue)
504523
.findFirst()
505524
.orElse(null);
506525
}
507526
if (selected != null) {
508527
return selected;
509528
}
510-
List<ISymbol> incarnations = context.getIncarnations(reference);
511-
return incarnations != null && incarnations.size() == 1 ? incarnations.get(0) : null;
529+
List<IncarnationContext.MappedElement> incarnations =
530+
referenceKey.map(context::getIncarnations).orElseGet(List::of);
531+
return incarnations.size() == 1 ? incarnations.get(0).symbol() : null;
512532
}
513533

514534
private static IncarnationSelector createSelector(
515-
Map<ISymbol, ISymbol> typeSelection, IncarnationContext context) {
535+
Map<ISymbol, ISymbol> typeSelection,
536+
IncarnationContext context,
537+
CDModelIndex referenceIndex,
538+
CDModelIndex concreteIndex) {
516539
return (referenceSymbol, availableIncarnations, ignored) -> {
517540
if (availableIncarnations == null || availableIncarnations.isEmpty()) {
518541
return null;
@@ -522,14 +545,15 @@ private static IncarnationSelector createSelector(
522545
return selectedType;
523546
}
524547
Optional<String> referenceOwner =
525-
context.getStableKey(referenceSymbol).flatMap(StableElementKey::getOwnerType);
548+
StableElementKey.fromSymbol(referenceSymbol, referenceIndex)
549+
.flatMap(StableElementKey::getOwnerType);
526550
if (referenceOwner.isPresent()) {
527551
Optional<ISymbol> selectedOwner =
528552
typeSelection.entrySet().stream()
529553
.filter(
530554
entry ->
531-
context
532-
.getStableKey(entry.getKey())
555+
StableElementKey
556+
.fromSymbol(entry.getKey(), referenceIndex)
533557
.filter(key -> key.getKind() == StableElementKey.Kind.TYPE)
534558
.map(StableElementKey::getName)
535559
.filter(referenceOwner.get()::equals)
@@ -541,8 +565,8 @@ private static IncarnationSelector createSelector(
541565
availableIncarnations.stream()
542566
.filter(
543567
candidate ->
544-
context
545-
.getStableKey(candidate)
568+
StableElementKey
569+
.fromSymbol(candidate, concreteIndex)
546570
.flatMap(StableElementKey::getOwnerType)
547571
.filter(selectedOwner.get().getName()::equals)
548572
.isPresent())
@@ -556,8 +580,8 @@ private static IncarnationSelector createSelector(
556580
Map<ISymbol, Integer> scores = new IdentityHashMap<>();
557581
for (ISymbol candidate : availableIncarnations) {
558582
String identity =
559-
context
560-
.getStableKey(candidate)
583+
StableElementKey
584+
.fromSymbol(candidate, concreteIndex)
561585
.map(StableElementKey::toString)
562586
.orElse(candidate.getName())
563587
.toLowerCase(Locale.ROOT);
@@ -613,12 +637,16 @@ private static List<Map<ISymbol, ISymbol>> buildCompleteTypeSelections(
613637
selections.add(new IdentityHashMap<>());
614638
for (ISymbol referenceType : referenceTypes) {
615639
List<ISymbol> incarnations =
616-
new ArrayList<>(
617-
Objects.requireNonNull(context.getIncarnations(referenceType), "incarnations"));
640+
context
641+
.getIncarnations(
642+
StableElementKey.fromSymbol(referenceType, referenceIndex).orElseThrow())
643+
.stream()
644+
.map(IncarnationContext.MappedElement::symbol)
645+
.collect(java.util.stream.Collectors.toCollection(ArrayList::new));
618646
incarnations.removeIf(incarnation -> !concreteIndex.hasType(incarnation.getName()));
619647
String referenceName =
620-
context
621-
.getStableKey(referenceType)
648+
StableElementKey
649+
.fromSymbol(referenceType, referenceIndex)
622650
.map(StableElementKey::getName)
623651
.orElse(referenceType.getName());
624652
if (incarnations.size() > 1 && !inputConcreteIndex.hasType(referenceName)) {
@@ -672,6 +700,13 @@ private static boolean sameTypeKind(
672700
&& incarnation instanceof de.monticore.cdinterfaceandenum._ast.ASTCDEnum);
673701
}
674702

703+
private static Optional<String> groupingName(
704+
IncarnationContext context, String concreteTypeName) {
705+
return context
706+
.getGroupingFor(StableElementKey.type(concreteTypeName))
707+
.map(grouping -> grouping.key().getName());
708+
}
709+
675710
private static String describeSelection(Map<ISymbol, ISymbol> selection) {
676711
return selection.entrySet().stream()
677712
.sorted(Map.Entry.comparingByKey(Comparator.comparing(ISymbol::getName)))

‎ref-code-adaptation/src/main/java/de/monticore/codeAdaption/context/GroupingMappingService.java‎

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package de.monticore.codeAdaption.context;
22

33
import de.monticore.codeAdaption.handler.multiIncarnation.IncarnationContext;
4-
import de.monticore.symboltable.ISymbol;
54
import java.util.LinkedHashMap;
6-
import java.util.List;
75
import java.util.Map;
86

97
/** Computes concrete-type to grouping-type replacements from incarnation contexts. */
@@ -18,23 +16,16 @@ public Map<String, String> compute(Map<String, IncarnationContext> mappingContex
1816
/** Computes replacements for one mapping only, preventing one mapping from leaking into another. */
1917
public Map<String, String> compute(IncarnationContext context) {
2018
Map<String, String> result = new LinkedHashMap<>();
21-
context.getReferenceToIncarnations().entrySet().stream()
22-
.sorted(Map.Entry.comparingByKey(java.util.Comparator.comparing(ISymbol::getName)))
23-
.forEach(entry -> {
24-
List<ISymbol> incarnations = entry.getValue();
25-
if (incarnations == null) {
26-
return;
27-
}
28-
incarnations.stream().filter(java.util.Objects::nonNull).sorted(java.util.Comparator.comparing(ISymbol::getName)).forEach(incarnation -> {
29-
if (incarnation == null) {
30-
return;
31-
}
32-
var groupingType = context.findGroupingTypeForImplementer(incarnation.getName());
33-
if (groupingType.isPresent() && !groupingType.get().equals(incarnation.getName())) {
34-
putUnambiguous(result, incarnation.getName(), groupingType.get());
35-
}
36-
});
37-
});
19+
context.getGroupingMappings().entrySet().stream()
20+
.sorted(Map.Entry.comparingByKey(java.util.Comparator.comparing(key -> key.signature())))
21+
.forEach(
22+
entry -> {
23+
String concrete = entry.getKey().getName();
24+
String grouping = entry.getValue().key().getName();
25+
if (!grouping.equals(concrete)) {
26+
putUnambiguous(result, concrete, grouping);
27+
}
28+
});
3829
return result;
3930
}
4031

0 commit comments

Comments
 (0)