Browse Source

Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger

newNRvisualizers
Eusebiu Marcu 15 years ago
parent
commit
90f86243f9
  1. 26
      ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs
  2. 28
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  3. 101
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  4. 29
      ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs
  5. 25
      ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  6. 1
      ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs
  7. 1
      ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs
  8. 4
      ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs
  9. 2
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  10. 12
      ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs
  11. 15
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  12. 254
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  13. 5
      ICSharpCode.NRefactory/TypeSystem/IAccessor.cs
  14. 6
      ICSharpCode.NRefactory/TypeSystem/IAttribute.cs
  15. 2
      ICSharpCode.NRefactory/TypeSystem/IMethod.cs
  16. 6
      ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs
  17. 17
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs
  18. 60
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs
  19. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

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

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.CSharp.Analysis
@ -39,7 +40,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); DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(block, CecilLoaderTests.Mscorlib);
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));
@ -89,7 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
TrueStatement = new BlockStatement(), TrueStatement = new BlockStatement(),
FalseStatement = new BlockStatement() FalseStatement = new BlockStatement()
}; };
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt); DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib);
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));
@ -120,7 +121,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
TrueStatement = new BlockStatement(), TrueStatement = new BlockStatement(),
FalseStatement = new BlockStatement() FalseStatement = new BlockStatement()
}; };
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt); DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib);
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));
@ -128,5 +129,24 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.FalseStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.FalseStatement));
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt));
} }
[Test]
public void WhileTrue()
{
WhileStatement loop = new WhileStatement {
Condition = new PrimitiveExpression(true),
EmbeddedStatement = new BlockStatement {
new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)),
new BreakStatement()
}
};
DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib);
da.Analyze("i");
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement));
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(loop.EmbeddedStatement));
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop));
}
} }
} }

28
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
[assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute( [assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute(
42, typeof(System.Action<>), typeof(IDictionary<string, IList<NUnit.Framework.TestAttribute>>))] 42, typeof(System.Action<>), typeof(IDictionary<string, IList<NUnit.Framework.TestAttribute>>))]
@ -65,4 +66,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
{ {
public MyStructWithCtor(int a) {} public MyStructWithCtor(int a) {}
} }
[Serializable]
public class NonCustomAttributes
{
[NonSerialized]
public readonly int NonSerializedField;
[DllImport("unmanaged.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DllMethod([In, Out] ref int p);
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8)]
public struct ExplicitFieldLayoutStruct
{
[FieldOffset(0)]
public int Field0;
[FieldOffset(100)]
public int Field100;
}
public class ParameterTests
{
public void MethodWithOutParameter(out int x) { x = 0; }
public void MethodWithParamsArray(params object[] x) {}
}
} }

101
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.TypeSystem.TestCase; using ICSharpCode.NRefactory.TypeSystem.TestCase;
using NUnit.Framework; using NUnit.Framework;
@ -261,5 +262,105 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(2, ctors.Count()); Assert.AreEqual(2, ctors.Count());
Assert.IsFalse(ctors.Any(c => c.IsStatic)); Assert.IsFalse(ctors.Any(c => c.IsStatic));
} }
[Test]
public void SerializableAttribute()
{
IAttribute attr = ctx.GetClass(typeof(NonCustomAttributes)).Attributes.Single();
Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.Resolve(ctx).FullName);
}
[Test]
public void NonSerializedAttribute()
{
IField field = ctx.GetClass(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField");
Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
}
[Test]
public void ExplicitStructLayoutAttribute()
{
IAttribute attr = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName);
IConstantValue arg1 = attr.PositionalArguments.Single();
Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.GetValueType(ctx).FullName);
Assert.AreEqual((int)LayoutKind.Explicit, arg1.GetValue(ctx));
var arg2 = attr.NamedArguments[0];
Assert.AreEqual("CharSet", arg2.Key);
Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.GetValueType(ctx).FullName);
Assert.AreEqual((int)CharSet.Unicode, arg2.Value.GetValue(ctx));
var arg3 = attr.NamedArguments[1];
Assert.AreEqual("Pack", arg3.Key);
Assert.AreEqual("System.Int32", arg3.Value.GetValueType(ctx).FullName);
Assert.AreEqual(8, arg3.Value.GetValue(ctx));
}
[Test]
public void FieldOffsetAttribute()
{
IField field = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
IConstantValue arg = field.Attributes.Single().PositionalArguments.Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName);
Assert.AreEqual(0, arg.GetValue(ctx));
field = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
arg = field.Attributes.Single().PositionalArguments.Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName);
Assert.AreEqual(100, arg.GetValue(ctx));
}
[Test]
public void DllImportAttribute()
{
IMethod method = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute dllImport = method.Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName);
Assert.AreEqual("unmanaged.dll", dllImport.PositionalArguments[0].GetValue(ctx));
Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value.GetValue(ctx));
}
[Test]
public void InOutParametersOnRefMethod()
{
IParameter p = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single();
Assert.IsTrue(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.AreEqual(2, p.Attributes.Count);
Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.Resolve(ctx).FullName);
Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.Resolve(ctx).FullName);
}
[Test]
public void MarshalAsAttributeOnMethod()
{
IMethod method = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute marshalAs = method.ReturnTypeAttributes.Single();
Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.PositionalArguments.Single().GetValue(ctx));
}
[Test]
public void MethodWithOutParameter()
{
IParameter p = ctx.GetClass(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single();
Assert.IsFalse(p.IsRef);
Assert.IsTrue(p.IsOut);
Assert.AreEqual(0, p.Attributes.Count);
Assert.IsTrue(p.Type is ByReferenceTypeReference);
}
[Test]
public void MethodWithParamsArray()
{
IParameter p = ctx.GetClass(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single();
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsTrue(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count);
Assert.IsTrue(p.Type is ArrayTypeReference);
}
} }
} }

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

@ -5,7 +5,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.CSharp.Analysis
{ {
@ -135,12 +138,24 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
} }
Statement rootStatement; Statement rootStatement;
ResolveVisitor resolveVisitor;
List<ControlFlowNode> nodes; List<ControlFlowNode> nodes;
Dictionary<string, ControlFlowNode> labels; Dictionary<string, ControlFlowNode> labels;
List<ControlFlowNode> gotoStatements; List<ControlFlowNode> gotoStatements;
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement) public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken))
{ {
return BuildControlFlowGraph(statement, new ResolveVisitor(
new CSharpResolver(context, cancellationToken), null, ConstantModeResolveVisitorNavigator.Skip));
}
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor)
{
if (statement == null)
throw new ArgumentNullException("statement");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor(); NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor();
nodeCreationVisitor.builder = this; nodeCreationVisitor.builder = this;
try { try {
@ -148,6 +163,7 @@ 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;
ControlFlowNode entryPoint = CreateStartNode(statement); ControlFlowNode entryPoint = CreateStartNode(statement);
statement.AcceptVisitor(nodeCreationVisitor, entryPoint); statement.AcceptVisitor(nodeCreationVisitor, entryPoint);
@ -167,6 +183,7 @@ 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;
} }
} }
@ -206,7 +223,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
ControlFlowNode CreateSpecialNode(Statement statement, ControlFlowNodeType type) ControlFlowNode CreateSpecialNode(Statement statement, ControlFlowNodeType type)
{ {
ControlFlowNode node = CreateNode(statement, null, type); ControlFlowNode node = CreateNode(null, statement, type);
nodes.Add(node); nodes.Add(node);
return node; return node;
} }
@ -238,7 +255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <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) ConstantResolveResult EvaluateConstant(Expression expr)
{ {
return null; // TODO: implement this using the C# resolver return resolveVisitor.Resolve(expr) as ConstantResolveResult;
} }
/// <summary> /// <summary>
@ -256,7 +273,11 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2) bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2)
{ {
return false; // TODO: implement this using the resolver's operator== if (c1 == null || c2 == null)
return false;
CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken);
ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2);
return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true;
} }
#endregion #endregion

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

@ -5,7 +5,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.CSharp.Analysis
@ -46,6 +48,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
readonly List<ControlFlowNode> allNodes = new List<ControlFlowNode>(); readonly List<ControlFlowNode> allNodes = new List<ControlFlowNode>();
readonly Dictionary<Statement, ControlFlowNode> beginNodeDict = new Dictionary<Statement, ControlFlowNode>(); readonly Dictionary<Statement, ControlFlowNode> beginNodeDict = new Dictionary<Statement, ControlFlowNode>();
readonly Dictionary<Statement, ControlFlowNode> endNodeDict = new Dictionary<Statement, ControlFlowNode>(); readonly Dictionary<Statement, ControlFlowNode> endNodeDict = new Dictionary<Statement, ControlFlowNode>();
readonly ResolveVisitor resolveVisitor;
readonly CancellationToken cancellationToken;
Dictionary<ControlFlowNode, DefiniteAssignmentStatus> nodeStatus = new Dictionary<ControlFlowNode, DefiniteAssignmentStatus>(); Dictionary<ControlFlowNode, DefiniteAssignmentStatus> nodeStatus = new Dictionary<ControlFlowNode, DefiniteAssignmentStatus>();
Dictionary<ControlFlowEdge, DefiniteAssignmentStatus> edgeStatus = new Dictionary<ControlFlowEdge, DefiniteAssignmentStatus>(); Dictionary<ControlFlowEdge, DefiniteAssignmentStatus> edgeStatus = new Dictionary<ControlFlowEdge, DefiniteAssignmentStatus>();
@ -54,19 +58,30 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Queue<ControlFlowNode> nodesWithModifiedInput = new Queue<ControlFlowNode>(); Queue<ControlFlowNode> nodesWithModifiedInput = new Queue<ControlFlowNode>();
public DefiniteAssignmentAnalysis(Statement rootStatement) public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken))
: this(rootStatement, new ResolveVisitor(new CSharpResolver(context, cancellationToken), null, ConstantModeResolveVisitorNavigator.Skip))
{ {
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor)
{
if (rootStatement == null)
throw new ArgumentNullException("rootStatement");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
this.resolveVisitor = resolveVisitor;
this.cancellationToken = resolveVisitor.CancellationToken;
visitor.analysis = this; visitor.analysis = this;
ControlFlowGraphBuilder b = new ControlFlowGraphBuilder(); ControlFlowGraphBuilder b = new ControlFlowGraphBuilder();
allNodes.AddRange(b.BuildControlFlowGraph(rootStatement)); allNodes.AddRange(b.BuildControlFlowGraph(rootStatement, resolveVisitor));
foreach (AstNode descendant in rootStatement.Descendants) { foreach (AstNode descendant in rootStatement.Descendants) {
// 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.
AnonymousMethodExpression ame = descendant as AnonymousMethodExpression; AnonymousMethodExpression ame = descendant as AnonymousMethodExpression;
if (ame != null) if (ame != null)
allNodes.AddRange(b.BuildControlFlowGraph(ame.Body)); allNodes.AddRange(b.BuildControlFlowGraph(ame.Body, resolveVisitor));
LambdaExpression lambda = descendant as LambdaExpression; LambdaExpression lambda = descendant as LambdaExpression;
if (lambda != null && lambda.Body is Statement) if (lambda != null && lambda.Body is Statement)
allNodes.AddRange(b.BuildControlFlowGraph((Statement)lambda.Body)); allNodes.AddRange(b.BuildControlFlowGraph((Statement)lambda.Body, resolveVisitor));
} }
// Verify that we created nodes for all statements: // Verify that we created nodes for all statements:
Debug.Assert(!rootStatement.DescendantsAndSelf.OfType<Statement>().Except(allNodes.Select(n => n.NextStatement)).Any()); Debug.Assert(!rootStatement.DescendantsAndSelf.OfType<Statement>().Except(allNodes.Select(n => n.NextStatement)).Any());
@ -289,7 +304,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <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) ConstantResolveResult EvaluateConstant(Expression expr)
{ {
return null; // TODO: implement this using the C# resolver return resolveVisitor.Resolve(expr) as ConstantResolveResult;
} }
/// <summary> /// <summary>

1
ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

@ -129,6 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { get {
AstNode next; AstNode next;
for (AstNode cur = firstChild; cur != null; cur = next) { for (AstNode cur = firstChild; cur != null; cur = next) {
Debug.Assert(cur.parent == this);
// Remember next before yielding cur. // Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list. // This allows removing/replacing nodes while iterating through the list.
next = cur.nextSibling; next = cur.nextSibling;

1
ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs

@ -117,6 +117,7 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
AstNode next; AstNode next;
for (AstNode cur = node.FirstChild; cur != null; cur = next) { for (AstNode cur = node.FirstChild; cur != null; cur = next) {
Debug.Assert(cur.Parent == node);
// Remember next before yielding cur. // Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list. // This allows removing/replacing nodes while iterating through the list.
next = cur.NextSibling; next = cur.NextSibling;

4
ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs

@ -374,9 +374,9 @@ namespace ICSharpCode.NRefactory.CSharp
variable.AddChild (new Identifier (em.Name, Convert (em.Location)), AstNode.Roles.Identifier); variable.AddChild (new Identifier (em.Name, Convert (em.Location)), AstNode.Roles.Identifier);
if (em.Initializer != null) { if (em.Initializer != null) {
var initializer = (VariableInitializer)em.Initializer.Accept (this); var initializer = (Expression)em.Initializer.Accept (this);
if (initializer != null) if (initializer != null)
variable.AddChild (initializer, AstNode.Roles.Variable); variable.AddChild (initializer, EnumMemberDeclaration.InitializerRole);
} }
newField.AddChild (variable, AstNode.Roles.Variable); newField.AddChild (variable, AstNode.Roles.Variable);

2
ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs

@ -33,7 +33,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.context = context; this.context = context;
} }
#if !DOTNET35
public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken) public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken)
{ {
if (context == null) if (context == null)
@ -41,7 +40,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.context = context; this.context = context;
this.cancellationToken = cancellationToken; this.cancellationToken = cancellationToken;
} }
#endif
#endregion #endregion
#region Properties #region Properties

12
ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs

@ -37,4 +37,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
ResolveAll ResolveAll
} }
sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator
{
ResolveVisitorNavigationMode mode;
public static readonly IResolveVisitorNavigator Skip = new ConstantModeResolveVisitorNavigator { mode = ResolveVisitorNavigationMode.Skip };
ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node)
{
return mode;
}
}
} }

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

@ -74,6 +74,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
#endregion #endregion
/// <summary>
/// Gets the TypeResolveContext used by this ResolveVisitor.
/// </summary>
public ITypeResolveContext TypeResolveContext {
get { return resolver.Context; }
}
/// <summary>
/// Gets the CancellationToken used by this ResolveVisitor.
/// </summary>
public CancellationToken CancellationToken {
get { return resolver.cancellationToken; }
}
#region Scan / Resolve #region Scan / Resolve
bool resolverEnabled { bool resolverEnabled {
get { return mode != ResolveVisitorNavigationMode.Scan; } get { return mode != ResolveVisitorNavigationMode.Scan; }
@ -118,6 +132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
mode = ResolveVisitorNavigationMode.Resolve; mode = ResolveVisitorNavigationMode.Resolve;
ResolveResult result; ResolveResult result;
if (!cache.TryGetValue(node, out result)) { if (!cache.TryGetValue(node, out result)) {
resolver.cancellationToken.ThrowIfCancellationRequested();
result = cache[node] = node.AcceptVisitor(this, null) ?? errorResult; result = cache[node] = node.AcceptVisitor(this, null) ?? errorResult;
} }
if (wasScan) if (wasScan)

254
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -46,6 +46,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion #endregion
#region Load From AssemblyDefinition #region Load From AssemblyDefinition
/// <summary>
/// Loads the assembly definition into a project content.
/// </summary>
/// <returns>IProjectContent that represents the assembly</returns>
public IProjectContent LoadAssembly(AssemblyDefinition assemblyDefinition) public IProjectContent LoadAssembly(AssemblyDefinition assemblyDefinition)
{ {
if (assemblyDefinition == null) if (assemblyDefinition == null)
@ -144,7 +148,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void Dispose() public void Dispose()
{ {
// Disposibng the synchronization context has no effect // Disposing the synchronization context has no effect
} }
string IDocumentationProvider.GetDocumentation(IEntity entity) string IDocumentationProvider.GetDocumentation(IEntity entity)
@ -297,14 +301,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
{ {
if (attributeProvider == null || !attributeProvider.HasCustomAttributes) if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
return false; return false;
foreach (CustomAttribute a in attributeProvider.CustomAttributes) { foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) { TypeReference type = a.AttributeType;
if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") {
if (a.ConstructorArguments.Count == 1) { if (a.ConstructorArguments.Count == 1) {
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
@ -325,21 +328,150 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
static readonly IAttribute inAttribute = new DefaultAttribute(typeof(InAttribute).ToTypeReference(), null);
static readonly IAttribute outAttribute = new DefaultAttribute(typeof(OutAttribute).ToTypeReference(), null);
void AddAttributes(ParameterDefinition parameter, DefaultParameter targetParameter) void AddAttributes(ParameterDefinition parameter, DefaultParameter targetParameter)
{ {
if (!targetParameter.IsOut) {
if (parameter.IsIn)
targetParameter.Attributes.Add(inAttribute);
if (parameter.IsOut)
targetParameter.Attributes.Add(outAttribute);
}
if (parameter.HasCustomAttributes) { if (parameter.HasCustomAttributes) {
AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes); AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes);
} }
} }
void AddAttributes(MethodDefinition accessorMethod, DefaultAccessor targetAccessor) static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference();
static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference();
static readonly IAttribute preserveSigAttribute = new DefaultAttribute(typeof(PreserveSigAttribute).ToTypeReference(), null);
static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference();
static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference();
bool HasAnyAttributes(MethodDefinition methodDefinition)
{ {
if (accessorMethod.HasCustomAttributes) { if (methodDefinition.HasPInvokeInfo)
AddCustomAttributes(accessorMethod.CustomAttributes, targetAccessor.Attributes); return true;
if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0)
return true;
if (methodDefinition.MethodReturnType.HasFieldMarshal)
return true;
return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes;
}
void AddAttributes(MethodDefinition methodDefinition, IList<IAttribute> attributes, IList<IAttribute> returnTypeAttributes)
{
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
#region DllImportAttribute
if (methodDefinition.HasPInvokeInfo) {
PInvokeInfo info = methodDefinition.PInvokeInfo;
DefaultAttribute dllImport = new DefaultAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name));
if (info.IsBestFitDisabled)
AddNamedArgument(dllImport, "BestFitMapping", falseValue);
if (info.IsBestFitEnabled)
AddNamedArgument(dllImport, "BestFitMapping", trueValue);
CallingConvention callingConvention;
switch (info.Attributes & PInvokeAttributes.CallConvMask) {
case PInvokeAttributes.CallConvCdecl:
callingConvention = CallingConvention.Cdecl;
break;
case PInvokeAttributes.CallConvFastcall:
callingConvention = CallingConvention.FastCall;
break;
case PInvokeAttributes.CallConvStdCall:
callingConvention = CallingConvention.StdCall;
break;
case PInvokeAttributes.CallConvThiscall:
callingConvention = CallingConvention.ThisCall;
break;
case PInvokeAttributes.CallConvWinapi:
callingConvention = CallingConvention.Winapi;
break;
default:
throw new NotSupportedException("unknown calling convention");
}
if (callingConvention != CallingConvention.Winapi)
AddNamedArgument(dllImport, "CallingConvention", new SimpleConstantValue(callingConventionTypeRef, (int)callingConvention));
CharSet charSet = CharSet.None;
switch (info.Attributes & PInvokeAttributes.CharSetMask) {
case PInvokeAttributes.CharSetAnsi:
charSet = CharSet.Ansi;
break;
case PInvokeAttributes.CharSetAuto:
charSet = CharSet.Auto;
break;
case PInvokeAttributes.CharSetUnicode:
charSet = CharSet.Unicode;
break;
}
if (charSet != CharSet.None)
dllImport.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(
"CharSet", new SimpleConstantValue(charSetTypeRef, (int)charSet)));
if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
AddNamedArgument(dllImport, "EntryPoint", new SimpleConstantValue(KnownTypeReference.String, info.EntryPoint));
if (info.IsNoMangle)
AddNamedArgument(dllImport, "ExactSpelling", trueValue);
if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
implAttributes &= ~MethodImplAttributes.PreserveSig;
else
AddNamedArgument(dllImport, "PreserveSig", falseValue);
if (info.SupportsLastError)
AddNamedArgument(dllImport, "SetLastError", trueValue);
if (info.IsThrowOnUnmappableCharDisabled)
AddNamedArgument(dllImport, "ThrowOnUnmappableChar", falseValue);
if (info.IsThrowOnUnmappableCharEnabled)
AddNamedArgument(dllImport, "ThrowOnUnmappableChar", trueValue);
attributes.Add(dllImport);
}
#endregion
#region PreserveSigAttribute
if (implAttributes == MethodImplAttributes.PreserveSig) {
attributes.Add(preserveSigAttribute);
implAttributes = 0;
}
#endregion
#region MethodImplAttribute
if (implAttributes != 0) {
DefaultAttribute methodImpl = new DefaultAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef });
methodImpl.PositionalArguments.Add(new SimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes));
attributes.Add(methodImpl);
}
#endregion
if (methodDefinition.HasCustomAttributes) {
AddCustomAttributes(methodDefinition.CustomAttributes, attributes);
}
if (methodDefinition.MethodReturnType.HasMarshalInfo) {
returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo));
} }
if (methodDefinition.MethodReturnType.HasCustomAttributes) {
AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes);
}
}
static void AddNamedArgument(DefaultAttribute attribute, string name, IConstantValue value)
{
attribute.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(name, value));
} }
static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference()); static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference(), null);
static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference(); static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference();
static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference(); static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference();
static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference(); static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference();
@ -373,8 +505,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
charSet = CharSet.Unicode; charSet = CharSet.Unicode;
break; break;
} }
if (layoutKind != LayoutKind.Auto || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
DefaultAttribute structLayout = new DefaultAttribute(structLayoutAttributeTypeRef); if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
DefaultAttribute structLayout = new DefaultAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef });
structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind));
if (charSet != CharSet.Ansi) { if (charSet != CharSet.Ansi) {
structLayout.NamedArguments.Add(new KeyValuePair<string, IConstantValue>( structLayout.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(
@ -400,12 +533,58 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference();
static readonly DefaultAttribute nonSerializedAttribute = new DefaultAttribute(typeof(NonSerializedAttribute).ToTypeReference(), null);
void AddAttributes(FieldDefinition fieldDefinition, IEntity targetEntity)
{
#region FieldOffsetAttribute
if (fieldDefinition.HasLayoutInfo) {
DefaultAttribute fieldOffset = new DefaultAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 });
fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset));
targetEntity.Attributes.Add(fieldOffset);
}
#endregion
#region NonSerializedAttribute
if (fieldDefinition.IsNotSerialized) {
targetEntity.Attributes.Add(nonSerializedAttribute);
}
#endregion
if (fieldDefinition.HasMarshalInfo) {
targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo));
}
if (fieldDefinition.HasCustomAttributes) {
AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes);
}
}
#region MarshalAsAttribute (ConvertMarshalInfo)
static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference();
static IAttribute ConvertMarshalInfo(MarshalInfo marshalInfo)
{
DefaultAttribute attr = new DefaultAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef });
attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType));
// TODO: handle classes derived from MarshalInfo
return attr;
}
#endregion
void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IAttribute> targetCollection) void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IAttribute> targetCollection)
{ {
foreach (var cecilAttribute in attributes) { foreach (var cecilAttribute in attributes) {
if (cecilAttribute.AttributeType.FullName != DynamicAttributeFullName) { TypeReference type = cecilAttribute.AttributeType;
targetCollection.Add(ReadAttribute(cecilAttribute)); if (type.Namespace == "System.Runtime.CompilerServices") {
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute")
continue;
} else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
continue;
} }
targetCollection.Add(ReadAttribute(cecilAttribute));
} }
} }
@ -413,7 +592,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
if (attribute == null) if (attribute == null)
throw new ArgumentNullException("attribute"); throw new ArgumentNullException("attribute");
DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType)); MethodReference ctor = attribute.Constructor;
ITypeReference[] ctorParameters = null;
if (ctor.HasParameters) {
ctorParameters = new ITypeReference[ctor.Parameters.Count];
for (int i = 0; i < ctorParameters.Length; i++) {
ctorParameters[i] = ReadTypeReference(ctor.Parameters[i].ParameterType);
}
}
DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType), ctorParameters);
try { try {
if (attribute.HasConstructorArguments) { if (attribute.HasConstructorArguments) {
foreach (var arg in attribute.ConstructorArguments) { foreach (var arg in attribute.ConstructorArguments) {
@ -442,8 +629,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Read Constant Value #region Read Constant Value
public IConstantValue ReadConstantValue(CustomAttributeArgument arg) public IConstantValue ReadConstantValue(CustomAttributeArgument arg)
{ {
ITypeReference type = ReadTypeReference(arg.Type);
object value = arg.Value; object value = arg.Value;
if (value is CustomAttributeArgument) {
// Cecil uses this representation for boxed values
arg = (CustomAttributeArgument)value;
value = arg.Value;
}
ITypeReference type = ReadTypeReference(arg.Type);
CustomAttributeArgument[] array = value as CustomAttributeArgument[]; CustomAttributeArgument[] array = value as CustomAttributeArgument[];
if (array != null) { if (array != null) {
// TODO: write unit test for this // TODO: write unit test for this
@ -500,9 +692,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
InitNestedTypes(loader); // nested types can be initialized only after generic parameters were created InitNestedTypes(loader); // nested types can be initialized only after generic parameters were created
if (typeDefinition.HasCustomAttributes) {
loader.AddAttributes(typeDefinition, this); loader.AddAttributes(typeDefinition, this);
}
this.HasExtensionMethods = HasExtensionAttribute(typeDefinition);
// set base classes // set base classes
if (typeDefinition.IsEnum) { if (typeDefinition.IsEnum) {
@ -699,7 +891,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
else else
m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType, entity: m); m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType, entity: m);
AddAttributes(method, m); if (HasAnyAttributes(method))
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
TranslateModifiers(method, m); TranslateModifiers(method, m);
if (method.HasParameters) { if (method.HasParameters) {
@ -708,18 +901,26 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
// mark as extension method is the attribute is set // mark as extension method if the attribute is set
if (method.IsStatic && method.HasCustomAttributes) { if (method.IsStatic && HasExtensionAttribute(method)) {
foreach (var attr in method.CustomAttributes) {
if (attr.AttributeType.FullName == typeof(ExtensionAttribute).FullName)
m.IsExtensionMethod = true; m.IsExtensionMethod = true;
} }
}
FinishReadMember(m); FinishReadMember(m);
return m; return m;
} }
static bool HasExtensionAttribute(ICustomAttributeProvider provider)
{
if (provider.HasCustomAttributes) {
foreach (var attr in provider.CustomAttributes) {
if (attr.AttributeType.Name == "ExtensionAttribute" && attr.AttributeType.Namespace == "System.Runtime.CompilerServices")
return true;
}
}
return false;
}
bool IsVisible(MethodAttributes att) bool IsVisible(MethodAttributes att)
{ {
att &= MethodAttributes.MemberAccessMask; att &= MethodAttributes.MemberAccessMask;
@ -782,14 +983,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember); var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember);
DefaultParameter p = new DefaultParameter(type, parameter.Name); DefaultParameter p = new DefaultParameter(type, parameter.Name);
AddAttributes(parameter, p);
if (parameter.ParameterType is Mono.Cecil.ByReferenceType) { if (parameter.ParameterType is Mono.Cecil.ByReferenceType) {
if (parameter.IsOut) if (!parameter.IsIn && parameter.IsOut)
p.IsOut = true; p.IsOut = true;
else else
p.IsRef = true; p.IsRef = true;
} }
AddAttributes(parameter, p);
if (parameter.IsOptional) { if (parameter.IsOptional) {
p.DefaultValue = ReadConstantValue(new CustomAttributeArgument(parameter.ParameterType, parameter.Constant)); p.DefaultValue = ReadConstantValue(new CustomAttributeArgument(parameter.ParameterType, parameter.Constant));
@ -917,10 +1117,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
if (accessorMethod != null && IsVisible(accessorMethod.Attributes)) { if (accessorMethod != null && IsVisible(accessorMethod.Attributes)) {
Accessibility accessibility = GetAccessibility(accessorMethod.Attributes); Accessibility accessibility = GetAccessibility(accessorMethod.Attributes);
if (accessorMethod.HasCustomAttributes) { if (HasAnyAttributes(accessorMethod)) {
DefaultAccessor a = new DefaultAccessor(); DefaultAccessor a = new DefaultAccessor();
a.Accessibility = accessibility; a.Accessibility = accessibility;
AddAttributes(accessorMethod, a); AddAttributes(accessorMethod, a.Attributes, a.ReturnTypeAttributes);
return a; return a;
} else { } else {
return DefaultAccessor.GetFromAccessibility(accessibility); return DefaultAccessor.GetFromAccessibility(accessibility);

5
ICSharpCode.NRefactory/TypeSystem/IAccessor.cs

@ -21,6 +21,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary> /// </summary>
IList<IAttribute> Attributes { get; } IList<IAttribute> Attributes { get; }
/// <summary>
/// Gets the attributes defined on the return type of the accessor. (e.g. [return: MarshalAs(...)])
/// </summary>
IList<IAttribute> ReturnTypeAttributes { get; }
/// <summary> /// <summary>
/// Gets the accessibility of this accessor. /// Gets the accessibility of this accessor.
/// </summary> /// </summary>

6
ICSharpCode.NRefactory/TypeSystem/IAttribute.cs

@ -35,6 +35,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the named arguments passed to the attribute. /// Gets the named arguments passed to the attribute.
/// </summary> /// </summary>
IList<KeyValuePair<string, IConstantValue>> NamedArguments { get; } IList<KeyValuePair<string, IConstantValue>> NamedArguments { get; }
/// <summary>
/// Resolves the constructor method used for this attribute invocation.
/// Returns null if the constructor cannot be found.
/// </summary>
IMethod ResolveConstructor(ITypeResolveContext context);
} }
#if WITH_CONTRACTS #if WITH_CONTRACTS

2
ICSharpCode.NRefactory/TypeSystem/IMethod.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public interface IMethod : IParameterizedMember public interface IMethod : IParameterizedMember
{ {
/// <summary> /// <summary>
/// Gets the attributes associated with the return type. /// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)])
/// </summary> /// </summary>
IList<IAttribute> ReturnTypeAttributes { get; } IList<IAttribute> ReturnTypeAttributes { get; }

6
ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs

@ -44,6 +44,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets all members declared in this class. This is the union of Fields,Properties,Methods and Events. /// Gets all members declared in this class. This is the union of Fields,Properties,Methods and Events.
/// </summary> /// </summary>
IEnumerable<IMember> Members { get; } IEnumerable<IMember> Members { get; }
/// <summary>
/// Gets whether this type contains extension methods.
/// </summary>
/// <remarks>This property is used to speed up the search for extension methods.</remarks>
bool HasExtensionMethods { get; }
} }
#if WITH_CONTRACTS #if WITH_CONTRACTS

17
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs

@ -44,6 +44,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
Accessibility accessibility; Accessibility accessibility;
DomRegion region; DomRegion region;
IList<IAttribute> attributes; IList<IAttribute> attributes;
IList<IAttribute> returnTypeAttributes;
protected override void FreezeInternal() protected override void FreezeInternal()
{ {
@ -75,20 +76,32 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public IList<IAttribute> ReturnTypeAttributes {
get {
if (returnTypeAttributes == null)
returnTypeAttributes = new List<IAttribute>();
return returnTypeAttributes;
}
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider) void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{ {
attributes = provider.InternList(attributes); attributes = provider.InternList(attributes);
returnTypeAttributes = provider.InternList(returnTypeAttributes);
} }
int ISupportsInterning.GetHashCodeForInterning() int ISupportsInterning.GetHashCodeForInterning()
{ {
return (attributes != null ? attributes.GetHashCode() : 0) ^ region.GetHashCode() ^ (int)accessibility; return (attributes != null ? attributes.GetHashCode() : 0)
^ (returnTypeAttributes != null ? returnTypeAttributes.GetHashCode() : 0)
^ region.GetHashCode() ^ (int)accessibility;
} }
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{ {
DefaultAccessor a = other as DefaultAccessor; DefaultAccessor a = other as DefaultAccessor;
return a != null && (attributes == a.attributes && accessibility == a.accessibility && region == a.region); return a != null && (attributes == a.attributes && returnTypeAttributes == a.returnTypeAttributes
&& accessibility == a.accessibility && region == a.region);
} }
} }
} }

60
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -13,8 +14,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary> /// </summary>
public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning
{ {
DomRegion region;
ITypeReference attributeType; ITypeReference attributeType;
readonly ITypeReference[] constructorParameterTypes;
DomRegion region;
IList<IConstantValue> positionalArguments; IList<IConstantValue> positionalArguments;
IList<KeyValuePair<string, IConstantValue>> namedArguments; IList<KeyValuePair<string, IConstantValue>> namedArguments;
@ -34,26 +36,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
base.FreezeInternal(); base.FreezeInternal();
} }
public DefaultAttribute(ITypeReference attributeType) public DefaultAttribute(ITypeReference attributeType, IEnumerable<ITypeReference> constructorParameterTypes)
{ {
if (attributeType == null) if (attributeType == null)
throw new ArgumentNullException("attributeType"); throw new ArgumentNullException("attributeType");
this.attributeType = attributeType; this.attributeType = attributeType;
this.constructorParameterTypes = constructorParameterTypes != null ? constructorParameterTypes.ToArray() : null;
} }
public DomRegion Region { public ITypeReference AttributeType {
get { return region; } get { return attributeType; }
set {
CheckBeforeMutation();
region = value;
} }
public ReadOnlyCollection<ITypeReference> ConstructorParameterTypes {
get { return Array.AsReadOnly(constructorParameterTypes); }
} }
public ITypeReference AttributeType { public DomRegion Region {
get { return attributeType; } get { return region; }
set { set {
CheckBeforeMutation(); CheckBeforeMutation();
attributeType = value; region = value;
} }
} }
@ -73,6 +76,38 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public IMethod ResolveConstructor(ITypeResolveContext context)
{
IType[] parameterTypes = null;
if (constructorParameterTypes != null && constructorParameterTypes.Length > 0) {
parameterTypes = new IType[constructorParameterTypes.Length];
for (int i = 0; i < parameterTypes.Length; i++) {
parameterTypes[i] = constructorParameterTypes[i].Resolve(context);
}
}
IMethod bestMatch = null;
foreach (IMethod ctor in attributeType.Resolve(context).GetConstructors(context)) {
if (ctor.IsStatic)
continue;
if (parameterTypes == null) {
if (ctor.Parameters.Count == 0)
return ctor;
} else if (ctor.Parameters.Count == parameterTypes.Length) {
bestMatch = ctor;
bool ok = true;
for (int i = 0; i < parameterTypes.Length; i++) {
if (ctor.Parameters[i].Type != parameterTypes[i]) {
ok = false;
break;
}
}
if (ok)
return ctor;
}
}
return bestMatch;
}
public override string ToString() public override string ToString()
{ {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
@ -100,6 +135,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
void ISupportsInterning.PrepareForInterning(IInterningProvider provider) void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{ {
attributeType = provider.Intern(attributeType); attributeType = provider.Intern(attributeType);
if (constructorParameterTypes != null) {
for (int i = 0; i < constructorParameterTypes.Length; i++) {
constructorParameterTypes[i] = provider.Intern(constructorParameterTypes[i]);
}
}
positionalArguments = provider.InternList(positionalArguments); positionalArguments = provider.InternList(positionalArguments);
} }

9
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -40,6 +40,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
const ushort FlagShadowing = 0x0004; const ushort FlagShadowing = 0x0004;
const ushort FlagSynthetic = 0x0008; const ushort FlagSynthetic = 0x0008;
const ushort FlagAddDefaultConstructorIfRequired = 0x0010; const ushort FlagAddDefaultConstructorIfRequired = 0x0010;
const ushort FlagHasExtensionMethods = 0x0020;
protected override void FreezeInternal() protected override void FreezeInternal()
{ {
@ -312,6 +313,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public bool HasExtensionMethods {
get { return flags[FlagHasExtensionMethods]; }
set {
CheckBeforeMutation();
flags[FlagHasExtensionMethods] = value;
}
}
public IProjectContent ProjectContent { public IProjectContent ProjectContent {
get { return projectContent; } get { return projectContent; }
} }

Loading…
Cancel
Save