Skip to content

Commit

Permalink
Merge pull request #1091 from rubenporras/noEagerProxyNodeModel
Browse files Browse the repository at this point in the history
feat: do not eagerly populate the idToEObjectMap
  • Loading branch information
rubenporras authored Feb 26, 2025
2 parents 8e5f548 + cf9f8c9 commit 33007c7
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,10 @@ public class DirectLinkingResourceStorageLoadable extends ResourceStorageLoadabl
* - count the number of EObjects added to the Resource
*/
private final class EObjectInputStreamExtension extends BinaryResourceImpl.EObjectInputStream {
private int objectCount;

private EObjectInputStreamExtension(final InputStream inputStream, final Map<?, ?> options) throws IOException {
super(inputStream, options);
}

public int eObjectCount() {
return objectCount;
}

@Override
public int readCompressedInt() throws IOException {
// HACK! null resource set, to avoid usage of resourceSet's package registry
Expand All @@ -86,7 +80,6 @@ public int readCompressedInt() throws IOException {
public InternalEObject loadEObject() throws IOException {
final InternalEObject result = super.loadEObject();
handleLoadEObject(result, this);
objectCount++;
return result;
}

Expand Down Expand Up @@ -146,8 +139,6 @@ public void loadResource(final Resource resource) throws IOException {

private ResourceLoadMode mode;

private int eObjectCount;

public DirectLinkingResourceStorageLoadable(final InputStream in, final boolean loadNodeModel, final boolean splitContents, final ITraceSet traceSet) {
super(in, loadNodeModel);
this.loadNodeModel = loadNodeModel;
Expand Down Expand Up @@ -271,7 +262,7 @@ protected void loadEntries(final StorageAwareResource resource, final ZipInputSt
case SKIP:
break;
case PROXY:
ProxyCompositeNode.installProxyNodeModel(resource, eObjectCount);
ProxyCompositeNode.installProxyNodeModel(resource);
break;
case LOAD:
readNodeModel(resource, new NonLockingBufferInputStream(zipIn), content);
Expand Down Expand Up @@ -379,7 +370,6 @@ private Deque<EObject> readMappedEObjects(final DirectLinkingEObjectInputStream
protected void readContents(final StorageAwareResource resource, final InputStream inputStream) throws IOException {
final EObjectInputStreamExtension in = new EObjectInputStreamExtension(inputStream, Collections.emptyMap());
in.loadResource(resource);
eObjectCount = in.eObjectCount();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList.FeatureIterator;
import org.eclipse.emf.ecore.util.EContentsEList.Filterable;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.nodemodel.BidiIterable;
import org.eclipse.xtext.nodemodel.BidiTreeIterable;
Expand All @@ -37,6 +35,7 @@
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.nodemodel.util.NodeTreeIterator;
import org.eclipse.xtext.nodemodel.util.ReversedBidiTreeIterable;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.parser.ParseResult;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.persistence.IResourceStorageFacade;
Expand All @@ -53,7 +52,7 @@
* To conserve memory this class implements the primary interfaces rather than extending an implementation like
* {@link org.eclipse.xtext.nodemodel.impl.CompositeNodeWithSemanticElement}.
*/
class ProxyCompositeNode implements ICompositeNode, BidiTreeIterable<INode>, Adapter {
public class ProxyCompositeNode implements ICompositeNode, BidiTreeIterable<INode>, Adapter {

/** The root node proxy stores the original EObject ID map so that it can be used when installing the real node model. */
private List<EObject> idToEObjectMap;
Expand All @@ -69,48 +68,34 @@ class ProxyCompositeNode implements ICompositeNode, BidiTreeIterable<INode>, Ada
*
* @param resource
* resource, must not be {@code null}
* @param expectedEObjectCount
* the expected EObject count of the resource
*/
static void installProxyNodeModel(final Resource resource, final int expectedEObjectCount) {
static void installProxyNodeModel(final Resource resource) {
if (resource.getContents().isEmpty()) {
return;
}

EObject root = resource.getContents().get(0);

ProxyCompositeNode rootNode = installProxyNodeModel(root);
rootNode.idToEObjectMap = new ArrayList<>(expectedEObjectCount);
fillIdToEObjectMap(root, rootNode.idToEObjectMap);

if (resource instanceof XtextResource) {
((XtextResource) resource).setParseResult(new ParseResult(root, rootNode, false));
if (resource instanceof XtextResource xtextResource) {
EObject root = resource.getContents().get(0);
xtextResource.setParseResult(new ParseResult(root, createRootNode(root), false));
}
}

private static ProxyCompositeNode installProxyNodeModel(final EObject eObject) {
private static ProxyCompositeNode createRootNode(final EObject eObject) {
ProxyCompositeNode result = new ProxyCompositeNode();
eObject.eAdapters().add(result);
return result;
}

private static void fillIdToEObjectMap(final EObject eObject, final List<EObject> map) {
map.add(eObject);

FeatureIterator<EObject> iterator = (FeatureIterator<EObject>) eObject.eContents().iterator();
if (iterator instanceof Filterable filterable) {
filterable.filter(f -> !f.isTransient());
for (FeatureIterator<EObject> it = iterator; it.hasNext();) {
fillIdToEObjectMap(it.next(), map);
}
} else {
// post-filter the iterator, which is extra work
for (FeatureIterator<EObject> it = iterator; it.hasNext();) {
EObject child = it.next();
if (!it.feature().isTransient()) {
fillIdToEObjectMap(child, map);
}
}
/**
* Fill id to EOject map.
*
* @param parseResult
* the {@link IParseResult}
*/
public static void fillIdToEObjectMap(final IParseResult parseResult) {
if (parseResult.getRootNode() instanceof ProxyCompositeNode rootNode && rootNode.idToEObjectMap == null) {
rootNode.idToEObjectMap = new ArrayList<>();
ProxyAwareSerializationConversionContext.fillIdToEObjectMap(parseResult.getRootASTElement(), rootNode.idToEObjectMap);
}
}

Expand Down

0 comments on commit 33007c7

Please sign in to comment.