/******************************************************************************* * Copyright (c) 2012 itemis AG (http://www.itemis.eu) 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 * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ package org.eclipse.xtext.xbase.typesystem; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtext.common.types.JvmTypeReference; import org.eclipse.xtext.common.types.TypesPackage; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.xbase.XExpression; import org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference; import org.eclipse.xtext.xbase.typing.IJvmTypeReferenceProvider; import org.eclipse.xtext.xtype.XComputedTypeReference; import org.eclipse.xtext.xtype.impl.XComputedTypeReferenceImplCustom; /** * This is a {@link IJvmTypeReferenceProvider type reference provider} that * can be used to describe an infered type reference during the model inference. * * Clients will usually use {@link #isInferred(JvmTypeReference)} and * {@link #resolveTo(JvmTypeReference, JvmTypeReference)}. * * @author Sebastian Zarnekow - Initial contribution and API */ public class InferredTypeIndicator implements IJvmTypeReferenceProvider { private boolean resolved = false; private final XExpression expression; public InferredTypeIndicator(XExpression expression) { this.expression = expression; } public InferredTypeIndicator() { this(null); } public static boolean isInferred(JvmTypeReference typeReference) { if (typeReference instanceof XComputedTypeReference) { IJvmTypeReferenceProvider typeProvider = ((XComputedTypeReference) typeReference).getTypeProvider(); if (typeProvider instanceof InferredTypeIndicator && !((InferredTypeIndicator)typeProvider).resolved) { return true; } } return false; } public static void resolveTo(JvmTypeReference inferred, JvmTypeReference resolved) { if (isInferred(inferred)) { XComputedTypeReference casted = (XComputedTypeReference) inferred; casted.setEquivalent(resolved); ((InferredTypeIndicator)casted.getTypeProvider()).resolved = true; } else { throw new IllegalStateException("Cannot resolve a reference that is not inferred"); } } @Override public JvmTypeReference getTypeReference(/* @NonNull */ XComputedTypeReferenceImplCustom context) { Resource resource = context.eResource(); IResolvedTypes resolvedTypes = null; if (resource instanceof XtextResource) { IBatchTypeResolver typeResolver = ((XtextResource) resource).getResourceServiceProvider().get(IBatchTypeResolver.class); if (typeResolver == null) { throw new IllegalStateException("typeResolver may not be null"); } resolvedTypes = typeResolver.resolveTypes(context); } if (context.eIsSet(TypesPackage.Literals.JVM_SPECIALIZED_TYPE_REFERENCE__EQUIVALENT)) { return context.getEquivalent(); } if (expression != null && resolvedTypes != null) { LightweightTypeReference expressionType = resolvedTypes.getActualType(expression); if (expressionType != null) { JvmTypeReference result = expressionType.toJavaCompliantTypeReference(); return result; } } throw new IllegalStateException("equivalent could not be computed"); } /* @Nullable */ public XExpression getExpression() { return expression; } @Override public String toString() { return String.format("InferredTypeIndicator[resolved=%s, expression=%s]", resolved, expression == null ? "null" : expression.eClass().getName()); } }