.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

273 lines
9.8 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.VB.Dom;
namespace ICSharpCode.NRefactory.VB.Visitors
{
public sealed class LocalLookupVariable
{
public readonly string Name;
public readonly TypeReference TypeRef;
public readonly Location StartPos;
public readonly Location EndPos;
public readonly bool IsConst;
public readonly bool IsLoopVariable;
public readonly Expression Initializer;
public readonly LambdaExpression ParentLambdaExpression;
public readonly bool IsQueryContinuation;
public LocalLookupVariable(string name, TypeReference typeRef, Location startPos, Location endPos, bool isConst, bool isLoopVariable, Expression initializer, LambdaExpression parentLambdaExpression, bool isQueryContinuation)
{
this.Name = name;
this.TypeRef = typeRef;
this.StartPos = startPos;
this.EndPos = endPos;
this.IsConst = isConst;
this.IsLoopVariable = isLoopVariable;
this.Initializer = initializer;
this.ParentLambdaExpression = parentLambdaExpression;
this.IsQueryContinuation = isQueryContinuation;
}
}
public sealed class LookupTableVisitor : AbstractDomVisitor
{
Dictionary<string, List<LocalLookupVariable>> variables;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
public Dictionary<string, List<LocalLookupVariable>> Variables {
get {
return variables;
}
}
List<WithStatement> withStatements = new List<WithStatement>();
public List<WithStatement> WithStatements {
get {
return withStatements;
}
}
public LookupTableVisitor()
{
variables = new Dictionary<string, List<LocalLookupVariable>>(StringComparer.InvariantCultureIgnoreCase);
}
public void AddVariable(TypeReference typeRef, string name,
Location startPos, Location endPos, bool isConst,
bool isLoopVariable, Expression initializer,
LambdaExpression parentLambdaExpression,
bool isQueryContinuation)
{
if (name == null || name.Length == 0) {
return;
}
List<LocalLookupVariable> list;
if (!variables.ContainsKey(name)) {
variables[name] = list = new List<LocalLookupVariable>();
} else {
list = (List<LocalLookupVariable>)variables[name];
}
list.Add(new LocalLookupVariable(name, typeRef, startPos, endPos, isConst, isLoopVariable, initializer, parentLambdaExpression, isQueryContinuation));
}
public override object VisitWithStatement(WithStatement withStatement, object data)
{
withStatements.Add(withStatement);
return base.VisitWithStatement(withStatement, data);
}
Stack<Location> endLocationStack = new Stack<Location>();
Location CurrentEndLocation {
get {
return (endLocationStack.Count == 0) ? Location.Empty : endLocationStack.Peek();
}
}
public override object VisitCompilationUnit (ICSharpCode.NRefactory.VB.Dom.CompilationUnit compilationUnit, object data)
{
variables.Clear ();
return base.VisitCompilationUnit (compilationUnit, data);
}
public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{
endLocationStack.Push(blockStatement.EndLocation);
base.VisitBlockStatement(blockStatement, data);
endLocationStack.Pop();
return null;
}
public override object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data)
{
for (int i = 0; i < localVariableDeclaration.Variables.Count; ++i) {
VariableDeclaration varDecl = (VariableDeclaration)localVariableDeclaration.Variables[i];
AddVariable(localVariableDeclaration.GetTypeForVariable(i),
varDecl.Name,
localVariableDeclaration.StartLocation,
CurrentEndLocation,
(localVariableDeclaration.Modifier & Modifiers.Const) == Modifiers.Const,
false, varDecl.Initializer, null, false);
}
return base.VisitLocalVariableDeclaration(localVariableDeclaration, data);
}
public override object VisitLambdaExpression(LambdaExpression lambdaExpression, object data)
{
foreach (ParameterDeclarationExpression p in lambdaExpression.Parameters) {
AddVariable(p.TypeReference, p.ParameterName,
lambdaExpression.StartLocation, lambdaExpression.ExtendedEndLocation,
false, false, null, lambdaExpression, false);
}
return base.VisitLambdaExpression(lambdaExpression, data);
}
public override object VisitQueryExpression(QueryExpression queryExpression, object data)
{
endLocationStack.Push(GetQueryVariableEndScope(queryExpression));
base.VisitQueryExpression(queryExpression, data);
endLocationStack.Pop();
return null;
}
Location GetQueryVariableEndScope(QueryExpression queryExpression)
{
return queryExpression.EndLocation;
}
public override object VisitQueryExpressionFromClause(QueryExpressionFromClause fromClause, object data)
{
// TODO : reimplement this!
// QueryExpression parent = fromClause.Parent as QueryExpression;
// foreach (CollectionRangeVariable variable in fromClause.Sources) {
// AddVariable(variable.Type, variable.Identifier,
// variable.StartLocation, CurrentEndLocation,
// false, true, variable.Expression, null, parent != null && parent.IsQueryContinuation);
// }
return base.VisitQueryExpressionFromClause(fromClause, data);
}
public override object VisitQueryExpressionJoinClause(QueryExpressionJoinClause joinClause, object data)
{
if (string.IsNullOrEmpty(joinClause.IntoIdentifier)) {
AddVariable(joinClause.Source.Type, joinClause.Source.Identifier,
joinClause.Source.StartLocation, CurrentEndLocation,
false, true, joinClause.Source.Expression, null, false);
} else {
AddVariable(joinClause.Source.Type, joinClause.Source.Identifier,
joinClause.Source.StartLocation, joinClause.Source.EndLocation,
false, true, joinClause.Source.Expression, null, false);
AddVariable(joinClause.Source.Type, joinClause.IntoIdentifier,
joinClause.Source.StartLocation, CurrentEndLocation,
false, false, joinClause.Source.Expression, null, false);
}
return base.VisitQueryExpressionJoinClause(joinClause, data);
}
public override object VisitQueryExpressionLetClause(QueryExpressionLetClause letClause, object data)
{
AddVariable(null, letClause.Identifier,
letClause.StartLocation, CurrentEndLocation,
false, false, letClause.Expression, null, false);
return base.VisitQueryExpressionLetClause(letClause, data);
}
public override object VisitForNextStatement(ForNextStatement forNextStatement, object data)
{
if (forNextStatement.EmbeddedStatement.EndLocation.IsEmpty) {
return base.VisitForNextStatement(forNextStatement, data);
} else {
endLocationStack.Push(forNextStatement.EmbeddedStatement.EndLocation);
AddVariable(forNextStatement.TypeReference,
forNextStatement.VariableName,
forNextStatement.StartLocation,
forNextStatement.EndLocation,
false, false,
forNextStatement.Start,
null,
false);
base.VisitForNextStatement(forNextStatement, data);
endLocationStack.Pop();
return null;
}
}
public override object VisitUsingStatement(UsingStatement usingStatement, object data)
{
// uses LocalVariableDeclaration, we just have to put the end location on the stack
if (usingStatement.EmbeddedStatement.EndLocation.IsEmpty) {
return base.VisitUsingStatement(usingStatement, data);
} else {
endLocationStack.Push(usingStatement.EmbeddedStatement.EndLocation);
base.VisitUsingStatement(usingStatement, data);
endLocationStack.Pop();
return null;
}
}
public override object VisitSwitchSection(SwitchSection switchSection, object data)
{
return VisitBlockStatement(switchSection, data);
}
public override object VisitForeachStatement(ForeachStatement foreachStatement, object data)
{
AddVariable(foreachStatement.TypeReference,
foreachStatement.VariableName,
foreachStatement.StartLocation,
foreachStatement.EndLocation,
false, true,
foreachStatement.Expression,
null,
false);
if (foreachStatement.Expression != null) {
foreachStatement.Expression.AcceptVisitor(this, data);
}
if (foreachStatement.EmbeddedStatement == null) {
return data;
}
return foreachStatement.EmbeddedStatement.AcceptVisitor(this, data);
}
public override object VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data)
{
if (tryCatchStatement == null) {
return data;
}
if (tryCatchStatement.StatementBlock != null) {
tryCatchStatement.StatementBlock.AcceptVisitor(this, data);
}
if (tryCatchStatement.CatchClauses != null) {
foreach (CatchClause catchClause in tryCatchStatement.CatchClauses) {
if (catchClause != null) {
if (catchClause.TypeReference != null && catchClause.VariableName != null) {
AddVariable(catchClause.TypeReference,
catchClause.VariableName,
catchClause.StartLocation,
catchClause.StatementBlock.EndLocation,
false, false, null, null, false);
}
catchClause.StatementBlock.AcceptVisitor(this, data);
}
}
}
if (tryCatchStatement.FinallyBlock != null) {
return tryCatchStatement.FinallyBlock.AcceptVisitor(this, data);
}
return data;
}
}
}