/******************************************************************************* * Copyright (c) 2005, 2016 IBM Corporation and others. * 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 * *******************************************************************************/ package org.eclipse.dltk.ruby.typeinference.evaluators; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.core.mixin.IMixinElement; import org.eclipse.dltk.core.mixin.IMixinRequestor; import org.eclipse.dltk.ruby.ast.RubyColonExpression; import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinElementInfo; import org.eclipse.dltk.ruby.typeinference.DefaultRubyEvaluatorFactory; import org.eclipse.dltk.ruby.typeinference.RubyClassType; import org.eclipse.dltk.ruby.typeinference.goals.ColonExpressionGoal; import org.eclipse.dltk.ruby.typeinference.goals.NonTypeConstantTypeGoal; import org.eclipse.dltk.ti.GoalState; import org.eclipse.dltk.ti.goals.AbstractTypeGoal; import org.eclipse.dltk.ti.goals.ExpressionTypeGoal; import org.eclipse.dltk.ti.goals.IGoal; import org.eclipse.dltk.ti.types.ClassType; import org.eclipse.dltk.ti.types.IEvaluatedType; public class ColonExpressionEvaluator extends RubyMixinGoalEvaluator { private AbstractTypeGoal helperGoal = null; private IEvaluatedType helperResult = null; private IEvaluatedType answer = null; public ColonExpressionEvaluator(IGoal goal) { super(goal); } private ColonExpressionGoal getTypedGoal() { return (ColonExpressionGoal) DefaultRubyEvaluatorFactory .translateGoal(this.goal); } @Override public Object produceResult() { return answer; } @Override public IGoal[] init() { RubyColonExpression expr = getTypedGoal().getColonExpression(); ASTNode left = expr.getLeft(); if (left != null) { helperGoal = new ExpressionTypeGoal(getGoal().getContext(), left); return new IGoal[] { helperGoal }; } else { IMixinElement mixinElement = mixinModel.getRawModel().get( expr.getName()); if (mixinElement != null) answer = new RubyClassType(mixinElement.getKey()); } return IGoal.NO_GOALS; } @Override public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) { this.helperResult = (IEvaluatedType) result; RubyColonExpression expr = getTypedGoal().getColonExpression(); ASTNode left = expr.getLeft(); if (left != null) { if (helperResult instanceof ClassType) { // TODO: check existance // of the new key ClassType classType = (ClassType) helperResult; String modelKey = classType.getModelKey(); modelKey += IMixinRequestor.MIXIN_NAME_SEPARATOR + expr.getName(); IMixinElement mixinElement = mixinModel.getRawModel().get( modelKey); if (mixinElement != null) { Object[] objects = mixinElement.getAllObjects(); boolean found = false; for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof RubyMixinElementInfo) { RubyMixinElementInfo info = (RubyMixinElementInfo) objects[i]; if (info.getKind() == RubyMixinElementInfo.K_VARIABLE) { found = true; break; } } } if (found) { // non-type constant NonTypeConstantTypeGoal g = new NonTypeConstantTypeGoal( goal.getContext(), mixinElement); return new IGoal[] { g }; } answer = new RubyClassType(modelKey); } else answer = null; } } else { IMixinElement mixinElement = mixinModel.getRawModel().get( expr.getName()); if (mixinElement != null) answer = new RubyClassType(mixinElement.getKey()); } return IGoal.NO_GOALS; } }