/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.tooling.engine.resolver;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import melnorme.lang.tooling.context.ISemanticContext;
import melnorme.lang.tooling.engine.ErrorElement;
import melnorme.lang.tooling.engine.ErrorElement.NotATypeErrorElement;
import melnorme.lang.tooling.symbols.IConcreteNamedElement;
import melnorme.lang.tooling.symbols.INamedElement;
import melnorme.lang.tooling.symbols.ITypeNamedElement;
import dtool.ast.expressions.Expression;
import dtool.ast.expressions.Resolvable;
public class ResolvableUtil {
public static INamedElement resolveReference(IReference reference, ISemanticContext context) {
if(reference == null) {
return null;
}
return reference.getSemantics(context).resolveTargetElement().result;
}
public static IConcreteNamedElement resolveConcreteElement(IReference reference, ISemanticContext parentContext) {
if(reference == null) {
return null;
}
INamedElement refTarget = reference.getSemantics(parentContext).resolveTargetElement_();
return refTarget.getSemantics(parentContext).resolveConcreteElement().result;
}
/**
* @param reference non-null.
* @return non-null.
*/
public static ITypeNamedElement resolveTargetType(IReference reference, ISemanticContext parentContext) {
assertNotNull(reference);
INamedElement refTarget = reference.getSemantics(parentContext).resolveTargetElement_();
return resolveTargeType(reference, refTarget, parentContext);
}
/**
* @param reference non-null.
* @param originalType non-null.
* @return non-null.
*/
public static ITypeNamedElement resolveTargeType(IReference reference, INamedElement originalType,
ISemanticContext parentContext) {
assertNotNull(reference);
assertNotNull(originalType);
IConcreteNamedElement concreteResult = originalType.resolveConcreteElement(parentContext);
if(concreteResult instanceof ITypeNamedElement) {
return (ITypeNamedElement) concreteResult;
} else {
return new NotATypeErrorElement(reference, concreteResult);
}
}
protected static TypeReferenceResult concreteTypeResult(IReference reference, INamedElement originalType,
ISemanticContext parentContext) {
if(originalType == null) {
return new TypeReferenceResult(ErrorElement.newNotFoundError(reference));
}
ITypeNamedElement concreteType = resolveTargeType(reference, originalType, parentContext);
return new TypeReferenceResult(originalType, concreteType);
}
/**
* Resolve a reference that should point to a type element.
*/
public static TypeReferenceResult resolveTypeReference2(IReference reference, ISemanticContext context) {
if(reference == null) {
return null;
}
INamedElement originalType = reference.getSemantics(context).resolveTargetElement_();
return concreteTypeResult(reference, originalType, context);
}
/* ----------------- ----------------- */
public static ITypeNamedElement resolveTypeOfExpression(Resolvable resolvable, ISemanticContext parentContext) {
if(resolvable instanceof Expression) {
Expression expression = (Expression) resolvable;
return expression.resolveTypeOfUnderlyingValue_nonNull(parentContext).concreteType;
} else {
final IReference reference = (IReference) resolvable;
TypeReferenceResult result = resolveTypeOfExpressionReference(reference, parentContext);
if(result == null) {
return ErrorElement.newNotFoundError(reference);
}
return result.concreteType;
}
}
/**
* Resolve a reference that should point to a var element
* (or a similar element that has an expression value).
*/
public static TypeReferenceResult resolveTypeOfExpressionReference(IReference reference,
ISemanticContext parentContext) {
if(reference == null) {
return null;
}
INamedElement expElement = reference.getSemantics(parentContext).resolveTargetElement_();
INamedElement type = expElement.getSemantics(parentContext).getTypeForValueContext();
return concreteTypeResult(reference, type, parentContext);
}
}