| /******************************************************************************* |
| * Copyright (c) 2005, 2016 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.ti; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.ti.goals.AbstractTypeGoal; |
| import org.eclipse.dltk.ti.goals.FieldReferencesGoal; |
| import org.eclipse.dltk.ti.goals.FieldReferencesGoalEvaluator; |
| import org.eclipse.dltk.ti.goals.GoalEvaluator; |
| import org.eclipse.dltk.ti.goals.IGoal; |
| import org.eclipse.dltk.ti.goals.MethodCallsGoal; |
| import org.eclipse.dltk.ti.goals.MethodCallsGoalEvaluator; |
| import org.eclipse.dltk.ti.goals.NullGoalEvaluator; |
| import org.eclipse.dltk.ti.statistics.IEvaluationStatisticsRequestor; |
| import org.eclipse.dltk.ti.types.IEvaluatedType; |
| |
| /** |
| * <p> |
| * Default DLTK type inferencing implementation, that uses ideas of |
| * demand-driven analisys with a subgoal pruning (see GoalEngine class).Type |
| * evaluation becomes a root goal for a GoalEngine. |
| * |
| * <p> |
| * Cause this class is common, it doesn't provide lots of evaluators. Only |
| * FieldReferencesGoalEvaluator and MethodCallsGoalEvaluator registered. Please, |
| * look for their javadocs for more info. |
| * |
| * <p> |
| * User can register evaluators via registerEvaluator() method. Also user are |
| * able to provide custom evaluators factory, it will have higher priority, than |
| * evaluators, registered via registerEvaluator() method. |
| * |
| */ |
| public class DefaultTypeInferencer implements ITypeInferencer { |
| |
| private static class ProxyStatisticsRequestor implements |
| IEvaluationStatisticsRequestor { |
| |
| @Override |
| public void evaluationStarted(IGoal rootGoal) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.evaluationStarted(rootGoal); |
| } |
| } |
| } |
| |
| @Override |
| public void evaluatorInitialized(GoalEvaluator evaluator, |
| IGoal[] subgoals, long time) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.evaluatorInitialized(evaluator, subgoals, time); |
| } |
| } |
| } |
| |
| @Override |
| public void evaluatorProducedResult(GoalEvaluator evaluator, |
| Object result, long time) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.evaluatorProducedResult(evaluator, result, time); |
| } |
| } |
| |
| } |
| |
| @Override |
| public void evaluatorReceivedResult(GoalEvaluator evaluator, |
| IGoal finishedGoal, IGoal[] newSubgoals, long time) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.evaluatorReceivedResult(evaluator, finishedGoal, |
| newSubgoals, time); |
| } |
| } |
| } |
| |
| @Override |
| public void goalEvaluatorAssigned(IGoal goal, GoalEvaluator evaluator) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.goalEvaluatorAssigned(goal, evaluator); |
| } |
| } |
| } |
| |
| @Override |
| public void goalStateChanged(IGoal goal, GoalState state, |
| GoalState oldState) { |
| for (Iterator iterator = statRequestors.iterator(); iterator |
| .hasNext();) { |
| IEvaluationStatisticsRequestor t = (IEvaluationStatisticsRequestor) iterator |
| .next(); |
| if (t != null) { |
| t.goalStateChanged(goal, state, oldState); |
| } |
| } |
| } |
| |
| } |
| |
| private class MapBasedEvaluatorFactory implements IGoalEvaluatorFactory { |
| |
| @Override |
| public GoalEvaluator createEvaluator(IGoal goal) { |
| Object evaluator = null; |
| if (userFactory != null) { |
| evaluator = userFactory.createEvaluator(goal); |
| if (evaluator != null) { |
| return (GoalEvaluator) evaluator; |
| } |
| } |
| |
| Class goalClass = goal.getClass(); |
| evaluator = evaluators.get(goalClass); |
| if (evaluator == null || (!(evaluator instanceof Class))) { |
| // throw new RuntimeException("No evaluator registered for " |
| // + goalClass.getName() + " : " + goal); |
| String className = goalClass.getName(); |
| if (DLTKCore.DEBUG) { |
| System.err.println("No evaluator registered for " //$NON-NLS-1$ |
| + className.substring(className.lastIndexOf('.')) |
| + ": " + goal + " - using NullGoalEvaluator"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return new NullGoalEvaluator(goal); |
| } |
| Class evalClass = (Class) evaluator; |
| GoalEvaluator newInstance; |
| |
| try { |
| newInstance = (GoalEvaluator) evalClass.getConstructor( |
| new Class[] { IGoal.class }).newInstance( |
| new Object[] { goal }); |
| return newInstance; |
| } catch (IllegalArgumentException e) { |
| e.printStackTrace(); |
| } catch (SecurityException e) { |
| e.printStackTrace(); |
| } catch (InvocationTargetException e) { |
| e.printStackTrace(); |
| } catch (NoSuchMethodException e) { |
| e.printStackTrace(); |
| } catch (InstantiationException e) { |
| e.printStackTrace(); |
| } catch (IllegalAccessException e) { |
| e.printStackTrace(); |
| } |
| |
| return null; |
| } |
| |
| } |
| |
| private Map evaluators = new HashMap(); |
| |
| private static Set statRequestors = new HashSet(); |
| |
| private final GoalEngine engine; |
| private final IGoalEvaluatorFactory userFactory; |
| |
| private final ProxyStatisticsRequestor stat = new ProxyStatisticsRequestor(); |
| |
| private void initStdGoals() { |
| registerEvaluator(FieldReferencesGoal.class, |
| FieldReferencesGoalEvaluator.class); |
| registerEvaluator(MethodCallsGoal.class, MethodCallsGoalEvaluator.class); |
| } |
| |
| public DefaultTypeInferencer(IGoalEvaluatorFactory userFactory) { |
| engine = new GoalEngine(new MapBasedEvaluatorFactory()); |
| this.userFactory = userFactory; |
| initStdGoals(); |
| } |
| |
| public void registerEvaluator(Class goalClass, Class evaluatorClass) { |
| Assert.isLegal((IGoal.class.isAssignableFrom(goalClass))); |
| Assert.isLegal(GoalEvaluator.class.isAssignableFrom(evaluatorClass)); |
| evaluators.put(goalClass, evaluatorClass); |
| } |
| |
| @Override |
| public IEvaluatedType evaluateType(AbstractTypeGoal goal, int timeLimit) { |
| Object result = this.evaluateType(goal, new TimelimitPruner(timeLimit)); |
| return (IEvaluatedType) result; |
| } |
| |
| public IEvaluatedType evaluateType(AbstractTypeGoal goal, IPruner pruner) { |
| return (IEvaluatedType) engine.evaluateGoal(goal, pruner, stat); |
| } |
| |
| protected Object evaluateGoal(IGoal goal, IPruner pruner) { |
| return engine.evaluateGoal(goal, pruner, stat); |
| } |
| |
| public IEvaluatedType evaluateType(AbstractTypeGoal goal) { |
| return evaluateType(goal, null); |
| } |
| |
| public static void addEvaluationStatisticsRequestor( |
| IEvaluationStatisticsRequestor r) { |
| statRequestors.add(r); |
| } |
| |
| public static void removeEvaluationStatisticsRequestor( |
| IEvaluationStatisticsRequestor r) { |
| statRequestors.remove(r); |
| } |
| |
| } |