/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.dev.jjs; import com.google.gwt.dev.jjs.Correlation.Axis; import com.google.gwt.dev.jjs.Correlation.Literal; import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JField; import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JType; import org.apache.commons.collections.map.ReferenceMap; import java.io.Serializable; import java.util.Collections; import java.util.EnumMap; import java.util.Map; /** * A {@link Correlation} factory. */ public abstract class CorrelationFactory implements Serializable { /** * A dummy factory that always returns <code>null</code>. */ public static final class DummyCorrelationFactory extends CorrelationFactory { public static final CorrelationFactory INSTANCE = new DummyCorrelationFactory(); private DummyCorrelationFactory() { } @Override public Correlation by(JDeclaredType type) { return null; } @Override public Correlation by(JField field) { return null; } @Override public Correlation by(JMethod method) { return null; } @Override public Correlation by(Literal type) { return null; } @Override public SourceInfo makeSourceInfo(SourceOrigin origin) { return origin; } } /** * A real factory that returns new {@link Correlation Correlations}. */ public static final class RealCorrelationFactory extends CorrelationFactory { /* * NB: The Correlation type uses AST nodes in its factory methods to make it * easier to extract whatever information we want to include in the Compile * Reports without having to update call sites with additional parameters. * * In the general case, references to AST nodes should not be exposed to any * public-API consumers of the Correlation. */ public static final CorrelationFactory INSTANCE = new RealCorrelationFactory(); /** * Correlations based on Literals are all the same, so we'll just cook up a * Map to make {@link #by(Literal)} fast. */ private static final Map<Literal, Correlation> LITERAL_CORRELATIONS = new EnumMap<Literal, Correlation>(Literal.class); static { for (Literal l : Literal.values()) { LITERAL_CORRELATIONS.put(l, new Correlation(Axis.LITERAL, l.getDescription(), l)); } } private static String getMethodIdent(JMethod method) { StringBuilder sb = new StringBuilder(); sb.append(method.getEnclosingType().getName()).append("::"); sb.append(method.getName()).append("("); for (JType type : method.getOriginalParamTypes()) { sb.append(type.getJsniSignatureName()); } sb.append(")"); sb.append(method.getOriginalReturnType().getJsniSignatureName()); return sb.toString(); } /** * This cuts down on the total number of Correlation objects allocated. */ @SuppressWarnings("unchecked") private final Map<Object, Correlation> canonicalMap = Collections .synchronizedMap(new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK)); private RealCorrelationFactory() { } @Override public Correlation by(JDeclaredType type) { Correlation toReturn = canonicalMap.get(type); if (toReturn == null) { toReturn = new Correlation(Axis.CLASS, type.getName(), type); canonicalMap.put(type, toReturn); } return toReturn; } @Override public Correlation by(JField field) { Correlation toReturn = canonicalMap.get(field); if (toReturn == null) { toReturn = new Correlation(Axis.FIELD, field.getEnclosingType().getName() + "::" + field.getName(), field); canonicalMap.put(field, toReturn); } return toReturn; } @Override public Correlation by(JMethod method) { Correlation toReturn = canonicalMap.get(method); if (toReturn == null) { toReturn = new Correlation(Axis.METHOD, getMethodIdent(method), method); canonicalMap.put(method, toReturn); } return toReturn; } @Override public Correlation by(Literal type) { assert LITERAL_CORRELATIONS.containsKey(type); return LITERAL_CORRELATIONS.get(type); } @Override public SourceInfo makeSourceInfo(SourceOrigin origin) { return new SourceInfoCorrelation(origin); } } public abstract Correlation by(JDeclaredType type); public abstract Correlation by(JField field); public abstract Correlation by(JMethod method); public abstract Correlation by(Literal type); public abstract SourceInfo makeSourceInfo(SourceOrigin origin); }