Browse Source

Merge remote-tracking branch 'upstream/master' into mansheng

newNRvisualizers
Mansheng Yang 14 years ago
parent
commit
4bc84b0f9f
  1. 13
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  2. 20
      ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  3. 21
      ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  4. 8
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  5. 121
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  6. 4
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  7. 11
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  8. 48
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  9. 4
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  10. 11
      ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
  11. 8
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  12. 1
      ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
  13. 376
      ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
  14. 2
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  15. 11
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  16. 32
      ICSharpCode.NRefactory/Editor/IDocument.cs
  17. 15
      ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs
  18. 28
      ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs
  19. 7
      ICSharpCode.NRefactory/Editor/StringTextSource.cs
  20. 30
      ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs
  21. 11
      ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs
  22. 10
      ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs
  23. 16
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  24. 17
      ICSharpCode.NRefactory/TypeSystem/IMethod.cs
  25. 14
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs
  26. 32
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs
  27. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  28. 23
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  29. 10
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

13
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -2256,18 +2256,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2256,18 +2256,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return;
}
string typeString = GetShortType(resolvedType, state);
if (typeString.Contains(".")) {
completionList.AddType(resolvedType, typeString);
}
foreach (var field in resolvedType.GetFields ()) {
if (field.IsConst || field.IsStatic) {
completionList.Result.Add(factory.CreateEntityCompletionData(
field,
typeString + "." + field.Name
)
);
}
}
completionList.AddEnumMembers (resolvedType, state, typeString);
DefaultCompletionString = typeString;
}

20
ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs

@ -28,6 +28,7 @@ using System.Collections.Generic; @@ -28,6 +28,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
@ -239,6 +240,25 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -239,6 +240,25 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return 1;
}
}
HashSet<IType> addedEnums = new HashSet<IType> ();
public void AddEnumMembers (IType resolvedType, CSharpResolver state, string typeString)
{
if (addedEnums.Contains (resolvedType))
return;
addedEnums.Add (resolvedType);
if (typeString.Contains(".")) {
AddType(resolvedType, typeString);
}
foreach (var field in resolvedType.GetFields ()) {
if (field.IsPublic && (field.IsConst || field.IsStatic)) {
Result.Add(Factory.CreateEntityCompletionData(
field,
typeString + "." + field.Name
)
);
}
}
}
}
}

21
ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -97,6 +97,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -97,6 +97,11 @@ namespace ICSharpCode.NRefactory.CSharp
get;
set;
}
public DomRegion FormattingRegion {
get;
set;
}
public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null)
{
@ -111,6 +116,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -111,6 +116,22 @@ namespace ICSharpCode.NRefactory.CSharp
this.options = options ?? TextEditorOptions.Default;
curIndent = new Indent(this.options);
}
protected virtual void VisitChildren (AstNode node)
{
if (!FormattingRegion.IsEmpty) {
if (node.EndLocation < FormattingRegion.Begin || node.StartLocation > FormattingRegion.End)
return;
}
AstNode next;
for (var child = node.FirstChild; child != null; child = next) {
// Store next to allow the loop to continue
// if the visitor removes/replaces child.
next = child.NextSibling;
child.AcceptVisitor (this);
}
}
/// <summary>
/// Applies the changes to the input document.

8
ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1007,6 +1007,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1007,6 +1007,14 @@ namespace ICSharpCode.NRefactory.CSharp
EndNode(primitiveExpression);
}
public static string PrintPrimitiveValue(object val)
{
StringWriter writer = new StringWriter();
CSharpOutputVisitor visitor = new CSharpOutputVisitor(writer, new CSharpFormattingOptions());
visitor.WritePrimitiveValue(val);
return writer.ToString();
}
void WritePrimitiveValue(object val)
{
if (val == null) {

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

@ -21,12 +21,12 @@ using System.CodeDom; @@ -21,12 +21,12 @@ using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp
{
@ -40,14 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,14 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp
{
//ICompilation compilation = MinimalResolveContext.Instance;
CSharpAstResolver resolver;
bool useFullyQualifiedTypeNames;
/// <summary>
/// Gets/Sets whether the visitor should use fully-qualified type references.
/// </summary>
public bool UseFullyQualifiedTypeNames {
get { return useFullyQualifiedTypeNames; }
set { useFullyQualifiedTypeNames = value; }
public bool UseFullyQualifiedTypeNames { get; set; }
/// <summary>
/// Gets whether the visitor is allowed to produce snippet nodes for
/// code that cannot be converted.
/// The default is true. If this property is set to false,
/// unconvertible code will throw a NotSupportedException.
/// </summary>
public bool AllowSnippetNodes { get; set; }
public CodeDomConvertVisitor()
{
this.AllowSnippetNodes = true;
}
/// <summary>
@ -136,7 +145,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -136,7 +145,15 @@ namespace ICSharpCode.NRefactory.CSharp
CodeTypeReference Convert(IType type)
{
return new CodeTypeReference(type.ReflectionName);
if (type.Kind == TypeKind.Array) {
ArrayType a = (ArrayType)type;
return new CodeTypeReference(Convert(a.ElementType), a.Dimensions);
} else if (type is ParameterizedType) {
var pt = (ParameterizedType)type;
return new CodeTypeReference(pt.GetDefinition().ReflectionName, pt.TypeArguments.Select(Convert).ToArray());
} else {
return new CodeTypeReference(type.ReflectionName);
}
}
CodeStatement Convert(Statement stmt)
@ -148,6 +165,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -148,6 +165,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
List<CodeStatement> result = new List<CodeStatement>();
foreach (Statement stmt in block.Statements) {
if (stmt is EmptyStatement)
continue;
CodeStatement s = Convert(stmt);
if (s != null)
result.Add(s);
@ -160,6 +179,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -160,6 +179,8 @@ namespace ICSharpCode.NRefactory.CSharp
BlockStatement block = embeddedStatement as BlockStatement;
if (block != null) {
return ConvertBlock(block);
} else if (embeddedStatement is EmptyStatement) {
return new CodeStatement[0];
}
CodeStatement s = Convert(embeddedStatement);
if (s != null)
@ -170,6 +191,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -170,6 +191,8 @@ namespace ICSharpCode.NRefactory.CSharp
string MakeSnippet(AstNode node)
{
if (!AllowSnippetNodes)
throw new NotSupportedException();
StringWriter w = new StringWriter();
CSharpOutputVisitor v = new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ());
node.AcceptVisitor(v);
@ -371,7 +394,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -371,7 +394,7 @@ namespace ICSharpCode.NRefactory.CSharp
TypeResolveResult trr = rr as TypeResolveResult;
if (trr != null) {
CodeTypeReference typeRef;
if (useFullyQualifiedTypeNames) {
if (UseFullyQualifiedTypeNames) {
typeRef = Convert(trr.Type);
} else {
typeRef = new CodeTypeReference(identifierExpression.Identifier);
@ -380,7 +403,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -380,7 +403,7 @@ namespace ICSharpCode.NRefactory.CSharp
return new CodeTypeReferenceExpression(typeRef);
}
MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
if (mgrr != null) {
if (mgrr != null || identifierExpression.TypeArguments.Any()) {
return new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), identifierExpression.Identifier, Convert(identifierExpression.TypeArguments));
}
return new CodeVariableReferenceExpression(identifierExpression.Identifier);
@ -658,7 +681,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -658,7 +681,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
{
CodeTypeDelegate d = new CodeTypeDelegate(delegateDeclaration.Name);
d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers);
d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers, EntityType.TypeDefinition);
d.CustomAttributes.AddRange(Convert(delegateDeclaration.Attributes));
d.ReturnType = Convert(delegateDeclaration.ReturnType);
d.Parameters.AddRange(Convert(delegateDeclaration.Parameters));
@ -666,13 +689,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -666,13 +689,15 @@ namespace ICSharpCode.NRefactory.CSharp
return d;
}
static MemberAttributes ConvertMemberAttributes(Modifiers modifiers)
MemberAttributes ConvertMemberAttributes(Modifiers modifiers, EntityType entityType)
{
MemberAttributes a = 0;
if ((modifiers & Modifiers.Abstract) != 0)
a |= MemberAttributes.Abstract;
if ((modifiers & Modifiers.Sealed) != 0)
a |= MemberAttributes.Final;
if (entityType != EntityType.TypeDefinition && (modifiers & (Modifiers.Abstract | Modifiers.Override | Modifiers.Virtual)) == 0)
a |= MemberAttributes.Final;
if ((modifiers & Modifiers.Static) != 0)
a |= MemberAttributes.Static;
if ((modifiers & Modifiers.Override) != 0)
@ -719,7 +744,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -719,7 +744,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
//bool isNestedType = typeStack.Count > 0;
CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name);
typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers);
typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers, EntityType.TypeDefinition);
typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes));
switch (typeDeclaration.ClassType) {
@ -809,7 +834,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -809,7 +834,12 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitEmptyStatement(EmptyStatement emptyStatement)
{
return null;
return EmptyStatement();
}
CodeStatement EmptyStatement()
{
return new CodeExpressionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(object))));
}
CodeObject IAstVisitor<CodeObject>.VisitExpressionStatement(ExpressionStatement expressionStatement)
@ -817,10 +847,55 @@ namespace ICSharpCode.NRefactory.CSharp @@ -817,10 +847,55 @@ namespace ICSharpCode.NRefactory.CSharp
AssignmentExpression assignment = expressionStatement.Expression as AssignmentExpression;
if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign) {
return new CodeAssignStatement(Convert(assignment.Left), Convert(assignment.Right));
} else if (assignment != null && CanBeDuplicatedForCompoundAssignment(assignment.Left)) {
CodeBinaryOperatorType op;
switch (assignment.Operator) {
case AssignmentOperatorType.Add:
op = CodeBinaryOperatorType.Add;
break;
case AssignmentOperatorType.Subtract:
op = CodeBinaryOperatorType.Subtract;
break;
case AssignmentOperatorType.Multiply:
op = CodeBinaryOperatorType.Multiply;
break;
case AssignmentOperatorType.Divide:
op = CodeBinaryOperatorType.Divide;
break;
case AssignmentOperatorType.Modulus:
op = CodeBinaryOperatorType.Modulus;
break;
case AssignmentOperatorType.BitwiseAnd:
op = CodeBinaryOperatorType.BitwiseAnd;
break;
case AssignmentOperatorType.BitwiseOr:
op = CodeBinaryOperatorType.BitwiseOr;
break;
default:
return MakeSnippetStatement(expressionStatement);
}
var cboe = new CodeBinaryOperatorExpression(Convert(assignment.Left), op, Convert(assignment.Right));
return new CodeAssignStatement(Convert(assignment.Left), cboe);
}
UnaryOperatorExpression unary = expressionStatement.Expression as UnaryOperatorExpression;
if (unary != null && CanBeDuplicatedForCompoundAssignment(unary.Expression)) {
var op = unary.Operator;
if (op == UnaryOperatorType.Increment || op == UnaryOperatorType.PostIncrement) {
var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1));
return new CodeAssignStatement(Convert(unary.Expression), cboe);
} else if (op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostDecrement) {
var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Subtract, new CodePrimitiveExpression(1));
return new CodeAssignStatement(Convert(unary.Expression), cboe);
}
}
return new CodeExpressionStatement(Convert(expressionStatement.Expression));
}
bool CanBeDuplicatedForCompoundAssignment(Expression expr)
{
return expr is IdentifierExpression;
}
CodeObject IAstVisitor<CodeObject>.VisitFixedStatement(FixedStatement fixedStatement)
{
return MakeSnippetStatement(fixedStatement);
@ -956,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -956,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitWhileStatement(WhileStatement whileStatement)
{
return new CodeIterationStatement(null, Convert(whileStatement.Condition), null, ConvertEmbeddedStatement(whileStatement.EmbeddedStatement));
return new CodeIterationStatement(EmptyStatement(), Convert(whileStatement.Condition), EmptyStatement(), ConvertEmbeddedStatement(whileStatement.EmbeddedStatement));
}
CodeObject IAstVisitor<CodeObject>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
@ -977,7 +1052,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -977,7 +1052,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
CodeConstructor ctor = new CodeConstructor();
ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers);
ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers, EntityType.Constructor);
ctor.CustomAttributes.AddRange(Convert(constructorDeclaration.Attributes));
if (constructorDeclaration.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) {
ctor.ChainedConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments));
@ -1019,7 +1094,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1019,7 +1094,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
CodeMemberEvent e = new CodeMemberEvent();
e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers);
e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers, EntityType.Event);
e.CustomAttributes.AddRange(Convert(eventDeclaration.Attributes));
e.Name = vi.Name;
e.Type = Convert(eventDeclaration.ReturnType);
@ -1037,7 +1112,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1037,7 +1112,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
foreach (VariableInitializer vi in fieldDeclaration.Variables) {
CodeMemberField f = new CodeMemberField(Convert(fieldDeclaration.ReturnType), vi.Name);
f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers);
f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers, EntityType.Field);
f.CustomAttributes.AddRange(Convert(fieldDeclaration.Attributes));
f.InitExpression = ConvertVariableInitializer(vi.Initializer, fieldDeclaration.ReturnType);
AddTypeMember(f);
@ -1048,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1048,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
{
CodeMemberProperty p = new CodeMemberProperty();
p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers);
p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers, EntityType.Indexer);
p.CustomAttributes.AddRange(Convert(indexerDeclaration.Attributes));
p.Name = "Items";
p.PrivateImplementationType = Convert(indexerDeclaration.PrivateImplementationType);
@ -1069,7 +1144,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1069,7 +1144,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
CodeMemberMethod m = new CodeMemberMethod();
m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers);
m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers, EntityType.Method);
m.CustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
m.ReturnTypeCustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
@ -1087,7 +1162,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1087,7 +1162,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
{
CodeMemberMethod m = new CodeMemberMethod();
m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers);
m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers, EntityType.Method);
m.CustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
m.ReturnTypeCustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
@ -1129,7 +1204,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1129,7 +1204,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
CodeMemberProperty p = new CodeMemberProperty();
p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers);
p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers, EntityType.Property);
p.CustomAttributes.AddRange(Convert(propertyDeclaration.Attributes));
p.Name = propertyDeclaration.Name;
p.PrivateImplementationType = Convert(propertyDeclaration.PrivateImplementationType);
@ -1181,7 +1256,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1181,7 +1256,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitSimpleType(SimpleType simpleType)
{
if (useFullyQualifiedTypeNames) {
if (UseFullyQualifiedTypeNames) {
IType type = Resolve(simpleType).Type;
if (type.Kind != TypeKind.Unknown)
return Convert(type);
@ -1198,7 +1273,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1198,7 +1273,7 @@ namespace ICSharpCode.NRefactory.CSharp
tr.TypeArguments.AddRange(Convert(memberType.TypeArguments));
return tr;
}
if (useFullyQualifiedTypeNames || memberType.IsDoubleColon) {
if (UseFullyQualifiedTypeNames || memberType.IsDoubleColon) {
IType type = Resolve(memberType).Type;
if (type.Kind != TypeKind.Unknown)
return Convert(type);
@ -1309,7 +1384,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1309,7 +1384,7 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, Pattern pattern)
{
return null;
}

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

@ -3750,7 +3750,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3750,7 +3750,7 @@ namespace ICSharpCode.NRefactory.CSharp
return AstType.Null;
}
public AstNode ParseExpression (TextReader reader)
public Expression ParseExpression (TextReader reader)
{
var es = ParseStatements (new StringReader ("tmp = " + Environment.NewLine + reader.ReadToEnd () + ";"), -1).FirstOrDefault () as ExpressionStatement;
if (es != null) {
@ -3758,7 +3758,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3758,7 +3758,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (ae != null)
return ae.Right;
}
return null;
return Expression.Null;
}
/// <summary>

11
ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs

@ -155,7 +155,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -155,7 +155,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Conversion.NullLiteralConversion;
if (ImplicitReferenceConversion(fromType, toType, 0))
return Conversion.ImplicitReferenceConversion;
if (BoxingConversion(fromType, toType))
if (IsBoxingConversion(fromType, toType))
return Conversion.BoxingConversion;
if (fromType.Kind == TypeKind.Dynamic)
return Conversion.ImplicitDynamicConversion;
@ -184,7 +184,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -184,7 +184,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return true;
if (ImplicitReferenceConversion(fromType, toType, 0))
return true;
if (BoxingConversion(fromType, toType) && !NullableType.IsNullable(fromType))
if (IsBoxingConversion(fromType, toType) && !NullableType.IsNullable(fromType))
return true;
if (ImplicitTypeParameterConversion(fromType, toType))
return true;
@ -398,6 +398,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -398,6 +398,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region Implicit Reference Conversion
public bool IsImplicitReferenceConversion(IType fromType, IType toType)
{
return ImplicitReferenceConversion(fromType, toType, 0);
}
bool ImplicitReferenceConversion(IType fromType, IType toType, int subtypeCheckNestingDepth)
{
// C# 4.0 spec: §6.1.6
@ -510,7 +515,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -510,7 +515,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region Boxing Conversions
bool BoxingConversion(IType fromType, IType toType)
public bool IsBoxingConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.1.7
fromType = NullableType.GetUnderlyingType(fromType);

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

@ -390,7 +390,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -390,7 +390,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool isNullable = NullableType.IsNullable(expression.Type);
// the operator is overloadable:
OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
OverloadResolution userDefinedOperatorOR = CreateOverloadResolution(new[] { expression });
foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) {
userDefinedOperatorOR.AddCandidate(candidate);
}
@ -439,7 +439,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -439,7 +439,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
default:
throw new InvalidOperationException();
}
OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { expression });
foreach (var candidate in methodGroup) {
builtinOperatorOR.AddCandidate(candidate);
}
@ -569,7 +569,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -569,7 +569,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IType rhsType = NullableType.GetUnderlyingType(rhs.Type);
// the operator is overloadable:
OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions);
OverloadResolution userDefinedOperatorOR = CreateOverloadResolution(new[] { lhs, rhs });
HashSet<IParameterizedMember> userOperatorCandidates = new HashSet<IParameterizedMember>();
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName));
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName));
@ -800,7 +800,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -800,7 +800,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
default:
throw new InvalidOperationException();
}
OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions);
OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { lhs, rhs });
foreach (var candidate in methodGroup) {
builtinOperatorOR.AddCandidate(candidate);
}
@ -1260,7 +1260,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1260,7 +1260,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
else if (rr.IsCompileTimeConstant && c != Conversion.None)
return ResolveCast(targetType, rr);
else
return new ConversionResolveResult(targetType, rr, c);
return new ConversionResolveResult(targetType, rr, c, checkForOverflow);
}
public ResolveResult ResolveCast(IType targetType, ResolveResult expression)
@ -1291,7 +1291,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1291,7 +1291,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
Conversion c = conversions.ExplicitConversion(expression, targetType);
return new ConversionResolveResult(targetType, expression, c);
return new ConversionResolveResult(targetType, expression, c, checkForOverflow);
}
internal object CSharpPrimitiveCast(TypeCode targetType, object input)
@ -1891,7 +1891,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1891,7 +1891,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MethodGroupResolveResult mgrr = target as MethodGroupResolveResult;
if (mgrr != null) {
OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, conversions: conversions);
OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, checkForOverflow: checkForOverflow, conversions: conversions);
if (or.BestCandidate != null) {
if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult))
return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetResult.Type));
@ -1914,7 +1914,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1914,7 +1914,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
IMethod invokeMethod = target.Type.GetDelegateInvokeMethod();
if (invokeMethod != null) {
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions);
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
or.AddCandidate(invokeMethod);
return new CSharpInvocationResolveResult(
target, invokeMethod, //invokeMethod.ReturnType.Resolve(context),
@ -2003,6 +2003,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2003,6 +2003,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
variableName = variableName.Substring(1);
return char.ToLower(variableName[0]) + variableName.Substring(1);
}
OverloadResolution CreateOverloadResolution(ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null)
{
var or = new OverloadResolution(compilation, arguments, argumentNames, typeArguments, conversions);
or.CheckForOverflow = checkForOverflow;
return or;
}
#endregion
#region ResolveIndexer
@ -2035,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2035,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
// §7.6.6.2 Indexer access
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions);
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup();
var indexers = lookup.LookupIndexers(target.Type);
or.AddMethodLists(indexers);
@ -2090,7 +2097,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2090,7 +2097,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (type.Kind == TypeKind.Delegate && arguments.Length == 1) {
return Convert(arguments[0], type);
}
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions);
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup();
foreach (IMethod ctor in type.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess))
@ -2197,6 +2204,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2197,6 +2204,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Convert(input, boolean, c);
}
/// <summary>
/// Converts the negated input to <c>bool</c> using the rules for boolean expressions.
/// Computes <c>!(bool)input</c> if the implicit cast to bool is valid; otherwise
/// computes <c>input.operator false()</c>.
/// </summary>
public ResolveResult ResolveConditionFalse(ResolveResult input)
{
if (input == null)
throw new ArgumentNullException("input");
IType boolean = compilation.FindType(KnownTypeCode.Boolean);
Conversion c = conversions.ImplicitConversion(input, boolean);
if (!c.IsValid) {
var opFalse = input.Type.GetMethods(m => m.IsOperator && m.Name == "op_False").FirstOrDefault();
if (opFalse != null) {
c = Conversion.UserDefinedImplicitConversion(opFalse, false);
return Convert(input, boolean, c);
}
}
return ResolveUnaryOperator(UnaryOperatorType.Not, Convert(input, boolean, c));
}
public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression)
{
// C# 4.0 spec §7.14: Conditional operator

4
ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs

@ -178,7 +178,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -178,7 +178,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return string.Format("[{0} with {1} method(s)]", GetType().Name, this.Methods.Count());
}
public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, CSharpConversions conversions = null)
public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, bool checkForOverflow = false, CSharpConversions conversions = null)
{
Log.WriteLine("Performing overload resolution for " + this);
Log.WriteCollection(" Arguments: ", arguments);
@ -186,6 +186,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -186,6 +186,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var typeArgumentArray = this.TypeArguments.ToArray();
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions);
or.AllowExpandingParams = allowExpandingParams;
or.CheckForOverflow = checkForOverflow;
or.AddMethodLists(methodLists);
@ -207,6 +208,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -207,6 +208,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var extOr = new OverloadResolution(compilation, extArguments, extArgumentNames, typeArgumentArray, conversions);
extOr.AllowExpandingParams = allowExpandingParams;
extOr.IsExtensionMethodInvocation = true;
extOr.CheckForOverflow = checkForOverflow;
foreach (var g in extensionMethods) {
foreach (var method in g) {

11
ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs

@ -170,6 +170,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -170,6 +170,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public bool AllowExpandingParams { get; set; }
/// <summary>
/// Gets/Sets whether ConversionResolveResults created by this OverloadResolution
/// instance apply overflow checking.
/// The default value is false.
/// </summary>
public bool CheckForOverflow { get; set; }
/// <summary>
/// Gets the arguments for which this OverloadResolution instance was created.
/// </summary>
@ -801,9 +808,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -801,9 +808,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
parameterType = SpecialType.UnknownType;
}
if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) {
args[i] = new CSharpResolver(compilation).ResolveCast(parameterType, argument);
args[i] = new CSharpResolver(compilation).WithCheckForOverflow(CheckForOverflow).ResolveCast(parameterType, argument);
} else {
args[i] = new ConversionResolveResult(parameterType, argument, conversions[i]);
args[i] = new ConversionResolveResult(parameterType, argument, conversions[i], CheckForOverflow);
}
}
}

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

@ -1236,7 +1236,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1236,7 +1236,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled) {
ResolveResult input = Resolve(asExpression.Expression);
var targetType = ResolveType(asExpression.Type);
return new ConversionResolveResult(targetType, input, Conversion.TryCast);
return new ConversionResolveResult(targetType, input, Conversion.TryCast, resolver.CheckForOverflow);
} else {
ScanChildren(asExpression);
return null;
@ -1498,7 +1498,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1498,7 +1498,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList<IType>.Instance, true);
var mgrr = addRR as MethodGroupResolveResult;
if (mgrr != null) {
OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, resolver.conversions);
OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, resolver.CheckForOverflow, resolver.conversions);
var invocationRR = or.CreateResolveResult(initializedObject);
StoreResult(aie, invocationRR);
ProcessConversionsInInvocation(null, aie.Elements, invocationRR);
@ -3415,7 +3415,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -3415,7 +3415,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
ResolveResult WrapResult(ResolveResult result)
{
return new ConversionResolveResult(result.Type, result, Conversion.IdentityConversion);
return new ConversionResolveResult(result.Type, result, Conversion.IdentityConversion, resolver.CheckForOverflow);
}
ResolveResult IAstVisitor<ResolveResult>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
@ -3603,7 +3603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -3603,7 +3603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType);
if (currentQueryResult != null) {
if (conversionToBool != Conversion.IdentityConversion && conversionToBool != Conversion.None) {
condition = new ConversionResolveResult(boolType, condition, conversionToBool);
condition = new ConversionResolveResult(boolType, condition, conversionToBool, resolver.CheckForOverflow);
}
var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Where", EmptyList<IType>.Instance);

1
ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs

@ -677,6 +677,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -677,6 +677,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
if (accessor.IsNull)
return null;
var a = new DefaultUnresolvedMethod(currentTypeDefinition, prefix + p.Name);
a.AccessorOwner = p;
a.Accessibility = GetAccessibility(accessor.Modifiers) ?? p.Accessibility;
a.IsAbstract = p.IsAbstract;
a.IsOverride = p.IsOverridable;

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

@ -20,11 +20,11 @@ using System; @@ -20,11 +20,11 @@ using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Microsoft.CSharp;
using NUnit.Framework;
@ -45,138 +45,388 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,138 +45,388 @@ namespace ICSharpCode.NRefactory.CSharp
parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Linq"));
convertVisitor = new CodeDomConvertVisitor();
convertVisitor.AllowSnippetNodes = false;
convertVisitor.UseFullyQualifiedTypeNames = true;
}
string Convert(Expression expr)
#region Helper methods
string ConvertHelper(AstNode node, Action<CSharpCodeProvider, CodeObject, TextWriter, CodeGeneratorOptions> action)
{
CSharpResolver resolver = new CSharpResolver(compilation);
resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(compilation));
resolver = resolver.WithCurrentTypeDefinition(compilation.FindType(KnownTypeCode.Object).GetDefinition());
var codeExpr = (CodeExpression)convertVisitor.Convert(expr, new CSharpAstResolver(resolver, expr, parsedFile));
var codeObj = convertVisitor.Convert(node, new CSharpAstResolver(resolver, node));
StringWriter writer = new StringWriter();
writer.NewLine = " ";
new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " });
return Regex.Replace(writer.ToString(), @"\s+", " ");
action(new CSharpCodeProvider(), codeObj, writer, new CodeGeneratorOptions { IndentString = " " });
return Regex.Replace(writer.ToString(), @"\s+", " ").Trim();
}
string ConvertExpression(Expression expr)
{
return ConvertHelper(expr, (p,obj,w,opt) => p.GenerateCodeFromExpression((CodeExpression)obj, w, opt));
}
string ConvertExpression(string code)
{
CSharpParser parser = new CSharpParser();
var expr = parser.ParseExpression(new StringReader(code));
Assert.IsFalse(parser.HasErrors);
return ConvertExpression(expr);
}
string ConvertStatement(Statement statement)
{
return ConvertHelper(statement, (p,obj,w,opt) => p.GenerateCodeFromStatement((CodeStatement)obj, w, opt));
}
string ConvertStatement(string code)
{
CSharpParser parser = new CSharpParser();
var expr = parser.ParseStatements(new StringReader(code)).Single();
Assert.IsFalse(parser.HasErrors);
return ConvertStatement(expr);
}
string ConvertMember(EntityDeclaration entity)
{
return ConvertHelper(entity, (p,obj,w,opt) => p.GenerateCodeFromMember((CodeTypeMember)obj, w, opt));
}
string ConvertMember(string code)
{
CSharpParser parser = new CSharpParser();
var expr = parser.ParseTypeMembers(new StringReader(code)).Single();
Assert.IsFalse(parser.HasErrors);
return ConvertMember(expr);
}
string ConvertTypeDeclaration(EntityDeclaration decl)
{
return ConvertHelper(decl, (p,obj,w,opt) => p.GenerateCodeFromType((CodeTypeDeclaration)obj, w, opt));
}
string ConvertTypeDeclaration(string code)
{
CSharpParser parser = new CSharpParser();
var cu = parser.Parse(new StringReader(code), "program.cs");
Assert.IsFalse(parser.HasErrors);
return ConvertTypeDeclaration((EntityDeclaration)cu.Children.Single());
}
#endregion
#region Type References
[Test]
public void CreateArray()
public void MultidimensionalArrayTypeReference()
{
Assert.AreEqual("new int[10]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10) }
}));
Assert.AreEqual("default(int[,][])", ConvertExpression("default(int[,][])"));
}
[Test]
public void CreateJaggedArray()
public void NestedTypeInGenericType()
{
Assert.AreEqual("new int[10][]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10) },
AdditionalArraySpecifiers = { new ArraySpecifier() }
}));
Assert.AreEqual("default(System.Collections.Generic.List<string>.Enumerator)",
ConvertExpression("default(List<string>.Enumerator)"));
convertVisitor.UseFullyQualifiedTypeNames = false;
Assert.AreEqual("default(List<string>.Enumerator)",
ConvertExpression("default(List<string>.Enumerator)"));
}
#endregion
#region Arrays
[Test]
public void CreateArray()
{
Assert.AreEqual("new int[10]", ConvertExpression("new int[10]"));
}
[Test, ExpectedException(typeof(NotSupportedException))]
public void CreateJaggedArray()
{
ConvertExpression("new int[10][]");
}
[Test, ExpectedException(typeof(NotSupportedException))]
public void Create2DArray()
{
Assert.AreEqual("new int[10, 20]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10), new PrimitiveExpression(20) }
}));
ConvertExpression("new int[10, 20]");
}
[Test]
public void CreateImplicitlyTypedArray()
{
// implicitly-typed array not supported in CodeDom, so the conversion should infer the type
Assert.AreEqual("new int[] { 1, 2, 3}", Convert(
new ArrayCreateExpression {
AdditionalArraySpecifiers = { new ArraySpecifier() },
Initializer = new ArrayInitializerExpression {
Elements = {
new PrimitiveExpression(1),
new PrimitiveExpression(2),
new PrimitiveExpression(3)
}
}
}));
Assert.AreEqual("new int[] { 1, 2, 3}", ConvertExpression("new [] { 1, 2, 3 }"));
Assert.AreEqual("new System.Collections.Generic.List<string>[] { new System.Collections.Generic.List<string>()}",
ConvertExpression("new [] { new List<string>() }"));
}
[Test]
[Test, ExpectedException(typeof(NotSupportedException))]
public void Create2DImplicitlyTypedArray()
{
Assert.AreEqual("new int[,] { { 1, 2 }, { 3, 4 }}", Convert(
new ArrayCreateExpression {
AdditionalArraySpecifiers = { new ArraySpecifier(2) },
Initializer = new ArrayInitializerExpression {
Elements = {
new ArrayInitializerExpression(new PrimitiveExpression(1), new PrimitiveExpression(2)),
new ArrayInitializerExpression(new PrimitiveExpression(3), new PrimitiveExpression(4))
}
}
}));
ConvertExpression("new [,] { { 1, 2 }, { 3, 4 }}");
}
#endregion
#region Operators
[Test]
public void AdditionOperator()
public void ArithmeticOperators()
{
Assert.AreEqual("(0 + 1)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Add, new PrimitiveExpression(1))));
Assert.AreEqual("(0 + 1)", ConvertExpression("0 + 1"));
Assert.AreEqual("(0 - 1)", ConvertExpression("0 - 1"));
Assert.AreEqual("(0 * 1)", ConvertExpression("0 * 1"));
Assert.AreEqual("(0 / 1)", ConvertExpression("0 / 1"));
Assert.AreEqual("(0 % 1)", ConvertExpression("0 % 1"));
Assert.AreEqual("(0 & 1)", ConvertExpression("0 & 1"));
Assert.AreEqual("(0 | 1)", ConvertExpression("0 | 1"));
Assert.AreEqual("(0 < 1)", ConvertExpression("0 < 1"));
Assert.AreEqual("(0 > 1)", ConvertExpression("0 > 1"));
Assert.AreEqual("(0 <= 1)", ConvertExpression("0 <= 1"));
Assert.AreEqual("(0 >= 1)", ConvertExpression("0 >= 1"));
Assert.AreEqual("(true && false)", ConvertExpression("true && false"));
Assert.AreEqual("(true || false)", ConvertExpression("true || false"));
}
[Test]
public void EqualityOperator()
{
Assert.AreEqual("(0 == 1)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Equality, new PrimitiveExpression(1))));
Assert.AreEqual("(0 == 1)", ConvertExpression("0 == 1"));
Assert.AreEqual("(default(object) == null)", ConvertExpression("default(object) == null"));
}
[Test]
public void InEqualityOperator()
{
Assert.AreEqual("((0 == 1) == false)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.InEquality, new PrimitiveExpression(1))));
Assert.AreEqual("((0 == 1) == false)", ConvertExpression("0 != 1"));
Assert.AreEqual("(default(object) != null)", ConvertExpression("default(object) != null"));
}
[Test]
public void ReferenceInEqualityOperator()
public void UnaryOperators()
{
Assert.AreEqual("(default(object) != null)", Convert(
new BinaryOperatorExpression(new DefaultValueExpression(new PrimitiveType("object")), BinaryOperatorType.InEquality, new NullReferenceExpression())));
Assert.AreEqual("(a == false)", ConvertExpression("!a"));
Assert.AreEqual("(0 - a)", ConvertExpression("-a"));
Assert.AreEqual("a", ConvertExpression("+a"));
}
[Test]
public void Cast()
{
Assert.AreEqual("((double)(0))", ConvertExpression("(double)0"));
}
#endregion
#region Member Access
[Test]
public void StaticProperty()
{
Assert.AreEqual("System.Environment.TickCount", Convert(
new IdentifierExpression("Environment").Member("TickCount")));
Assert.AreEqual("System.Environment.TickCount", ConvertExpression("Environment.TickCount"));
}
[Test]
public void InstanceMethodInvocation()
{
Assert.AreEqual("this.Equals(null)",
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression())));
Assert.AreEqual("this.Equals(null)", ConvertExpression("Equals(null)"));
}
[Test]
public void StaticMethodInvocation()
{
Assert.AreEqual("object.Equals(null, null)",
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression(), new NullReferenceExpression())));
Assert.AreEqual("object.Equals(null, null)", ConvertExpression("Equals(null, null)"));
}
[Test]
public void BaseMemberAccess()
{
Assert.AreEqual("base.X", ConvertExpression("base.X"));
Assert.AreEqual("base[i]", ConvertExpression("base[i]"));
}
[Test]
public void GenericMethodReference()
{
Assert.AreEqual("this.Stuff<string>", ConvertExpression("this.Stuff<string>"));
Assert.AreEqual("this.Stuff<string>", ConvertExpression("Stuff<string>"));
}
[Test]
public void ByReferenceCall()
{
Assert.AreEqual("a.Call(ref x, out y, z)", ConvertExpression("a.Call(ref x, out y, z)"));
}
[Test]
public void MemberAccessOnType()
{
Assert.AreEqual("string.Empty", ConvertExpression("string.Empty"));
}
#endregion
#region Statements
[Test]
public void MethodInvocationStatement()
{
Assert.AreEqual("a.SomeMethod();", ConvertStatement("a.SomeMethod();"));
}
[Test]
public void Assignment()
{
Assert.AreEqual("a = 1;", ConvertStatement("a = 1;"));
}
[Test, ExpectedException(typeof(NotSupportedException))]
public void AssignmentNotSupportedInExpression()
{
ConvertStatement("a = b = 1;");
}
[Test]
public void BlockStatement()
{
Assert.AreEqual("if (true) { a = 1; b = 2; }",
ConvertStatement("{ a = 1; b = 2; }"));
}
[Test]
public void CompoundAssign()
{
Assert.AreEqual("a = (a + 1);", ConvertStatement("a += 1;"));
Assert.AreEqual("a = (a - 1);", ConvertStatement("a -= 1;"));
Assert.AreEqual("a = (a * 1);", ConvertStatement("a *= 1;"));
Assert.AreEqual("a = (a / 1);", ConvertStatement("a /= 1;"));
Assert.AreEqual("a = (a % 1);", ConvertStatement("a %= 1;"));
Assert.AreEqual("a = (a & 1);", ConvertStatement("a &= 1;"));
Assert.AreEqual("a = (a | 1);", ConvertStatement("a |= 1;"));
}
[Test]
public void Increment()
{
Assert.AreEqual("a = (a + 1);", ConvertStatement("a++;"));
Assert.AreEqual("a = (a + 1);", ConvertStatement("++a;"));
Assert.AreEqual("a = (a - 1);", ConvertStatement("a--;"));
Assert.AreEqual("a = (a - 1);", ConvertStatement("--a;"));
}
[Test]
public void ForLoop()
{
Assert.AreEqual("for (int i = 0; (i < 10); i = (i + 1)) { }",
ConvertStatement("for (int i = 0; i < 10; i++) {}"));
}
[Test]
public void WhileLoop()
{
Assert.AreEqual("for (new object(); (i < 10); new object()) { }",
ConvertStatement("while (i < 10);"));
}
[Test]
public void VariableDeclarationWithArrayInitializer()
{
Assert.AreEqual("int[] nums = new int[] { 1, 2};",
ConvertStatement("int[] nums = { 1, 2 };"));
}
[Test]
public void TryCatch()
{
Assert.AreEqual("try { a = 1; } catch (System.Exception ex) { ex.ToString(); }",
ConvertStatement("try { a = 1; } catch (Exception ex) { ex.ToString(); }"));
}
[Test]
public void TryEmptyCatch()
{
Assert.AreEqual("try { a = 1; } catch (System.Exception ) { }",
ConvertStatement("try { a = 1; } catch (Exception) { }"));
}
[Test]
public void TryFinally()
{
Assert.AreEqual("try { a = 1; } finally { a = 0; }",
ConvertStatement("try { a = 1; } finally { a = 0; }"));
}
#endregion
#region Type Members
[Test]
public void MethodParameterNamedValue()
{
Assert.AreEqual("void M(string value) { System.Console.WriteLine(value); }",
ConvertMember("void M(string value) { Console.WriteLine(value); }"));
}
[Test]
public void ValueInProperty()
{
Assert.AreEqual("string P { set { System.Console.WriteLine(value); } }",
ConvertMember("string P { set { Console.WriteLine(value); } }"));
}
[Test]
public void MethodWithAttribute()
{
Assert.AreEqual("[Test()] void MethodWithAttribute() { }",
ConvertMember("[Test] void MethodWithAttribute() { }"));
}
[Test]
public void PublicNonVirtualMethod()
{
Assert.AreEqual("public void Method() { }",
ConvertMember("public void Method() { }"));
}
[Test]
public void PublicVirtualMethod()
{
Assert.AreEqual("public virtual void Method() { }",
ConvertMember("public virtual void Method() { }"));
}
[Test]
public void NestedClass()
{
Assert.AreEqual("public class Outer { public class Inner { } }",
ConvertTypeDeclaration("class Outer { class Inner { } }"));
}
[Test]
public void Constructor()
{
string code = "public class Test : Base { public Test(string x) : base(x) { } }";
Assert.AreEqual(code, ConvertTypeDeclaration(code));
}
[Test]
public void Enum()
{
string code = "public enum E { [Description(\"Text\")] None, B = 2, }";
Assert.AreEqual(code, ConvertTypeDeclaration(code));
}
[Test]
public void Field()
{
Assert.AreEqual("public class X {" +
" int A;" +
" int B; }",
ConvertMember("public class X { int A, B; }"));
}
[Test]
public void NotOperator()
public void Event()
{
Assert.AreEqual("(a == false)", Convert(new UnaryOperatorExpression(UnaryOperatorType.Not, new IdentifierExpression("a"))));
Assert.AreEqual("public class X {" +
" protected event System.EventHandler A;" +
" protected event System.EventHandler B; }",
ConvertMember("public class X { protected event EventHandler A, B; }"));
}
#endregion
}
}

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

@ -72,6 +72,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -72,6 +72,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public NestedEnum EnumField;
public A Property { get; set; }
public enum NestedEnum {
EnumMember
}

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

@ -351,6 +351,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -351,6 +351,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility);
Assert.AreEqual(new[] { "index" }, p.Getter.Parameters.Select(x => x.Name).ToArray());
Assert.AreEqual("System.String", p.Getter.ReturnType.ReflectionName);
Assert.AreEqual(p, p.Getter.AccessorOwner);
}
[Test]
@ -365,6 +366,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -365,6 +366,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(TypeKind.Void, p.Setter.ReturnType.Kind);
}
[Test]
public void GenericPropertyGetter()
{
var type = compilation.FindType(typeof(GenericClass<string, object>));
var prop = type.GetProperties(p => p.Name == "Property").Single();
Assert.AreEqual("System.String", prop.Getter.ReturnType.ReflectionName);
Assert.IsTrue(prop.Getter.IsAccessor);
Assert.AreEqual(prop, prop.Getter.AccessorOwner);
}
[Test]
public void EnumTest()
{

32
ICSharpCode.NRefactory/Editor/IDocument.cs

@ -109,6 +109,18 @@ namespace ICSharpCode.NRefactory.Editor @@ -109,6 +109,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </remarks>
void Insert(int offset, string text);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
void Insert(int offset, ITextSource text);
/// <summary>
/// Inserts text.
/// </summary>
@ -121,6 +133,18 @@ namespace ICSharpCode.NRefactory.Editor @@ -121,6 +133,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </param>
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Removes text.
/// </summary>
@ -136,6 +160,14 @@ namespace ICSharpCode.NRefactory.Editor @@ -136,6 +160,14 @@ namespace ICSharpCode.NRefactory.Editor
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, string newText);
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, ITextSource newText);
/// <summary>
/// Make the document combine the following actions into a single
/// action for undo purposes.

15
ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs

@ -257,6 +257,21 @@ namespace ICSharpCode.NRefactory.Editor @@ -257,6 +257,21 @@ namespace ICSharpCode.NRefactory.Editor
throw new NotSupportedException();
}
void IDocument.Insert(int offset, ITextSource text)
{
throw new NotImplementedException();
}
void IDocument.Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
throw new NotImplementedException();
}
void IDocument.Replace(int offset, int length, ITextSource newText)
{
throw new NotImplementedException();
}
void IDocument.StartUndoableAction()
{
}

28
ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs

@ -104,17 +104,35 @@ namespace ICSharpCode.NRefactory.Editor @@ -104,17 +104,35 @@ namespace ICSharpCode.NRefactory.Editor
Replace(offset, 0, text);
}
/// <inheritdoc/>
public void Insert(int offset, ITextSource text)
{
if (text == null)
throw new ArgumentNullException("text");
Replace(offset, 0, text.Text);
}
/// <inheritdoc/>
public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
if (offset < 0 || offset > this.TextLength)
throw new ArgumentOutOfRangeException("offset");
if (text == null)
throw new ArgumentNullException("text");
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion)
PerformChange(new InsertionWithMovementBefore(offset, text));
else
Replace(offset, 0, text);
}
/// <inheritdoc/>
public void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
if (text == null)
throw new ArgumentNullException("text");
Insert(offset, text.Text, defaultAnchorMovementType);
}
[Serializable]
sealed class InsertionWithMovementBefore : TextChangeEventArgs
{
@ -149,6 +167,14 @@ namespace ICSharpCode.NRefactory.Editor @@ -149,6 +167,14 @@ namespace ICSharpCode.NRefactory.Editor
PerformChange(new TextChangeEventArgs(offset, b.ToString(offset, length), newText));
}
/// <inheritdoc/>
public void Replace(int offset, int length, ITextSource newText)
{
if (newText == null)
throw new ArgumentNullException("newText");
Replace(offset, length, newText.Text);
}
bool isInChange;
void PerformChange(TextChangeEventArgs change)
@ -166,7 +192,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -166,7 +192,7 @@ namespace ICSharpCode.NRefactory.Editor
documentSnapshot = null;
cachedText = null;
b.Remove(change.Offset, change.RemovalLength);
b.Insert(change.Offset, change.InsertedText);
b.Insert(change.Offset, change.InsertedText.Text);
versionProvider.AppendChange(change);
// Update anchors and fire Deleted events

7
ICSharpCode.NRefactory/Editor/StringTextSource.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Editor @@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Editor
[Serializable]
public class StringTextSource : ITextSource
{
/// <summary>
/// Gets a text source containing the empty string.
/// </summary>
public static readonly StringTextSource Empty = new StringTextSource(string.Empty);
readonly string text;
readonly ITextSourceVersion version;
@ -69,7 +74,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -69,7 +74,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return this; // StringTextBuffer is immutable
return this; // StringTextSource is immutable
}
/// <inheritdoc/>

30
ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs

@ -28,8 +28,8 @@ namespace ICSharpCode.NRefactory.Editor @@ -28,8 +28,8 @@ namespace ICSharpCode.NRefactory.Editor
public class TextChangeEventArgs : EventArgs
{
readonly int offset;
readonly string removedText;
readonly string insertedText;
readonly ITextSource removedText;
readonly ITextSource insertedText;
/// <summary>
/// The offset at which the change occurs.
@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <summary>
/// The text that was removed.
/// </summary>
public string RemovedText {
public ITextSource RemovedText {
get { return removedText; }
}
@ -49,13 +49,13 @@ namespace ICSharpCode.NRefactory.Editor @@ -49,13 +49,13 @@ namespace ICSharpCode.NRefactory.Editor
/// The number of characters removed.
/// </summary>
public int RemovalLength {
get { return removedText.Length; }
get { return removedText.TextLength; }
}
/// <summary>
/// The text that was inserted.
/// </summary>
public string InsertedText {
public ITextSource InsertedText {
get { return insertedText; }
}
@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.Editor
/// The number of characters inserted.
/// </summary>
public int InsertionLength {
get { return insertedText.Length; }
get { return insertedText.TextLength; }
}
/// <summary>
@ -71,9 +71,23 @@ namespace ICSharpCode.NRefactory.Editor @@ -71,9 +71,23 @@ namespace ICSharpCode.NRefactory.Editor
/// </summary>
public TextChangeEventArgs(int offset, string removedText, string insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset;
this.removedText = removedText ?? string.Empty;
this.insertedText = insertedText ?? string.Empty;
this.removedText = removedText != null ? new StringTextSource(removedText) : StringTextSource.Empty;
this.insertedText = insertedText != null ? new StringTextSource(insertedText) : StringTextSource.Empty;
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, ITextSource removedText, ITextSource insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset;
this.removedText = removedText ?? StringTextSource.Empty;
this.insertedText = insertedText ?? StringTextSource.Empty;
}
/// <summary>

11
ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Semantics @@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Semantics
public readonly ResolveResult Input;
public readonly Conversion Conversion;
/// <summary>
/// For numeric conversions, specifies whether overflow checking is enabled.
/// </summary>
public readonly bool CheckForOverflow;
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion)
: base(targetType)
{
@ -38,6 +43,12 @@ namespace ICSharpCode.NRefactory.Semantics @@ -38,6 +43,12 @@ namespace ICSharpCode.NRefactory.Semantics
this.Conversion = conversion;
}
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow)
: this(targetType, input, conversion)
{
this.CheckForOverflow = checkForOverflow;
}
public override bool IsError {
get { return !Conversion.IsValid; }
}

10
ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs

@ -35,8 +35,18 @@ namespace ICSharpCode.NRefactory.Semantics @@ -35,8 +35,18 @@ namespace ICSharpCode.NRefactory.Semantics
{
}
public ErrorResolveResult(IType type, string message, TextLocation location) : base(type)
{
this.Message = message;
this.Location = location;
}
public override bool IsError {
get { return true; }
}
public string Message { get; private set; }
public TextLocation Location { get; private set; }
}
}

16
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -1646,11 +1646,17 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1646,11 +1646,17 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Read Method
[CLSCompliant(false)]
public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType = EntityType.Method)
{
return ReadMethod(method, parentType, null, methodType);
}
IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method)
{
if (method == null)
return null;
DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name);
m.EntityType = methodType;
m.AccessorOwner = accessorOwner;
if (method.HasGenericParameters) {
for (int i = 0; i < method.GenericParameters.Count; i++) {
if (method.GenericParameters[i].Position != i)
@ -1876,8 +1882,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1876,8 +1882,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
TranslateModifiers(property.GetMethod ?? property.SetMethod, p);
p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property);
p.Getter = ReadMethod(property.GetMethod, parentType);
p.Setter = ReadMethod(property.SetMethod, parentType);
p.Getter = ReadMethod(property.GetMethod, parentType, p);
p.Setter = ReadMethod(property.SetMethod, parentType, p);
if (property.HasParameters) {
foreach (ParameterDefinition par in property.Parameters) {
@ -1904,9 +1910,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1904,9 +1910,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
TranslateModifiers(ev.AddMethod, e);
e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev);
e.AddAccessor = ReadMethod(ev.AddMethod, parentType);
e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType);
e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType);
e.AddAccessor = ReadMethod(ev.AddMethod, parentType, e);
e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, e);
e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, e);
AddAttributes(ev, e);

17
ICSharpCode.NRefactory/TypeSystem/IMethod.cs

@ -39,6 +39,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -39,6 +39,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsPartialMethodDeclaration { get; }
bool IsPartialMethodImplementation { get; }
/// <summary>
/// If this method is an accessor, returns a reference to the corresponding property/event.
/// Otherwise, returns null.
/// </summary>
IUnresolvedMember AccessorOwner { get; }
/// <summary>
/// Resolves the member.
/// </summary>
@ -75,5 +81,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -75,5 +81,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsConstructor { get; }
bool IsDestructor { get; }
bool IsOperator { get; }
/// <summary>
/// Gets whether the method is a property/event accessor.
/// </summary>
bool IsAccessor { get; }
/// <summary>
/// If this method is an accessor, returns the corresponding property/event.
/// Otherwise, returns null.
/// </summary>
IMember AccessorOwner { get; }
}
}

14
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs

@ -190,6 +190,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -190,6 +190,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public bool IsOperator {
get { return ((IUnresolvedMethod)unresolved).IsOperator; }
}
public bool IsAccessor {
get { return ((IUnresolvedMethod)unresolved).AccessorOwner != null; }
}
public IMember AccessorOwner {
get {
var reference = ((IUnresolvedMethod)unresolved).AccessorOwner;
if (reference != null)
return reference.Resolve(context);
else
return null;
}
}
public override IMemberReference ToMemberReference()
{

32
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs

@ -32,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -32,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IList<IUnresolvedAttribute> returnTypeAttributes;
IList<IUnresolvedTypeParameter> typeParameters;
IList<IUnresolvedParameter> parameters;
IUnresolvedMember accessorOwner;
protected override void FreezeInternal()
{
@ -125,6 +126,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -125,6 +126,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
public IUnresolvedMember AccessorOwner {
get { return accessorOwner; }
set {
ThrowIfFrozen();
accessorOwner = value;
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
@ -150,6 +159,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -150,6 +159,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override IMember Resolve(ITypeResolveContext context)
{
if (accessorOwner != null) {
var owner = accessorOwner.Resolve(context);
if (owner != null) {
IProperty p = owner as IProperty;
if (p != null) {
if (p.CanGet && p.Getter.Name == this.Name)
return p.Getter;
if (p.CanSet && p.Setter.Name == this.Name)
return p.Setter;
}
IEvent e = owner as IEvent;
if (e != null) {
if (e.CanAdd && e.AddAccessor.Name == this.Name)
return e.AddAccessor;
if (e.CanRemove && e.RemoveAccessor.Name == this.Name)
return e.RemoveAccessor;
if (e.CanInvoke && e.InvokeAccessor.Name == this.Name)
return e.InvokeAccessor;
}
}
return null;
}
ITypeReference interfaceTypeReference = null;
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1)
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference;

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

@ -101,10 +101,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -101,10 +101,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (accessorDefinition == null)
return null;
var result = LazyInit.VolatileRead(ref cachingField);
if (result != null)
if (result != null) {
return result;
else
return LazyInit.GetOrSet(ref cachingField, new SpecializedMethod(accessorDefinition, substitution));
} else {
var sm = new SpecializedMethod(accessorDefinition, substitution);
//sm.AccessorOwner = this;
return LazyInit.GetOrSet(ref cachingField, sm);
}
}
/// <summary>

23
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

@ -21,7 +21,7 @@ using System.Collections.Generic; @@ -21,7 +21,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -121,6 +121,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -121,6 +121,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return methodDefinition.IsOperator; }
}
public bool IsAccessor {
get { return methodDefinition.IsAccessor; }
}
IMember accessorOwner;
public IMember AccessorOwner {
get {
var result = LazyInit.VolatileRead(ref accessorOwner);
if (result != null) {
return result;
} else {
result = SpecializedMember.Create(methodDefinition.AccessorOwner, this.Substitution);
return LazyInit.GetOrSet(ref accessorOwner, result);
}
}
internal set {
accessorOwner = value;
}
}
public override IMemberReference ToMemberReference()
{
// Pass the MethodTypeArguments to the SpecializingMemberReference only if

10
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -101,6 +101,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -101,6 +101,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
IEnumerableOfT,
/// <summary><c>System.Collections.Generic.IEnumerator{T}</c></summary>
IEnumeratorOfT,
/// <summary><c>System.Collections.Generic.ICollection</c></summary>
ICollection,
/// <summary><c>System.Collections.Generic.ICollection{T}</c></summary>
ICollectionOfT,
/// <summary><c>System.Collections.Generic.IList</c></summary>
IList,
/// <summary><c>System.Collections.Generic.IList{T}</c></summary>
IListOfT,
/// <summary><c>System.Collections.Generic.IReadOnlyList{T}</c></summary>
@ -158,7 +164,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -158,7 +164,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
new KnownTypeReference(KnownTypeCode.IEnumerator, "System.Collections", "IEnumerator"),
new KnownTypeReference(KnownTypeCode.IEnumerableOfT, "System.Collections.Generic", "IEnumerable", 1),
new KnownTypeReference(KnownTypeCode.IEnumeratorOfT, "System.Collections.Generic", "IEnumerator", 1),
new KnownTypeReference(KnownTypeCode.ICollection, "System.Collections", "ICollection"),
new KnownTypeReference(KnownTypeCode.ICollectionOfT, "System.Collections.Generic", "ICollection", 1),
new KnownTypeReference(KnownTypeCode.IList, "System.Collections", "IList"),
new KnownTypeReference(KnownTypeCode.IListOfT, "System.Collections.Generic", "IList", 1),
new KnownTypeReference(KnownTypeCode.IReadOnlyListOfT, "System.Collections.Generic", "IReadOnlyList", 1),
new KnownTypeReference(KnownTypeCode.Task, "System.Threading.Tasks", "Task"),
new KnownTypeReference(KnownTypeCode.TaskOfT, "System.Threading.Tasks", "Task", 1, baseType: KnownTypeCode.Task),

Loading…
Cancel
Save