Browse Source

Merge branch 'master' into soc-master

Conflicts:
	ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
	ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
newNRvisualizers
Simon Lindgren 14 years ago
parent
commit
f562e974a9
  1. 88
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  2. 182
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  3. 26
      ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  4. 198
      ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs
  5. 40
      ICSharpCode.NRefactory.CSharp/Completion/IMemberProvider.cs
  6. 2
      ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  7. 8
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  8. 8
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  9. 119
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  10. 21
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  11. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs
  12. 93
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractFieldAction.cs
  13. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/UseExplicitTypeAction.cs
  14. 43
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/DefaultRules.cs
  15. 18
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/WordParser.cs
  16. 11
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  17. 48
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  18. 4
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  19. 11
      ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
  20. 8
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  21. 1
      ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
  22. 2
      ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs
  23. 2
      ICSharpCode.NRefactory.Demo/CSDemo.cs
  24. 149
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs
  25. 6
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs
  26. 67
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  27. 52
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs
  28. 376
      ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
  29. 106
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs
  30. 20
      ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs
  31. 34
      ICSharpCode.NRefactory.Tests/FormattingTests/TestWrapping.cs
  32. 3
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  33. 1
      ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs
  34. 2
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  35. 11
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  36. 11
      ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs
  37. 32
      ICSharpCode.NRefactory/Editor/IDocument.cs
  38. 15
      ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs
  39. 28
      ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs
  40. 7
      ICSharpCode.NRefactory/Editor/StringTextSource.cs
  41. 30
      ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs
  42. 11
      ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs
  43. 10
      ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs
  44. 16
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  45. 17
      ICSharpCode.NRefactory/TypeSystem/IMethod.cs
  46. 14
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs
  47. 32
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs
  48. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  49. 23
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  50. 10
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

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

@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
public bool CloseOnSquareBrackets; public bool CloseOnSquareBrackets;
#endregion #endregion
public CSharpCompletionEngine(IDocument document, ICompletionDataFactory factory, IProjectContent content, CSharpTypeResolveContext ctx, CompilationUnit unit, CSharpParsedFile parsedFile) : base (content, ctx, unit, parsedFile) public CSharpCompletionEngine(IDocument document, ICompletionContextProvider completionContextProvider, ICompletionDataFactory factory, IProjectContent content, CSharpTypeResolveContext ctx) : base (content, completionContextProvider, ctx)
{ {
if (document == null) { if (document == null) {
throw new ArgumentNullException("document"); throw new ArgumentNullException("document");
@ -239,7 +239,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
parent = (ArrayInitializerExpression)parent.Parent; parent = (ArrayInitializerExpression)parent.Parent;
if (p != null) { if (p != null) {
var contextList = new CompletionDataWrapper(this); var contextList = new CompletionDataWrapper(this);
var initializerResult = ResolveExpression(p, unit); var initializerResult = ResolveExpression(p);
if (initializerResult != null && initializerResult.Item1.Type.Kind != TypeKind.Unknown) { if (initializerResult != null && initializerResult.Item1.Type.Kind != TypeKind.Unknown) {
// check 3 cases: // check 3 cases:
// 1) New initalizer { xpr // 1) New initalizer { xpr
@ -255,7 +255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
if (prev != null && !(prev is NamedExpression)) { if (prev != null && !(prev is NamedExpression)) {
AddContextCompletion(contextList, GetState(), n, unit); AddContextCompletion(contextList, GetState(), n);
// case 3) // case 3)
return contextList.Result; return contextList.Result;
} }
@ -279,7 +279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return contextList.Result; return contextList.Result;
} }
AddContextCompletion(contextList, GetState(), n, unit); AddContextCompletion(contextList, GetState(), n);
return contextList.Result; return contextList.Result;
} }
} }
@ -480,8 +480,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AddContextCompletion( AddContextCompletion(
wrapper, wrapper,
resolveResult.Item2, resolveResult.Item2,
expressionOrVariableDeclaration.Node, expressionOrVariableDeclaration.Node);
expressionOrVariableDeclaration.Unit);
AddEnumMembers(wrapper, resolveResult.Item1.Type, resolveResult.Item2); AddEnumMembers(wrapper, resolveResult.Item1.Type, resolveResult.Item2);
AutoCompleteEmptyMatch = false; AutoCompleteEmptyMatch = false;
return wrapper.Result; return wrapper.Result;
@ -742,8 +741,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (n != null && n.Parent is InvocationExpression) { if (n != null && n.Parent is InvocationExpression) {
var invokeParent = (InvocationExpression)n.Parent; var invokeParent = (InvocationExpression)n.Parent;
var invokeResult = ResolveExpression( var invokeResult = ResolveExpression(
invokeParent.Target, invokeParent.Target
identifierStart.Unit
); );
var mgr = invokeResult != null ? invokeResult.Item1 as MethodGroupResolveResult : null; var mgr = invokeResult != null ? invokeResult.Item1 as MethodGroupResolveResult : null;
if (mgr != null) { if (mgr != null) {
@ -777,7 +775,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
if (n != null && n.Parent is ObjectCreateExpression) { if (n != null && n.Parent is ObjectCreateExpression) {
var invokeResult = ResolveExpression(n.Parent, identifierStart.Unit); var invokeResult = ResolveExpression(n.Parent);
var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null; var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null;
if (mgr != null) { if (mgr != null) {
foreach (var constructor in mgr.Type.GetConstructors ()) { foreach (var constructor in mgr.Type.GetConstructors ()) {
@ -797,14 +795,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
// check for compare to enum case // check for compare to enum case
if (evaluationExpr != null) { if (evaluationExpr != null) {
resolveResult = ResolveExpression(evaluationExpr, identifierStart.Unit); resolveResult = ResolveExpression(evaluationExpr);
if (resolveResult != null && resolveResult.Item1.Type.Kind == TypeKind.Enum) { if (resolveResult != null && resolveResult.Item1.Type.Kind == TypeKind.Enum) {
var wrapper = new CompletionDataWrapper(this); var wrapper = new CompletionDataWrapper(this);
AddContextCompletion( AddContextCompletion(
wrapper, wrapper,
resolveResult.Item2, resolveResult.Item2,
evaluationExpr, evaluationExpr
identifierStart.Unit
); );
AddEnumMembers(wrapper, resolveResult.Item1.Type, resolveResult.Item2); AddEnumMembers(wrapper, resolveResult.Item1.Type, resolveResult.Item2);
AutoCompleteEmptyMatch = false; AutoCompleteEmptyMatch = false;
@ -827,7 +824,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return DefaultControlSpaceItems(); return DefaultControlSpaceItems();
} }
var initalizerResult = ResolveExpression(n.Parent, identifierStart.Unit); var initalizerResult = ResolveExpression(n.Parent);
var concreteNode = identifierStart.Unit.GetNodeAt<IdentifierExpression>(location); var concreteNode = identifierStart.Unit.GetNodeAt<IdentifierExpression>(location);
// check if we're on the right side of an initializer expression // check if we're on the right side of an initializer expression
@ -869,8 +866,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
if (n is MemberType) { if (n is MemberType) {
resolveResult = ResolveExpression( resolveResult = ResolveExpression(
((MemberType)n).Target, ((MemberType)n).Target
identifierStart.Unit
); );
return CreateTypeAndNamespaceCompletionData( return CreateTypeAndNamespaceCompletionData(
location, location,
@ -886,11 +882,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) { if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) {
nodes.Add(n.Parent); nodes.Add(n.Parent);
} }
var astResolver = new CSharpAstResolver( var astResolver = CompletionContextProvider.GetResolver (csResolver, identifierStart.Unit);
csResolver,
identifierStart.Unit,
CSharpParsedFile
);
astResolver.ApplyNavigator(new NodeListResolveVisitorNavigator(nodes)); astResolver.ApplyNavigator(new NodeListResolveVisitorNavigator(nodes));
try { try {
csResolver = astResolver.GetResolverStateBefore(n); csResolver = astResolver.GetResolverStateBefore(n);
@ -917,8 +909,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AddContextCompletion( AddContextCompletion(
contextList, contextList,
csResolver, csResolver,
identifierStart.Node, identifierStart.Node
identifierStart.Unit
); );
return contextList.Result; return contextList.Result;
// if (stub.Parent is BlockStatement) // if (stub.Parent is BlockStatement)
@ -1111,7 +1102,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
Tuple<ResolveResult, CSharpResolver> rr; Tuple<ResolveResult, CSharpResolver> rr;
if (xp != null) { if (xp != null) {
node = xp.Node; node = xp.Node;
rr = ResolveExpression(node, xp.Unit); rr = ResolveExpression(node);
unit = xp.Unit; unit = xp.Unit;
} else { } else {
unit = ParseStub("foo", false); unit = ParseStub("foo", false);
@ -1120,7 +1111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
location.Column + 2, location.Column + 2,
n => n is Expression || n is AstType n => n is Expression || n is AstType
); );
rr = ResolveExpression(node, unit); rr = ResolveExpression(node);
} }
if (node is Identifier && node.Parent is ForeachStatement) { if (node is Identifier && node.Parent is ForeachStatement) {
var foreachStmt = (ForeachStatement)node.Parent; var foreachStmt = (ForeachStatement)node.Parent;
@ -1152,7 +1143,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return wrapper.Result; return wrapper.Result;
} }
} }
if (Unit != null && (node == null || node is TypeDeclaration)) { /* if (Unit != null && (node == null || node is TypeDeclaration)) {
var constructor = Unit.GetNodeAt<ConstructorDeclaration>( var constructor = Unit.GetNodeAt<ConstructorDeclaration>(
location.Line, location.Line,
location.Column - 3 location.Column - 3
@ -1162,7 +1153,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.AddCustom("base"); wrapper.AddCustom("base");
return wrapper.Result; return wrapper.Result;
} }
} }*/
var initializer = node != null ? node.Parent as ArrayInitializerExpression : null; var initializer = node != null ? node.Parent as ArrayInitializerExpression : null;
if (initializer != null) { if (initializer != null) {
@ -1190,12 +1181,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
csResolver = GetState(); csResolver = GetState();
} }
} }
AddContextCompletion(wrapper, csResolver, node, unit); AddContextCompletion(wrapper, csResolver, node);
return wrapper.Result; return wrapper.Result;
} }
void AddContextCompletion(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, CompilationUnit unit) void AddContextCompletion(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node)
{ {
if (state != null && !(node is AstType)) { if (state != null && !(node is AstType)) {
foreach (var variable in state.LocalVariables) { foreach (var variable in state.LocalVariables) {
@ -1266,7 +1257,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.Result.AddRange(factory.CreateCodeTemplateCompletionData()); wrapper.Result.AddRange(factory.CreateCodeTemplateCompletionData());
if (node != null && node.Role == Roles.Argument) { if (node != null && node.Role == Roles.Argument) {
var resolved = ResolveExpression(node.Parent, unit); var resolved = ResolveExpression(node.Parent);
var invokeResult = resolved != null ? resolved.Item1 as CSharpInvocationResolveResult : null; var invokeResult = resolved != null ? resolved.Item1 as CSharpInvocationResolveResult : null;
if (invokeResult != null) { if (invokeResult != null) {
int argNum = 0; int argNum = 0;
@ -1284,7 +1275,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
if (node is Expression) { if (node is Expression) {
var astResolver = new CSharpAstResolver(state, unit, CSharpParsedFile); var root = node;
while (root.Parent != null)
root = root.Parent;
var astResolver = CompletionContextProvider.GetResolver (state, root);
foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)node)) { foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)node)) {
if (type.Kind == TypeKind.Enum) { if (type.Kind == TypeKind.Enum) {
AddEnumMembers(wrapper, type, state); AddEnumMembers(wrapper, type, state);
@ -1320,10 +1314,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null, Action<ICompletionData, IType> callback = null) void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null, Action<ICompletionData, IType> callback = null)
{ {
var lookup = new MemberLookup( var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
ctx.CurrentTypeDefinition,
Compilation.MainAssembly
);
if (currentType != null) { if (currentType != null) {
for (var ct = currentType; ct != null; ct = ct.DeclaringTypeDefinition) { for (var ct = currentType; ct != null; ct = ct.DeclaringTypeDefinition) {
foreach (var nestedType in ct.NestedTypes) { foreach (var nestedType in ct.NestedTypes) {
@ -1384,7 +1375,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.AddTypeParameter(p); wrapper.AddTypeParameter(p);
} }
} }
var scope = CSharpParsedFile.GetUsingScope(location).Resolve(Compilation); var scope = ctx.CurrentUsingScope;
for (var n = scope; n != null; n = n.Parent) { for (var n = scope; n != null; n = n.Parent) {
foreach (var pair in n.UsingAliases) { foreach (var pair in n.UsingAliases) {
@ -1523,7 +1514,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
parent = parent.Parent; parent = parent.Parent;
} }
if (parent is VariableDeclarationStatement) { if (parent is VariableDeclarationStatement) {
var resolved = ResolveExpression(parent, isAsExpression.Unit); var resolved = ResolveExpression(parent);
if (resolved != null) { if (resolved != null) {
isAsType = resolved.Item1.Type; isAsType = resolved.Item1.Type;
} }
@ -1662,11 +1653,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var expressionOrVariableDeclaration = GetNewExpressionAt(j); var expressionOrVariableDeclaration = GetNewExpressionAt(j);
if (expressionOrVariableDeclaration == null) if (expressionOrVariableDeclaration == null)
return null; return null;
var astResolver = new CSharpAstResolver( var astResolver = CompletionContextProvider.GetResolver(GetState(), expressionOrVariableDeclaration.Unit);
GetState(),
expressionOrVariableDeclaration.Unit,
CSharpParsedFile
);
hintType = CreateFieldAction.GetValidTypes( hintType = CreateFieldAction.GetValidTypes(
astResolver, astResolver,
expressionOrVariableDeclaration.Node as Expression expressionOrVariableDeclaration.Node as Expression
@ -1689,8 +1676,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AddContextCompletion( AddContextCompletion(
inList, inList,
rr != null ? rr.Item2 : GetState(), rr != null ? rr.Item2 : GetState(),
expr.Node, expr.Node
Unit
); );
return inList.Result; return inList.Result;
} }
@ -2149,11 +2135,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var exprParent = resolvedNode.GetParent<Expression>(); var exprParent = resolvedNode.GetParent<Expression>();
var unit = exprParent != null ? exprParent.GetParent<CompilationUnit>() : null; var unit = exprParent != null ? exprParent.GetParent<CompilationUnit>() : null;
var astResolver = unit != null ? new CSharpAstResolver( var astResolver = unit != null ? CompletionContextProvider.GetResolver(state, unit) : null;
state,
unit,
CSharpParsedFile
) : null;
IType hintType = exprParent != null && astResolver != null ? IType hintType = exprParent != null && astResolver != null ?
CreateFieldAction.GetValidTypes(astResolver, exprParent) .FirstOrDefault() : CreateFieldAction.GetValidTypes(astResolver, exprParent) .FirstOrDefault() :
null; null;
@ -2238,7 +2220,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AutoCompleteEmptyMatch = false; AutoCompleteEmptyMatch = false;
AutoSelect = false; AutoSelect = false;
} }
AddContextCompletion(result, state, invocation, unit); AddContextCompletion(result, state, invocation);
// resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc); // resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc);
// if (addedDelegates.Count > 0) { // if (addedDelegates.Count > 0) {
@ -2372,7 +2354,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
// ADD Aliases // ADD Aliases
var scope = CSharpParsedFile.GetUsingScope(location).Resolve(Compilation); var scope = ctx.CurrentUsingScope;
for (var n = scope; n != null; n = n.Parent) { for (var n = scope; n != null; n = n.Parent) {
foreach (var pair in n.UsingAliases) { foreach (var pair in n.UsingAliases) {
@ -2752,7 +2734,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
sb.Append("a;"); sb.Append("a;");
AppendMissingClosingBrackets(sb, text, false); AppendMissingClosingBrackets(sb, text, false);
var stream = new System.IO.StringReader(sb.ToString()); var stream = new System.IO.StringReader(sb.ToString());
var completionUnit = parser.Parse(stream, CSharpParsedFile.FileName, 0); var completionUnit = parser.Parse(stream, "a.cs", 0);
stream.Close(); stream.Close();
var loc = document.GetLocation(offset); var loc = document.GetLocation(offset);
@ -2775,7 +2757,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AppendMissingClosingBrackets(sb, text, false); AppendMissingClosingBrackets(sb, text, false);
var stream = new System.IO.StringReader(sb.ToString()); var stream = new System.IO.StringReader(sb.ToString());
var completionUnit = parser.Parse(stream, CSharpParsedFile.FileName, 0); var completionUnit = parser.Parse(stream, "a.cs", 0);
stream.Close(); stream.Close();
var loc = document.GetLocation(offset); var loc = document.GetLocation(offset);
@ -2786,7 +2768,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
sb.Append("a ()"); sb.Append("a ()");
AppendMissingClosingBrackets(sb, text, false); AppendMissingClosingBrackets(sb, text, false);
stream = new System.IO.StringReader(sb.ToString()); stream = new System.IO.StringReader(sb.ToString());
completionUnit = parser.Parse(stream, CSharpParsedFile.FileName, 0); completionUnit = parser.Parse(stream, "a.cs", 0);
stream.Close(); stream.Close();
loc = document.GetLocation(offset); loc = document.GetLocation(offset);

182
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -1,4 +1,4 @@
// //
// CSharpCompletionEngineBase.cs // CSharpCompletionEngineBase.cs
// //
// Author: // Author:
@ -51,10 +51,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
#region Input properties #region Input properties
public CSharpTypeResolveContext ctx { get; private set; } public CSharpTypeResolveContext ctx { get; private set; }
public CompilationUnit Unit { get; private set; }
public CSharpParsedFile CSharpParsedFile { get; private set; }
public IProjectContent ProjectContent { get; private set; } public IProjectContent ProjectContent { get; private set; }
ICompilation compilation; ICompilation compilation;
@ -68,27 +64,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
#endregion #endregion
protected CSharpCompletionEngineBase (IProjectContent content, CSharpTypeResolveContext ctx, CompilationUnit unit, CSharpParsedFile parsedFile) protected CSharpCompletionEngineBase(IProjectContent content, ICompletionContextProvider completionContextProvider, CSharpTypeResolveContext ctx)
{ {
if (content == null) if (content == null)
throw new ArgumentNullException ("content"); throw new ArgumentNullException("content");
if (ctx == null) if (ctx == null)
throw new ArgumentNullException ("ctx"); throw new ArgumentNullException("ctx");
if (unit == null) if (completionContextProvider == null)
throw new ArgumentNullException ("unit"); throw new ArgumentNullException("completionContextProvider");
if (parsedFile == null)
throw new ArgumentNullException ("parsedFile");
this.ProjectContent = content; this.ProjectContent = content;
this.CompletionContextProvider = completionContextProvider;
this.ctx = ctx; this.ctx = ctx;
this.Unit = unit;
this.CSharpParsedFile = parsedFile;
} }
public IMemberProvider MemberProvider { public ICompletionContextProvider CompletionContextProvider {
get; get;
set; private set;
} }
public void SetOffset (int offset) public void SetOffset (int offset)
@ -97,8 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
this.offset = offset; this.offset = offset;
this.location = document.GetLocation (offset); this.location = document.GetLocation (offset);
var provider = MemberProvider ?? new DefaultMemberProvider (this); CompletionContextProvider.GetCurrentMembers (offset, out currentType, out currentMember);
provider.GetCurrentMembers (offset, out currentType, out currentMember);
} }
public bool GetParameterCompletionCommandOffset (out int cpos) public bool GetParameterCompletionCommandOffset (out int cpos)
@ -702,34 +694,16 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
string cachedText = null; // string cachedText = null;
protected virtual void Reset () protected virtual void Reset ()
{ {
cachedText = null; // cachedText = null;
} }
protected Tuple<string, TextLocation> GetMemberTextToCaret() protected Tuple<string, TextLocation> GetMemberTextToCaret()
{ {
int startOffset; return CompletionContextProvider.GetMemberTextToCaret(offset, currentType, currentMember);
if (currentMember != null && currentType != null && currentType.Kind != TypeKind.Enum) {
startOffset = document.GetOffset(currentMember.Region.Begin);
} else if (currentType != null) {
startOffset = document.GetOffset(currentType.Region.Begin);
} else {
startOffset = 0;
}
while (startOffset > 0) {
char ch = document.GetCharAt(startOffset - 1);
if (ch != ' ' && ch != '\t') {
break;
}
--startOffset;
}
if (cachedText == null)
cachedText = document.GetText (startOffset, offset - startOffset);
return Tuple.Create (cachedText, document.GetLocation (startOffset));
} }
protected ExpressionResult GetInvocationBeforeCursor(bool afterBracket) protected ExpressionResult GetInvocationBeforeCursor(bool afterBracket)
@ -806,10 +780,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (ExpressionResult tuple) protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (ExpressionResult tuple)
{ {
return ResolveExpression (tuple.Node, tuple.Unit); return ResolveExpression (tuple.Node);
} }
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(AstNode expr, CompilationUnit unit) protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(AstNode expr)
{ {
if (expr == null) { if (expr == null) {
return null; return null;
@ -823,12 +797,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
resolveNode = expr; resolveNode = expr;
} }
try { try {
var ctx = CSharpParsedFile.GetResolver(Compilation, location);
var root = expr.AncestorsAndSelf.FirstOrDefault(n => n is EntityDeclaration || n is CompilationUnit); var root = expr.AncestorsAndSelf.FirstOrDefault(n => n is EntityDeclaration || n is CompilationUnit);
if (root == null) { if (root == null) {
return null; return null;
} }
var csResolver = new CSharpAstResolver (ctx, root, CSharpParsedFile); var csResolver = CompletionContextProvider.GetResolver (GetState(), root);
var result = csResolver.Resolve(resolveNode); var result = csResolver.Resolve(resolveNode);
var state = csResolver.GetResolverStateBefore(resolveNode); var state = csResolver.GetResolverStateBefore(resolveNode);
return Tuple.Create(result, state); return Tuple.Create(result, state);
@ -839,128 +812,5 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
#endregion #endregion
class DefaultMemberProvider : IMemberProvider
{
CSharpCompletionEngineBase engine;
public DefaultMemberProvider (CSharpCompletionEngineBase engine)
{
this.engine = engine;
}
public void GetCurrentMembers (int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember)
{
//var document = engine.document;
var location = engine.location;
currentType = null;
foreach (var type in engine.CSharpParsedFile.TopLevelTypeDefinitions) {
if (type.Region.Begin < location)
currentType = type;
}
currentType = FindInnerType (currentType, location);
// location is beyond last reported end region, now we need to check, if the end region changed
if (currentType != null && currentType.Region.End < location) {
if (!IsInsideType (currentType, location))
currentType = null;
}
currentMember = null;
if (currentType != null) {
foreach (var member in currentType.Members) {
if (member.Region.Begin < location && (currentMember == null || currentMember.Region.Begin < member.Region.Begin))
currentMember = member;
}
}
// location is beyond last reported end region, now we need to check, if the end region changed
// NOTE: Enums are a special case, there the "last" field needs to be treated as current member
if (currentMember != null && currentMember.Region.End < location && currentType.Kind != TypeKind.Enum) {
if (!IsInsideType (currentMember, location))
currentMember = null;
}
var stack = GetBracketStack (engine.GetMemberTextToCaret ().Item1);
if (stack.Count == 0)
currentMember = null;
}
IUnresolvedTypeDefinition FindInnerType (IUnresolvedTypeDefinition parent, TextLocation location)
{
if (parent == null)
return null;
var currentType = parent;
foreach (var type in parent.NestedTypes) {
if (type.Region.Begin < location && location < type.Region.End)
currentType = FindInnerType (type, location);
}
return currentType;
}
bool IsInsideType (IUnresolvedEntity currentType, TextLocation location)
{
var document = engine.document;
int startOffset = document.GetOffset (currentType.Region.Begin);
int endOffset = document.GetOffset (location);
//bool foundEndBracket = false;
var bracketStack = new Stack<char> ();
bool isInString = false, isInChar = false;
bool isInLineComment = false, isInBlockComment = false;
for (int i = startOffset; i < endOffset; i++) {
char ch = document.GetCharAt (i);
switch (ch) {
case '(':
case '[':
case '{':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
bracketStack.Push (ch);
break;
case ')':
case ']':
case '}':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
if (bracketStack.Count > 0)
bracketStack.Pop ();
break;
case '\r':
case '\n':
isInLineComment = false;
break;
case '/':
if (isInBlockComment) {
if (i > 0 && document.GetCharAt (i - 1) == '*')
isInBlockComment = false;
} else if (!isInString && !isInChar && i + 1 < document.TextLength) {
char nextChar = document.GetCharAt (i + 1);
if (nextChar == '/')
isInLineComment = true;
if (!isInLineComment && nextChar == '*')
isInBlockComment = true;
}
break;
case '"':
if (!(isInChar || isInLineComment || isInBlockComment))
isInString = !isInString;
break;
case '\'':
if (!(isInString || isInLineComment || isInBlockComment))
isInChar = !isInChar;
break;
default :
break;
}
}
return bracketStack.Any (t => t == '{');
}
}
} }
} }

26
ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{ {
internal IParameterCompletionDataFactory factory; internal IParameterCompletionDataFactory factory;
public CSharpParameterCompletionEngine(IDocument document, IParameterCompletionDataFactory factory, IProjectContent content, CSharpTypeResolveContext ctx, CompilationUnit unit, CSharpParsedFile parsedFile) : base (content, ctx, unit, parsedFile) public CSharpParameterCompletionEngine(IDocument document, ICompletionContextProvider completionContextProvider, IParameterCompletionDataFactory factory, IProjectContent content, CSharpTypeResolveContext ctx) : base (content, completionContextProvider, ctx)
{ {
if (document == null) { if (document == null) {
throw new ArgumentNullException("document"); throw new ArgumentNullException("document");
@ -57,9 +57,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (currentMember == null && currentType == null) { if (currentMember == null && currentType == null) {
return null; return null;
} }
if (Unit == null) {
return null;
}
baseUnit = ParseStub("x] = a[1"); baseUnit = ParseStub("x] = a[1");
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; //var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
@ -80,9 +77,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (currentMember == null && currentType == null) { if (currentMember == null && currentType == null) {
return null; return null;
} }
if (Unit == null) {
return null;
}
baseUnit = ParseStub("a) {}", false); baseUnit = ParseStub("a) {}", false);
var expr = baseUnit.GetNodeAt <ConstructorInitializer>(location); var expr = baseUnit.GetNodeAt <ConstructorInitializer>(location);
@ -98,9 +92,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (currentMember == null && currentType == null) { if (currentMember == null && currentType == null) {
return null; return null;
} }
if (Unit == null) {
return null;
}
baseUnit = ParseStub("x> a"); baseUnit = ParseStub("x> a");
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; //var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
@ -171,7 +162,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
if (invoke.Node is ObjectCreateExpression) { if (invoke.Node is ObjectCreateExpression) {
var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type, invoke.Unit); var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type);
if (createType.Item1.Type.Kind == TypeKind.Unknown) if (createType.Item1.Type.Kind == TypeKind.Unknown)
return null; return null;
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
@ -234,7 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0) if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0)
return null; return null;
if (invoke.Node is ObjectCreateExpression) { if (invoke.Node is ObjectCreateExpression) {
var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type, invoke.Unit); var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
} }
@ -316,17 +307,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
List<string> GetUsedNamespaces() List<string> GetUsedNamespaces()
{ {
var scope = CSharpParsedFile.GetUsingScope(location); var scope = ctx.CurrentUsingScope;
var result = new List<string>(); var result = new List<string>();
var resolver = new CSharpResolver(ctx);
while (scope != null) { while (scope != null) {
result.Add(scope.NamespaceName); result.Add(scope.Namespace.FullName);
foreach (var u in scope.Usings) { foreach (var ns in scope.Usings) {
var ns = u.ResolveNamespace(resolver);
if (ns == null) {
continue;
}
result.Add(ns.FullName); result.Add(ns.FullName);
} }
scope = scope.Parent; scope = scope.Parent;

198
ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs

@ -0,0 +1,198 @@
//
// IMemberProvider.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
public interface ICompletionContextProvider
{
void GetCurrentMembers (int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember);
Tuple<string, TextLocation> GetMemberTextToCaret(int caretOffset, IUnresolvedTypeDefinition currentType, IUnresolvedMember currentMember);
CSharpAstResolver GetResolver (CSharpResolver resolver, AstNode rootNode);
}
public class DefaultCompletionContextProvider : ICompletionContextProvider
{
readonly IDocument document;
readonly CSharpParsedFile parsedFile;
public DefaultCompletionContextProvider (IDocument document, CSharpParsedFile parsedFile)
{
if (document == null)
throw new ArgumentNullException("document");
if (parsedFile == null)
throw new ArgumentNullException("parsedFile");
this.document = document;
this.parsedFile = parsedFile;
}
public void GetCurrentMembers(int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember)
{
//var document = engine.document;
var location = document.GetLocation(offset);
currentType = null;
foreach (var type in parsedFile.TopLevelTypeDefinitions) {
if (type.Region.Begin < location)
currentType = type;
}
currentType = FindInnerType (currentType, location);
// location is beyond last reported end region, now we need to check, if the end region changed
if (currentType != null && currentType.Region.End < location) {
if (!IsInsideType (currentType, location))
currentType = null;
}
currentMember = null;
if (currentType != null) {
foreach (var member in currentType.Members) {
if (member.Region.Begin < location && (currentMember == null || currentMember.Region.Begin < member.Region.Begin))
currentMember = member;
}
}
// location is beyond last reported end region, now we need to check, if the end region changed
// NOTE: Enums are a special case, there the "last" field needs to be treated as current member
if (currentMember != null && currentMember.Region.End < location && currentType.Kind != TypeKind.Enum) {
if (!IsInsideType (currentMember, location))
currentMember = null;
}/*
var stack = GetBracketStack (engine.GetMemberTextToCaret ().Item1);
if (stack.Count == 0)
currentMember = null;*/
}
IUnresolvedTypeDefinition FindInnerType (IUnresolvedTypeDefinition parent, TextLocation location)
{
if (parent == null)
return null;
var currentType = parent;
foreach (var type in parent.NestedTypes) {
if (type.Region.Begin < location && location < type.Region.End)
currentType = FindInnerType (type, location);
}
return currentType;
}
bool IsInsideType (IUnresolvedEntity currentType, TextLocation location)
{
int startOffset = document.GetOffset (currentType.Region.Begin);
int endOffset = document.GetOffset (location);
//bool foundEndBracket = false;
var bracketStack = new Stack<char> ();
bool isInString = false, isInChar = false;
bool isInLineComment = false, isInBlockComment = false;
for (int i = startOffset; i < endOffset; i++) {
char ch = document.GetCharAt (i);
switch (ch) {
case '(':
case '[':
case '{':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
bracketStack.Push (ch);
break;
case ')':
case ']':
case '}':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
if (bracketStack.Count > 0)
bracketStack.Pop ();
break;
case '\r':
case '\n':
isInLineComment = false;
break;
case '/':
if (isInBlockComment) {
if (i > 0 && document.GetCharAt (i - 1) == '*')
isInBlockComment = false;
} else if (!isInString && !isInChar && i + 1 < document.TextLength) {
char nextChar = document.GetCharAt (i + 1);
if (nextChar == '/')
isInLineComment = true;
if (!isInLineComment && nextChar == '*')
isInBlockComment = true;
}
break;
case '"':
if (!(isInChar || isInLineComment || isInBlockComment))
isInString = !isInString;
break;
case '\'':
if (!(isInString || isInLineComment || isInBlockComment))
isInChar = !isInChar;
break;
default :
break;
}
}
return bracketStack.Any (t => t == '{');
}
public Tuple<string, TextLocation> GetMemberTextToCaret(int caretOffset, IUnresolvedTypeDefinition currentType, IUnresolvedMember currentMember)
{
int startOffset;
if (currentMember != null && currentType != null && currentType.Kind != TypeKind.Enum) {
startOffset = document.GetOffset(currentMember.Region.Begin);
} else if (currentType != null) {
startOffset = document.GetOffset(currentType.Region.Begin);
} else {
startOffset = 0;
}
while (startOffset > 0) {
char ch = document.GetCharAt(startOffset - 1);
if (ch != ' ' && ch != '\t') {
break;
}
--startOffset;
}
return Tuple.Create (document.GetText (startOffset, caretOffset - startOffset), document.GetLocation (startOffset));
}
public CSharpAstResolver GetResolver (CSharpResolver resolver, AstNode rootNode)
{
return new CSharpAstResolver (resolver, rootNode, parsedFile);
}
}
}

40
ICSharpCode.NRefactory.CSharp/Completion/IMemberProvider.cs

@ -1,40 +0,0 @@
//
// IMemberProvider.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
public interface IMemberProvider
{
void GetCurrentMembers (int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember);
}
}

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

@ -1822,7 +1822,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) { if (methodCallArgumentWrapping == Wrapping.DoNotWrap) {
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
} else { } else {
bool sameLine = rParToken.GetPrevNode().StartLocation.Line == rParToken.StartLocation.Line; bool sameLine = rParToken.GetPrevNode().EndLocation.Line == rParToken.StartLocation.Line;
if (sameLine) { if (sameLine) {
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
} else { } else {

8
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{53DCA265-3C3C-42F9-B647-F72BA678122B}</ProjectGuid> <ProjectGuid>{53DCA265-3C3C-42F9-B647-F72BA678122B}</ProjectGuid>
@ -41,8 +41,7 @@
<DefineConstants>TRACE;FULL_AST</DefineConstants> <DefineConstants>TRACE;FULL_AST</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType> <DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>
@ -294,7 +293,6 @@
<Compile Include="Completion\CSharpCompletionEngine.cs" /> <Compile Include="Completion\CSharpCompletionEngine.cs" />
<Compile Include="Completion\CSharpCompletionEngineBase.cs" /> <Compile Include="Completion\CSharpCompletionEngineBase.cs" />
<Compile Include="Completion\CSharpParameterCompletionEngine.cs" /> <Compile Include="Completion\CSharpParameterCompletionEngine.cs" />
<Compile Include="Completion\IMemberProvider.cs" />
<Compile Include="Parser\mcs\module.cs" /> <Compile Include="Parser\mcs\module.cs" />
<Compile Include="Parser\mcs\settings.cs" /> <Compile Include="Parser\mcs\settings.cs" />
<Compile Include="Parser\mcs\SourceMethodBuilder.cs" /> <Compile Include="Parser\mcs\SourceMethodBuilder.cs" />
@ -381,6 +379,8 @@
<Compile Include="Refactoring\CodeActions\StaticMethodInvocationToExtensionMethodInvocationAction.cs" /> <Compile Include="Refactoring\CodeActions\StaticMethodInvocationToExtensionMethodInvocationAction.cs" />
<Compile Include="Refactoring\CodeActions\ExtensionMethodInvocationToStaticMethodInvocationAction.cs" /> <Compile Include="Refactoring\CodeActions\ExtensionMethodInvocationToStaticMethodInvocationAction.cs" />
<Compile Include="Refactoring\CodeActions\IterateViaForeachAction.cs" /> <Compile Include="Refactoring\CodeActions\IterateViaForeachAction.cs" />
<Compile Include="Refactoring\CodeActions\ExtractFieldAction.cs" />
<Compile Include="Completion\ICompletionContextProvider.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> <ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

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) {

119
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,8 +145,16 @@ namespace ICSharpCode.NRefactory.CSharp
CodeTypeReference Convert(IType type) CodeTypeReference Convert(IType type)
{ {
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); 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;
} }

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

@ -3598,6 +3598,7 @@ namespace ICSharpCode.NRefactory.CSharp
} }
ErrorReportPrinter errorReportPrinter = new ErrorReportPrinter (null); ErrorReportPrinter errorReportPrinter = new ErrorReportPrinter (null);
[Obsolete("Use the Errors/Warnings/ErrorsAndWarnings properties instead")]
public ErrorReportPrinter ErrorPrinter { public ErrorReportPrinter ErrorPrinter {
get { get {
return errorReportPrinter; return errorReportPrinter;
@ -3616,6 +3617,22 @@ namespace ICSharpCode.NRefactory.CSharp
} }
} }
public IEnumerable<Error> Errors {
get {
return errorReportPrinter.Errors.Where(e => e.ErrorType == ErrorType.Error);
}
}
public IEnumerable<Error> Warnings {
get {
return errorReportPrinter.Errors.Where(e => e.ErrorType == ErrorType.Warning);
}
}
public IEnumerable<Error> ErrorsAndWarnings {
get { return errorReportPrinter.Errors; }
}
public CompilationUnit Parse (ITextSource textSource, string fileName, int lineModifier = 0) public CompilationUnit Parse (ITextSource textSource, string fileName, int lineModifier = 0)
{ {
return Parse (textSource.CreateReader (), fileName, lineModifier); return Parse (textSource.CreateReader (), fileName, lineModifier);
@ -3733,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) {
@ -3741,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>

2
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs

@ -63,6 +63,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
ResolveResult targetResolveResult = null; ResolveResult targetResolveResult = null;
if (identifier is MemberReferenceExpression) { if (identifier is MemberReferenceExpression) {
targetResolveResult = context.Resolve(((MemberReferenceExpression)identifier).Target); targetResolveResult = context.Resolve(((MemberReferenceExpression)identifier).Target);
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition()); createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
} }

93
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractFieldAction.cs

@ -0,0 +1,93 @@
//
// ExtractFieldAction.cs
//
// Author:
// Nieve <>
//
// Copyright (c) 2012 Nieve
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using Mono.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Extract field", Description = "Extracts a field from a local variable declaration.")]
public class ExtractFieldAction : ICodeActionProvider
{
public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
//TODO: implement variable assignment & ctor param
var varInit = context.GetNode<VariableInitializer>();
if (varInit != null) {
AstType type = varInit.GetPrevNode() as AstType;
if (type == null) yield break;
if (varInit.Parent is FieldDeclaration) yield break;
if (CannotExtractField(varInit)) yield break;
yield return new CodeAction("Extract field", s=>{
var name = varInit.Name;
FieldDeclaration field = new FieldDeclaration(){
ReturnType = type.Clone(),
Variables = { new VariableInitializer(name) }
};
AstNode nodeToRemove = RemoveDeclaration(varInit) ? varInit.Parent : type;
s.Remove(nodeToRemove, true);
s.InsertWithCursor(context.TranslateString("Extract field"),Script.InsertPosition.Before,field);
s.FormatText(varInit.Parent);
});
}
var idntf = context.GetNode<Identifier>();
if (idntf == null) yield break;
var paramDec = idntf.Parent as ParameterDeclaration;
if (paramDec != null) {
var ctor = paramDec.Parent as ConstructorDeclaration;
if (ctor == null) yield break;
MemberReferenceExpression thisField = new MemberReferenceExpression(new ThisReferenceExpression(), idntf.Name, new AstType[]{});
var assign = new AssignmentExpression(thisField, AssignmentOperatorType.Assign, new IdentifierExpression(idntf.Name));
var statement = new ExpressionStatement(assign);
var type = (idntf.GetPrevNode() as AstType).Clone();
FieldDeclaration field = new FieldDeclaration(){
ReturnType = type.Clone(),
Variables = { new VariableInitializer(idntf.Name) }
};
yield return new CodeAction("Extract field", s=>{
s.InsertWithCursor(context.TranslateString("Extract field"),Script.InsertPosition.Before,field);
s.AddTo(ctor.Body, statement);
});
}
}
static bool RemoveDeclaration (VariableInitializer varInit){
var result = varInit.Parent as VariableDeclarationStatement;
return result.Variables.First ().Initializer.IsNull;
}
static bool CannotExtractField (VariableInitializer varInit)
{
var result = varInit.Parent as VariableDeclarationStatement;
return result == null || result.Variables.Count != 1;
}
}
}

2
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/UseExplicitTypeAction.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!(!type.Equals(SpecialType.NullType) && !type.Equals(SpecialType.UnknownType))) { if (!(!type.Equals(SpecialType.NullType) && !type.Equals(SpecialType.UnknownType))) {
yield break; yield break;
} }
yield return new CodeAction (context.TranslateString("Use expcicit type"), script => { yield return new CodeAction (context.TranslateString("Use explicit type"), script => {
if (varDecl != null) { if (varDecl != null) {
script.Replace (varDecl.Type, context.CreateShortType (type)); script.Replace (varDecl.Type, context.CreateShortType (type));
} else { } else {

43
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/DefaultRules.cs

@ -39,24 +39,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield return new NamingRule(AffectedEntity.Class | AffectedEntity.Struct | AffectedEntity.Enum | AffectedEntity.Delegate) { yield return new NamingRule(AffectedEntity.Class | AffectedEntity.Struct | AffectedEntity.Enum | AffectedEntity.Delegate) {
Name = "Types", Name = "Types",
VisibilityMask = Modifiers.Public,
NamingStyle = NamingStyle.PascalCase NamingStyle = NamingStyle.PascalCase
}; };
yield return new NamingRule(AffectedEntity.Interface) { yield return new NamingRule(AffectedEntity.Interface) {
Name = "Interfaces", Name = "Interfaces",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public,
RequiredPrefixes = new [] { "I" } RequiredPrefixes = new [] { "I" }
}; };
yield return new NamingRule(AffectedEntity.CustomAttributes) { yield return new NamingRule(AffectedEntity.CustomAttributes) {
Name = "Attributes", Name = "Attributes",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public,
RequiredSuffixes = new [] { "Attribute" } RequiredSuffixes = new [] { "Attribute" }
}; };
yield return new NamingRule(AffectedEntity.CustomEventArgs) { yield return new NamingRule(AffectedEntity.CustomEventArgs) {
Name = "Event Arguments", Name = "Event Arguments",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public,
RequiredSuffixes = new [] { "EventArgs" } RequiredSuffixes = new [] { "EventArgs" }
}; };
@ -68,66 +72,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield return new NamingRule(AffectedEntity.Methods) { yield return new NamingRule(AffectedEntity.Methods) {
Name = "Methods", Name = "Methods",
VisibilityMask = Modifiers.Public | Modifiers.Protected,
NamingStyle = NamingStyle.PascalCase NamingStyle = NamingStyle.PascalCase
}; };
yield return new NamingRule(AffectedEntity.ReadonlyField) { yield return new NamingRule(AffectedEntity.ReadonlyField) {
Name = "Static Readonly Fields", Name = "Static Readonly Fields",
VisibilityMask = Modifiers.Public | Modifiers.Protected | Modifiers.Internal, VisibilityMask = Modifiers.Public | Modifiers.Protected,
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
IncludeInstanceMembers = false IncludeInstanceMembers = false
}; };
yield return new NamingRule(AffectedEntity.Field) { yield return new NamingRule(AffectedEntity.Field) {
Name = "Fields (Non Private)", Name = "Fields",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public | Modifiers.Protected | Modifiers.Internal VisibilityMask = Modifiers.Public | Modifiers.Protected
}; };
yield return new NamingRule(AffectedEntity.ReadonlyField) { yield return new NamingRule(AffectedEntity.ReadonlyField) {
Name = "ReadOnly Fields (Non Private)", Name = "ReadOnly Fields",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public | Modifiers.Protected | Modifiers.Internal, VisibilityMask = Modifiers.Public | Modifiers.Protected,
IncludeStaticEntities = false
};
yield return new NamingRule(AffectedEntity.Field | AffectedEntity.ReadonlyField) {
Name = "Fields (Private)",
NamingStyle = NamingStyle.CamelCase,
AllowedPrefixes = new [] { "_", "m_" },
VisibilityMask = Modifiers.Private,
IncludeStaticEntities = false
};
yield return new NamingRule(AffectedEntity.Field) {
Name = "Static Fields (Private)",
NamingStyle = NamingStyle.CamelCase,
VisibilityMask = Modifiers.Private,
IncludeStaticEntities = true,
IncludeInstanceMembers = false
};
yield return new NamingRule(AffectedEntity.ReadonlyField) {
Name = "ReadOnly Fields (Private)",
NamingStyle = NamingStyle.CamelCase,
VisibilityMask = Modifiers.Private,
AllowedPrefixes = new [] { "_", "m_" },
IncludeStaticEntities = false IncludeStaticEntities = false
}; };
yield return new NamingRule(AffectedEntity.ConstantField) { yield return new NamingRule(AffectedEntity.ConstantField) {
Name = "Constant Fields", Name = "Constant Fields",
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
VisibilityMask = Modifiers.Public | Modifiers.Protected | Modifiers.Internal | Modifiers.Private VisibilityMask = Modifiers.Public | Modifiers.Protected
}; };
yield return new NamingRule(AffectedEntity.Property) { yield return new NamingRule(AffectedEntity.Property) {
Name = "Properties", Name = "Properties",
VisibilityMask = Modifiers.Public | Modifiers.Protected,
NamingStyle = NamingStyle.PascalCase NamingStyle = NamingStyle.PascalCase
}; };
yield return new NamingRule(AffectedEntity.Event) { yield return new NamingRule(AffectedEntity.Event) {
Name = "Events", Name = "Events",
VisibilityMask = Modifiers.Public | Modifiers.Protected,
NamingStyle = NamingStyle.PascalCase NamingStyle = NamingStyle.PascalCase
}; };

18
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/WordParser.cs

@ -37,26 +37,28 @@ namespace ICSharpCode.NRefactory.CSharp
bool lastWasLower = false, lastWasUpper = false; bool lastWasLower = false, lastWasUpper = false;
for (int i = 0; i < identifier.Length; i++) { for (int i = 0; i < identifier.Length; i++) {
char c = identifier[i]; char c = identifier[i];
if (c == '_') { var category = char.GetUnicodeCategory (c);
if ((i - wordStart) > 0) { if (category == System.Globalization.UnicodeCategory.LowercaseLetter) {
words.Add (identifier.Substring (wordStart, i - wordStart));
}
wordStart = i + 1;
lastWasLower = lastWasUpper = false;
} else if (Char.IsLower (c)) {
if (lastWasUpper && (i - wordStart) > 2) { if (lastWasUpper && (i - wordStart) > 2) {
words.Add (identifier.Substring (wordStart, i - wordStart - 1)); words.Add (identifier.Substring (wordStart, i - wordStart - 1));
wordStart = i - 1; wordStart = i - 1;
} }
lastWasLower = true; lastWasLower = true;
lastWasUpper = false; lastWasUpper = false;
} else if (Char.IsUpper (c)) { } else if (category == System.Globalization.UnicodeCategory.UppercaseLetter) {
if (lastWasLower) { if (lastWasLower) {
words.Add (identifier.Substring (wordStart, i - wordStart)); words.Add (identifier.Substring (wordStart, i - wordStart));
wordStart = i; wordStart = i;
} }
lastWasLower = false; lastWasLower = false;
lastWasUpper = true; lastWasUpper = true;
} else {
if (c == '_') {
if ((i - wordStart) > 0)
words.Add(identifier.Substring(wordStart, i - wordStart));
wordStart = i + 1;
lastWasLower = lastWasUpper = false;
}
} }
} }
if (wordStart < identifier.Length) if (wordStart < identifier.Length)

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

@ -1243,7 +1243,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;
@ -1505,7 +1505,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);
@ -3422,7 +3422,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)
@ -3610,7 +3610,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;

2
ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs

@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
this.CompilationUnit = p.Parse(Content.CreateReader(), fileName); this.CompilationUnit = p.Parse(Content.CreateReader(), fileName);
if (p.HasErrors) { if (p.HasErrors) {
Console.WriteLine("Error parsing " + fileName + ":"); Console.WriteLine("Error parsing " + fileName + ":");
foreach (var error in p.ErrorPrinter.Errors) { foreach (var error in p.ErrorsAndWarnings) {
Console.WriteLine(" " + error.Region + " " + error.Message); Console.WriteLine(" " + error.Region + " " + error.Message);
} }
} }

2
ICSharpCode.NRefactory.Demo/CSDemo.cs

@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.Demo
b.Append(node.GetType().Name); b.Append(node.GetType().Name);
bool hasProperties = false; bool hasProperties = false;
foreach (PropertyInfo p in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { foreach (PropertyInfo p in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
if (p.Name == "NodeType" || p.Name == "IsNull") if (p.Name == "NodeType" || p.Name == "IsNull" || p.Name == "IsFrozen" || p.Name == "HasChildren")
continue; continue;
if (p.PropertyType == typeof(string) || p.PropertyType.IsEnum || p.PropertyType == typeof(bool)) { if (p.PropertyType == typeof(string) || p.PropertyType.IsEnum || p.PropertyType == typeof(bool)) {
if (!hasProperties) { if (!hasProperties) {

149
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs

@ -0,0 +1,149 @@
//
// CreateFieldTests.cs
//
// Author:
// Nieve Goor
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeActions
{
[TestFixture]
public class ExtractFieldTests : ContextActionTestBase
{
[Test]
public void TestWrongContext1 ()
{
TestWrongContext<ExtractFieldAction> (
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" $foo = 2;" + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
}
[Test]
public void TestWrongContext2 ()
{
TestWrongContext<ExtractFieldAction> (
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" int foo;" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" $foo = 2;" + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
}
[Test]
public void TestLocalInitializer()
{
string result = RunContextAction (
new ExtractFieldAction (),
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" int $foo = 5;" + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
Console.WriteLine (result);
Assert.AreEqual (
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" int foo;" + Environment.NewLine +
"" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" foo = 5;" + Environment.NewLine +
" }" + Environment.NewLine +
"}", result);
}
[Test]
public void TestLocalDeclaration()
{
string result = RunContextAction (
new ExtractFieldAction (),
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" int $foo;" + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
Console.WriteLine (result);
Assert.AreEqual (
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" int foo;" + Environment.NewLine +
"" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" }" + Environment.NewLine +
"}", result);
}
[Test]
public void TestCtorParam ()
{
string result = RunContextAction (
new ExtractFieldAction (),
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" TestClass (int $foo)" + Environment.NewLine +
" {" + Environment.NewLine +
" " + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
Assert.AreEqual (
"using System;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" int foo;" + Environment.NewLine +
"" + Environment.NewLine +
" TestClass (int foo)" + Environment.NewLine +
" {" + Environment.NewLine +
" this.foo = foo;" + Environment.NewLine +
" " + Environment.NewLine +
" }" + Environment.NewLine +
"}", result);
}
}
}

6
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs

@ -1,4 +1,4 @@
// //
// TestRefactoringContext.cs // TestRefactoringContext.cs
// //
// Author: // Author:
@ -246,8 +246,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
var doc = new StringBuilderDocument (content); var doc = new StringBuilderDocument (content);
var parser = new CSharpParser (); var parser = new CSharpParser ();
var unit = parser.Parse (content, "program.cs"); var unit = parser.Parse (content, "program.cs");
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (e => Console.WriteLine (e.Message)); Console.WriteLine (error.Message);
Assert.IsFalse (parser.HasErrors, "File contains parsing errors."); Assert.IsFalse (parser.HasErrors, "File contains parsing errors.");
unit.Freeze (); unit.Freeze ();
var parsedFile = unit.ToTypeSystem (); var parsedFile = unit.ToTypeSystem ();

67
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -199,46 +199,48 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
#endregion #endregion
} }
static CompletionDataList CreateProvider (string text, bool isCtrlSpace) static CompletionDataList CreateProvider(string text, bool isCtrlSpace)
{ {
string parsedText; string parsedText;
string editorText; string editorText;
int cursorPosition = text.IndexOf ('$'); int cursorPosition = text.IndexOf('$');
int endPos = text.IndexOf ('$', cursorPosition + 1); int endPos = text.IndexOf('$', cursorPosition + 1);
if (endPos == -1) { if (endPos == -1) {
parsedText = editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1); parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1);
} else { } else {
parsedText = text.Substring (0, cursorPosition) + new string (' ', endPos - cursorPosition) + text.Substring (endPos + 1); parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1);
editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring (endPos + 1); editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1);
cursorPosition = endPos - 1; cursorPosition = endPos - 1;
} }
var doc = new ReadOnlyDocument (editorText); var doc = new ReadOnlyDocument(editorText);
IProjectContent pctx = new CSharpProjectContent (); IProjectContent pctx = new CSharpProjectContent();
pctx = pctx.AddAssemblyReferences (new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
var compilationUnit = new CSharpParser ().Parse (parsedText, "program.cs"); var compilationUnit = new CSharpParser().Parse(parsedText, "program.cs");
compilationUnit.Freeze (); compilationUnit.Freeze();
var parsedFile = compilationUnit.ToTypeSystem (); var parsedFile = compilationUnit.ToTypeSystem();
pctx = pctx.UpdateProjectContent (null, parsedFile); pctx = pctx.UpdateProjectContent(null, parsedFile);
var cmp = pctx.CreateCompilation (); var cmp = pctx.CreateCompilation();
var loc = doc.GetLocation (cursorPosition); var loc = doc.GetLocation(cursorPosition);
var rctx = new CSharpTypeResolveContext (cmp.MainAssembly); var rctx = new CSharpTypeResolveContext(cmp.MainAssembly);
rctx = rctx.WithUsingScope (parsedFile.GetUsingScope (loc).Resolve (cmp)); rctx = rctx.WithUsingScope(parsedFile.GetUsingScope(loc).Resolve(cmp));
var curDef = parsedFile.GetInnermostTypeDefinition (loc); var curDef = parsedFile.GetInnermostTypeDefinition(loc);
if (curDef != null) { if (curDef != null) {
var resolvedDef = curDef.Resolve (rctx).GetDefinition (); var resolvedDef = curDef.Resolve(rctx).GetDefinition();
rctx = rctx.WithCurrentTypeDefinition (resolvedDef); rctx = rctx.WithCurrentTypeDefinition(resolvedDef);
var curMember = resolvedDef.Members.FirstOrDefault (m => m.Region.Begin <= loc && loc < m.BodyRegion.End); var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= loc && loc < m.BodyRegion.End);
if (curMember != null) if (curMember != null) {
rctx = rctx.WithCurrentMember (curMember); rctx = rctx.WithCurrentMember(curMember);
} }
var engine = new CSharpCompletionEngine (doc, new TestFactory (), pctx, rctx, compilationUnit, parsedFile); }
var mb = new DefaultCompletionContextProvider(doc, parsedFile);
var engine = new CSharpCompletionEngine (doc, mb, new TestFactory (), pctx, rctx);
engine.EolMarker = Environment.NewLine; engine.EolMarker = Environment.NewLine;
engine.FormattingPolicy = FormattingOptionsFactory.CreateMono (); engine.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
@ -253,17 +255,18 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
}; };
} }
Tuple<ReadOnlyDocument, CSharpCompletionEngine> GetContent (string text, CompilationUnit compilationUnit) Tuple<ReadOnlyDocument, CSharpCompletionEngine> GetContent(string text, CompilationUnit compilationUnit)
{ {
var doc = new ReadOnlyDocument (text); var doc = new ReadOnlyDocument(text);
IProjectContent pctx = new CSharpProjectContent (); IProjectContent pctx = new CSharpProjectContent();
pctx = pctx.AddAssemblyReferences (new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
var parsedFile = compilationUnit.ToTypeSystem (); var parsedFile = compilationUnit.ToTypeSystem();
pctx = pctx.UpdateProjectContent (null, parsedFile); pctx = pctx.UpdateProjectContent(null, parsedFile);
var cmp = pctx.CreateCompilation (); var cmp = pctx.CreateCompilation();
var engine = new CSharpCompletionEngine (doc, new TestFactory (), pctx, new CSharpTypeResolveContext (cmp.MainAssembly), compilationUnit, parsedFile); var mb = new DefaultCompletionContextProvider(doc, parsedFile);
var engine = new CSharpCompletionEngine (doc, mb, new TestFactory (), pctx, new CSharpTypeResolveContext (cmp.MainAssembly));
engine.EolMarker = Environment.NewLine; engine.EolMarker = Environment.NewLine;
engine.FormattingPolicy = FormattingOptionsFactory.CreateMono (); engine.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
return Tuple.Create (doc, engine); return Tuple.Create (doc, engine);

52
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs

@ -254,43 +254,45 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
#endregion #endregion
} }
internal static IParameterDataProvider CreateProvider (string text) internal static IParameterDataProvider CreateProvider(string text)
{ {
string parsedText; string parsedText;
string editorText; string editorText;
int cursorPosition = text.IndexOf ('$'); int cursorPosition = text.IndexOf('$');
int endPos = text.IndexOf ('$', cursorPosition + 1); int endPos = text.IndexOf('$', cursorPosition + 1);
if (endPos == -1) if (endPos == -1) {
parsedText = editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1); parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1);
else { } else {
parsedText = text.Substring (0, cursorPosition) + new string (' ', endPos - cursorPosition) + text.Substring (endPos + 1); parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1);
editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring (endPos + 1); editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1);
cursorPosition = endPos - 1; cursorPosition = endPos - 1;
} }
var doc = new ReadOnlyDocument (editorText); var doc = new ReadOnlyDocument(editorText);
IProjectContent pctx = new CSharpProjectContent (); IProjectContent pctx = new CSharpProjectContent();
pctx = pctx.AddAssemblyReferences (new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
var compilationUnit = new CSharpParser ().Parse (parsedText, "program.cs"); var compilationUnit = new CSharpParser().Parse(parsedText, "program.cs");
compilationUnit.Freeze (); compilationUnit.Freeze();
var parsedFile = compilationUnit.ToTypeSystem (); var parsedFile = compilationUnit.ToTypeSystem();
pctx = pctx.UpdateProjectContent (null, parsedFile); pctx = pctx.UpdateProjectContent(null, parsedFile);
var cmp = pctx.CreateCompilation (); var cmp = pctx.CreateCompilation();
var loc = doc.GetLocation (cursorPosition); var loc = doc.GetLocation(cursorPosition);
var rctx = new CSharpTypeResolveContext (cmp.MainAssembly); var rctx = new CSharpTypeResolveContext(cmp.MainAssembly);
rctx = rctx.WithUsingScope (parsedFile.GetUsingScope (loc).Resolve (cmp)); rctx = rctx.WithUsingScope(parsedFile.GetUsingScope(loc).Resolve(cmp));
var curDef = parsedFile.GetInnermostTypeDefinition (loc); var curDef = parsedFile.GetInnermostTypeDefinition(loc);
if (curDef != null) { if (curDef != null) {
rctx = rctx.WithCurrentTypeDefinition (curDef.Resolve (rctx).GetDefinition ()); rctx = rctx.WithCurrentTypeDefinition(curDef.Resolve(rctx).GetDefinition());
var curMember = parsedFile.GetMember (loc); var curMember = parsedFile.GetMember(loc);
if (curMember != null) if (curMember != null) {
rctx = rctx.WithCurrentMember (curMember.CreateResolved (rctx)); rctx = rctx.WithCurrentMember(curMember.CreateResolved(rctx));
} }
var engine = new CSharpParameterCompletionEngine (doc, new TestFactory (pctx), pctx, rctx, compilationUnit, parsedFile); }
var mb = new DefaultCompletionContextProvider(doc, parsedFile);
var engine = new CSharpParameterCompletionEngine (doc, mb, new TestFactory (pctx), pctx, rctx);
return engine.GetParameterDataProvider (cursorPosition, doc.GetCharAt (cursorPosition - 1)); return engine.GetParameterDataProvider (cursorPosition, doc.GetCharAt (cursorPosition - 1));
} }

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
} }
} }

106
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs

@ -57,24 +57,24 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
[Test] [Test]
public void TestClassName () public void TestClassName ()
{ {
var input = @"class anIssue {}"; var input = @"public class anIssue {}";
var output = @"class AnIssue {}"; var output = @"public class AnIssue {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestAttributeName () public void TestAttributeName ()
{ {
var input = @"class test : System.Attribute {}"; var input = @"public class test : System.Attribute {}";
var output = @"class TestAttribute : System.Attribute {}"; var output = @"public class TestAttribute : System.Attribute {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestEventArgsName () public void TestEventArgsName ()
{ {
var input = @"class test : System.EventArgs {}"; var input = @"public class test : System.EventArgs {}";
var output = @"class TestEventArgs : System.EventArgs {}"; var output = @"public class TestEventArgs : System.EventArgs {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
@ -89,50 +89,50 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
[Test] [Test]
public void TestStructName () public void TestStructName ()
{ {
var input = @"struct anIssue {}"; var input = @"public struct anIssue {}";
var output = @"struct AnIssue {}"; var output = @"public struct AnIssue {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestInterfaceName () public void TestInterfaceName ()
{ {
var input = @"interface anIssue {}"; var input = @"public interface anIssue {}";
var output = @"interface IAnIssue {}"; var output = @"public interface IAnIssue {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestEnumName () public void TestEnumName ()
{ {
var input = @"enum anIssue {}"; var input = @"public enum anIssue {}";
var output = @"enum AnIssue {}"; var output = @"public enum AnIssue {}";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestDelegateName () public void TestDelegateName ()
{ {
var input = @"delegate void anIssue ();"; var input = @"public delegate void anIssue ();";
var output = @"delegate void AnIssue ();"; var output = @"public delegate void AnIssue ();";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] // [Test]
public void TestPrivateFieldName () // public void TestPrivateFieldName ()
{ // {
var input = @"class AClass { int Field; }"; // var input = @"class AClass { int Field; }";
var output = @"class AClass { int field; }"; // var output = @"class AClass { int field; }";
CheckNaming (input, output); // CheckNaming (input, output);
} // }
[Test] // [Test]
public void TestUnderscoreFieldName () // public void TestUnderscoreFieldName ()
{ // {
var input = @"class AClass { int _Field; }"; // var input = @"class AClass { int _Field; }";
var output = @"class AClass { int _field; }"; // var output = @"class AClass { int _field; }";
CheckNaming (input, output); // CheckNaming (input, output);
} // }
[Test] [Test]
public void TestPublicFieldName () public void TestPublicFieldName ()
@ -142,13 +142,13 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] // [Test]
public void TestPrivateConstantFieldName () // public void TestPrivateConstantFieldName ()
{ // {
var input = @"class AClass { const int field = 5; }"; // var input = @"class AClass { const int field = 5; }";
var output = @"class AClass { const int Field = 5; }"; // var output = @"class AClass { const int Field = 5; }";
CheckNaming (input, output); // CheckNaming (input, output);
} // }
[Test] [Test]
public void TestPublicReadOnlyFieldName () public void TestPublicReadOnlyFieldName ()
@ -174,13 +174,13 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
CheckNaming (input, output, true); CheckNaming (input, output, true);
} }
[Test] // [Test]
public void TestPrivateStaticFieldName () // public void TestPrivateStaticFieldName ()
{ // {
var input = @"class AClass { static int Field; }"; // var input = @"class AClass { static int Field; }";
var output = @"class AClass { static int field; }"; // var output = @"class AClass { static int field; }";
CheckNaming (input, output); // CheckNaming (input, output);
} // }
[Test] [Test]
public void TestPublicStaticReadOnlyFieldName () public void TestPublicStaticReadOnlyFieldName ()
@ -190,13 +190,13 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] // [Test]
public void TestPrivateReadOnlyFieldName () // public void TestPrivateReadOnlyFieldName ()
{ // {
var input = @"class AClass { readonly int Field; }"; // var input = @"class AClass { readonly int Field; }";
var output = @"class AClass { readonly int field; }"; // var output = @"class AClass { readonly int field; }";
CheckNaming (input, output); // CheckNaming (input, output);
} // }
[Test] [Test]
public void TestPublicConstantFieldName () public void TestPublicConstantFieldName ()
@ -209,16 +209,16 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
[Test] [Test]
public void TestMethodName () public void TestMethodName ()
{ {
var input = @"class AClass { int method () {} }"; var input = @"class AClass { public int method () {} }";
var output = @"class AClass { int Method () {} }"; var output = @"class AClass { public int Method () {} }";
CheckNaming (input, output); CheckNaming (input, output);
} }
[Test] [Test]
public void TestPropertyName () public void TestPropertyName ()
{ {
var input = @"class AClass { int property { get; set; } }"; var input = @"class AClass { public int property { get; set; } }";
var output = @"class AClass { int Property { get; set; } }"; var output = @"class AClass { public int Property { get; set; } }";
CheckNaming (input, output); CheckNaming (input, output);
} }

20
ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs

@ -35,8 +35,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
CompilationUnit cu = parser.Parse(new StringReader(code), "parsed.cs"); CompilationUnit cu = parser.Parse(new StringReader(code), "parsed.cs");
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (err => Console.WriteLine (err.Message)); Console.WriteLine (error.Message);
Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors");
AstNode node = cu.Children.Single(); AstNode node = cu.Children.Single();
@ -58,8 +58,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
var statements = parser.ParseStatements(new StringReader(stmt)); var statements = parser.ParseStatements(new StringReader(stmt));
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (err => Console.WriteLine (err.Message)); Console.WriteLine (error.Message);
Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors");
AstNode statement = statements.Single(); AstNode statement = statements.Single();
@ -81,8 +81,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
AstNode parsedExpression = parser.ParseExpression(new StringReader(expr)); AstNode parsedExpression = parser.ParseExpression(new StringReader(expr));
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (err => Console.WriteLine (err.Message)); Console.WriteLine (error.Message);
Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors");
if (expectErrors && parsedExpression == null) if (expectErrors && parsedExpression == null)
return default (T); return default (T);
@ -103,8 +103,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
{ {
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
var members = parser.ParseTypeMembers(new StringReader(expr)); var members = parser.ParseTypeMembers(new StringReader(expr));
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (err => Console.WriteLine (err.Message)); Console.WriteLine (error.Message);
Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors");
EntityDeclaration m = members.Single(); EntityDeclaration m = members.Single();
Type type = typeof(T); Type type = typeof(T);
@ -125,8 +125,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
var parsedExpression = parser.ParseDocumentationReference(cref); var parsedExpression = parser.ParseDocumentationReference(cref);
if (parser.HasErrors) foreach (var error in parser.Errors)
parser.ErrorPrinter.Errors.ForEach (err => Console.WriteLine (err.Message)); Console.WriteLine (error.Message);
Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors");
if (expectErrors && parsedExpression == null) if (expectErrors && parsedExpression == null)
return null; return null;

34
ICSharpCode.NRefactory.Tests/FormattingTests/TestWrapping.cs

@ -580,5 +580,39 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests
}"); }");
} }
[Test()]
public void TestNoBlankLinesBetweenEndBraceAndEndParenthesis ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenMembers = 1;
var adapter = Test (policy, @"class Test
{
int Foo (int i, double d, Action a)
{
a ();
}
void Bar ()
{
Foo (1, 2, () => {
});
}
}",
@"class Test
{
int Foo (int i, double d, Action a)
{
a ();
}
void Bar ()
{
Foo (1, 2, () => {
});
}
}", FormattingMode.Intrusive);
}
} }
} }

3
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{63D3B27A-D966-4902-90B3-30290E1692F1}</ProjectGuid> <ProjectGuid>{63D3B27A-D966-4902-90B3-30290E1692F1}</ProjectGuid>
@ -277,6 +277,7 @@
<Compile Include="CSharp\CodeActions\StaticMethodInvocationToExtensionMethodInvocationTests.cs" /> <Compile Include="CSharp\CodeActions\StaticMethodInvocationToExtensionMethodInvocationTests.cs" />
<Compile Include="CSharp\CodeActions\ExtensionMethodInvocationToStaticMethodInvocationTests.cs" /> <Compile Include="CSharp\CodeActions\ExtensionMethodInvocationToStaticMethodInvocationTests.cs" />
<Compile Include="CSharp\CodeActions\IterateViaForeachTests.cs" /> <Compile Include="CSharp\CodeActions\IterateViaForeachTests.cs" />
<Compile Include="CSharp\CodeActions\ExtractFieldTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj"> <ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">

1
ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs

@ -145,7 +145,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(0, c.GetProperties().Count()); Assert.AreEqual(0, c.GetProperties().Count());
Assert.AreEqual(0, c.GetEvents().Count()); Assert.AreEqual(0, c.GetEvents().Count());
Assert.AreEqual(0, c.GetFields().Count()); Assert.AreEqual(0, c.GetFields().Count());
Assert.AreEqual(3, c.Attributes.Count);
} }
[Test] [Test]

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()
{ {

11
ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs

@ -121,7 +121,7 @@ namespace ICSharpCode.NRefactory.Documentation
this.fileName = fileName; this.fileName = fileName;
ReadXmlDoc(xmlReader); ReadXmlDoc(xmlReader);
} else { } else {
string redirectionTarget = GetRedirectionTarget(xmlReader.GetAttribute("redirect")); string redirectionTarget = GetRedirectionTarget(fileName, xmlReader.GetAttribute("redirect"));
if (redirectionTarget != null) { if (redirectionTarget != null) {
Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget); Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget);
using (FileStream redirectedFs = new FileStream(redirectionTarget, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { using (FileStream redirectedFs = new FileStream(redirectionTarget, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
@ -138,7 +138,7 @@ namespace ICSharpCode.NRefactory.Documentation
} }
} }
static string GetRedirectionTarget(string target) static string GetRedirectionTarget(string xmlFileName, string target)
{ {
string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
programFilesDir = AppendDirectorySeparator(programFilesDir); programFilesDir = AppendDirectorySeparator(programFilesDir);
@ -146,8 +146,11 @@ namespace ICSharpCode.NRefactory.Documentation
string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
corSysDir = AppendDirectorySeparator(corSysDir); corSysDir = AppendDirectorySeparator(corSysDir);
return LookupLocalizedXmlDoc(target.Replace("%PROGRAMFILESDIR%", programFilesDir) var fileName = target.Replace ("%PROGRAMFILESDIR%", programFilesDir)
.Replace("%CORSYSDIR%", corSysDir)); .Replace ("%CORSYSDIR%", corSysDir);
if (!Path.IsPathRooted (fileName))
fileName = Path.Combine (Path.GetDirectoryName (xmlFileName), fileName);
return LookupLocalizedXmlDoc(fileName);
} }
static string AppendDirectorySeparator(string dir) static string AppendDirectorySeparator(string dir)

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

@ -191,6 +191,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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()
{ {
var declTypeRef = this.DeclaringType.ToTypeReference(); var declTypeRef = this.DeclaringType.ToTypeReference();

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