blob: 16720738d9e79b5d05a76451e6fd4e6c1ca04913 [file] [log] [blame]
/*
*
* 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;
}
}