blob: 60bc13f250bbfff5dd9406427575d5dc1fdcda9c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.xtext.base.cs2as;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.internal.scoping.EnvironmentView;
import org.eclipse.ocl.pivot.internal.scoping.ScopeFilter;
import org.eclipse.ocl.pivot.internal.scoping.ScopeView;
import org.eclipse.ocl.pivot.internal.utilities.AbstractConversion;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.resource.ASResource;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.ParserContext;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotHelper;
import org.eclipse.ocl.pivot.utilities.StringUtil;
import org.eclipse.ocl.xtext.base.scoping.AbstractJavaClassScope;
import org.eclipse.ocl.xtext.base.scoping.BaseScopeView;
import org.eclipse.ocl.xtext.base.utilities.BaseCSResource;
import org.eclipse.ocl.xtext.base.utilities.CSI;
import org.eclipse.ocl.xtext.base.utilities.CSI2ASMapping;
import org.eclipse.ocl.xtext.basecs.BaseCSPackage;
import org.eclipse.ocl.xtext.basecs.ElementCS;
import org.eclipse.ocl.xtext.basecs.ElementRefCS;
import org.eclipse.ocl.xtext.basecs.ModelElementCS;
import org.eclipse.ocl.xtext.basecs.MultiplicityCS;
import org.eclipse.ocl.xtext.basecs.PathElementCS;
import org.eclipse.ocl.xtext.basecs.PathNameCS;
import org.eclipse.ocl.xtext.basecs.PivotableElementCS;
import org.eclipse.ocl.xtext.basecs.RootCS;
import org.eclipse.ocl.xtext.basecs.TypedRefCS;
import org.eclipse.ocl.xtext.basecs.TypedTypeRefCS;
import org.eclipse.ocl.xtext.basecs.util.BaseCSVisitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.diagnostics.Diagnostic;
import org.eclipse.xtext.diagnostics.DiagnosticMessage;
import org.eclipse.xtext.diagnostics.IDiagnosticConsumer;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.util.Triple;
import org.eclipse.xtext.util.Tuples;
/**
* CS2AS manages the equivalence between a Concrete Syntax Resources
* and their corresponding Pivot Resources creating a CS2ASConversion
* to update.
*/
public abstract class CS2AS extends AbstractConversion // FIXME migrate functionality to PivotHelper
{
public static interface UnresolvedProxyMessageProvider
{
@NonNull EReference getEReference();
@Nullable String getMessage(@NonNull EObject context, @NonNull String linkText);
}
public static abstract class AbstractUnresolvedProxyMessageProvider implements UnresolvedProxyMessageProvider
{
protected final @NonNull EReference eReference;
public AbstractUnresolvedProxyMessageProvider(/*@NonNull*/ EReference eReference) {
assert eReference != null;
this.eReference = eReference;
}
@Override
public @NonNull EReference getEReference() {
return eReference;
}
@Override
public abstract @Nullable String getMessage(@NonNull EObject context, @NonNull String linkText);
}
/**
* Return the containment features ordered so that library and import features are processed before anything else.
*/
public static EList<EObject> computeRootContainmentFeatures(RootCS csRoot) {
BasicEList<EReference> containmentsList = new BasicEList<EReference>();
for (EStructuralFeature eStructuralFeature : csRoot.eClass().getEAllStructuralFeatures()) {
if (eStructuralFeature instanceof EReference) {
EReference eReference = (EReference) eStructuralFeature;
if (eReference.isContainment()) {
containmentsList.add(eReference);
}
}
}
int index = containmentsList.indexOf(BaseCSPackage.Literals.ROOT_CS__OWNED_IMPORTS);
if (index > 0) {
containmentsList.move(0, index); // Process imports second
}
return new EContentsEList<EObject>(csRoot, containmentsList);
}
private static Map<EReference, UnresolvedProxyMessageProvider> unresolvedProxyMessageProviderMap = new HashMap<EReference, UnresolvedProxyMessageProvider>();
/**
* Whether to show file and line number context at the start of messages.
*/
public static boolean showContext = false;
/**
* Interface for an optional message binder that may be used to affix additional context
* for standalone and command line applications.
*/
public static interface MessageBinder
{
@NonNull String bind(@NonNull EObject csContext, @NonNull String messageTemplate, Object... bindings);
}
/**
* Default message binder that just invokes {@link NLS#bind(String, Object[])}.
*/
public static class DefaultMessageBinder implements CS2AS.MessageBinder
{
public static final @NonNull MessageBinder INSTANCE = new DefaultMessageBinder();
@Override
public @NonNull String bind(@NonNull EObject csContext, @NonNull String messageTemplate, Object... bindings) {
return StringUtil.bind(messageTemplate, bindings);
}
}
/**
* Message binder that prefixes the uri and line number to the return from {@link NLS#bind(String, Object[])}.
*/
public static class MessageBinderWithLineContext implements CS2AS.MessageBinder
{
public static final MessageBinder INSTANCE = new MessageBinderWithLineContext();
@Override
public @NonNull String bind(@NonNull EObject csContext, @NonNull String messageTemplate, Object... bindings) {
String message = StringUtil.bind(messageTemplate, bindings);
ICompositeNode node = NodeModelUtils.getNode(csContext);
if (node != null) {
int startLine = node.getStartLine();
String uri = csContext.eResource().getURI().toString();
return uri + ":" + startLine + " " + message;
}
return message;
}
}
private static MessageBinder messageBinder = DefaultMessageBinder.INSTANCE;
public static void addUnresolvedProxyMessageProvider(UnresolvedProxyMessageProvider unresolvedProxyMessageProvider) {
unresolvedProxyMessageProviderMap.put(unresolvedProxyMessageProvider.getEReference(), unresolvedProxyMessageProvider);
}
public static Element basicGetType(TypedTypeRefCS csTypedRef) {
List<PathElementCS> path = csTypedRef.getOwnedPathName().getOwnedPathElements();
int iLast = path.size()-1;
for (int i = 0; i < iLast; i++) {
Element element = path.get(i).basicGetReferredElement();
if (element == null) {
return null;
}
}
Element element = path.get(iLast).basicGetReferredElement();
if (element == null) {
return null;
}
return element;
}
public static @Nullable DiagnosticMessage getUnresolvedProxyMessage(@NonNull EReference eReference, @NonNull EObject csContext, @NonNull String linkText) {
String message = getUnresolvedProxyText(eReference, csContext, linkText);
return message != null ? new DiagnosticMessage(message, Severity.ERROR, Diagnostic.LINKING_DIAGNOSTIC) : null;
}
public static @Nullable String getUnresolvedProxyText(@NonNull EReference eReference, @NonNull EObject csContext, @NonNull String linkText) {
ExceptionAdapter exceptionAdapter = ClassUtil.getAdapter(ExceptionAdapter.class, csContext);
if (exceptionAdapter != null) {
return exceptionAdapter.getErrorMessage();
}
UnresolvedProxyMessageProvider unresolvedProxyMessageProvider = unresolvedProxyMessageProviderMap.get(eReference);
if (unresolvedProxyMessageProvider != null) {
return unresolvedProxyMessageProvider.getMessage(csContext, linkText);
}
@SuppressWarnings("null") @NonNull String messageTemplate = PivotMessagesInternal.Unresolved_ERROR_;
String errorContext = "Unknown";
EClass referenceType = eReference.getEReferenceType();
if (referenceType != null) {
errorContext = referenceType.getName();
}
return messageBinder.bind(csContext, messageTemplate, errorContext, linkText);
}
public static List<ILeafNode> getDocumentationNodes(@NonNull ICompositeNode node) {
List<ILeafNode> documentationNodes = null;
for (ILeafNode leafNode : node.getLeafNodes()) {
EObject grammarElement = leafNode.getGrammarElement();
if (!(grammarElement instanceof TerminalRule)) {
break;
}
TerminalRule terminalRule = (TerminalRule) grammarElement;
String name = terminalRule.getName();
if ("WS".equals(name)) {
}
else if ("SL_COMMENT".equals(name)) {
}
else if ("ML_COMMENT".equals(name)) {
if (documentationNodes == null) {
documentationNodes = new ArrayList<ILeafNode>();
}
documentationNodes.add(leafNode);
}
else {
break;
}
}
return documentationNodes;
}
private static final class TypeValueFilter implements ScopeFilter
{
public static TypeValueFilter INSTANCE = new TypeValueFilter();
@Override
public boolean matches(@NonNull EnvironmentView environmentView, @NonNull Object object) {
if (object instanceof Type) {
return true;
}
if (object instanceof TypedElement) {
return false; //((TypedElement)object).getType() instanceof Metaclass<?>;
}
return false;
}
}
private static final class UndecoratedNameFilter implements ScopeFilter
{
public static UndecoratedNameFilter INSTANCE = new UndecoratedNameFilter();
@Override
public boolean matches(@NonNull EnvironmentView environmentView, @NonNull Object object) {
return !(object instanceof Operation) && !(object instanceof org.eclipse.ocl.pivot.Package);
}
}
public static MessageBinder getMessageBinder() {
return messageBinder;
}
private static long startTime = System.currentTimeMillis();
private static @NonNull Map<Thread,Long> threadRunTimes = new HashMap<Thread,Long>();
private static long[] indentRunTimes = new long[100];
private static @NonNull Integer indentation = 0;
private static @NonNull String indents= ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
public static void printDiagnostic(@NonNull String message, boolean dispose, int indent) {
synchronized (indentation) {
if (indent < 0) {
indentation--;
}
long currentTimeMillis = System.currentTimeMillis();
Thread currentThread = Thread.currentThread();
Long threadStartTime = threadRunTimes.get(currentThread);
if (threadStartTime == null) {
threadStartTime = currentTimeMillis;
threadRunTimes.put(currentThread, threadStartTime);
}
if (indent > 0) {
System.out.printf("%s %8.3f %s -- %6.3f %s\n", indents.substring(0, Math.min(indentation, indents.length()-1)), (currentTimeMillis - startTime) * 0.001, currentThread.getName(),
(currentTimeMillis - threadStartTime) * 0.001, message);
}
else {
System.out.printf("%s %8.3f %s -- %6.3f %6.3f %s\n", indents.substring(0, Math.min(indentation, indents.length()-1)), (currentTimeMillis - startTime) * 0.001, currentThread.getName(),
(currentTimeMillis - threadStartTime) * 0.001, (currentTimeMillis - indentRunTimes[indentation]) * 0.001, message);
}
if (dispose) {
threadRunTimes.remove(currentThread);
}
if (indent > 0) {
indentRunTimes[indentation] = currentTimeMillis;
indentation++;
}
}
}
public static void refreshContext(@NonNull PathNameCS pathNameCS, ElementCS csContext) {
if (pathNameCS.getContext() != csContext) {
pathNameCS.setContext(csContext);
}
}
public static void refreshElementType(PathElementCS pathElementCS, EClassifier elementType) {
if ((pathElementCS != null) && (pathElementCS.getElementType() != elementType)) {
pathElementCS.setElementType(elementType);
}
}
public static void refreshScopeFilter(@NonNull PathNameCS pathNameCS, ScopeFilter scopeFilter) {
if (pathNameCS.getScopeFilter() != scopeFilter) {
pathNameCS.setScopeFilter(scopeFilter);
}
}
public static void setElementType(@NonNull PathNameCS pathNameCS, /*@NonNull*/ EClass elementType, @NonNull ElementCS csContext, @Nullable ScopeFilter scopeFilter) {
assert elementType != null;
refreshContext(pathNameCS, csContext);
refreshScopeFilter(pathNameCS, scopeFilter);
List<PathElementCS> path = pathNameCS.getOwnedPathElements();
int iMax = path.size()-1;
refreshElementType(path.get(iMax), elementType);
if (PivotPackage.Literals.FEATURE.isSuperTypeOf(elementType) && (iMax > 0)) {
refreshElementType(path.get(--iMax), PivotPackage.Literals.TYPE);
}
for (int i = 0; i < iMax; i++) {
refreshElementType(path.get(i), PivotPackage.Literals.NAMESPACE);
}
}
/**
* Define an alternative message binder. THe default null messageBinder uses
* {@link NLS#bind(String, Object[])}
*/
public static MessageBinder setMessageBinder(MessageBinder messageBinder) {
MessageBinder savedMessageBinder = CS2AS.messageBinder;
CS2AS.messageBinder = messageBinder;
return savedMessageBinder;
}
/**
* Define the resolution of a PathNameCS explicitly avoiding the need for the normal Xtext proxy resolution.
* This is used after a non-trivial selection occurs such as the selection of the best operation overload.
* If element is null the Xtext error message corresponding to an unresolved proxy is generated.
* @param ambiguities
*/
public static void setPathElement(@NonNull PathNameCS csPathName, @Nullable Element element, @Nullable List<@NonNull ? extends EObject> ambiguities) {
List<@NonNull PathElementCS> csPath = ClassUtil.nullFree(csPathName.getOwnedPathElements());
PathElementCS csLastElement = csPath.get(csPath.size()-1);
AmbiguitiesAdapter.setAmbiguities(csLastElement, ambiguities);
if ((element == null) || (ambiguities != null)) {
EObject eObject = csLastElement;
INode iNode = NodeModelUtils.getNode(csLastElement);
Triple<EObject, EReference, INode> triple = Tuples.create(eObject, BaseCSPackage.Literals.PATH_ELEMENT_CS__REFERRED_ELEMENT, iNode);
Resource eResource = csLastElement.eResource();
if (eResource instanceof BaseCSResource) {
((BaseCSResource)eResource).createAndAddDiagnostic(triple);
}
csLastElement.setReferredElement(null);
}
else {
csLastElement.setReferredElement(element);
}
}
/**
* The CS resource mapped by this CS2AS.
*/
protected final @NonNull BaseCSResource csResource;
/**
* The AS resource mapped by this CS2AS.
*/
protected final @NonNull ASResource asResource;
/**
* CS to Pivot mapping controller for aliases and CSIs.
*/
protected final @NonNull CSI2ASMapping csi2asMapping;
/**
* Construction helper, lazily created by the overrideable getHelper/createHelper.
*/
private @Nullable PivotHelper helper = null;
private final @Nullable ParserContext parserContext; // FIXME only non-null for API compatibility
public CS2AS(@NonNull EnvironmentFactoryInternal environmentFactory, @NonNull BaseCSResource csResource, @NonNull ASResource asResource) {
super(environmentFactory);
this.csi2asMapping = CSI2ASMapping.getCSI2ASMapping(environmentFactory);
this.csResource = csResource;
this.asResource = asResource;
csi2asMapping.add(csResource, this);
this.parserContext = csResource.getParserContext();
assert parserContext != null;
assert parserContext.getEnvironmentFactory() == environmentFactory;
}
protected CS2AS(@NonNull CS2AS aConverter) {
super(aConverter.getEnvironmentFactory());
this.csResource = aConverter.csResource;
this.asResource = aConverter.asResource;
this.csi2asMapping = CSI2ASMapping.getCSI2ASMapping(environmentFactory);
// csi2asMapping.add(this);
this.parserContext = aConverter.parserContext;
assert parserContext != null;
assert parserContext.getEnvironmentFactory() == environmentFactory;
}
public @NonNull String bind(@NonNull EObject csContext, /*@NonNull*/ String messageTemplate, Object... bindings) {
assert messageTemplate != null;
return messageBinder.bind(csContext, messageTemplate, bindings);
}
protected abstract @NonNull BaseCSVisitor<Continuation<?>> createContainmentVisitor(@NonNull CS2ASConversion cs2asConversion);
protected@NonNull CS2ASConversion createConversion(@NonNull IDiagnosticConsumer diagnosticsConsumer, @NonNull BaseCSResource csResource) {
return new CS2ASConversion(this, diagnosticsConsumer);
}
protected @NonNull PivotHelper createHelper() {
return new PivotHelper(environmentFactory);
}
protected abstract @NonNull BaseCSVisitor<Element> createLeft2RightVisitor(@NonNull CS2ASConversion cs2asConversion);
protected abstract @NonNull BaseCSVisitor<Continuation<?>> createPostOrderVisitor(@NonNull CS2ASConversion converter) ;
protected abstract @NonNull BaseCSVisitor<Continuation<?>> createPreOrderVisitor(@NonNull CS2ASConversion converter);
public void dispose() {
csi2asMapping.removeCSResource(csResource);
}
public @NonNull ASResource getASResource() {
return asResource;
}
public @Nullable ModelElementCS getCSElement(@NonNull Element pivotElement) {
return csi2asMapping.getCSElement(pivotElement);
}
public @NonNull BaseCSResource getCSResource() {
return csResource;
}
public @NonNull PivotHelper getHelper() {
PivotHelper helper2 = helper;
if (helper2 == null) {
helper = helper2 = createHelper();
}
return helper2;
}
public Element getPivotElement(@NonNull ModelElementCS csElement) {
return csi2asMapping.get(csElement);
}
public @Nullable <T extends Element> T getPivotElement(@NonNull Class<T> pivotClass, @NonNull ModelElementCS csElement) {
Element pivotElement = csi2asMapping.get(csElement);
if (pivotElement == null) {
return null;
}
if (!pivotClass.isAssignableFrom(pivotElement.getClass())) {
throw new ClassCastException(pivotElement.getClass().getName() + " is not assignable to " + pivotClass.getName());
}
@SuppressWarnings("unchecked")
T castElement = (T) pivotElement;
return castElement;
}
/**
* Install the mapping from a CS element that defines a pivot element to the defined pivot element. The definition
* is 'owned' by the CS element, so if the CS element vanishes, so does the pivot element.
*/
public void installPivotDefinition(@NonNull ModelElementCS csElement, @NonNull Element newPivotElement) {
// logger.trace("Installing " + csElement.getDescription()); //$NON-NLS-1$ //$NON-NLS-2$
EObject oldPivotElement = csElement.getPivot();
if (oldPivotElement != newPivotElement) {
assert !newPivotElement.eIsProxy();
csElement.setPivot(newPivotElement);
if (oldPivotElement != null) {
// WIP Queue dead element
}
}
csi2asMapping.put(csElement, newPivotElement);
}
/**
* Install the mapping from a CS element to a completely independent pivot element. If the pivot element vanishes, the
* reference is stale, if the CS element the pivot element is less referenced.
*/
public void installPivotReference(@NonNull ElementRefCS csElement, @NonNull Element newPivotElement, @NonNull EReference eReference) {
assert eReference.getEContainingClass().isSuperTypeOf(csElement.eClass());
// logger.trace("Installing " + csElement.getDescription()); //$NON-NLS-1$ //$NON-NLS-2$
EObject oldPivotElement = csElement.getPivot();
if (oldPivotElement != newPivotElement) {
assert !newPivotElement.eIsProxy();
csElement.setPivot(newPivotElement);
}
}
/**
* Install the mapping from a CS element to a related pivot element. This normally arises when more than one CS element
* are associated with a single pivot element. In this case one of the CS elements is the defining CS element and the
* others are users.
*/
public void installPivotUsage(@NonNull PivotableElementCS csElement, @NonNull Element newPivotElement) {
// logger.trace("Installing " + csElement.getDescription()); //$NON-NLS-1$ //$NON-NLS-2$
EObject oldPivotElement = csElement.getPivot();
if (oldPivotElement != newPivotElement) {
assert !newPivotElement.eIsProxy();
csElement.setPivot(newPivotElement);
}
}
@Deprecated /* @deprecated FIXME Bug 548500 workaround */
public void installRootContents(@NonNull BaseCSResource csResource2) {}
/**
* Return true if csTYpeRef referes to a type that cannot be null, e.g. T[1],
* or false if it refers to a type that may be null, e.g. T[?],
* or null if the nulloty is unspecifued.
*
* Note that a lazy UML Set such as T[*] is always required; UML collections cannot be null.
*/
public @Nullable Boolean isRequired(@NonNull TypedRefCS csTypeRef) {
MultiplicityCS csMultiplicity = csTypeRef.getOwnedMultiplicity();
if (csMultiplicity != null) {
int upper = csMultiplicity.getUpper();
if (upper != 1) { // Lazy UML-style Set
assert !csTypeRef.eContainer().eClass().getName().equals("CollectionTypeCS");
return true;
}
int lower = csMultiplicity.getLower();
return lower > 0;
}
return null;
}
public @Nullable Iteration lookupIteration(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName, @Nullable ScopeFilter scopeFilter) {
setElementType(csPathName, PivotPackage.Literals.ITERATION, csElement, scopeFilter);
Element namedElement = csPathName.getReferredElement();
if ((namedElement instanceof Iteration) && !namedElement.eIsProxy()) {
return (Iteration) namedElement;
}
else {
return null;
}
}
public @Nullable Operation lookupOperation(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName, @Nullable ScopeFilter scopeFilter) {
setElementType(csPathName, PivotPackage.Literals.OPERATION, csElement, scopeFilter);
Element namedElement = csPathName.getReferredElement();
if ((namedElement instanceof Operation) && !namedElement.eIsProxy()) {
return (Operation) namedElement;
}
else {
return null;
}
}
public @Nullable Property lookupProperty(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName, @Nullable ScopeFilter scopeFilter) {
setElementType(csPathName, PivotPackage.Literals.PROPERTY, csElement, scopeFilter);
Element namedElement = csPathName.getReferredElement();
if ((namedElement instanceof Property) && !namedElement.eIsProxy()) {
return (Property) namedElement;
}
else {
return null;
}
}
public @Nullable VariableDeclaration lookupSelf(@NonNull ElementCS csElement) {
@SuppressWarnings("null") @NonNull EReference eReference = PivotPackage.Literals.EXPRESSION_IN_OCL__OWNED_CONTEXT;
@SuppressWarnings("deprecation")
EnvironmentView environmentView = parserContext != null ? new EnvironmentView(parserContext, eReference, PivotConstants.SELF_NAME) : new EnvironmentView(environmentFactory, eReference, PivotConstants.SELF_NAME);
ScopeView baseScopeView = BaseScopeView.getScopeView(environmentFactory, csElement, eReference);
environmentView.computeLookups(baseScopeView);
VariableDeclaration variableDeclaration = (VariableDeclaration) environmentView.getContent();
return variableDeclaration;
}
public @Nullable Type lookupType(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName) {
setElementType(csPathName, PivotPackage.Literals.TYPE, csElement, null);
Element namedElement = csPathName.getReferredElement();
if ((namedElement instanceof Type) && !namedElement.eIsProxy()) {
return (Type) namedElement;
}
else {
return null;
}
}
public @Nullable Type lookupTypeQualifier(@NonNull PathNameCS csPathName) {
List<PathElementCS> path = csPathName.getOwnedPathElements();
int iMax = path.size();
if (iMax <= 1) {
return null;
}
PathElementCS pathElementCS = path.get(iMax-2);
refreshElementType(pathElementCS, PivotPackage.Literals.TYPE);
for (int i = 0; i < iMax-2; i++) {
refreshElementType(path.get(i), PivotPackage.Literals.NAMESPACE);
}
Element namedElement = pathElementCS.getReferredElement();
if ((namedElement instanceof Type) && !namedElement.eIsProxy()) {
return (Type) namedElement;
}
else {
return null;
}
}
public @Nullable Type lookupTypeValue(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName) {
setElementType(csPathName, PivotPackage.Literals.NAMED_ELEMENT, csElement, TypeValueFilter.INSTANCE); // Type or Variable
Element namedElement = csPathName.getReferredElement();
if ((namedElement instanceof Type) && !namedElement.eIsProxy()) {
return (Type) namedElement;
}
else {
return null;
}
}
public @Nullable Element lookupUndecoratedName(@NonNull ElementCS csElement, @NonNull PathNameCS csPathName) {
setElementType(csPathName, PivotPackage.Literals.ELEMENT, csElement, UndecoratedNameFilter.INSTANCE);
Element namedElement = csPathName.getReferredElement();
return namedElement;
}
public @NonNull <T extends Element> T refreshModelElement(@NonNull Class<T> pivotClass, @NonNull EClass pivotEClass, @Nullable ModelElementCS csElement) {
Element pivotElement = csElement != null ? getPivotElement(csElement) : null;
@NonNull Element pivotElement2;
if ((pivotElement != null)
&& pivotClass.isAssignableFrom(pivotElement.getClass()) // Avoid resetting container of incidental reference
&& ((csElement == null) || (csElement.eContainer() != null))) { // Avoid resetting container of potentially re-used root
PivotUtilInternal.resetContainer(pivotElement); // Bypass child-stealing detector
}
if ((pivotElement == null) || (pivotEClass != pivotElement.eClass())) {
EFactory eFactoryInstance = pivotEClass.getEPackage().getEFactoryInstance();
@NonNull Element pivotElement3 = (Element) eFactoryInstance.create(pivotEClass);
pivotElement2 = pivotElement3;
}
else {
pivotElement2 = pivotElement;
}
if (csElement != null) {
installPivotDefinition(csElement, pivotElement2);
}
@SuppressWarnings("unchecked")
@NonNull T castElement = (T) pivotElement2;
return castElement;
}
public synchronized void update(@NonNull IDiagnosticConsumer diagnosticsConsumer) {
// printDiagnostic("CS2AS.update start", false, 0);
@SuppressWarnings("unused") Map<CSI, Element> oldCSI2AS = csi2asMapping.getMapping();
@SuppressWarnings("unused") Set<CSI> newCSIs = csi2asMapping.computeCSIs(csResource);
// System.out.println("==========================================================================");
// for (Resource csResource : csResources) {
// System.out.println("CS " + csResource.getClass().getName() + "@" + csResource.hashCode() + " " + csResource.getURI());
// }
CS2ASConversion conversion = createConversion(diagnosticsConsumer, csResource);
conversion.update(csResource);
// System.out.println("---------------------------------------------------------------------------");
// Collection<? extends Resource> pivotResources = cs2asResourceMap.values();
// for (Entry<? extends Resource, ? extends Resource> entry : cs2asResourceMap.entrySet()) {
// Resource csResource = entry.getKey();
// Resource asResource = entry.getValue();
// System.out.println("CS " + csResource.getClass().getName() + "@" + csResource.hashCode() + " => " + asResource.getClass().getName() + "@" + asResource.hashCode());
// }
/* Set<String> deadCSIs = new HashSet<String>(oldCSI2AS.keySet());
deadCSIs.removeAll(newCSIs);
for (String deadCSI : deadCSIs) {
Element deadPivot = oldCSI2AS.get(deadCSI); // WIP
// metamodelManager.kill(deadPivot);
} */
Map<BaseCSResource, ASResource> cs2asResourceMap = new HashMap<BaseCSResource, ASResource>();
ASResource asResource = csi2asMapping.getASResource(csResource);
cs2asResourceMap.put(csResource, asResource);
AbstractJavaClassScope javaClassScope = AbstractJavaClassScope.findAdapter(csResource);
if (javaClassScope != null) {
javaClassScope.installContents(csResource);
}
conversion.garbageCollect(cs2asResourceMap);
csi2asMapping.update();
// printDiagnostic("CS2AS.update end", false, 0);
}
}