blob: 200030945ca12eccca0482140b6607f7a84745c4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2020 1C-Soft LLC and others.
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vladimir Piskarev (1C) - initial API and implementation
*******************************************************************************/
package org.eclipse.handly.internal.examples.basic.ui.model;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.handly.examples.basic.foo.Def;
import org.eclipse.handly.examples.basic.foo.Unit;
import org.eclipse.handly.examples.basic.foo.Var;
import org.eclipse.handly.model.Elements;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.impl.support.Body;
import org.eclipse.handly.model.impl.support.SourceElementBody;
import org.eclipse.handly.model.impl.support.StructureHelper;
import org.eclipse.handly.util.TextRange;
import org.eclipse.xtext.resource.ILocationInFileProvider;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.util.ITextRegion;
/**
* Builds the inner structure for a {@link FooFile}.
*/
class FooFileStructureBuilder
{
private final Map<IElement, Object> newElements;
private final ILocationInFileProvider locationProvider;
private final StructureHelper helper = new StructureHelper();
/**
* Constructs a new Foo file structure builder.
*
* @param newElements the map to populate with structure elements
* (not <code>null</code>)
* @param resourceServiceProvider Xtext's {@link IResourceServiceProvider}
* for the language (not <code>null</code>)
*/
FooFileStructureBuilder(Map<IElement, Object> newElements,
IResourceServiceProvider resourceServiceProvider)
{
if (newElements == null)
throw new IllegalArgumentException();
this.newElements = newElements;
if (resourceServiceProvider == null)
throw new IllegalArgumentException();
this.locationProvider = resourceServiceProvider.get(
ILocationInFileProvider.class);
}
/**
* Builds the structure for the given {@link FooFile} based on
* its {@link Unit AST}.
*
* @param handle the handle to a Foo file (not <code>null</code>)
* @param body the body of the Foo file (not <code>null</code>)
* @param unit the AST of the Foo file (not <code>null</code>)
* @param monitor a progress monitor, or <code>null</code>
* if progress reporting is not desired. The caller must not rely on
* {@link IProgressMonitor#done()} having been called by the receiver
* @throws OperationCanceledException if this method is canceled
*/
void buildStructure(FooFile handle, SourceElementBody body, Unit unit,
IProgressMonitor monitor)
{
SubMonitor subMonitor = SubMonitor.convert(monitor,
unit.getVars().size() + unit.getDefs().size());
for (Var var : unit.getVars())
{
buildStructure(handle, body, var);
subMonitor.split(1);
}
for (Def def : unit.getDefs())
{
buildStructure(handle, body, def);
subMonitor.split(1);
}
body.setChildren(helper.popChildren(body).toArray(
Elements.EMPTY_ARRAY));
}
private void buildStructure(FooFile parent, Body parentBody, Var var)
{
if (var.getName() == null || var.getName().isEmpty())
return;
FooVar handle = new FooVar(parent, var.getName());
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getFullRange(var));
body.setIdentifyingRange(getIdentifyingRange(var));
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(FooFile parent, Body parentBody, Def def)
{
if (def.getName() == null || def.getName().isEmpty())
return;
int arity = def.getParams().size();
FooDef handle = new FooDef(parent, def.getName(), arity);
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getFullRange(def));
body.setIdentifyingRange(getIdentifyingRange(def));
body.set(FooDef.PARAMETER_NAMES, def.getParams().toArray(
new String[arity]));
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private TextRange getFullRange(EObject eObject)
{
return toTextRange(locationProvider.getFullTextRegion(eObject));
}
private TextRange getIdentifyingRange(EObject eObject)
{
return toTextRange(locationProvider.getSignificantTextRegion(eObject));
}
private static TextRange toTextRange(ITextRegion region)
{
if (region == null || region.equals(ITextRegion.EMPTY_REGION))
return null;
else
return new TextRange(region.getOffset(), region.getLength());
}
}