From 1e285aaed2f408b9eac61e57034bd5ffa43d17ad Mon Sep 17 00:00:00 2001 From: kevin-m-knight-gs Date: Thu, 16 Jan 2025 16:49:33 -0500 Subject: [PATCH] Add compiled state integrity tests for annotation modelElement and function application source info --- .../AbstractCompiledStateIntegrityTest.java | 255 ++++++++++++++---- .../CompiledStateIntegrityTestTools.java | 207 +++++++------- 2 files changed, 295 insertions(+), 167 deletions(-) diff --git a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java index d7492a736d..c9a158893b 100644 --- a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java +++ b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java @@ -37,9 +37,10 @@ import org.finos.legend.pure.m3.compiler.Context; import org.finos.legend.pure.m3.compiler.ReferenceUsage; import org.finos.legend.pure.m3.coreinstance.Package; -import org.finos.legend.pure.m3.coreinstance.PackageAccessor; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.ModelElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.Referenceable; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.AnnotatedElement; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Unit; import org.finos.legend.pure.m3.navigation.Instance; import org.finos.legend.pure.m3.navigation.M3Paths; @@ -1179,6 +1180,53 @@ else if (Instance.instanceOf(instance, functionExpressionClass, processorSupport }); Assert.assertEquals(expected, actual); + + MutableMap> noSourceInfo = Maps.mutable.empty(); + expected.forEachKeyValue((function, applications) -> + { + MutableList noSourceInfoApplications = applications.select(a -> a.getSourceInformation() == null, Lists.mutable.empty()); + if (noSourceInfoApplications.notEmpty()) + { + noSourceInfo.put(function, noSourceInfoApplications); + } + }); + if (noSourceInfo.notEmpty()) + { + StringBuilder builder = new StringBuilder("There are ").append(noSourceInfo.size()).append(" functions with applications with no source info:"); + noSourceInfo.forEachKeyValue((function, applications) -> + { + builder.append("\n\t"); + if (PackageableElement.isPackageableElement(function, processorSupport)) + { + PackageableElement.writeUserPathForPackageableElement(builder, function); + } + else + { + builder.append(function); + } + SourceInformation sourceInfo = function.getSourceInformation(); + if (sourceInfo == null) + { + ResolvedGraphPath path = CompiledStateIntegrityTestTools.findPathToInstance(function, processorSupport); + if (path != null) + { + path.getGraphPath().writeDescription(builder.append(" (")).append(')'); + } + } + else + { + sourceInfo.appendMessage(builder.append(" (")).append(')'); + } + builder.append(" [").append(applications.size()).append("]:"); + MutableSet remaining = CompiledStateIntegrityTestTools.forEachInstancePath(applications, processorSupport, (application, path) -> + { + builder.append("\n\t\t").append(application); + path.getGraphPath().writeDescription(builder.append(" (")).append(')'); + }); + remaining.forEach(application -> builder.append("\n\t\t").append(application)); + }); + Assert.fail(builder.toString()); + } } @Test @@ -1444,75 +1492,170 @@ public void testSourceSerialization() } @Test - public void testReferencerUsageOwners() + public void testAnnotationModelElements() { MutableList errorMessages = Lists.mutable.empty(); - PackageTreeIterable.newRootPackageTreeIterable(repository) - .flatCollect(PackageAccessor::_children) - .select(e -> e.getSourceInformation() != null) - .collect(e -> (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement) e) - .concatenate(repository.getTopLevels().asLazy().collect(e -> (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement) e)) - .forEach(element -> + CompiledStateIntegrityTestTools.getTopLevelAndPackagedIterable(processorSupport).selectInstancesOf(Profile.class).forEach(profile -> + { + profile._p_stereotypes().forEach(st -> + { + MutableList missingStereotype = Lists.mutable.empty(); + MutableList noSourceInfo = Lists.mutable.empty(); + st._modelElements().forEach(e -> { - SourceInformation elementSourceInfo = element.getSourceInformation(); - MutableSet internalNodes = GraphNodeIterable.builder() - .withStartingNode(element) - .withKeyFilter((node, key) -> !M3PropertyPaths.BACK_REFERENCE_PROPERTY_PATHS.contains(node.getRealKeyByName(key))) - .withNodeFilter(node -> - { - SourceInformation nodeSourceInfo = node.getSourceInformation(); - return (nodeSourceInfo == null) || elementSourceInfo.subsumes(nodeSourceInfo) ? GraphWalkFilterResult.ACCEPT_AND_CONTINUE : GraphWalkFilterResult.REJECT_AND_STOP; - }) - .build() - .toSet(); - MutableMap> badRefUsages = Maps.mutable.empty(); - internalNodes.forEach(node -> + if (!e._stereotypes().contains(st)) { - if (node instanceof Referenceable) - { - ((Referenceable) node)._referenceUsages().forEach(refUsage -> - { - CoreInstance owner = refUsage._ownerCoreInstance(); - if ((owner.getSourceInformation() == null) && !internalNodes.contains(owner)) - { - badRefUsages.getIfAbsentPut(node, Lists.mutable::empty).add(refUsage); - } - }); - } - }); - badRefUsages.forEachKeyValue((node, refUsages) -> + missingStereotype.add(e); + } + if (e.getSourceInformation() == null) { - StringBuilder builder = new StringBuilder(); - if (node == element) - { - PackageableElement.writeUserPathForPackageableElement(builder, node); - } - else + noSourceInfo.add(e); + } + }); + if (noSourceInfo.notEmpty() || missingStereotype.notEmpty()) + { + StringBuilder builder = new StringBuilder("Stereotype "); + PackageableElement.writeUserPathForPackageableElement(builder, profile).append('.').append(st._value()); + if (missingStereotype.notEmpty()) + { + builder.append("\n\t\thas ").append(missingStereotype.size()).append(" modelElements without the stereotype:"); + missingStereotype.forEach(e -> { - ResolvedGraphPath pathToNode = CompiledStateIntegrityTestTools.findPathToInstance(node, processorSupport); - if (pathToNode == null) + builder.append("\n\t\t\t").append(e); + SourceInformation sourceInfo = e.getSourceInformation(); + if (sourceInfo != null) { - builder.append(node); + sourceInfo.appendMessage(builder.append(" (")).append(')'); } - else + }); + } + if (noSourceInfo.notEmpty()) + { + builder.append("\n\t\thas ").append(missingStereotype.size()).append(" modelElements without no source info:"); + MutableSet remaining = CompiledStateIntegrityTestTools.forEachInstancePath(noSourceInfo, processorSupport, + (instance, path) -> path.getGraphPath().writeDescription(builder.append("\n\t\t\t").append(instance).append(" (")).append(')')); + remaining.forEach(instance -> builder.append("\n\t\t\t").append(instance).append(" (no path found)")); + } + errorMessages.add(builder.toString()); + } + }); + profile._p_tags().forEach(tag -> + { + MutableList noSourceInfo = Lists.mutable.empty(); + MutableList missingTag = Lists.mutable.empty(); + tag._modelElements().forEach(e -> + { + if (e.getSourceInformation() == null) + { + noSourceInfo.add(e); + } + if (e._taggedValues().noneSatisfy(tv -> tag == tv._tag())) + { + missingTag.add(e); + } + }); + if (noSourceInfo.notEmpty() || missingTag.notEmpty()) + { + StringBuilder builder = new StringBuilder("Stereotype "); + PackageableElement.writeUserPathForPackageableElement(builder, profile).append('.').append(tag._value()); + if (missingTag.notEmpty()) + { + builder.append("\n\t\thas ").append(missingTag.size()).append(" modelElements without the tag:"); + missingTag.forEach(e -> + { + builder.append("\n\t\t\t").append(e); + SourceInformation sourceInfo = e.getSourceInformation(); + if (sourceInfo != null) { - pathToNode.getGraphPath().writeDescription(builder); + sourceInfo.appendMessage(builder.append(" (")).append(')'); } - } + }); + } + if (noSourceInfo.notEmpty()) + { + builder.append("\n\t\thas ").append(missingTag.size()).append(" modelElements without no source info:"); + MutableSet remaining = CompiledStateIntegrityTestTools.forEachInstancePath(noSourceInfo, processorSupport, + (instance, path) -> path.getGraphPath().writeDescription(builder.append("\n\t\t\t").append(instance).append(" (")).append(')')); + remaining.forEach(instance -> builder.append("\n\t\t\t").append(instance).append(" (no path found)")); + } + errorMessages.add(builder.toString()); + } + }); + }); + if (errorMessages.notEmpty()) + { + StringBuilder builder = new StringBuilder("There are ").append(errorMessages.size()).append(" annotations with invalid model elements"); + errorMessages.forEach(m -> builder.append("\n\t").append(m)); + Assert.fail(builder.toString()); + } + } + + @Test + public void testReferencerUsageOwners() + { + MutableList errorMessages = Lists.mutable.empty(); + CompiledStateIntegrityTestTools.getTopLevelAndPackagedIterable(processorSupport).forEach(element -> + { + SourceInformation elementSourceInfo = element.getSourceInformation(); + MutableSet internalNodes = GraphNodeIterable.builder() + .withStartingNode(element) + .withKeyFilter((node, key) -> !M3PropertyPaths.BACK_REFERENCE_PROPERTY_PATHS.contains(node.getRealKeyByName(key))) + .withNodeFilter(node -> + { SourceInformation nodeSourceInfo = node.getSourceInformation(); - if (nodeSourceInfo != null) - { - nodeSourceInfo.appendMessage(builder.append(" (")).append(')'); - } - else + boolean internal = (nodeSourceInfo == null) ? !(node instanceof Package) : elementSourceInfo.subsumes(nodeSourceInfo); + return internal ? GraphWalkFilterResult.ACCEPT_AND_CONTINUE : GraphWalkFilterResult.REJECT_AND_STOP; + }) + .build() + .toSet(); + MutableMap> badRefUsages = Maps.mutable.empty(); + internalNodes.forEach(node -> + { + if (node instanceof Referenceable) + { + ((Referenceable) node)._referenceUsages().forEach(refUsage -> + { + CoreInstance owner = refUsage._ownerCoreInstance(); + if ((owner.getSourceInformation() == null) && !internalNodes.contains(owner)) { - elementSourceInfo.appendMessage(builder.append(" (within ")).append(')'); + badRefUsages.getIfAbsentPut(node, Lists.mutable::empty).add(refUsage); } - builder.append(" [").append(refUsages.size()).append("]:"); - refUsages.forEach(refUsage -> ReferenceUsage.writeReferenceUsage(builder.append("\n\t\t"), refUsage)); - errorMessages.add(builder.toString()); }); - }); + } + }); + badRefUsages.forEachKeyValue((node, refUsages) -> + { + StringBuilder builder = new StringBuilder(); + if (node == element) + { + PackageableElement.writeUserPathForPackageableElement(builder, node); + } + else + { + ResolvedGraphPath pathToNode = CompiledStateIntegrityTestTools.findPathToInstance(node, processorSupport); + if (pathToNode == null) + { + builder.append(node); + } + else + { + pathToNode.getGraphPath().writeDescription(builder); + } + } + SourceInformation nodeSourceInfo = node.getSourceInformation(); + if (nodeSourceInfo != null) + { + nodeSourceInfo.appendMessage(builder.append(" (")).append(')'); + } + else + { + elementSourceInfo.appendMessage(builder.append(" (within ")).append(')'); + } + builder.append(" [").append(refUsages.size()).append("]:"); + refUsages.forEach(refUsage -> ReferenceUsage.writeReferenceUsage(builder.append("\n\t\t"), refUsage)); + errorMessages.add(builder.toString()); + }); + }); if (errorMessages.notEmpty()) { StringBuilder builder = new StringBuilder("There are ").append(errorMessages.size()).append(" instances with ReferenceUsages with no owner source information"); diff --git a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/CompiledStateIntegrityTestTools.java b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/CompiledStateIntegrityTestTools.java index 8ab9af54a8..41a003816e 100644 --- a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/CompiledStateIntegrityTestTools.java +++ b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/CompiledStateIntegrityTestTools.java @@ -17,13 +17,11 @@ import org.eclipse.collections.api.LazyIterable; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Sets; -import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ListIterable; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.map.MapIterable; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.impl.utility.Iterate; -import org.eclipse.collections.impl.utility.LazyIterate; import org.finos.legend.pure.m3.coreinstance.Package; import org.finos.legend.pure.m3.coreinstance.PackageAccessor; import org.finos.legend.pure.m3.navigation.Instance; @@ -34,7 +32,6 @@ import org.finos.legend.pure.m3.navigation.PrimitiveUtilities; import org.finos.legend.pure.m3.navigation.ProcessorSupport; import org.finos.legend.pure.m3.navigation._class._Class; -import org.finos.legend.pure.m3.navigation._package._Package; import org.finos.legend.pure.m3.navigation.generictype.GenericType; import org.finos.legend.pure.m3.navigation.graph.GraphPathIterable; import org.finos.legend.pure.m3.navigation.graph.ResolvedGraphPath; @@ -48,11 +45,9 @@ import org.finos.legend.pure.m4.tools.GraphWalkFilterResult; import org.junit.Assert; -import java.util.Collection; import java.util.Formatter; import java.util.Objects; import java.util.function.BiConsumer; -import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; @@ -245,7 +240,7 @@ static MutableSet forEachInstancePath(Iterable in static MutableSet forEachInstancePath(Iterable instances, Iterable startNodes, ProcessorSupport processorSupport, BiConsumer consumer) { MutableSet remaining = Sets.mutable.withAll(instances); - for (CoreInstance startNode : (startNodes == null) ? getTopLevelAndPackagedIterable(processorSupport).select(n -> n.getSourceInformation() != null) : LazyIterate.adapt(startNodes)) + for (CoreInstance startNode : (startNodes == null) ? getTopLevelAndPackagedIterable(processorSupport).select(n -> n.getSourceInformation() != null) : startNodes) { for (ResolvedGraphPath rgp : internalGraphPaths(startNode, processorSupport)) { @@ -268,22 +263,60 @@ static LazyIterable getTopLevelAndPackagedIterable(ModelRepository return repository.getTopLevels() .asLazy() .concatenate(PackageTreeIterable.newRootPackageTreeIterable(repository) - .flatCollect(pkg -> Lists.mutable.withAll(pkg._children()))); + .flatCollect(PackageAccessor::_children) + .collect(e -> (CoreInstance) e)); } static LazyIterable getTopLevelAndPackagedIterable(ProcessorSupport processorSupport) { - return PrimitiveUtilities.getPrimitiveTypes(processorSupport, Lists.mutable.empty()) + return PrimitiveUtilities.getPrimitiveTypes(processorSupport, Lists.mutable.ofInitialCapacity(PrimitiveUtilities.getPrimitiveTypeNames().size() + 2)) .with(processorSupport.repository_getTopLevel(M3Paths.Package)) .with(processorSupport.repository_getTopLevel(M3Paths.Root)) .asLazy() .concatenate(PackageTreeIterable.newRootPackageTreeIterable(processorSupport) - .flatCollect(pkg -> Lists.mutable.withAll(pkg._children()))); + .flatCollect(PackageAccessor::_children) + .collect(e -> (CoreInstance) e)); } - private static GraphPathIterable internalGraphPaths(CoreInstance element, ProcessorSupport processorSupport) + static LazyIterable componentInstances(CoreInstance element) { - SourceInformation sourceInfo = element.getSourceInformation(); + SourceInformation sourceInfo = Objects.requireNonNull(element.getSourceInformation(), "element source information may not be null"); + return GraphNodeIterable.builder() + .withStartingNode(element) + .withKeyFilter((node, key) -> + { + switch (key) + { + case M3Properties._package: + { + return !M3PropertyPaths._package.equals(node.getRealKeyByName(key)); + } + case M3Properties.children: + { + return !M3PropertyPaths.children.equals(node.getRealKeyByName(key)); + } + default: + { + return true; + } + } + }) + .withNodeFilter(node -> + { + if (node == element) + { + return GraphWalkFilterResult.ACCEPT_AND_CONTINUE; + } + SourceInformation nodeSourceInfo = node.getSourceInformation(); + boolean internal = (nodeSourceInfo == null) ? !(node instanceof Package) : sourceInfo.subsumes(nodeSourceInfo); + return internal ? GraphWalkFilterResult.ACCEPT_AND_CONTINUE : GraphWalkFilterResult.REJECT_AND_STOP; + }) + .build(); + } + + static GraphPathIterable internalGraphPaths(CoreInstance element, ProcessorSupport processorSupport) + { + SourceInformation sourceInfo = Objects.requireNonNull(element.getSourceInformation(), "element source information may not be null"); return GraphPathIterable.builder(processorSupport) .withStartNode(element) .withPropertyFilter((rgp, property) -> @@ -309,37 +342,49 @@ private static GraphPathIterable internalGraphPaths(CoreInstance element, Proces CoreInstance node = rgp.getLastResolvedNode(); if (node == element) { + // all graph paths start from element and cannot contain loops: so this must be the starting path return GraphWalkFilterResult.ACCEPT_AND_CONTINUE; } - if (node instanceof Package) - { - return GraphWalkFilterResult.REJECT_AND_STOP; - } - SourceInformation nodeSourceInfo = node.getSourceInformation(); - return ((nodeSourceInfo == null) || sourceInfo.subsumes(nodeSourceInfo)) ? - GraphWalkFilterResult.ACCEPT_AND_CONTINUE : - GraphWalkFilterResult.REJECT_AND_STOP; + boolean internal = (nodeSourceInfo == null) ? !(node instanceof Package) : sourceInfo.subsumes(nodeSourceInfo); + return internal ? GraphWalkFilterResult.ACCEPT_AND_CONTINUE : GraphWalkFilterResult.REJECT_AND_STOP; }) .build(); } - static LazyIterable componentInstances(CoreInstance element) + static ResolvedGraphPath findPathToInstance(CoreInstance instance, ProcessorSupport processorSupport) { - SourceInformation sourceInfo = Objects.requireNonNull(element.getSourceInformation(), "element source information may not be null"); - return GraphNodeIterable.builder() - .withStartingNode(element) - .withKeyFilter((n, k) -> + return getTopLevelAndPackagedIterable(processorSupport) + .flatCollect(e -> Lists.immutable.with(findPathToInstanceWithinElement(e, instance, processorSupport))) + .detect(Objects::nonNull); + } + + static ResolvedGraphPath findPathToInstanceWithinElement(CoreInstance element, CoreInstance instance, ProcessorSupport processorSupport) + { + SourceInformation sourceInfo = element.getSourceInformation(); + if (sourceInfo == null) + { + return null; + } + SourceInformation instanceSourceInfo = instance.getSourceInformation(); + if ((instanceSourceInfo != null) && !sourceInfo.subsumes(instanceSourceInfo)) + { + return null; + } + MutableSet visited = Sets.mutable.empty(); + return GraphPathIterable.builder(processorSupport) + .withStartNode(element) + .withPropertyFilter((rgp, property) -> { - switch (k) + switch (property) { case M3Properties._package: { - return !M3PropertyPaths._package.equals(n.getRealKeyByName(k)); + return !M3PropertyPaths._package.equals(rgp.getLastResolvedNode().getRealKeyByName(property)); } case M3Properties.children: { - return !M3PropertyPaths.children.equals(n.getRealKeyByName(k)); + return !M3PropertyPaths.children.equals(rgp.getLastResolvedNode().getRealKeyByName(property)); } default: { @@ -347,10 +392,30 @@ static LazyIterable componentInstances(CoreInstance element) } } }) - .withNodeFilter(n -> ((n.getSourceInformation() == null) || sourceInfo.subsumes(n.getSourceInformation())) ? - GraphWalkFilterResult.ACCEPT_AND_CONTINUE : - GraphWalkFilterResult.REJECT_AND_STOP) - .build(); + .withPathFilter(rgp -> + { + CoreInstance node = rgp.getLastResolvedNode(); + if (node == instance) + { + return GraphWalkFilterResult.ACCEPT_AND_STOP; + } + if (node == element) + { + // all graph paths start from element and cannot contain loops: so this must be the starting path + return GraphWalkFilterResult.REJECT_AND_CONTINUE; + } + if (visited.add(node)) + { + SourceInformation nodeSourceInfo = node.getSourceInformation(); + if ((nodeSourceInfo == null) ? !(node instanceof Package) : sourceInfo.subsumes(nodeSourceInfo)) + { + return GraphWalkFilterResult.REJECT_AND_CONTINUE; + } + } + return GraphWalkFilterResult.REJECT_AND_STOP; + }) + .build() + .getAny(); } private static void runIntegrityTest(Iterable instances, String violationDescription, BiConsumer> test) @@ -623,84 +688,4 @@ else if (!GenericType.isGenericCompatibleWith(valueGenericType, genericType, pro } }); } - - public static ResolvedGraphPath findPathToInstance(CoreInstance instance, ProcessorSupport processorSupport) - { - Objects.requireNonNull(instance); - BiPredicate propFilter = isNotBackRefPropertyFilter(); - return getTopLevels(processorSupport).asLazy() - .concatenate(PackageTreeIterable.newRootPackageTreeIterable(processorSupport).flatCollect(PackageAccessor::_children).collect(e -> (CoreInstance) e)) - .collect(elt -> findPathToInstanceFromElement(elt, instance, propFilter, processorSupport)) - .detect(Objects::nonNull); - } - - public static ResolvedGraphPath findPathToInstanceFromElement(CoreInstance element, CoreInstance instance, ProcessorSupport processorSupport) - { - if (!PackageableElement.isPackageableElement(element, processorSupport)) - { - throw new IllegalArgumentException("element must be a PackageableElement"); - } - return findPathToInstanceFromElement(element, Objects.requireNonNull(instance), isNotBackRefPropertyFilter(), processorSupport); - } - - private static ResolvedGraphPath findPathToInstanceFromElement(CoreInstance element, CoreInstance instance, BiPredicate propFilter, ProcessorSupport processorSupport) - { - SourceInformation sourceInfo = element.getSourceInformation(); - if (sourceInfo == null) - { - return null; - } - MutableSet visited = Sets.mutable.empty(); - return GraphPathIterable.builder(processorSupport) - .withStartNode(element) - .withPropertyFilter(propFilter) - .withPathFilter(rgp -> - { - CoreInstance node = rgp.getLastResolvedNode(); - if (node == instance) - { - return GraphWalkFilterResult.ACCEPT_AND_STOP; - } - if (visited.add(node)) - { - SourceInformation nodeSourceInfo = node.getSourceInformation(); - if ((nodeSourceInfo == null) || sourceInfo.subsumes(nodeSourceInfo)) - { - return GraphWalkFilterResult.REJECT_AND_CONTINUE; - } - } - return GraphWalkFilterResult.REJECT_AND_STOP; - }) - .build() - .getAny(); - } - - private static BiPredicate isNotBackRefPropertyFilter() - { - try - { - MapIterable> backRefs = M3PropertyPaths.BACK_REFERENCE_PROPERTY_PATHS.groupByUniqueKey(ImmutableList::getLast); - return (rgp, prop) -> - { - ImmutableList realKey = backRefs.get(prop); - return (realKey == null) || !realKey.equals(rgp.getLastResolvedNode().getRealKeyByName(prop)); - }; - } - catch (Exception ignore) - { - return (rgp, prop) -> !M3PropertyPaths.BACK_REFERENCE_PROPERTY_PATHS.contains(rgp.getLastResolvedNode().getRealKeyByName(prop)); - } - } - - private static MutableList getTopLevels(ProcessorSupport processorSupport) - { - return collectTopLevels(processorSupport, Lists.mutable.ofInitialCapacity(_Package.SPECIAL_TYPES.size() + 1)); - } - - private static > T collectTopLevels(ProcessorSupport processorSupport, T target) - { - _Package.SPECIAL_TYPES.forEach(typeName -> target.add(processorSupport.repository_getTopLevel(typeName))); - target.add(processorSupport.repository_getTopLevel(M3Paths.Root)); - return target; - } }