/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.flex.abc.diagnostics; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.flex.abc.graph.IBasicBlock; import org.apache.flex.abc.graph.IFlowgraph; import org.apache.flex.abc.semantics.MethodInfo; import org.apache.flex.abc.semantics.MethodBodyInfo; import org.apache.flex.abc.semantics.ScriptInfo; import org.apache.flex.abc.visitors.IDiagnosticsVisitor; /** * A DiagnosticsAggregator collects AET diagnostics for analysis. */ public class DiagnosticsAggregator implements IDiagnosticsVisitor { private final List<ProblemDescription> errors = new ArrayList<ProblemDescription>(); private final List<ProblemDescription> warnings = new ArrayList<ProblemDescription>(); /** * Get problem-level diagnostics seen by this visitor. * @return problems encountered, as an immutable list. */ public List<ProblemDescription> getErrors() { return Collections.unmodifiableList(this.errors); } /** * Get warning-level diagnostics seen by this visitor. * @return warnings encountered, as an immutable list. */ public List<ProblemDescription> getWarnings() { return Collections.unmodifiableList(this.warnings); } @Override public void operandStackUnderflow(MethodBodyInfo methodBodyInfo, IFlowgraph cfg, IBasicBlock block, int instructionIndex) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.OperandStackUnderflow, cfg, block, instructionIndex)); } @Override public void scopeStackUnderflow(MethodBodyInfo methodBodyInfo, IFlowgraph cfg, IBasicBlock block, int instructionIndex) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.ScopeStackUnderflow, cfg, block, instructionIndex)); } @Override public void unreachableBlock(MethodBodyInfo methodBodyInfo, IFlowgraph cfg, IBasicBlock block) { warnings.add(new ProblemDescription(ProblemDescription.ProblemType.UnreachableBlock, cfg, block, block.size() - 1)); } @Override public void tooManyDefaultParameters(MethodInfo methodInfo) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.TooManyDefaultParameters, methodInfo)); } @Override public void incorrectNumberOfParameterNames(MethodInfo methodInfo) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.IncorrectNumberOfParameterNames, methodInfo)); } @Override public void nativeMethodWithMethodBody(MethodInfo methodInfo, MethodBodyInfo methodBodyInfo) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.NativeMethodWithMethodBody, methodInfo)); } @Override public void scriptInitWithRequiredArguments(ScriptInfo scriptInfo, MethodInfo methodInfo) { errors.add(new ProblemDescription(ProblemDescription.ProblemType.ScriptInitWithRequiredArguments, scriptInfo, methodInfo)); } /** * A ProblemDescription holds information about a particular problem occurrence. */ @SuppressWarnings("nls") public static class ProblemDescription { /** * The type of problem observed. */ public enum ProblemType { OperandStackUnderflow, ScopeStackUnderflow, UnreachableBlock, TooManyDefaultParameters, IncorrectNumberOfParameterNames, NativeMethodWithMethodBody, ScriptInitWithRequiredArguments } /** * Construct a description of a problem that occurred in a method body. * @param problemType - the type of problem encountered. * @param cfg - the control flow graph. * @param b - the block where the problem occurred. * @param offset - the offset of the instruction where the problem occurred. */ private ProblemDescription(ProblemType problemType, IFlowgraph cfg, IBasicBlock b, int offset) { switch ( problemType ) { case OperandStackUnderflow: case ScopeStackUnderflow: case UnreachableBlock: this.problemType = problemType; this.sourcePath = cfg.findSourcePath(b, offset); this.lineNumber = cfg.findLineNumber(b, offset); this.methodInfo = null; this.scriptInfo = null; break; default: throw new IllegalStateException(String.format("Invalid problem type %s", problemType)); } } /** * Construct a description of a problem that occurred in a method header. * @param problemType - the type of problem that occurred. * @param methodInfo - the method header where the problem occurred. */ private ProblemDescription(ProblemType problemType, MethodInfo methodInfo) { switch(problemType) { case TooManyDefaultParameters: case IncorrectNumberOfParameterNames: case NativeMethodWithMethodBody: this.problemType = problemType; this.methodInfo = methodInfo; this.scriptInfo = null; this.sourcePath = null; this.lineNumber = -1; break; default: throw new IllegalStateException(String.format("Invalid problem type %s", problemType)); } } /** * Construct a description of a problem that occurred due to a mismatch * between the script info header and the corresponding method header. * @param problemType - the type of problem that occurred. * @param scriptInfo - the script info header. * @param methodInfo - the method info header. */ private ProblemDescription(ProblemType problemType, ScriptInfo scriptInfo, MethodInfo methodInfo) { switch(problemType) { case ScriptInitWithRequiredArguments: this.problemType = problemType; this.methodInfo = methodInfo; this.scriptInfo = scriptInfo; this.sourcePath = null; this.lineNumber = -1; break; default: throw new IllegalStateException(String.format("Invalid problem type %s", problemType)); } } /** * The type of problem encountered. */ public final ProblemType problemType; /** * Source path to the problem's occurrence, where known and applicable. */ public final String sourcePath; /** * Line number of the problem's occurrence, where known and applicable. */ public final int lineNumber; /** * MethodInfo of the problem's occurrence, where known and applicable. */ public final MethodInfo methodInfo; /** * ScriptInfo of the problem's occurrence, where known and applicable. */ public final ScriptInfo scriptInfo; } }