| /******************************************************************************* |
| * 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.ast.declarations.ModuleDeclaration; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.ruby.ast.RubyAssignment; |
| import org.eclipse.dltk.ruby.internal.parsers.jruby.ASTUtils; |
| import org.eclipse.dltk.ruby.typeinference.RubyClassType; |
| import org.eclipse.dltk.ruby.typeinference.RubyFieldReference; |
| import org.eclipse.dltk.ruby.typeinference.RubyTypeInferencingUtils; |
| import org.eclipse.dltk.ti.GoalState; |
| import org.eclipse.dltk.ti.goals.FieldPositionVerificationGoal; |
| import org.eclipse.dltk.ti.goals.IGoal; |
| import org.eclipse.dltk.ti.goals.PossiblePosition; |
| |
| public class FieldParentKeyVerificator extends RubyMixinGoalEvaluator { |
| |
| private RubyFieldReference result = null; |
| |
| public FieldParentKeyVerificator(IGoal goal) { |
| super(goal); |
| } |
| |
| private ASTNode translateNode(ASTNode node, ModuleDeclaration decl) { |
| ASTNode[] way = ASTUtils.restoreWayToNode(decl, node); |
| if (way.length >= 2 && way[way.length - 2] instanceof RubyAssignment) { |
| RubyAssignment assignment = (RubyAssignment) way[way.length - 2]; |
| if (assignment.getLeft().locationMatches(node)) |
| return way[way.length - 2]; |
| } |
| return node; |
| } |
| |
| @Override |
| public IGoal[] init() { |
| FieldPositionVerificationGoal goal = (FieldPositionVerificationGoal) this.goal; |
| PossiblePosition position = goal.getPosition(); |
| |
| boolean constant = false; |
| String name = goal.getGoal().getName(); |
| if (Character.isUpperCase(name.charAt(0))) { |
| constant = true; |
| } |
| |
| if (position.getNode() != null) { |
| ASTNode node = position.getNode(); |
| IModelElement element = DLTKCore.create(position.getResource()); |
| if (element instanceof ISourceModule) { |
| ISourceModule sourceModule = (ISourceModule) element; |
| ModuleDeclaration module = ASTUtils.getAST(sourceModule); |
| RubyClassType selfClass = RubyTypeInferencingUtils |
| .determineSelfClass(mixinModel, sourceModule, module, |
| node.sourceStart()); |
| |
| if (selfClass == null) |
| return null; |
| |
| node = translateNode(node, module); |
| |
| boolean approve = false; |
| |
| if (name.startsWith("$")) //$NON-NLS-1$ |
| approve = true; |
| else if (goal.getGoal().getParentModelKey().equals( |
| selfClass.getModelKey())) { |
| approve = true; |
| } else if (constant) { // up-scope visible |
| if (goal.getGoal().getParentModelKey().startsWith( |
| selfClass.getModelKey())) { |
| approve = true; |
| } |
| } |
| |
| if (approve) { |
| result = new RubyFieldReference(goal.getGoal().getName(), |
| selfClass.getModelKey(), position, node); |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public Object produceResult() { |
| return result; |
| } |
| |
| @Override |
| public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) { |
| return null; |
| } |
| |
| } |