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
return; return;
} }
string typeString = GetShortType(resolvedType, state); string typeString = GetShortType(resolvedType, state);
if (typeString.Contains(".")) { completionList.AddEnumMembers (resolvedType, state, typeString);
completionList.AddType(resolvedType, typeString);
}
foreach (var field in resolvedType.GetFields ()) {
if (field.IsConst || field.IsStatic) {
completionList.Result.Add(factory.CreateEntityCompletionData(
field,
typeString + "." + field.Name
)
);
}
}
DefaultCompletionString = typeString; DefaultCompletionString = typeString;
} }

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

@ -28,6 +28,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Completion namespace ICSharpCode.NRefactory.CSharp.Completion
{ {
@ -239,6 +240,25 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return 1; 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
get; get;
set; set;
} }
public DomRegion FormattingRegion {
get;
set;
}
public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null) public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null)
{ {
@ -111,6 +116,22 @@ namespace ICSharpCode.NRefactory.CSharp
this.options = options ?? TextEditorOptions.Default; this.options = options ?? TextEditorOptions.Default;
curIndent = new Indent(this.options); 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> /// <summary>
/// Applies the changes to the input document. /// Applies the changes to the input document.

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

@ -1007,6 +1007,14 @@ namespace ICSharpCode.NRefactory.CSharp
EndNode(primitiveExpression); 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) void WritePrimitiveValue(object val)
{ {
if (val == null) { if (val == null) {

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

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

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

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

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

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

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

@ -390,7 +390,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool isNullable = NullableType.IsNullable(expression.Type); bool isNullable = NullableType.IsNullable(expression.Type);
// the operator is overloadable: // 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)) { foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) {
userDefinedOperatorOR.AddCandidate(candidate); userDefinedOperatorOR.AddCandidate(candidate);
} }
@ -439,7 +439,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions); OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { expression });
foreach (var candidate in methodGroup) { foreach (var candidate in methodGroup) {
builtinOperatorOR.AddCandidate(candidate); builtinOperatorOR.AddCandidate(candidate);
} }
@ -569,7 +569,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IType rhsType = NullableType.GetUnderlyingType(rhs.Type); IType rhsType = NullableType.GetUnderlyingType(rhs.Type);
// the operator is overloadable: // 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>(); HashSet<IParameterizedMember> userOperatorCandidates = new HashSet<IParameterizedMember>();
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName)); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName));
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName)); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName));
@ -800,7 +800,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions); OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { lhs, rhs });
foreach (var candidate in methodGroup) { foreach (var candidate in methodGroup) {
builtinOperatorOR.AddCandidate(candidate); builtinOperatorOR.AddCandidate(candidate);
} }
@ -1260,7 +1260,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
else if (rr.IsCompileTimeConstant && c != Conversion.None) else if (rr.IsCompileTimeConstant && c != Conversion.None)
return ResolveCast(targetType, rr); return ResolveCast(targetType, rr);
else else
return new ConversionResolveResult(targetType, rr, c); return new ConversionResolveResult(targetType, rr, c, checkForOverflow);
} }
public ResolveResult ResolveCast(IType targetType, ResolveResult expression) public ResolveResult ResolveCast(IType targetType, ResolveResult expression)
@ -1291,7 +1291,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
Conversion c = conversions.ExplicitConversion(expression, targetType); 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) internal object CSharpPrimitiveCast(TypeCode targetType, object input)
@ -1891,7 +1891,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; MethodGroupResolveResult mgrr = target as MethodGroupResolveResult;
if (mgrr != null) { 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 != null) {
if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult)) if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult))
return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetResult.Type)); return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetResult.Type));
@ -1914,7 +1914,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); IMethod invokeMethod = target.Type.GetDelegateInvokeMethod();
if (invokeMethod != null) { if (invokeMethod != null) {
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
or.AddCandidate(invokeMethod); or.AddCandidate(invokeMethod);
return new CSharpInvocationResolveResult( return new CSharpInvocationResolveResult(
target, invokeMethod, //invokeMethod.ReturnType.Resolve(context), target, invokeMethod, //invokeMethod.ReturnType.Resolve(context),
@ -2003,6 +2003,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
variableName = variableName.Substring(1); variableName = variableName.Substring(1);
return char.ToLower(variableName[0]) + 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 #endregion
#region ResolveIndexer #region ResolveIndexer
@ -2035,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
// §7.6.6.2 Indexer access // §7.6.6.2 Indexer access
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup(); MemberLookup lookup = CreateMemberLookup();
var indexers = lookup.LookupIndexers(target.Type); var indexers = lookup.LookupIndexers(target.Type);
or.AddMethodLists(indexers); or.AddMethodLists(indexers);
@ -2090,7 +2097,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { if (type.Kind == TypeKind.Delegate && arguments.Length == 1) {
return Convert(arguments[0], type); return Convert(arguments[0], type);
} }
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup(); MemberLookup lookup = CreateMemberLookup();
foreach (IMethod ctor in type.GetConstructors()) { foreach (IMethod ctor in type.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess)) if (lookup.IsAccessible(ctor, allowProtectedAccess))
@ -2197,6 +2204,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Convert(input, boolean, c); 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) public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression)
{ {
// C# 4.0 spec §7.14: Conditional operator // C# 4.0 spec §7.14: Conditional operator

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

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

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

@ -170,6 +170,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
public bool AllowExpandingParams { get; set; } 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> /// <summary>
/// Gets the arguments for which this OverloadResolution instance was created. /// Gets the arguments for which this OverloadResolution instance was created.
/// </summary> /// </summary>
@ -801,9 +808,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
parameterType = SpecialType.UnknownType; parameterType = SpecialType.UnknownType;
} }
if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { 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 { } 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
if (resolverEnabled) { if (resolverEnabled) {
ResolveResult input = Resolve(asExpression.Expression); ResolveResult input = Resolve(asExpression.Expression);
var targetType = ResolveType(asExpression.Type); var targetType = ResolveType(asExpression.Type);
return new ConversionResolveResult(targetType, input, Conversion.TryCast); return new ConversionResolveResult(targetType, input, Conversion.TryCast, resolver.CheckForOverflow);
} else { } else {
ScanChildren(asExpression); ScanChildren(asExpression);
return null; return null;
@ -1498,7 +1498,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList<IType>.Instance, true); var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList<IType>.Instance, true);
var mgrr = addRR as MethodGroupResolveResult; var mgrr = addRR as MethodGroupResolveResult;
if (mgrr != null) { 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); var invocationRR = or.CreateResolveResult(initializedObject);
StoreResult(aie, invocationRR); StoreResult(aie, invocationRR);
ProcessConversionsInInvocation(null, aie.Elements, invocationRR); ProcessConversionsInInvocation(null, aie.Elements, invocationRR);
@ -3415,7 +3415,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
ResolveResult WrapResult(ResolveResult result) 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) ResolveResult IAstVisitor<ResolveResult>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
@ -3603,7 +3603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType); ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType);
if (currentQueryResult != null) { if (currentQueryResult != null) {
if (conversionToBool != Conversion.IdentityConversion && conversionToBool != Conversion.None) { 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); 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
if (accessor.IsNull) if (accessor.IsNull)
return null; return null;
var a = new DefaultUnresolvedMethod(currentTypeDefinition, prefix + p.Name); var a = new DefaultUnresolvedMethod(currentTypeDefinition, prefix + p.Name);
a.AccessorOwner = p;
a.Accessibility = GetAccessibility(accessor.Modifiers) ?? p.Accessibility; a.Accessibility = GetAccessibility(accessor.Modifiers) ?? p.Accessibility;
a.IsAbstract = p.IsAbstract; a.IsAbstract = p.IsAbstract;
a.IsOverride = p.IsOverridable; a.IsOverride = p.IsOverridable;

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

@ -20,11 +20,11 @@ using System;
using System.CodeDom; using System.CodeDom;
using System.CodeDom.Compiler; using System.CodeDom.Compiler;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Microsoft.CSharp; using Microsoft.CSharp;
using NUnit.Framework; using NUnit.Framework;
@ -45,138 +45,388 @@ namespace ICSharpCode.NRefactory.CSharp
parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Linq")); parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Linq"));
convertVisitor = new CodeDomConvertVisitor(); convertVisitor = new CodeDomConvertVisitor();
convertVisitor.AllowSnippetNodes = false;
convertVisitor.UseFullyQualifiedTypeNames = true; 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); CSharpResolver resolver = new CSharpResolver(compilation);
resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(compilation)); resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(compilation));
resolver = resolver.WithCurrentTypeDefinition(compilation.FindType(KnownTypeCode.Object).GetDefinition()); 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(); StringWriter writer = new StringWriter();
writer.NewLine = " "; writer.NewLine = " ";
new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); action(new CSharpCodeProvider(), codeObj, writer, new CodeGeneratorOptions { IndentString = " " });
return Regex.Replace(writer.ToString(), @"\s+", " "); 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] [Test]
public void CreateArray() public void MultidimensionalArrayTypeReference()
{ {
Assert.AreEqual("new int[10]", Convert( Assert.AreEqual("default(int[,][])", ConvertExpression("default(int[,][])"));
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10) }
}));
} }
[Test] [Test]
public void CreateJaggedArray() public void NestedTypeInGenericType()
{ {
Assert.AreEqual("new int[10][]", Convert( Assert.AreEqual("default(System.Collections.Generic.List<string>.Enumerator)",
new ArrayCreateExpression { ConvertExpression("default(List<string>.Enumerator)"));
Type = new PrimitiveType("int"), convertVisitor.UseFullyQualifiedTypeNames = false;
Arguments = { new PrimitiveExpression(10) }, Assert.AreEqual("default(List<string>.Enumerator)",
AdditionalArraySpecifiers = { new ArraySpecifier() } ConvertExpression("default(List<string>.Enumerator)"));
}));
} }
#endregion
#region Arrays
[Test] [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() public void Create2DArray()
{ {
Assert.AreEqual("new int[10, 20]", Convert( ConvertExpression("new int[10, 20]");
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10), new PrimitiveExpression(20) }
}));
} }
[Test] [Test]
public void CreateImplicitlyTypedArray() public void CreateImplicitlyTypedArray()
{ {
// implicitly-typed array not supported in CodeDom, so the conversion should infer the type // implicitly-typed array not supported in CodeDom, so the conversion should infer the type
Assert.AreEqual("new int[] { 1, 2, 3}", Convert( Assert.AreEqual("new int[] { 1, 2, 3}", ConvertExpression("new [] { 1, 2, 3 }"));
new ArrayCreateExpression { Assert.AreEqual("new System.Collections.Generic.List<string>[] { new System.Collections.Generic.List<string>()}",
AdditionalArraySpecifiers = { new ArraySpecifier() }, ConvertExpression("new [] { new List<string>() }"));
Initializer = new ArrayInitializerExpression {
Elements = {
new PrimitiveExpression(1),
new PrimitiveExpression(2),
new PrimitiveExpression(3)
}
}
}));
} }
[Test] [Test, ExpectedException(typeof(NotSupportedException))]
public void Create2DImplicitlyTypedArray() public void Create2DImplicitlyTypedArray()
{ {
Assert.AreEqual("new int[,] { { 1, 2 }, { 3, 4 }}", Convert( ConvertExpression("new [,] { { 1, 2 }, { 3, 4 }}");
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))
}
}
}));
} }
#endregion
#region Operators
[Test] [Test]
public void AdditionOperator() public void ArithmeticOperators()
{ {
Assert.AreEqual("(0 + 1)", Convert( Assert.AreEqual("(0 + 1)", ConvertExpression("0 + 1"));
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("(true && false)", ConvertExpression("true && false"));
Assert.AreEqual("(true || false)", ConvertExpression("true || false"));
} }
[Test] [Test]
public void EqualityOperator() public void EqualityOperator()
{ {
Assert.AreEqual("(0 == 1)", Convert( Assert.AreEqual("(0 == 1)", ConvertExpression("0 == 1"));
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Equality, new PrimitiveExpression(1)))); Assert.AreEqual("(default(object) == null)", ConvertExpression("default(object) == null"));
} }
[Test] [Test]
public void InEqualityOperator() public void InEqualityOperator()
{ {
Assert.AreEqual("((0 == 1) == false)", Convert( Assert.AreEqual("((0 == 1) == false)", ConvertExpression("0 != 1"));
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.InEquality, new PrimitiveExpression(1)))); Assert.AreEqual("(default(object) != null)", ConvertExpression("default(object) != null"));
} }
[Test] [Test]
public void ReferenceInEqualityOperator() public void UnaryOperators()
{ {
Assert.AreEqual("(default(object) != null)", Convert( Assert.AreEqual("(a == false)", ConvertExpression("!a"));
new BinaryOperatorExpression(new DefaultValueExpression(new PrimitiveType("object")), BinaryOperatorType.InEquality, new NullReferenceExpression()))); 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] [Test]
public void StaticProperty() public void StaticProperty()
{ {
Assert.AreEqual("System.Environment.TickCount", Convert( Assert.AreEqual("System.Environment.TickCount", ConvertExpression("Environment.TickCount"));
new IdentifierExpression("Environment").Member("TickCount")));
} }
[Test] [Test]
public void InstanceMethodInvocation() public void InstanceMethodInvocation()
{ {
Assert.AreEqual("this.Equals(null)", Assert.AreEqual("this.Equals(null)", ConvertExpression("Equals(null)"));
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression())));
} }
[Test] [Test]
public void StaticMethodInvocation() public void StaticMethodInvocation()
{ {
Assert.AreEqual("object.Equals(null, null)", Assert.AreEqual("object.Equals(null, null)", ConvertExpression("Equals(null, null)"));
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression(), new NullReferenceExpression()))); }
[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] [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
public NestedEnum EnumField; public NestedEnum EnumField;
public A Property { get; set; }
public enum NestedEnum { public enum NestedEnum {
EnumMember EnumMember
} }

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

@ -351,6 +351,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility);
Assert.AreEqual(new[] { "index" }, p.Getter.Parameters.Select(x => x.Name).ToArray()); Assert.AreEqual(new[] { "index" }, p.Getter.Parameters.Select(x => x.Name).ToArray());
Assert.AreEqual("System.String", p.Getter.ReturnType.ReflectionName); Assert.AreEqual("System.String", p.Getter.ReturnType.ReflectionName);
Assert.AreEqual(p, p.Getter.AccessorOwner);
} }
[Test] [Test]
@ -365,6 +366,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(TypeKind.Void, p.Setter.ReturnType.Kind); 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] [Test]
public void EnumTest() public void EnumTest()
{ {

32
ICSharpCode.NRefactory/Editor/IDocument.cs

@ -109,6 +109,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </remarks> /// </remarks>
void Insert(int offset, string text); 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> /// <summary>
/// Inserts text. /// Inserts text.
/// </summary> /// </summary>
@ -121,6 +133,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </param> /// </param>
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType); 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> /// <summary>
/// Removes text. /// Removes text.
/// </summary> /// </summary>
@ -136,6 +160,14 @@ namespace ICSharpCode.NRefactory.Editor
/// <param name="newText">The new text.</param> /// <param name="newText">The new text.</param>
void Replace(int offset, int length, string newText); 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> /// <summary>
/// Make the document combine the following actions into a single /// Make the document combine the following actions into a single
/// action for undo purposes. /// action for undo purposes.

15
ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs

@ -257,6 +257,21 @@ namespace ICSharpCode.NRefactory.Editor
throw new NotSupportedException(); 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() void IDocument.StartUndoableAction()
{ {
} }

28
ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs

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

7
ICSharpCode.NRefactory/Editor/StringTextSource.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Editor
[Serializable] [Serializable]
public class StringTextSource : ITextSource 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 string text;
readonly ITextSourceVersion version; readonly ITextSourceVersion version;
@ -69,7 +74,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <inheritdoc/> /// <inheritdoc/>
public ITextSource CreateSnapshot() public ITextSource CreateSnapshot()
{ {
return this; // StringTextBuffer is immutable return this; // StringTextSource is immutable
} }
/// <inheritdoc/> /// <inheritdoc/>

30
ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs

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

11
ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Semantics
public readonly ResolveResult Input; public readonly ResolveResult Input;
public readonly Conversion Conversion; 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) public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion)
: base(targetType) : base(targetType)
{ {
@ -38,6 +43,12 @@ namespace ICSharpCode.NRefactory.Semantics
this.Conversion = conversion; this.Conversion = conversion;
} }
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow)
: this(targetType, input, conversion)
{
this.CheckForOverflow = checkForOverflow;
}
public override bool IsError { public override bool IsError {
get { return !Conversion.IsValid; } get { return !Conversion.IsValid; }
} }

10
ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs

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

17
ICSharpCode.NRefactory/TypeSystem/IMethod.cs

@ -39,6 +39,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsPartialMethodDeclaration { get; } bool IsPartialMethodDeclaration { get; }
bool IsPartialMethodImplementation { 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> /// <summary>
/// Resolves the member. /// Resolves the member.
/// </summary> /// </summary>
@ -75,5 +81,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsConstructor { get; } bool IsConstructor { get; }
bool IsDestructor { get; } bool IsDestructor { get; }
bool IsOperator { 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
public bool IsOperator { public bool IsOperator {
get { return ((IUnresolvedMethod)unresolved).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() public override IMemberReference ToMemberReference()
{ {

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

@ -32,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IList<IUnresolvedAttribute> returnTypeAttributes; IList<IUnresolvedAttribute> returnTypeAttributes;
IList<IUnresolvedTypeParameter> typeParameters; IList<IUnresolvedTypeParameter> typeParameters;
IList<IUnresolvedParameter> parameters; IList<IUnresolvedParameter> parameters;
IUnresolvedMember accessorOwner;
protected override void FreezeInternal() protected override void FreezeInternal()
{ {
@ -125,6 +126,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public IUnresolvedMember AccessorOwner {
get { return accessorOwner; }
set {
ThrowIfFrozen();
accessorOwner = value;
}
}
public override string ToString() public override string ToString()
{ {
StringBuilder b = new StringBuilder("["); StringBuilder b = new StringBuilder("[");
@ -150,6 +159,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override IMember Resolve(ITypeResolveContext context) 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; ITypeReference interfaceTypeReference = null;
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1) if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1)
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference; interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference;

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

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

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

@ -21,7 +21,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -121,6 +121,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return methodDefinition.IsOperator; } 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() public override IMemberReference ToMemberReference()
{ {
// Pass the MethodTypeArguments to the SpecializingMemberReference only if // Pass the MethodTypeArguments to the SpecializingMemberReference only if

10
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

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

Loading…
Cancel
Save