Browse Source

Adjust CodeDomConvertVisitor and DefiniteAssignmentAnalysis to new type system.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
e2cb5467c2
  1. 53
      ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  2. 104
      ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  3. 31
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  4. 16
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
  5. 6
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  6. 2
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
  7. 2
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedTypeDefinition.cs
  8. 5
      ICSharpCode.NRefactory.CSharp/TypeSystem/UsingScope.cs
  9. 19
      ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs
  10. 33
      ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
  11. 2
      ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs
  12. 14
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  13. 10
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  14. 2
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  15. 68
      ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalCorlib.cs
  16. 182
      ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs
  17. 48
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

53
ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs

@ -21,10 +21,10 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.CSharp.Analysis
{ {
@ -145,36 +145,35 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
protected virtual ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) protected virtual ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type)
{ {
cancellationToken.ThrowIfCancellationRequested();
return new ControlFlowNode(previousStatement, nextStatement, type); return new ControlFlowNode(previousStatement, nextStatement, type);
} }
protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type) protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type)
{ {
cancellationToken.ThrowIfCancellationRequested();
return new ControlFlowEdge(from, to, type); return new ControlFlowEdge(from, to, type);
} }
Statement rootStatement; Statement rootStatement;
ResolveVisitor resolveVisitor; CSharpAstResolver resolver;
List<ControlFlowNode> nodes; List<ControlFlowNode> nodes;
Dictionary<string, ControlFlowNode> labels; Dictionary<string, ControlFlowNode> labels;
List<ControlFlowNode> gotoStatements; List<ControlFlowNode> gotoStatements;
CancellationToken cancellationToken;
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement) public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, CancellationToken cancellationToken = default(CancellationToken))
{ {
return BuildControlFlowGraph(statement, CancellationToken.None); CSharpResolver r = new CSharpResolver(MinimalCorlib.Instance.CreateCompilation());
return BuildControlFlowGraph(statement, new CSharpAstResolver(r, statement), cancellationToken);
} }
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, CancellationToken cancellationToken) public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}
internal IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor)
{ {
if (statement == null) if (statement == null)
throw new ArgumentNullException("statement"); throw new ArgumentNullException("statement");
if (resolveVisitor == null) if (resolver == null)
throw new ArgumentNullException("resolveVisitor"); throw new ArgumentNullException("resolver");
NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor(); NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor();
nodeCreationVisitor.builder = this; nodeCreationVisitor.builder = this;
@ -183,7 +182,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.labels = new Dictionary<string, ControlFlowNode>(); this.labels = new Dictionary<string, ControlFlowNode>();
this.gotoStatements = new List<ControlFlowNode>(); this.gotoStatements = new List<ControlFlowNode>();
this.rootStatement = statement; this.rootStatement = statement;
this.resolveVisitor = resolveVisitor; this.resolver = resolver;
this.cancellationToken = cancellationToken;
ControlFlowNode entryPoint = CreateStartNode(statement); ControlFlowNode entryPoint = CreateStartNode(statement);
statement.AcceptVisitor(nodeCreationVisitor, entryPoint); statement.AcceptVisitor(nodeCreationVisitor, entryPoint);
@ -203,7 +204,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.labels = null; this.labels = null;
this.gotoStatements = null; this.gotoStatements = null;
this.rootStatement = null; this.rootStatement = null;
this.resolveVisitor = null; this.resolver = null;
this.cancellationToken = CancellationToken.None;
} }
} }
@ -280,13 +282,13 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// Evaluates an expression. /// Evaluates an expression.
/// </summary> /// </summary>
/// <returns>The constant value of the expression; or null if the expression is not a constant.</returns> /// <returns>The constant value of the expression; or null if the expression is not a constant.</returns>
ConstantResolveResult EvaluateConstant(Expression expr) ResolveResult EvaluateConstant(Expression expr)
{ {
if (EvaluateOnlyPrimitiveConstants) { if (EvaluateOnlyPrimitiveConstants) {
if (!(expr is PrimitiveExpression || expr is NullReferenceExpression)) if (!(expr is PrimitiveExpression || expr is NullReferenceExpression))
return null; return null;
} }
return resolveVisitor.Resolve(expr) as ConstantResolveResult; return resolver.Resolve(expr, cancellationToken);
} }
/// <summary> /// <summary>
@ -295,21 +297,20 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns> /// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns>
bool? EvaluateCondition(Expression expr) bool? EvaluateCondition(Expression expr)
{ {
ConstantResolveResult rr = EvaluateConstant(expr); ResolveResult rr = EvaluateConstant(expr);
if (rr != null) if (rr != null && rr.IsCompileTimeConstant)
return rr.ConstantValue as bool?; return rr.ConstantValue as bool?;
else else
return null; return null;
} }
bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2) bool AreEqualConstants(ResolveResult c1, ResolveResult c2)
{ {
if (c1 == null || c2 == null) if (c1 == null || c2 == null || !c1.IsCompileTimeConstant || !c2.IsCompileTimeConstant)
return false; return false;
throw new NotImplementedException(); CSharpResolver r = new CSharpResolver(resolver.TypeResolveContext);
/*CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken);
ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2); ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2);
return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true;*/ return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true;
} }
#endregion #endregion
@ -421,7 +422,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data) public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data)
{ {
// First, figure out which switch section will get called (if the expression is constant): // First, figure out which switch section will get called (if the expression is constant):
ConstantResolveResult constant = builder.EvaluateConstant(switchStatement.Expression); ResolveResult constant = builder.EvaluateConstant(switchStatement.Expression);
SwitchSection defaultSection = null; SwitchSection defaultSection = null;
SwitchSection sectionMatchedByConstant = null; SwitchSection sectionMatchedByConstant = null;
foreach (SwitchSection section in switchStatement.SwitchSections) { foreach (SwitchSection section in switchStatement.SwitchSections) {
@ -429,13 +430,13 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
if (label.Expression.IsNull) { if (label.Expression.IsNull) {
defaultSection = section; defaultSection = section;
} else if (constant != null) { } else if (constant != null) {
ConstantResolveResult labelConstant = builder.EvaluateConstant(label.Expression); ResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
if (builder.AreEqualConstants(constant, labelConstant)) if (builder.AreEqualConstants(constant, labelConstant))
sectionMatchedByConstant = section; sectionMatchedByConstant = section;
} }
} }
} }
if (constant != null && sectionMatchedByConstant == null) if (constant.IsCompileTimeConstant && sectionMatchedByConstant == null)
sectionMatchedByConstant = defaultSection; sectionMatchedByConstant = defaultSection;
int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count; int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count;

104
ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -81,52 +81,42 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
} }
} }
readonly DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder();
readonly DefiniteAssignmentVisitor visitor = new DefiniteAssignmentVisitor(); readonly DefiniteAssignmentVisitor visitor = new DefiniteAssignmentVisitor();
readonly List<DefiniteAssignmentNode> allNodes = new List<DefiniteAssignmentNode>(); readonly List<DefiniteAssignmentNode> allNodes = new List<DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> beginNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>(); readonly Dictionary<Statement, DefiniteAssignmentNode> beginNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> endNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>(); readonly Dictionary<Statement, DefiniteAssignmentNode> endNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> conditionNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>(); readonly Dictionary<Statement, DefiniteAssignmentNode> conditionNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly ResolveVisitor resolveVisitor; readonly CSharpAstResolver resolver;
readonly CancellationToken cancellationToken;
Dictionary<ControlFlowEdge, DefiniteAssignmentStatus> edgeStatus = new Dictionary<ControlFlowEdge, DefiniteAssignmentStatus>(); Dictionary<ControlFlowEdge, DefiniteAssignmentStatus> edgeStatus = new Dictionary<ControlFlowEdge, DefiniteAssignmentStatus>();
string variableName; string variableName;
List<IdentifierExpression> unassignedVariableUses = new List<IdentifierExpression>(); List<IdentifierExpression> unassignedVariableUses = new List<IdentifierExpression>();
int analyzedRangeStart, analyzedRangeEnd; int analyzedRangeStart, analyzedRangeEnd;
CancellationToken analysisCancellationToken;
Queue<DefiniteAssignmentNode> nodesWithModifiedInput = new Queue<DefiniteAssignmentNode>(); Queue<DefiniteAssignmentNode> nodesWithModifiedInput = new Queue<DefiniteAssignmentNode>();
public DefiniteAssignmentAnalysis(Statement rootStatement)
: this(rootStatement, CancellationToken.None)
{
}
[ObsoleteAttribute]
public DefiniteAssignmentAnalysis(params object[] args)
{
throw new NotImplementedException();
}
public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken) public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken)
: this(rootStatement,
new CSharpAstResolver(new CSharpResolver(MinimalCorlib.Instance.CreateCompilation()), rootStatement),
cancellationToken)
{ {
throw new NotImplementedException();
} }
/* public DefiniteAssignmentAnalysis(Statement rootStatement, CSharpAstResolver resolver, CancellationToken cancellationToken)
public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor)
{ {
if (rootStatement == null) if (rootStatement == null)
throw new ArgumentNullException("rootStatement"); throw new ArgumentNullException("rootStatement");
if (resolveVisitor == null) if (resolver == null)
throw new ArgumentNullException("resolveVisitor"); throw new ArgumentNullException("resolver");
this.resolveVisitor = resolveVisitor; this.resolver = resolver;
this.cancellationToken = resolveVisitor.CancellationToken;
visitor.analysis = this; visitor.analysis = this;
if (resolveVisitor.TypeResolveContext is MinimalResolveContext) { DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder();
if (resolver.TypeResolveContext.Compilation.MainAssembly.UnresolvedAssembly is MinimalCorlib) {
cfgBuilder.EvaluateOnlyPrimitiveConstants = true; cfgBuilder.EvaluateOnlyPrimitiveConstants = true;
} }
allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolveVisitor).Cast<DefiniteAssignmentNode>()); allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
for (int i = 0; i < allNodes.Count; i++) { for (int i = 0; i < allNodes.Count; i++) {
DefiniteAssignmentNode node = allNodes[i]; DefiniteAssignmentNode node = allNodes[i];
node.Index = i; // assign numbers to the nodes node.Index = i; // assign numbers to the nodes
@ -134,7 +124,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
// Anonymous methods have separate control flow graphs, but we also need to analyze those. // Anonymous methods have separate control flow graphs, but we also need to analyze those.
// Iterate backwards so that anonymous methods are inserted in the correct order // Iterate backwards so that anonymous methods are inserted in the correct order
for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling) { for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling) {
InsertAnonymousMethods(i + 1, child); InsertAnonymousMethods(i + 1, child, cfgBuilder, cancellationToken);
} }
} }
// Now register the node in the dictionaries: // Now register the node in the dictionaries:
@ -153,27 +143,27 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.analyzedRangeStart = 0; this.analyzedRangeStart = 0;
this.analyzedRangeEnd = allNodes.Count - 1; this.analyzedRangeEnd = allNodes.Count - 1;
}*/ }
void InsertAnonymousMethods(int insertPos, AstNode node) void InsertAnonymousMethods(int insertPos, AstNode node, ControlFlowGraphBuilder cfgBuilder, CancellationToken cancellationToken)
{ {
// Ignore any statements, as those have their own ControlFlowNode and get handled separately // Ignore any statements, as those have their own ControlFlowNode and get handled separately
if (node is Statement) if (node is Statement)
return; return;
AnonymousMethodExpression ame = node as AnonymousMethodExpression; AnonymousMethodExpression ame = node as AnonymousMethodExpression;
if (ame != null) { if (ame != null) {
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph(ame.Body, resolveVisitor).Cast<DefiniteAssignmentNode>()); allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph(ame.Body, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
return; return;
} }
LambdaExpression lambda = node as LambdaExpression; LambdaExpression lambda = node as LambdaExpression;
if (lambda != null && lambda.Body is Statement) { if (lambda != null && lambda.Body is Statement) {
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolveVisitor).Cast<DefiniteAssignmentNode>()); allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
return; return;
} }
// Descend into child expressions // Descend into child expressions
// Iterate backwards so that anonymous methods are inserted in the correct order // Iterate backwards so that anonymous methods are inserted in the correct order
for (AstNode child = node.LastChild; child != null; child = child.PrevSibling) { for (AstNode child = node.LastChild; child != null; child = child.PrevSibling) {
InsertAnonymousMethods(insertPos, child); InsertAnonymousMethods(insertPos, child, cfgBuilder, cancellationToken);
} }
} }
@ -205,26 +195,32 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.analyzedRangeEnd = endIndex; this.analyzedRangeEnd = endIndex;
} }
public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned) public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned, CancellationToken cancellationToken = default(CancellationToken))
{ {
this.analysisCancellationToken = cancellationToken;
this.variableName = variable; this.variableName = variable;
// Reset the status: try {
unassignedVariableUses.Clear(); // Reset the status:
foreach (DefiniteAssignmentNode node in allNodes) { unassignedVariableUses.Clear();
node.NodeStatus = DefiniteAssignmentStatus.CodeUnreachable; foreach (DefiniteAssignmentNode node in allNodes) {
foreach (ControlFlowEdge edge in node.Outgoing) node.NodeStatus = DefiniteAssignmentStatus.CodeUnreachable;
edgeStatus[edge] = DefiniteAssignmentStatus.CodeUnreachable; foreach (ControlFlowEdge edge in node.Outgoing)
} edgeStatus[edge] = DefiniteAssignmentStatus.CodeUnreachable;
}
ChangeNodeStatus(allNodes[analyzedRangeStart], initialStatus);
// Iterate as long as the input status of some nodes is changing: ChangeNodeStatus(allNodes[analyzedRangeStart], initialStatus);
while (nodesWithModifiedInput.Count > 0) { // Iterate as long as the input status of some nodes is changing:
DefiniteAssignmentNode node = nodesWithModifiedInput.Dequeue(); while (nodesWithModifiedInput.Count > 0) {
DefiniteAssignmentStatus inputStatus = DefiniteAssignmentStatus.CodeUnreachable; DefiniteAssignmentNode node = nodesWithModifiedInput.Dequeue();
foreach (ControlFlowEdge edge in node.Incoming) { DefiniteAssignmentStatus inputStatus = DefiniteAssignmentStatus.CodeUnreachable;
inputStatus = MergeStatus(inputStatus, edgeStatus[edge]); foreach (ControlFlowEdge edge in node.Incoming) {
inputStatus = MergeStatus(inputStatus, edgeStatus[edge]);
}
ChangeNodeStatus(node, inputStatus);
} }
ChangeNodeStatus(node, inputStatus); } finally {
this.analysisCancellationToken = CancellationToken.None;
this.variableName = null;
} }
} }
@ -410,9 +406,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// Evaluates an expression. /// Evaluates an expression.
/// </summary> /// </summary>
/// <returns>The constant value of the expression; or null if the expression is not a constant.</returns> /// <returns>The constant value of the expression; or null if the expression is not a constant.</returns>
ConstantResolveResult EvaluateConstant(Expression expr) ResolveResult EvaluateConstant(Expression expr)
{ {
return resolveVisitor.Resolve(expr) as ConstantResolveResult; return resolver.Resolve(expr, analysisCancellationToken);
} }
/// <summary> /// <summary>
@ -421,8 +417,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns> /// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns>
bool? EvaluateCondition(Expression expr) bool? EvaluateCondition(Expression expr)
{ {
ConstantResolveResult rr = EvaluateConstant(expr); ResolveResult rr = EvaluateConstant(expr);
if (rr != null) if (rr != null && rr.IsCompileTimeConstant)
return rr.ConstantValue as bool?; return rr.ConstantValue as bool?;
else else
return null; return null;
@ -449,6 +445,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Debug.Assert(data == CleanSpecialValues(data)); Debug.Assert(data == CleanSpecialValues(data));
DefiniteAssignmentStatus status = data; DefiniteAssignmentStatus status = data;
foreach (AstNode child in node.Children) { foreach (AstNode child in node.Children) {
analysis.analysisCancellationToken.ThrowIfCancellationRequested();
Debug.Assert(!(child is Statement)); // statements are visited with the CFG, not with the visitor pattern Debug.Assert(!(child is Statement)); // statements are visited with the CFG, not with the visitor pattern
status = child.AcceptVisitor(this, status); status = child.AcceptVisitor(this, status);
status = CleanSpecialValues(status); status = CleanSpecialValues(status);
@ -561,6 +559,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
} }
#endregion #endregion
#region Expressions
public override DefiniteAssignmentStatus VisitDirectionExpression(DirectionExpression directionExpression, DefiniteAssignmentStatus data) public override DefiniteAssignmentStatus VisitDirectionExpression(DirectionExpression directionExpression, DefiniteAssignmentStatus data)
{ {
if (directionExpression.FieldDirection == FieldDirection.Out) { if (directionExpression.FieldDirection == FieldDirection.Out) {
@ -670,8 +669,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return DefiniteAssignmentStatus.PotentiallyAssigned; return DefiniteAssignmentStatus.PotentiallyAssigned;
} else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) { } else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) {
// C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions // C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions
ConstantResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left); ResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left);
if (crr != null && crr.ConstantValue == null) if (crr != null && crr.IsCompileTimeConstant && crr.ConstantValue == null)
return binaryOperatorExpression.Right.AcceptVisitor(this, data); return binaryOperatorExpression.Right.AcceptVisitor(this, data);
DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data)); DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data));
binaryOperatorExpression.Right.AcceptVisitor(this, status); binaryOperatorExpression.Right.AcceptVisitor(this, status);
@ -755,6 +754,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
} }
return data; return data;
} }
#endregion
} }
} }
} }

31
ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class CodeDomConvertVisitor : IAstVisitor<object, CodeObject> public class CodeDomConvertVisitor : IAstVisitor<object, CodeObject>
{ {
//ICompilation compilation = MinimalResolveContext.Instance; //ICompilation compilation = MinimalResolveContext.Instance;
ResolveVisitor resolveVisitor; CSharpAstResolver resolver;
bool useFullyQualifiedTypeNames; bool useFullyQualifiedTypeNames;
/// <summary> /// <summary>
@ -60,23 +60,17 @@ namespace ICSharpCode.NRefactory.CSharp
/// <remarks> /// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks> /// </remarks>
public CodeCompileUnit Convert(CompilationUnit compilationUnit, ICompilation compilation) public CodeCompileUnit Convert(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile)
{ {
if (compilationUnit == null) if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit"); throw new ArgumentNullException("compilationUnit");
if (compilation == null) if (compilation == null)
throw new ArgumentNullException("compilation"); throw new ArgumentNullException("compilation");
throw new NotImplementedException(); CSharpAstResolver resolver = new CSharpAstResolver(compilation, compilationUnit, parsedFile);
/* return (CodeCompileUnit)Convert(compilationUnit, resolver);
using (var ctx = context.Synchronize()) {
ResolveVisitor resolveVisitor = new ResolveVisitor(new CSharpResolver(ctx), parsedFile);
resolveVisitor.Scan(compilationUnit);
return (CodeCompileUnit)Convert(compilationUnit, resolveVisitor);
}*/
} }
/*
/// <summary> /// <summary>
/// Converts a C# AST node to CodeDom. /// Converts a C# AST node to CodeDom.
/// </summary> /// </summary>
@ -87,29 +81,26 @@ namespace ICSharpCode.NRefactory.CSharp
/// <remarks> /// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks> /// </remarks>
public CodeObject Convert(AstNode node, ResolveVisitor resolveVisitor) public CodeObject Convert(AstNode node, CSharpAstResolver resolver)
{ {
if (node == null) if (node == null)
throw new ArgumentNullException("node"); throw new ArgumentNullException("node");
if (resolveVisitor == null) if (resolver == null)
throw new ArgumentNullException("resolveVisitor"); throw new ArgumentNullException("resolver");
try { try {
this.resolveVisitor = resolveVisitor; this.resolver = resolver;
this.context = resolveVisitor.TypeResolveContext;
return node.AcceptVisitor(this); return node.AcceptVisitor(this);
} finally { } finally {
this.resolveVisitor = null; this.resolver = null;
this.context = MinimalResolveContext.Instance;
} }
} }
*/
ResolveResult Resolve(AstNode node) ResolveResult Resolve(AstNode node)
{ {
if (resolveVisitor == null) if (resolver == null)
return ErrorResolveResult.UnknownError; return ErrorResolveResult.UnknownError;
else else
return resolveVisitor.GetResolveResult(node); return resolver.Resolve(node);
} }
CodeExpression Convert(Expression expr) CodeExpression Convert(Expression expr)

16
ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
@ -73,13 +74,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.parsedFile = parsedFile; this.parsedFile = parsedFile;
} }
/// <summary>
/// Gets the type resolve context for the root resolver.
/// </summary>
public CSharpTypeResolveContext TypeResolveContext {
get { return initialResolverState.CurrentTypeResolveContext; }
}
/// <summary> /// <summary>
/// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the /// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the
/// navigator of the results. /// navigator of the results.
/// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator /// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator
/// after a portion of the file was already resolved. /// after a portion of the file was already resolved.
/// </summary> /// </summary>
public void ApplyNavigator(IResolveVisitorNavigator navigator) public void ApplyNavigator(IResolveVisitorNavigator navigator, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (resolveVisitor != null) if (resolveVisitor != null)
throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver."); throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver.");
@ -91,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary> /// <summary>
/// Resolves the specified node. /// Resolves the specified node.
/// </summary> /// </summary>
public ResolveResult Resolve(AstNode node) public ResolveResult Resolve(AstNode node, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (resolveVisitor == null) { if (resolveVisitor == null) {
resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile);
@ -104,7 +112,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary> /// <summary>
/// Gets the expected type for the specified node. This is the type being that a node is being converted to. /// Gets the expected type for the specified node. This is the type being that a node is being converted to.
/// </summary> /// </summary>
public IType GetExpectedType(Expression expr) public IType GetExpectedType(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -112,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary> /// <summary>
/// Gets the conversion that is being applied to the specified expression. /// Gets the conversion that is being applied to the specified expression.
/// </summary> /// </summary>
public Conversion GetConversion(Expression expr) public Conversion GetConversion(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

6
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -97,7 +97,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
if (resolver == null) if (resolver == null)
throw new ArgumentNullException("resolver"); throw new ArgumentNullException("resolver");
this.resolver = resolver; this.resolver = resolver.Clone();
this.parsedFile = parsedFile; this.parsedFile = parsedFile;
this.navigator = navigator ?? new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null); this.navigator = navigator ?? new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null);
this.voidResult = new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void)); this.voidResult = new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void));
@ -461,7 +461,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolvedUsingScope previousUsingScope = resolver.CurrentUsingScope; ResolvedUsingScope previousUsingScope = resolver.CurrentUsingScope;
try { try {
if (parsedFile != null) if (parsedFile != null)
resolver.CurrentUsingScope = parsedFile.RootUsingScope.Resolve(resolver.CurrentTypeResolveContext); resolver.CurrentUsingScope = parsedFile.RootUsingScope.Resolve(resolver.Compilation);
ScanChildren(unit); ScanChildren(unit);
return voidResult; return voidResult;
} finally { } finally {
@ -474,7 +474,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolvedUsingScope previousUsingScope = resolver.CurrentUsingScope; ResolvedUsingScope previousUsingScope = resolver.CurrentUsingScope;
try { try {
if (parsedFile != null) { if (parsedFile != null) {
resolver.CurrentUsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.CurrentTypeResolveContext); resolver.CurrentUsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation);
} }
ScanChildren(namespaceDeclaration); ScanChildren(namespaceDeclaration);
// merge undecided lambdas before leaving the using scope so that // merge undecided lambdas before leaving the using scope so that

2
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
result = new List<IAttribute>(); result = new List<IAttribute>();
foreach (var parsedFile in projectContent.Files.OfType<CSharpParsedFile>()) { foreach (var parsedFile in projectContent.Files.OfType<CSharpParsedFile>()) {
var attributes = assemblyAttributes ? parsedFile.AssemblyAttributes : parsedFile.ModuleAttributes; var attributes = assemblyAttributes ? parsedFile.AssemblyAttributes : parsedFile.ModuleAttributes;
var context = new CSharpTypeResolveContext(this, parsedFile.RootUsingScope.Resolve(new CSharpTypeResolveContext(this))); var context = new CSharpTypeResolveContext(this, parsedFile.RootUsingScope.Resolve(compilation));
foreach (var unresolvedAttr in attributes) { foreach (var unresolvedAttr in attributes) {
result.Add(unresolvedAttr.CreateResolvedAttribute(context)); result.Add(unresolvedAttr.CreateResolvedAttribute(context));
} }

2
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedTypeDefinition.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public override ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext) public override ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext)
{ {
return new CSharpTypeResolveContext(parentContext.CurrentAssembly, usingScope.Resolve(parentContext), parentContext.CurrentTypeDefinition); return new CSharpTypeResolveContext(parentContext.CurrentAssembly, usingScope.Resolve(parentContext.Compilation), parentContext.CurrentTypeDefinition);
} }
} }
} }

5
ICSharpCode.NRefactory.CSharp/TypeSystem/UsingScope.cs

@ -160,13 +160,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// <summary> /// <summary>
/// Resolves the namespace represented by this using scope. /// Resolves the namespace represented by this using scope.
/// </summary> /// </summary>
public ResolvedUsingScope Resolve(ITypeResolveContext context) public ResolvedUsingScope Resolve(ICompilation compilation)
{ {
ICompilation compilation = context.Compilation;
CacheManager cache = compilation.CacheManager; CacheManager cache = compilation.CacheManager;
ResolvedUsingScope resolved = (ResolvedUsingScope)cache.GetShared(this); ResolvedUsingScope resolved = (ResolvedUsingScope)cache.GetShared(this);
if (resolved == null) { if (resolved == null) {
var csContext = new CSharpTypeResolveContext(compilation.MainAssembly, parent != null ? parent.Resolve(context) : null); var csContext = new CSharpTypeResolveContext(compilation.MainAssembly, parent != null ? parent.Resolve(compilation) : null);
resolved = (ResolvedUsingScope)cache.GetOrAddShared(this, new ResolvedUsingScope(csContext, this)); resolved = (ResolvedUsingScope)cache.GetOrAddShared(this, new ResolvedUsingScope(csContext, this));
} }
return resolved; return resolved;

19
ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs

@ -18,7 +18,10 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.CSharp.Analysis
@ -26,6 +29,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
[TestFixture] [TestFixture]
public class DefiniteAssignmentTests public class DefiniteAssignmentTests
{ {
DefiniteAssignmentAnalysis CreateDefiniteAssignmentAnalysis(Statement rootStatement)
{
var resolver = new CSharpAstResolver(new CSharpResolver(new SimpleCompilation(CecilLoaderTests.Mscorlib)), rootStatement);
return new DefiniteAssignmentAnalysis(rootStatement, resolver, CancellationToken.None);
}
[Test] [Test]
public void TryFinally() public void TryFinally()
{ {
@ -55,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Statement stmt5 = tryCatchStatement.FinallyBlock.Statements.Single(); Statement stmt5 = tryCatchStatement.FinallyBlock.Statements.Single();
LabelStatement label = (LabelStatement)block.Statements.ElementAt(1); LabelStatement label = (LabelStatement)block.Statements.ElementAt(1);
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(block, CecilLoaderTests.Mscorlib); DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
da.Analyze("i"); da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement));
@ -105,7 +114,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
TrueStatement = new BlockStatement(), TrueStatement = new BlockStatement(),
FalseStatement = new BlockStatement() FalseStatement = new BlockStatement()
}; };
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib); DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(ifStmt);
da.Analyze("i"); da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt));
@ -136,7 +145,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
TrueStatement = new BlockStatement(), TrueStatement = new BlockStatement(),
FalseStatement = new BlockStatement() FalseStatement = new BlockStatement()
}; };
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib); DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(ifStmt);
da.Analyze("i"); da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt));
@ -155,7 +164,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
new BreakStatement() new BreakStatement()
} }
}; };
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(loop);
da.Analyze("i"); da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));
@ -187,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
new AssignmentExpression(new IdentifierExpression("j"), new IdentifierExpression("i")) new AssignmentExpression(new IdentifierExpression("j"), new IdentifierExpression("i"))
)}; )};
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(loop);
da.Analyze("i"); da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));

33
ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs

@ -17,8 +17,15 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Microsoft.CSharp;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp namespace ICSharpCode.NRefactory.CSharp
@ -27,33 +34,31 @@ namespace ICSharpCode.NRefactory.CSharp
public class CodeDomConvertVisitorTests : ResolverTestBase public class CodeDomConvertVisitorTests : ResolverTestBase
{ {
CodeDomConvertVisitor convertVisitor; CodeDomConvertVisitor convertVisitor;
CSharpResolver resolver; CSharpParsedFile parsedFile;
public override void SetUp() public override void SetUp()
{ {
base.SetUp(); base.SetUp();
resolver = new CSharpResolver(compilation); parsedFile = new CSharpParsedFile("test.cs", new UsingScope());
throw new NotImplementedException(); parsedFile.RootUsingScope.Usings.Add(MakeReference("System"));
/*resolver.CurrentUsingScope = new UsingScope(); parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Collections.Generic"));
resolver.CurrentUsingScope.Usings.Add(MakeReference("System")); parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Linq"));
resolver.CurrentUsingScope.Usings.Add(MakeReference("System.Collections.Generic"));
resolver.CurrentUsingScope.Usings.Add(MakeReference("System.Linq"));
*/
convertVisitor = new CodeDomConvertVisitor(); convertVisitor = new CodeDomConvertVisitor();
convertVisitor.UseFullyQualifiedTypeNames = true; convertVisitor.UseFullyQualifiedTypeNames = true;
} }
string Convert(Expression expr) string Convert(Expression expr)
{ {
throw new NotImplementedException(); CSharpResolver resolver = new CSharpResolver(compilation);
/* resolver.CurrentUsingScope = parsedFile.RootUsingScope.Resolve(compilation);
ResolveVisitor rv = new ResolveVisitor(resolver, null); resolver.CurrentTypeDefinition = compilation.FindType(KnownTypeCode.Object).GetDefinition();
rv.Scan(expr); var codeExpr = (CodeExpression)convertVisitor.Convert(expr, new CSharpAstResolver(resolver, expr, parsedFile));
var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv);
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
writer.NewLine = " "; writer.NewLine = " ";
new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " });
return Regex.Replace(writer.ToString(), @"\s+", " ");*/ return Regex.Replace(writer.ToString(), @"\s+", " ");
} }
[Test] [Test]

2
ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs

@ -80,7 +80,7 @@ namespace OtherNS {
UsingScope usingScope = currentTypeDef != null ? parsedFile.GetUsingScope(currentTypeDef.Region.Begin) : parsedFile.RootUsingScope; UsingScope usingScope = currentTypeDef != null ? parsedFile.GetUsingScope(currentTypeDef.Region.Begin) : parsedFile.RootUsingScope;
return new TypeSystemAstBuilder( return new TypeSystemAstBuilder(
new CSharpResolver(compilation) { new CSharpResolver(compilation) {
CurrentUsingScope = usingScope.Resolve(compilation.TypeResolveContext), CurrentUsingScope = usingScope.Resolve(compilation),
CurrentTypeDefinition = currentTypeDef CurrentTypeDefinition = currentTypeDef
}); });
} }

14
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -40,16 +40,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.CurrentUsingScope = MakeUsingScope(string.Empty); resolver.CurrentUsingScope = MakeUsingScope(string.Empty);
} }
TypeOrNamespaceReference MakeReference(string namespaceName)
{
string[] nameParts = namespaceName.Split('.');
TypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], SimpleNameLookupMode.TypeInUsingDeclaration);
for (int i = 1; i < nameParts.Length; i++) {
r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0]);
}
return r;
}
ResolvedUsingScope MakeUsingScope(string namespaceName = "", string[] usings = null, KeyValuePair<string, string>[] usingAliases = null) ResolvedUsingScope MakeUsingScope(string namespaceName = "", string[] usings = null, KeyValuePair<string, string>[] usingAliases = null)
{ {
UsingScope usingScope = new UsingScope(); UsingScope usingScope = new UsingScope();
@ -66,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
foreach (var pair in usingAliases) foreach (var pair in usingAliases)
usingScope.UsingAliases.Add(new KeyValuePair<string, TypeOrNamespaceReference>(pair.Key, MakeReference(pair.Value))); usingScope.UsingAliases.Add(new KeyValuePair<string, TypeOrNamespaceReference>(pair.Key, MakeReference(pair.Value)));
} }
return usingScope.Resolve(resolver.CurrentTypeResolveContext); return usingScope.Resolve(resolver.Compilation);
} }
[Test] [Test]
@ -145,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
mainUsingScope.Usings.Add(MakeReference("System")); mainUsingScope.Usings.Add(MakeReference("System"));
UsingScope nestedUsingScope = new UsingScope(mainUsingScope, "SomeNamespace"); UsingScope nestedUsingScope = new UsingScope(mainUsingScope, "SomeNamespace");
nestedUsingScope.UsingAliases.Add(new KeyValuePair<string, TypeOrNamespaceReference>("x", MakeReference("String"))); nestedUsingScope.UsingAliases.Add(new KeyValuePair<string, TypeOrNamespaceReference>("x", MakeReference("String")));
resolver.CurrentUsingScope = nestedUsingScope.Resolve(compilation.TypeResolveContext); resolver.CurrentUsingScope = nestedUsingScope.Resolve(compilation);
TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]);
Assert.AreEqual("System.String", trr.Type.FullName); Assert.AreEqual("System.String", trr.Type.FullName);

10
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -69,6 +69,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new ResolveResult(ResolveType(type)); return new ResolveResult(ResolveType(type));
} }
protected static TypeOrNamespaceReference MakeReference(string namespaceName)
{
string[] nameParts = namespaceName.Split('.');
TypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], SimpleNameLookupMode.TypeInUsingDeclaration);
for (int i = 1; i < nameParts.Length; i++) {
r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0]);
}
return r;
}
protected void AssertConstant(object expectedValue, ResolveResult rr) protected void AssertConstant(object expectedValue, ResolveResult rr)
{ {
Assert.IsFalse(rr.IsError, rr.ToString() + " is an error"); Assert.IsFalse(rr.IsError, rr.ToString() + " is an error");

2
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -154,7 +154,7 @@
<Compile Include="TypeSystem\Implementation\GetMembersHelper.cs" /> <Compile Include="TypeSystem\Implementation\GetMembersHelper.cs" />
<Compile Include="TypeSystem\Implementation\KnownTypeCache.cs" /> <Compile Include="TypeSystem\Implementation\KnownTypeCache.cs" />
<Compile Include="TypeSystem\Implementation\MergedNamespace.cs" /> <Compile Include="TypeSystem\Implementation\MergedNamespace.cs" />
<Compile Include="TypeSystem\Implementation\MinimalResolveContext.cs" /> <Compile Include="TypeSystem\Implementation\MinimalCorlib.cs" />
<Compile Include="TypeSystem\Implementation\NestedTypeReference.cs" /> <Compile Include="TypeSystem\Implementation\NestedTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\SimpleCompilation.cs" /> <Compile Include="TypeSystem\Implementation\SimpleCompilation.cs" />
<Compile Include="TypeSystem\Implementation\SimpleConstantValue.cs" /> <Compile Include="TypeSystem\Implementation\SimpleConstantValue.cs" />

68
ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalCorlib.cs

@ -0,0 +1,68 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Resolve context represents the minimal mscorlib required for evaluating constants.
/// This contains all known types (<see cref="KnownTypeCode"/>) and no other types.
/// </summary>
public sealed class MinimalCorlib : DefaultUnresolvedAssembly
{
static readonly Lazy<MinimalCorlib> instance = new Lazy<MinimalCorlib>(() => new MinimalCorlib());
public static MinimalCorlib Instance {
get { return instance.Value; }
}
public ICompilation CreateCompilation()
{
return new SimpleCompilation(this);
}
private MinimalCorlib() : base("corlib")
{
var types = new DefaultUnresolvedTypeDefinition[KnownTypeReference.KnownTypeCodeCount];
for (int i = 0; i < types.Length; i++) {
var typeRef = KnownTypeReference.Get((KnownTypeCode)i);
if (typeRef != null) {
types[i] = new DefaultUnresolvedTypeDefinition(typeRef.Namespace, typeRef.Name);
for (int j = 0; j < typeRef.TypeParameterCount; j++) {
types[i].TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, j));
}
AddTypeDefinition(types[i]);
}
}
for (int i = 0; i < types.Length; i++) {
var typeRef = KnownTypeReference.Get((KnownTypeCode)i);
if (typeRef != null && typeRef.baseType != KnownTypeCode.None) {
types[i].BaseTypes.Add(types[(int)typeRef.baseType]);
if (typeRef.baseType == KnownTypeCode.ValueType && i != (int)KnownTypeCode.Enum) {
types[i].Kind = TypeKind.Struct;
}
}
}
Freeze();
}
}
}

182
ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs

@ -1,182 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/*
/// <summary>
/// Resolve context represents the minimal mscorlib required for evaluating constants.
/// </summary>
public sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext
{
static readonly Lazy<MinimalResolveContext> instance = new Lazy<MinimalResolveContext>(() => new MinimalResolveContext());
public static MinimalResolveContext Instance {
get { return instance.Value; }
}
readonly ReadOnlyCollection<string> namespaces = Array.AsReadOnly(new string[] { "System" });
readonly ITypeDefinition systemObject, systemValueType;
readonly ReadOnlyCollection<ITypeDefinition> types;
private MinimalResolveContext()
{
List<ITypeDefinition> types = new List<ITypeDefinition>();
systemObject = new DefaultTypeDefinition(this, "System", "Object") {
Accessibility = Accessibility.Public
};
systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") {
Accessibility = Accessibility.Public,
BaseTypes = { systemObject }
};
// TypeCode.Empty = void
types.Add(new VoidTypeDefinition(this));
// types are added in the order they are defined in the TypeCode enum
types.Add(systemObject);
types.Add(CreateClass("System", "DBNull"));
types.Add(CreateStruct("System", "Boolean"));
types.Add(CreateStruct("System", "Char"));
types.Add(CreateStruct("System", "SByte"));
types.Add(CreateStruct("System", "Byte"));
types.Add(CreateStruct("System", "Int16"));
types.Add(CreateStruct("System", "UInt16"));
types.Add(CreateStruct("System", "Int32"));
types.Add(CreateStruct("System", "UInt32"));
types.Add(CreateStruct("System", "Int64"));
types.Add(CreateStruct("System", "UInt64"));
types.Add(CreateStruct("System", "Single"));
types.Add(CreateStruct("System", "Double"));
types.Add(CreateStruct("System", "Decimal"));
types.Add(CreateStruct("System", "DateTime"));
types.Add(systemValueType); // misuse unused enum value (TypeCode)17 for System.ValueType
types.Add(CreateClass("System", "String"));
foreach (ITypeDefinition type in types)
type.Freeze();
this.types = types.AsReadOnly();
}
ITypeDefinition CreateClass(string nameSpace, string name)
{
return new DefaultTypeDefinition(this, nameSpace, name) {
Kind = TypeKind.Class,
Accessibility = Accessibility.Public,
BaseTypes = { systemObject }
};
}
ITypeDefinition CreateStruct(string nameSpace, string name)
{
return new DefaultTypeDefinition(this, nameSpace, name) {
Kind = TypeKind.Struct,
Accessibility = Accessibility.Public,
BaseTypes = { systemValueType }
};
}
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{
foreach (ITypeDefinition type in types) {
if (nameComparer.Equals(type.Name, name) && nameComparer.Equals(type.Namespace, nameSpace) && type.TypeParameterCount == typeParameterCount)
return type;
}
return null;
}
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
return types[(int)typeCode];
}
public IEnumerable<ITypeDefinition> GetTypes()
{
return types;
}
public IEnumerable<ITypeDefinition> GetTypes(string nameSpace, StringComparer nameComparer)
{
return types.Where(t => nameComparer.Equals(t.Namespace, nameSpace));
}
public IEnumerable<string> GetNamespaces()
{
return namespaces;
}
public string GetNamespace(string nameSpace, StringComparer nameComparer)
{
foreach (string ns in namespaces) {
if (nameComparer.Equals(ns, nameSpace))
return ns;
}
return null;
}
IList<IAttribute> IProjectContent.AssemblyAttributes {
get { return EmptyList<IAttribute>.Instance; }
}
IList<IAttribute> IProjectContent.ModuleAttributes {
get { return EmptyList<IAttribute>.Instance; }
}
ICSharpCode.NRefactory.Utils.CacheManager ITypeResolveContext.CacheManager {
get {
// We don't support caching
return null;
}
}
ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize()
{
// This class is immutable
return this;
}
void IDisposable.Dispose()
{
// exit from Synchronize() block
}
IParsedFile IProjectContent.GetFile(string fileName)
{
return null;
}
IEnumerable<IParsedFile> IProjectContent.Files {
get {
return EmptyList<IParsedFile>.Instance;
}
}
void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile)
{
throw new NotSupportedException();
}
public string AssemblyName {
get { return "MinimalResolveContext"; }
}
}
*/
}

48
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -123,22 +123,22 @@ namespace ICSharpCode.NRefactory.TypeSystem
static readonly KnownTypeReference[] knownTypeReferences = new KnownTypeReference[KnownTypeCodeCount] { static readonly KnownTypeReference[] knownTypeReferences = new KnownTypeReference[KnownTypeCodeCount] {
null, // None null, // None
new KnownTypeReference(KnownTypeCode.Object, "System", "Object"), new KnownTypeReference(KnownTypeCode.Object, "System", "Object", baseType: KnownTypeCode.None),
new KnownTypeReference(KnownTypeCode.DBNull, "System", "DBNull"), new KnownTypeReference(KnownTypeCode.DBNull, "System", "DBNull"),
new KnownTypeReference(KnownTypeCode.Boolean, "System", "Boolean"), new KnownTypeReference(KnownTypeCode.Boolean, "System", "Boolean", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Char, "System", "Char"), new KnownTypeReference(KnownTypeCode.Char, "System", "Char", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.SByte, "System", "SByte"), new KnownTypeReference(KnownTypeCode.SByte, "System", "SByte", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Byte, "System", "Byte"), new KnownTypeReference(KnownTypeCode.Byte, "System", "Byte", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Int16, "System", "Int16"), new KnownTypeReference(KnownTypeCode.Int16, "System", "Int16", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.UInt16, "System", "UInt16"), new KnownTypeReference(KnownTypeCode.UInt16, "System", "UInt16", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Int32, "System", "Int32"), new KnownTypeReference(KnownTypeCode.Int32, "System", "Int32", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.UInt32, "System", "UInt32"), new KnownTypeReference(KnownTypeCode.UInt32, "System", "UInt32", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Int64, "System", "Int64"), new KnownTypeReference(KnownTypeCode.Int64, "System", "Int64", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.UInt64, "System", "UInt64"), new KnownTypeReference(KnownTypeCode.UInt64, "System", "UInt64", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Single, "System", "Single"), new KnownTypeReference(KnownTypeCode.Single, "System", "Single", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Double, "System", "Double"), new KnownTypeReference(KnownTypeCode.Double, "System", "Double", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Decimal, "System", "Decimal"), new KnownTypeReference(KnownTypeCode.Decimal, "System", "Decimal", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.DateTime, "System", "DateTime"), new KnownTypeReference(KnownTypeCode.DateTime, "System", "DateTime", baseType: KnownTypeCode.ValueType),
null, null,
new KnownTypeReference(KnownTypeCode.String, "System", "String"), new KnownTypeReference(KnownTypeCode.String, "System", "String"),
new KnownTypeReference(KnownTypeCode.Void, "System", "Void"), new KnownTypeReference(KnownTypeCode.Void, "System", "Void"),
@ -146,21 +146,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
new KnownTypeReference(KnownTypeCode.Array, "System", "Array"), new KnownTypeReference(KnownTypeCode.Array, "System", "Array"),
new KnownTypeReference(KnownTypeCode.Attribute, "System", "Attribute"), new KnownTypeReference(KnownTypeCode.Attribute, "System", "Attribute"),
new KnownTypeReference(KnownTypeCode.ValueType, "System", "ValueType"), new KnownTypeReference(KnownTypeCode.ValueType, "System", "ValueType"),
new KnownTypeReference(KnownTypeCode.Enum, "System", "Enum"), new KnownTypeReference(KnownTypeCode.Enum, "System", "Enum", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.Delegate, "System", "Delegate"), new KnownTypeReference(KnownTypeCode.Delegate, "System", "Delegate"),
new KnownTypeReference(KnownTypeCode.MulticastDelegate, "System", "MulticastDelegate"), new KnownTypeReference(KnownTypeCode.MulticastDelegate, "System", "MulticastDelegate", baseType: KnownTypeCode.Delegate),
new KnownTypeReference(KnownTypeCode.Exception, "System", "Exception"), new KnownTypeReference(KnownTypeCode.Exception, "System", "Exception"),
new KnownTypeReference(KnownTypeCode.IntPtr, "System", "IntPtr"), new KnownTypeReference(KnownTypeCode.IntPtr, "System", "IntPtr", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.UIntPtr, "System", "UIntPtr"), new KnownTypeReference(KnownTypeCode.UIntPtr, "System", "UIntPtr", baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.IEnumerable, "System.Collections", "IEnumerable"), new KnownTypeReference(KnownTypeCode.IEnumerable, "System.Collections", "IEnumerable"),
new KnownTypeReference(KnownTypeCode.IEnumerator, "System.Collections", "IEnumerator"), new KnownTypeReference(KnownTypeCode.IEnumerator, "System.Collections", "IEnumerator"),
new KnownTypeReference(KnownTypeCode.IEnumerableOfT, "System.Collections.Generic", "IEnumerable", 1), new KnownTypeReference(KnownTypeCode.IEnumerableOfT, "System.Collections.Generic", "IEnumerable", 1),
new KnownTypeReference(KnownTypeCode.IEnumeratorOfT, "System.Collections.Generic", "IEnumerator", 1), new KnownTypeReference(KnownTypeCode.IEnumeratorOfT, "System.Collections.Generic", "IEnumerator", 1),
new KnownTypeReference(KnownTypeCode.IListOfT, "System.Collections.Generic", "IList", 1), new KnownTypeReference(KnownTypeCode.IListOfT, "System.Collections.Generic", "IList", 1),
new KnownTypeReference(KnownTypeCode.Task, "System.Threading.Tasks", "Task"), new KnownTypeReference(KnownTypeCode.Task, "System.Threading.Tasks", "Task"),
new KnownTypeReference(KnownTypeCode.TaskOfT, "System.Threading.Tasks", "Task", 1), new KnownTypeReference(KnownTypeCode.TaskOfT, "System.Threading.Tasks", "Task", 1, baseType: KnownTypeCode.Task),
new KnownTypeReference(KnownTypeCode.NullableOfT, "System", "Nullable", 1), new KnownTypeReference(KnownTypeCode.NullableOfT, "System", "Nullable", 1, baseType: KnownTypeCode.ValueType),
new KnownTypeReference(KnownTypeCode.IDisposable, "System", "IDispoable"), new KnownTypeReference(KnownTypeCode.IDisposable, "System", "IDisposable"),
}; };
/// <summary> /// <summary>
@ -366,13 +366,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
readonly string namespaceName; readonly string namespaceName;
readonly string name; readonly string name;
readonly int typeParameterCount; readonly int typeParameterCount;
internal readonly KnownTypeCode baseType;
private KnownTypeReference(KnownTypeCode knownTypeCode, string namespaceName, string name, int typeParameterCount = 0) private KnownTypeReference(KnownTypeCode knownTypeCode, string namespaceName, string name, int typeParameterCount = 0, KnownTypeCode baseType = KnownTypeCode.Object)
{ {
this.knownTypeCode = knownTypeCode; this.knownTypeCode = knownTypeCode;
this.namespaceName = namespaceName; this.namespaceName = namespaceName;
this.name = name; this.name = name;
this.typeParameterCount = typeParameterCount; this.typeParameterCount = typeParameterCount;
this.baseType = baseType;
} }
public KnownTypeCode KnownTypeCode { public KnownTypeCode KnownTypeCode {

Loading…
Cancel
Save