Browse Source

Merge NRefactory commit '180a690f373354796520d9468138d95f193f8156' into SharpDevelop newNR branch.

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
311ab03c15
  1. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  2. 108
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  3. 51
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs
  4. 132
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NewLineNode.cs
  5. 94
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TextNode.cs
  6. 91
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/WhitespaceNode.cs
  7. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs
  8. 33
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs
  9. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Roles.cs
  10. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs
  11. 407
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  12. 286
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  13. 74
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  14. 69
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  15. 159
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs
  16. 339
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs
  17. 216
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/GeneratedCodeSettings.cs
  18. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  19. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs
  20. 34
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  21. 21
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  22. 347
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs
  23. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs
  24. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs
  25. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs
  26. 502
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs
  27. 14
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs
  28. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs
  29. 97
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs
  30. 42
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs
  31. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/const.cs
  32. 39
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs
  33. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs
  34. 13
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs
  35. 8809
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs
  36. 130
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay
  37. 22
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  38. 17
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs
  39. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs
  40. 112
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs
  41. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs
  42. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/dynamic.cs
  43. 146
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
  44. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs
  45. 136
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs
  46. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs
  47. 152
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs
  48. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs
  49. 20
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs
  50. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs
  51. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs
  52. 30
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs
  53. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/module.cs
  54. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs
  55. 126
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs
  56. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs
  57. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs
  58. 567
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs
  59. 153
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs
  60. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs
  61. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs
  62. 27
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
  63. 18
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeAction.cs
  64. 29
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CheckIfParameterIsNullAction.cs
  65. 13
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertDecToHexAction.cs
  66. 105
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs
  67. 52
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs
  68. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateIndexerAction.cs
  69. 136
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs
  70. 11
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs
  71. 186
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/ExtractMethodAction.cs
  72. 85
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/StaticVisitor.cs
  73. 97
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/VariableLookupVisitor.cs
  74. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/GeneratePropertyAction.cs
  75. 89
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs
  76. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveBackingStoreAction.cs
  77. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveBracesAction.cs
  78. 38
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SpecializedCodeAction.cs
  79. 49
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs
  80. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ConditionalToNullCoalescingIssue.cs
  81. 71
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExplicitConversionInForEachIssue.cs
  82. 23
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/GatherVisitorBase.cs
  83. 14
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/DefaultRules.cs
  84. 22
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/NamingConventionService.cs
  85. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/NotImplementedExceptionIssue.cs
  86. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantInternalIssue.cs
  87. 52
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantNamespaceUsageIssue.cs
  88. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantPrivateIssue.cs
  89. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantThisIssue.cs
  90. 76
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantUsingIssue.cs
  91. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StringIsNullOrEmptyIssue.cs
  92. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/UseVarKeywordIssue.cs
  93. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ICodeIssueProvider.cs
  94. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  95. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs
  96. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
  97. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  98. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs
  99. 32
      src/Libraries/NRefactory/ICSharpCode.NRefactory.ConsistencyCheck/Xml/IncrementalXmlParserTests.cs
  100. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.GtkDemo/gtk-gui/ICSharpCode.NRefactory.GtkDemo.MainWindow.cs
  101. Some files were not shown because too many files have changed in this diff Show More

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs

@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy of this // 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 // software and associated documentation files (the "Software"), to deal in the Software
@ -420,7 +420,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin); falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin);
} }
ControlFlowNode end = builder.CreateEndNode(ifElseStatement); ControlFlowNode end = builder.CreateEndNode(ifElseStatement);
Connect(trueEnd, end); if (trueEnd != null)
Connect(trueEnd, end);
if (falseEnd != null) { if (falseEnd != null) {
Connect(falseEnd, end); Connect(falseEnd, end);
} else if (cond != true) { } else if (cond != true) {

108
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -1,4 +1,4 @@
// //
// AstNode.cs // AstNode.cs
// //
// Author: // Author:
@ -366,6 +366,13 @@ namespace ICSharpCode.NRefactory.CSharp
lastChild = child; lastChild = child;
} }
} }
public void InsertChildsBefore<T>(AstNode nextSibling, Role<T> role, params T[] child) where T : AstNode
{
foreach (var cur in child) {
InsertChildBefore(nextSibling, cur, role);
}
}
public void InsertChildBefore<T> (AstNode nextSibling, T child, Role<T> role) where T : AstNode public void InsertChildBefore<T> (AstNode nextSibling, T child, Role<T> role) where T : AstNode
{ {
@ -606,7 +613,6 @@ namespace ICSharpCode.NRefactory.CSharp
return Parent.GetPrevNode (); return Parent.GetPrevNode ();
return null; return null;
} }
// filters all non c# nodes (comments, white spaces or pre processor directives) // filters all non c# nodes (comments, white spaces or pre processor directives)
public AstNode GetCSharpNodeBefore (AstNode node) public AstNode GetCSharpNodeBefore (AstNode node)
{ {
@ -619,11 +625,22 @@ namespace ICSharpCode.NRefactory.CSharp
return null; return null;
} }
#region GetNodeAt
/// <summary>
/// Gets the node specified by T at the location line, column. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End exclusive)
/// </summary>
public AstNode GetNodeAt (int line, int column, Predicate<AstNode> pred = null) public AstNode GetNodeAt (int line, int column, Predicate<AstNode> pred = null)
{ {
return GetNodeAt (new TextLocation (line, column), pred); return GetNodeAt (new TextLocation (line, column), pred);
} }
/// <summary>
/// Gets the node specified by pred at location. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End exclusive)
/// </summary>
public AstNode GetNodeAt (TextLocation location, Predicate<AstNode> pred = null) public AstNode GetNodeAt (TextLocation location, Predicate<AstNode> pred = null)
{ {
AstNode result = null; AstNode result = null;
@ -646,6 +663,11 @@ namespace ICSharpCode.NRefactory.CSharp
return result; return result;
} }
/// <summary>
/// Gets the node specified by T at the location line, column. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End exclusive)
/// </summary>
public T GetNodeAt<T> (int line, int column) where T : AstNode public T GetNodeAt<T> (int line, int column) where T : AstNode
{ {
return GetNodeAt<T> (new TextLocation (line, column)); return GetNodeAt<T> (new TextLocation (line, column));
@ -654,6 +676,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary> /// <summary>
/// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching /// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration. /// the current method declaration.
/// (End exclusive)
/// </summary> /// </summary>
public T GetNodeAt<T> (TextLocation location) where T : AstNode public T GetNodeAt<T> (TextLocation location) where T : AstNode
{ {
@ -676,7 +699,86 @@ namespace ICSharpCode.NRefactory.CSharp
} }
return result; return result;
} }
#endregion
#region GetAdjacentNodeAt
/// <summary>
/// Gets the node specified by pred at the location line, column. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End inclusive)
/// </summary>
public AstNode GetAdjacentNodeAt(int line, int column, Predicate<AstNode> pred = null)
{
return GetAdjacentNodeAt (new TextLocation (line, column), pred);
}
/// <summary>
/// Gets the node specified by pred at location. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End inclusive)
/// </summary>
public AstNode GetAdjacentNodeAt (TextLocation location, Predicate<AstNode> pred = null)
{
AstNode result = null;
AstNode node = this;
while (node.FirstChild != null) {
var child = node.FirstChild;
while (child != null) {
if (child.StartLocation <= location && location <= child.EndLocation) {
if (pred == null || pred (child))
result = child;
node = child;
break;
}
child = child.NextSibling;
}
// found no better child node - therefore the parent is the right one.
if (child == null)
break;
}
return result;
}
/// <summary>
/// Gets the node specified by T at the location line, column. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End inclusive)
/// </summary>
public T GetAdjacentNodeAt<T>(int line, int column) where T : AstNode
{
return GetAdjacentNodeAt<T> (new TextLocation (line, column));
}
/// <summary>
/// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// (End inclusive)
/// </summary>
public T GetAdjacentNodeAt<T> (TextLocation location) where T : AstNode
{
T result = null;
AstNode node = this;
while (node.FirstChild != null) {
var child = node.FirstChild;
while (child != null) {
if (child.StartLocation <= location && location < child.EndLocation) {
if (child is T)
result = (T)child;
node = child;
break;
}
child = child.NextSibling;
}
// found no better child node - therefore the parent is the right one.
if (child == null)
break;
}
return result;
}
#endregion
/// <summary> /// <summary>
/// Gets the node that fully contains the range from startLocation to endLocation. /// Gets the node that fully contains the range from startLocation to endLocation.
/// </summary> /// </summary>
@ -729,7 +831,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (IsNull) if (IsNull)
return ""; return "";
var w = new StringWriter (); var w = new StringWriter ();
AcceptVisitor (new CSharpOutputVisitor (w, formattingOptions ?? new CSharpFormattingOptions ())); AcceptVisitor (new CSharpOutputVisitor (w, formattingOptions ?? FormattingOptionsFactory.CreateMono ()));
return w.ToString (); return w.ToString ();
} }

51
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs

@ -49,11 +49,26 @@ namespace ICSharpCode.NRefactory.CSharp
VisitChildren (unit); VisitChildren (unit);
} }
public virtual void VisitComment (Comment comment) public virtual void VisitComment(Comment comment)
{ {
VisitChildren (comment); VisitChildren(comment);
} }
public virtual void VisitNewLine(NewLineNode newLineNode)
{
VisitChildren(newLineNode);
}
public virtual void VisitWhitespace(WhitespaceNode whitespaceNode)
{
VisitChildren(whitespaceNode);
}
public virtual void VisitText(TextNode textNode)
{
VisitChildren(textNode);
}
public virtual void VisitDocumentationReference (DocumentationReference documentationReference) public virtual void VisitDocumentationReference (DocumentationReference documentationReference)
{ {
VisitChildren (documentationReference); VisitChildren (documentationReference);
@ -637,6 +652,21 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (comment); return VisitChildren (comment);
} }
public virtual T VisitNewLine(NewLineNode newLineNode)
{
return VisitChildren(newLineNode);
}
public virtual T VisitWhitespace(WhitespaceNode whitespaceNode)
{
return VisitChildren(whitespaceNode);
}
public virtual T VisitText(TextNode textNode)
{
return VisitChildren(textNode);
}
public virtual T VisitDocumentationReference (DocumentationReference documentationReference) public virtual T VisitDocumentationReference (DocumentationReference documentationReference)
{ {
return VisitChildren (documentationReference); return VisitChildren (documentationReference);
@ -1220,6 +1250,21 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (comment, data); return VisitChildren (comment, data);
} }
public virtual S VisitNewLine(NewLineNode newLineNode, T data)
{
return VisitChildren(newLineNode, data);
}
public virtual S VisitWhitespace(WhitespaceNode whitespaceNode, T data)
{
return VisitChildren(whitespaceNode, data);
}
public virtual S VisitText(TextNode textNode, T data)
{
return VisitChildren(textNode, data);
}
public virtual S VisitDocumentationReference (DocumentationReference documentationReference, T data) public virtual S VisitDocumentationReference (DocumentationReference documentationReference, T data)
{ {
return VisitChildren (documentationReference, data); return VisitChildren (documentationReference, data);

132
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NewLineNode.cs

@ -0,0 +1,132 @@
using System;
namespace ICSharpCode.NRefactory.CSharp
{
public enum NewLineType {
Unix,
Windows,
Mac
}
/// <summary>
/// A New line node represents a line break in the text.
/// </summary>
public abstract class NewLineNode : AstNode
{
public override NodeType NodeType {
get {
return NodeType.Whitespace;
}
}
public abstract NewLineType NewLineType {
get;
}
TextLocation startLocation;
public override TextLocation StartLocation {
get {
return startLocation;
}
}
public override TextLocation EndLocation {
get {
return new TextLocation (startLocation.Line + 1, 1);
}
}
public NewLineNode() : this (TextLocation.Empty)
{
}
public NewLineNode(TextLocation startLocation)
{
this.startLocation = startLocation;
}
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitNewLine (this);
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
return visitor.VisitNewLine (this);
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitNewLine (this, data);
}
}
public class UnixNewLine : NewLineNode
{
public override NewLineType NewLineType {
get {
return NewLineType.Unix;
}
}
public UnixNewLine()
{
}
public UnixNewLine(TextLocation startLocation) : base (startLocation)
{
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as UnixNewLine;
return o != null;
}
}
public class WindowsNewLine : NewLineNode
{
public override NewLineType NewLineType {
get {
return NewLineType.Windows;
}
}
public WindowsNewLine()
{
}
public WindowsNewLine(TextLocation startLocation) : base (startLocation)
{
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as WindowsNewLine;
return o != null;
}
}
public class MacNewLine : NewLineNode
{
public override NewLineType NewLineType {
get {
return NewLineType.Mac;
}
}
public MacNewLine()
{
}
public MacNewLine(TextLocation startLocation) : base (startLocation)
{
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as MacNewLine;
return o != null;
}
}
}

94
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TextNode.cs

@ -0,0 +1,94 @@
//
// TextNode.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// A text node contains text without syntactic or semantic information.
/// (non parseable part of a text)
/// </summary>
public class TextNode : AstNode
{
public override NodeType NodeType {
get {
return NodeType.Whitespace;
}
}
public string Text {
get;
set;
}
TextLocation startLocation;
public override TextLocation StartLocation {
get {
return startLocation;
}
}
TextLocation endLocation;
public override TextLocation EndLocation {
get {
return endLocation;
}
}
public TextNode(string text) : this (text, TextLocation.Empty, TextLocation.Empty)
{
}
public TextNode(string text, TextLocation startLocation, TextLocation endLocation)
{
this.Text = text;
this.startLocation = startLocation;
this.endLocation = endLocation;
}
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitText (this);
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
return visitor.VisitText (this);
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitText (this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as TextNode;
return o != null && o.Text == Text;
}
}
}

91
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/WhitespaceNode.cs

@ -0,0 +1,91 @@
//
// WhitespaceNode.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// A Whitespace node contains only whitespaces.
/// </summary>
public class WhitespaceNode : AstNode
{
public override NodeType NodeType {
get {
return NodeType.Whitespace;
}
}
public string WhiteSpaceText {
get;
set;
}
TextLocation startLocation;
public override TextLocation StartLocation {
get {
return startLocation;
}
}
public override TextLocation EndLocation {
get {
return new TextLocation (startLocation.Line, startLocation.Column + WhiteSpaceText.Length);
}
}
public WhitespaceNode(string whiteSpaceText) : this (whiteSpaceText, TextLocation.Empty)
{
}
public WhitespaceNode(string whiteSpaceText, TextLocation startLocation)
{
this.WhiteSpaceText = WhiteSpaceText;
this.startLocation = startLocation;
}
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitWhitespace (this);
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
return visitor.VisitWhitespace (this);
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitWhitespace (this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as WhitespaceNode;
return o != null && o.WhiteSpaceText == WhiteSpaceText;
}
}
}

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs

@ -137,6 +137,9 @@ namespace ICSharpCode.NRefactory.CSharp
void VisitPrimitiveType(PrimitiveType primitiveType); void VisitPrimitiveType(PrimitiveType primitiveType);
void VisitComment(Comment comment); void VisitComment(Comment comment);
void VisitNewLine(NewLineNode newLineNode);
void VisitWhitespace(WhitespaceNode whitespaceNode);
void VisitText(TextNode textNode);
void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective); void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective);
void VisitDocumentationReference(DocumentationReference documentationReference); void VisitDocumentationReference(DocumentationReference documentationReference);
@ -265,6 +268,9 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitPrimitiveType(PrimitiveType primitiveType); S VisitPrimitiveType(PrimitiveType primitiveType);
S VisitComment(Comment comment); S VisitComment(Comment comment);
S VisitWhitespace(WhitespaceNode whitespaceNode);
S VisitText(TextNode textNode);
S VisitNewLine(NewLineNode newLineNode);
S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective); S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective);
S VisitDocumentationReference(DocumentationReference documentationReference); S VisitDocumentationReference(DocumentationReference documentationReference);
@ -393,6 +399,9 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitPrimitiveType(PrimitiveType primitiveType, T data); S VisitPrimitiveType(PrimitiveType primitiveType, T data);
S VisitComment(Comment comment, T data); S VisitComment(Comment comment, T data);
S VisitNewLine(NewLineNode newLineNode, T data);
S VisitWhitespace(WhitespaceNode whitespaceNode, T data);
S VisitText(TextNode textNode, T data);
S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective, T data); S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective, T data);
S VisitDocumentationReference(DocumentationReference documentationReference, T data); S VisitDocumentationReference(DocumentationReference documentationReference, T data);

33
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs

@ -60,9 +60,38 @@ namespace ICSharpCode.NRefactory.CSharp
handler (comment, data); handler (comment, data);
return VisitChildren (comment, data); return VisitChildren (comment, data);
} }
public event Action<PreProcessorDirective, T> PreProcessorDirectiveVisited;
public event Action<NewLineNode, T> NewLineVisited;
S IAstVisitor<T, S>.VisitNewLine(NewLineNode newLineNode, T data)
{
var handler = NewLineVisited;
if (handler != null)
handler(newLineNode, data);
return VisitChildren(newLineNode, data);
}
public event Action<WhitespaceNode, T> WhitespaceVisited;
S IAstVisitor<T, S>.VisitWhitespace(WhitespaceNode whitespace, T data)
{
var handler = WhitespaceVisited;
if (handler != null)
handler(whitespace, data);
return VisitChildren(whitespace, data);
}
public event Action<TextNode, T> TextVisited;
S IAstVisitor<T, S>.VisitText(TextNode textNode, T data)
{
var handler = TextVisited;
if (handler != null)
handler(textNode, data);
return VisitChildren(textNode, data);
}
public event Action<PreProcessorDirective, T> PreProcessorDirectiveVisited;
S IAstVisitor<T, S>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, T data) S IAstVisitor<T, S>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, T data)
{ {
var handler = PreProcessorDirectiveVisited; var handler = PreProcessorDirectiveVisited;

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Roles.cs

@ -68,6 +68,9 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly TokenRole Colon = new TokenRole (":"); public static readonly TokenRole Colon = new TokenRole (":");
public static readonly TokenRole DoubleColon = new TokenRole ("::"); public static readonly TokenRole DoubleColon = new TokenRole ("::");
public static readonly Role<Comment> Comment = new Role<Comment> ("Comment"); public static readonly Role<Comment> Comment = new Role<Comment> ("Comment");
public static readonly Role<NewLineNode> NewLine = new Role<NewLineNode> ("NewLine");
public static readonly Role<WhitespaceNode> Whitespace = new Role<WhitespaceNode> ("Whitespace");
public static readonly Role<TextNode> Text = new Role<TextNode> ("Text");
public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective> ("PreProcessorDirective"); public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective> ("PreProcessorDirective");
public static readonly Role<ErrorNode> Error = new Role<ErrorNode> ("Error"); public static readonly Role<ErrorNode> Error = new Role<ErrorNode> ("Error");

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs

@ -121,10 +121,11 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
} }
public ParameterDeclaration(AstType type, string name) public ParameterDeclaration(AstType type, string name, ParameterModifier modifier = ParameterModifier.None)
{ {
this.Type = type; Type = type;
this.Name = name; Name = name;
ParameterModifier = modifier;
} }
} }
} }

407
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -1,4 +1,4 @@
// //
// CSharpCompletionEngine.cs // CSharpCompletionEngine.cs
// //
// Author: // Author:
@ -68,7 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
this.document = document; this.document = document;
this.factory = factory; this.factory = factory;
// Set defaults for additional input properties // Set defaults for additional input properties
this.FormattingPolicy = new CSharpFormattingOptions (); this.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
this.EolMarker = Environment.NewLine; this.EolMarker = Environment.NewLine;
this.IndentString = "\t"; this.IndentString = "\t";
} }
@ -207,26 +207,55 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2); return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2);
} }
bool IsInPreprocessorDirective()
{
var text = GetMemberTextToCaret().Item1;
var miniLexer = new MiniLexer(text);
miniLexer.Parse();
return miniLexer.IsInPreprocessorDirective;
}
IEnumerable<ICompletionData> HandleObjectInitializer(CompilationUnit unit, AstNode n)
{
var p = n.Parent;
while (p != null && !(p is ObjectCreateExpression)) {
p = p.Parent;
}
if (p != null) {
var contextList = new CompletionDataWrapper(this);
var initializerResult = ResolveExpression(p, unit);
if (initializerResult != null && initializerResult.Item1.Type.Kind != TypeKind.Unknown) {
foreach (var m in initializerResult.Item1.Type.GetMembers (m => m.IsPublic && (m.EntityType == EntityType.Property || m.EntityType == EntityType.Field))) {
contextList.AddMember(m);
}
var enumerableType = typeof(IEnumerable<>).ToTypeReference().Resolve(ctx);
// check if we may be in a collection initializer, or enumerable initializer
if (enumerableType.Kind == TypeKind.Unknown || !initializerResult.Item1.Type.GetDefinition().IsDerivedFrom(enumerableType.GetDefinition())) {
return contextList.Result;
}
}
}
return null;
}
IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace) IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace)
{ {
ExpressionResult expr; ExpressionResult expr;
Tuple<ResolveResult, CSharpResolver> resolveResult; Tuple<ResolveResult, CSharpResolver> resolveResult;
switch (completionChar) { switch (completionChar) {
// Magic key completion // Magic key completion
case ':': case ':':
case '.': case '.':
if (IsInsideCommentOrString()) { if (IsInsideCommentStringOrDirective()) {
return Enumerable.Empty<ICompletionData>(); return Enumerable.Empty<ICompletionData>();
} }
return HandleMemberReferenceCompletion(GetExpressionBeforeCursor()); return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
case '#': case '#':
if (IsInsideCommentOrString()) { if (!IsInPreprocessorDirective())
return null; return null;
}
return GetDirectiveCompletionData(); return GetDirectiveCompletionData();
// XML doc completion
// XML doc completion
case '<': case '<':
if (IsInsideDocComment()) { if (IsInsideDocComment()) {
return GetXmlDocumentationCompletionData(); return GetXmlDocumentationCompletionData();
@ -265,11 +294,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// Parameter completion // Parameter completion
case '(': case '(':
if (IsInsideCommentOrString()) { if (IsInsideCommentStringOrDirective()) {
return null; return null;
} }
var invoke = GetInvocationBeforeCursor(true); var invoke = GetInvocationBeforeCursor(true);
if (invoke == null) { if (invoke == null) {
if (controlSpace)
return DefaultControlSpaceItems(invoke);
return null; return null;
} }
if (invoke.Node is TypeOfExpression) { if (invoke.Node is TypeOfExpression) {
@ -287,7 +318,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (controlSpace) { if (controlSpace) {
return DefaultControlSpaceItems(invoke); return DefaultControlSpaceItems(invoke);
} }
return null; return null;
case '=': case '=':
return controlSpace ? DefaultControlSpaceItems() : null; return controlSpace ? DefaultControlSpaceItems() : null;
@ -303,12 +333,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// Completion on space: // Completion on space:
case ' ': case ' ':
if (IsInsideCommentOrString()) {
return null;
}
int tokenIndex = offset; int tokenIndex = offset;
string token = GetPreviousToken(ref tokenIndex, false); string token = GetPreviousToken(ref tokenIndex, false);
if (IsInsideCommentStringOrDirective()) {
if (IsInPreprocessorDirective())
return HandleKeywordCompletion(tokenIndex, token);
return null;
}
// check propose name, for context <variable name> <ctrl+space> (but only in control space context) // check propose name, for context <variable name> <ctrl+space> (but only in control space context)
//IType isAsType = null; //IType isAsType = null;
var isAsExpression = GetExpressionAt(offset); var isAsExpression = GetExpressionAt(offset);
@ -461,8 +492,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null; return null;
case ":": case ":":
if (currentMember == null) { if (currentMember == null) {
token = GetPreviousToken(ref tokenIndex, false);
token = GetPreviousToken(ref tokenIndex, false);
if (token == "enum")
return HandleEnumContext();
var wrapper = new CompletionDataWrapper(this); var wrapper = new CompletionDataWrapper(this);
AddTypesAndNamespaces(wrapper, GetState(), null, t => currentType != null ? !currentType.ReflectionName.Equals(t.ReflectionName) : true);
AddTypesAndNamespaces(wrapper, GetState(), null, t => currentType != null && !currentType.ReflectionName.Equals(t.ReflectionName) ? t : null);
return wrapper.Result; return wrapper.Result;
} }
return null; return null;
@ -475,7 +511,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return keywordCompletion; return keywordCompletion;
// Automatic completion // Automatic completion
default: default:
if (IsInsideCommentOrString()) { if (IsInsideCommentStringOrDirective()) {
return null; return null;
} }
if (IsInLinqContext(offset)) { if (IsInLinqContext(offset)) {
@ -565,7 +601,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null; return null;
} }
if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentOrString() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) { if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
char last = token [token.Length - 1]; char last = token [token.Length - 1];
if (char.IsLetterOrDigit(last) || last == '_' || token == ">") { if (char.IsLetterOrDigit(last) || last == '_' || token == ">") {
return HandleKeywordCompletion(tokenIndex, token); return HandleKeywordCompletion(tokenIndex, token);
@ -599,24 +635,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// Handle object/enumerable initialzer expressions: "new O () { P$" // Handle object/enumerable initialzer expressions: "new O () { P$"
if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression) { if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression) {
var p = n.Parent; var result = HandleObjectInitializer(identifierStart.Unit, n);
while (p != null && !(p is ObjectCreateExpression)) { if (result != null)
p = p.Parent; return result;
}
if (p != null) {
var initializerResult = ResolveExpression(p, identifierStart.Unit);
if (initializerResult != null && initializerResult.Item1.Type.Kind != TypeKind.Unknown) {
foreach (var m in initializerResult.Item1.Type.GetMembers (m => m.IsPublic && (m.EntityType == EntityType.Property || m.EntityType == EntityType.Field))) {
contextList.AddMember(m);
}
var enumerableType = typeof(IEnumerable<>).ToTypeReference().Resolve(ctx);
// check if we may be in a collection initializer, or enumerable initializer
if (enumerableType.Kind == TypeKind.Unknown || !initializerResult.Item1.Type.GetDefinition().IsDerivedFrom(enumerableType.GetDefinition())) {
return contextList.Result;
}
}
}
} }
if (n != null && n.Parent is InvocationExpression) { if (n != null && n.Parent is InvocationExpression) {
@ -845,13 +866,26 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return null; return null;
} }
string[] validEnumBaseTypes = { "byte", "sbyte", "short", "int", "long", "ushort", "uint", "ulong" };
IEnumerable<ICompletionData> HandleEnumContext() IEnumerable<ICompletionData> HandleEnumContext()
{ {
var cu = ParseStub("a", false); var cu = ParseStub("a", false);
if (cu == null) { if (cu == null) {
return null; return null;
} }
var curType = cu.GetNodeAt<TypeDeclaration> (location);
if (curType == null || curType.ClassType != ClassType.Enum) {
cu = ParseStub("a {}", false);
var node = cu.GetNodeAt<AstType>(location);
if (node != null) {
var wrapper = new CompletionDataWrapper(this);
AddKeywords(wrapper, validEnumBaseTypes);
return wrapper.Result;
}
}
var member = cu.GetNodeAt<EnumMemberDeclaration>(location); var member = cu.GetNodeAt<EnumMemberDeclaration>(location);
if (member != null && member.NameToken.EndLocation < location) { if (member != null && member.NameToken.EndLocation < location) {
return DefaultControlSpaceItems(); return DefaultControlSpaceItems();
@ -862,7 +896,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
bool IsInLinqContext(int offset) bool IsInLinqContext(int offset)
{ {
string token; string token;
while (null != (token = GetPreviousToken (ref offset, true)) && !IsInsideCommentOrString ()) { while (null != (token = GetPreviousToken (ref offset, true)) && !IsInsideCommentStringOrDirective ()) {
if (token == "from") { if (token == "from") {
return true; return true;
} }
@ -880,7 +914,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (node is Accessor) { if (node is Accessor) {
node = node.Parent; node = node.Parent;
} }
var contextList = new CompletionDataWrapper (this); var contextList = new CompletionDataWrapper(this);
if (node is PropertyDeclaration) { if (node is PropertyDeclaration) {
contextList.AddCustom("get"); contextList.AddCustom("get");
contextList.AddCustom("set"); contextList.AddCustom("set");
@ -897,7 +931,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> DefaultControlSpaceItems(ExpressionResult xp = null, bool controlSpace = true) IEnumerable<ICompletionData> DefaultControlSpaceItems(ExpressionResult xp = null, bool controlSpace = true)
{ {
var wrapper = new CompletionDataWrapper (this); var wrapper = new CompletionDataWrapper(this);
if (offset >= document.TextLength) { if (offset >= document.TextLength) {
offset = document.TextLength - 1; offset = document.TextLength - 1;
} }
@ -917,10 +951,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
rr = ResolveExpression(node, xp.Unit); rr = ResolveExpression(node, xp.Unit);
unit = xp.Unit; unit = xp.Unit;
} else { } else {
unit = ParseStub("a"); unit = ParseStub("a", false);
node = unit.GetNodeAt(location); node = unit.GetNodeAt(location);
rr = ResolveExpression(node, unit); rr = ResolveExpression(node, unit);
} }
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;
foreach (var possibleName in GenerateNameProposals (foreachStmt.VariableType)) { foreach (var possibleName in GenerateNameProposals (foreachStmt.VariableType)) {
@ -933,7 +968,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AutoCompleteEmptyMatch = false; AutoCompleteEmptyMatch = false;
return wrapper.Result; return wrapper.Result;
} }
if (node is Identifier && node.Parent is ParameterDeclaration) { if (node is Identifier && node.Parent is ParameterDeclaration) {
if (!controlSpace) { if (!controlSpace) {
return null; return null;
@ -959,6 +994,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return wrapper.Result; return wrapper.Result;
} }
} }
var initializer = node != null ? node.Parent as ArrayInitializerExpression : null;
if (initializer != null) {
var result = HandleObjectInitializer(unit, initializer);
if (result != null)
return result;
}
CSharpResolver csResolver = null; CSharpResolver csResolver = null;
if (rr != null) { if (rr != null) {
csResolver = rr.Item2; csResolver = rr.Item2;
@ -1010,11 +1052,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
Predicate<IType> typePred = null; Func<IType, IType> typePred = null;
if (IsAttributeContext(node)) { if (IsAttributeContext(node)) {
var attribute = Compilation.FindType(KnownTypeCode.Attribute); var attribute = Compilation.FindType(KnownTypeCode.Attribute);
typePred = t => { typePred = t => {
return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)); return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null;
}; };
} }
AddTypesAndNamespaces(wrapper, state, node, typePred); AddTypesAndNamespaces(wrapper, state, node, typePred);
@ -1088,18 +1130,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return false; return false;
} }
void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Predicate<IType> typePred = null, Predicate<IMember> memberPred = null) void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null)
{ {
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) {
if (typePred == null || typePred(nestedType.Resolve(ctx))) { string name = nestedType.Name;
string name = nestedType.Name; if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length)
if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) { name = name.Substring(0, name.Length - "Attribute".Length);
name = name.Substring(0, name.Length - "Attribute".Length);
} if (typePred == null) {
wrapper.AddType(nestedType, name); wrapper.AddType(nestedType, name);
continue;
} }
wrapper.AddType(typePred(nestedType.Resolve(ctx)), name);
continue;
} }
} }
if (this.currentMember != null && !(node is AstType)) { if (this.currentMember != null && !(node is AstType)) {
@ -1142,19 +1188,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
foreach (var u in n.Usings) { foreach (var u in n.Usings) {
foreach (var type in u.Types) { foreach (var type in u.Types) {
if (typePred == null || typePred(type)) { IType addType = typePred != null ? typePred(type) : type;
if (addType != null) {
string name = type.Name; string name = type.Name;
if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) { if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) {
name = name.Substring(0, name.Length - "Attribute".Length); name = name.Substring(0, name.Length - "Attribute".Length);
} }
wrapper.AddType(type, name); wrapper.AddType(addType, name);
} }
} }
} }
foreach (var type in n.Namespace.Types) { foreach (var type in n.Namespace.Types) {
if (typePred == null || typePred(type)) { IType addType = typePred != null ? typePred(type) : type;
wrapper.AddType(type, type.Name); if (addType != null) {
wrapper.AddType(addType, addType.Name);
} }
} }
@ -1166,7 +1214,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> HandleKeywordCompletion(int wordStart, string word) IEnumerable<ICompletionData> HandleKeywordCompletion(int wordStart, string word)
{ {
if (IsInsideCommentOrString()) { if (IsInsideCommentStringOrDirective()) {
if (IsInPreprocessorDirective()) {
if (word == "if" || word == "elif") {
if (wordStart > 0 && document.GetCharAt(wordStart - 1) == '#') {
return factory.CreatePreProcessorDefinesCompletionData();
}
}
}
return null; return null;
} }
switch (word) { switch (word) {
@ -1176,7 +1231,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null; return null;
} }
var wrapper = new CompletionDataWrapper(this); var wrapper = new CompletionDataWrapper(this);
AddTypesAndNamespaces(wrapper, GetState(), null, t => false); AddTypesAndNamespaces(wrapper, GetState(), null, t => null);
return wrapper.Result; return wrapper.Result;
case "case": case "case":
return CreateCaseCompletionData(location); return CreateCaseCompletionData(location);
@ -1260,7 +1315,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
var isAsWrapper = new CompletionDataWrapper(this); var isAsWrapper = new CompletionDataWrapper(this);
var def = isAsType != null ? isAsType.GetDefinition() : null; var def = isAsType != null ? isAsType.GetDefinition() : null;
AddTypesAndNamespaces(isAsWrapper, GetState(), null, t => t.GetDefinition() == null || def == null || t.GetDefinition().IsDerivedFrom(def), m => false); AddTypesAndNamespaces(isAsWrapper, GetState(), null, t => t.GetDefinition() == null || def == null || t.GetDefinition().IsDerivedFrom(def) ? t : null, m => false);
return isAsWrapper.Result; return isAsWrapper.Result;
// { // {
// CompletionDataList completionList = new ProjectDomCompletionDataList (); // CompletionDataList completionList = new ProjectDomCompletionDataList ();
@ -1466,31 +1521,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return CreateTypeCompletionData(hintType, hintTypeAst); return CreateTypeCompletionData(hintType, hintTypeAst);
// IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new TextLocation (document.Caret.Line, document.Caret.Column));
// ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (document, Document.CompilationUnit, Document.FileName, callingType);
// if (newExactContext is ExpressionContext.TypeExpressionContext)
// return CreateTypeCompletionData (location, callingType, newExactContext, ((ExpressionContext.TypeExpressionContext)newExactContext).Type, ((ExpressionContext.TypeExpressionContext)newExactContext).UnresolvedType);
// if (newExactContext == null) {
// int j = offset - 4;
//
// string yieldToken = GetPreviousToken (ref j, true);
// if (token == "return") {
// NRefactoryResolver resolver = CreateResolver ();
// resolver.SetupResolver (new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
// IReturnType returnType = resolver.CallingMember.ReturnType;
// if (yieldToken == "yield" && returnType.GenericArguments.Count > 0)
// returnType = returnType.GenericArguments [0];
// if (resolver.CallingMember != null)
// return CreateTypeCompletionData (location, callingType, newExactContext, null, returnType);
// }
// }
// return CreateCtrlSpaceCompletionData (completionContext, null);
case "if":
case "elif":
if (wordStart > 0 && document.GetCharAt(wordStart - 1) == '#') {
return factory.CreatePreProcessorDefinesCompletionData();
}
return null;
case "yield": case "yield":
var yieldDataList = new CompletionDataWrapper(this); var yieldDataList = new CompletionDataWrapper(this);
DefaultCompletionString = "return"; DefaultCompletionString = "return";
@ -1505,38 +1535,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AddContextCompletion(inList, rr != null ? rr.Item2 : GetState(), expr.Node, Unit); AddContextCompletion(inList, rr != null ? rr.Item2 : GetState(), expr.Node, Unit);
return inList.Result; return inList.Result;
// case "where": }
// CompletionDataList whereDataList = new CompletionDataList ();
// NRefactoryResolver constraintResolver = CreateResolver ();
// constraintResolver.SetupResolver (new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
// if (constraintResolver.CallingMember is IMethod) {
// foreach (ITypeParameter tp in ((IMethod)constraintResolver.CallingMember).TypeParameters) {
// whereDataList.Add (tp.Name, "md-keyword");
// }
// } else {
// if (constraintResolver.CallingType != null) {
// foreach (ITypeParameter tp in constraintResolver.CallingType.TypeParameters) {
// whereDataList.Add (tp.Name, "md-keyword");
// }
// }
// }
//
// return whereDataList;
}
// if (IsInLinqContext (result)) {
// if (linqKeywords.Contains (word)) {
// if (word == "from") // after from no auto code completion.
// return null;
// result.Expression = "";
// return CreateCtrlSpaceCompletionData (completionContext, result);
// }
// CompletionDataList dataList = new ProjectDomCompletionDataList ();
// CompletionDataCollector col = new CompletionDataCollector (this, dom, dataList, Document.CompilationUnit, null, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
// foreach (string kw in linqKeywords) {
// col.Add (kw, "md-keyword");
// }
// return dataList;
// }
return null; return null;
} }
@ -1563,42 +1562,55 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return ""; return "";
} }
static CSharpAmbience amb = new CSharpAmbience ();
IEnumerable<ICompletionData> CreateTypeCompletionData(IType hintType, AstType hintTypeAst) IEnumerable<ICompletionData> CreateTypeCompletionData(IType hintType, AstType hintTypeAst)
{ {
var wrapper = new CompletionDataWrapper (this); var wrapper = new CompletionDataWrapper(this);
var state = GetState(); var state = GetState();
Predicate<IType> pred = null; Func<IType, IType> pred = null;
if (hintType != null) { if (hintType != null) {
if (hintType.Kind != TypeKind.Unknown) { if (hintType.Kind != TypeKind.Unknown) {
var lookup = new MemberLookup (ctx.CurrentTypeDefinition, Compilation.MainAssembly); var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
pred = t => { pred = t => {
// check if type is in inheritance tree. // check if type is in inheritance tree.
if (hintType.GetDefinition() != null && !t.GetDefinition().IsDerivedFrom(hintType.GetDefinition())) { if (hintType.GetDefinition() != null && !t.GetDefinition().IsDerivedFrom(hintType.GetDefinition())) {
return false; return null;
} }
if (t.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array) { if (t.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array) {
return false; return null;
} }
// check for valid constructors // check for valid constructors
if (t.GetConstructors().Count() == 0) { if (t.GetConstructors().Count() > 0) {
return true; bool isProtectedAllowed = currentType != null ? currentType.Resolve(ctx).GetDefinition().IsDerivedFrom(t.GetDefinition()) : false;
if (!t.GetConstructors().Any(m => lookup.IsAccessible(m, isProtectedAllowed)))
return null;
} }
bool isProtectedAllowed = currentType != null ? currentType.Resolve(ctx).GetDefinition().IsDerivedFrom(t.GetDefinition()) : false;
return t.GetConstructors().Any(m => lookup.IsAccessible(m, isProtectedAllowed)); var typeInference = new TypeInference(Compilation);
typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults;
var inferedType = typeInference.FindTypeInBounds(new [] { t }, new [] { hintType });
wrapper.AddType(inferedType, amb.ConvertType(inferedType));
return null;
}; };
if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) { if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) {
DefaultCompletionString = GetShortType(hintType, GetState()); DefaultCompletionString = GetShortType(hintType, GetState());
wrapper.AddType(hintType, DefaultCompletionString); wrapper.AddType(hintType, DefaultCompletionString);
} }
if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") {
var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault();
var array = new ArrayTypeReference(arg.ToTypeReference(), 1).Resolve(ctx);
wrapper.AddType(array, amb.ConvertType(array));
}
} else { } else {
DefaultCompletionString = hintTypeAst.ToString(); DefaultCompletionString = hintTypeAst.ToString();
wrapper.AddType(hintType, DefaultCompletionString); wrapper.AddType(hintType, DefaultCompletionString);
} }
} }
AddTypesAndNamespaces(wrapper, state, null, pred, m => false); AddTypesAndNamespaces(wrapper, state, null, pred, m => false);
AddKeywords(wrapper, primitiveTypesKeywords.Where(k => k != "void")); if (hintType == null || hintType == SpecialType.UnknownType)
AddKeywords(wrapper, primitiveTypesKeywords.Where(k => k != "void"));
CloseOnSquareBrackets = true; CloseOnSquareBrackets = true;
AutoCompleteEmptyMatch = true; AutoCompleteEmptyMatch = true;
return wrapper.Result; return wrapper.Result;
@ -1712,7 +1724,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (alreadyInserted.Any(cm => SignatureComparer.Ordinal.Equals(cm, m))) if (alreadyInserted.Any(cm => SignatureComparer.Ordinal.Equals(cm, m)))
continue; continue;
alreadyInserted.Add (m); alreadyInserted.Add (m);
data.CompletionCategory = col.GetCompletionCategory(curType); data.CompletionCategory = col.GetCompletionCategory(m.DeclaringTypeDefinition);
col.Add(data); col.Add(data);
} }
} }
@ -1942,9 +1954,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> CreateParameterCompletion(MethodGroupResolveResult resolveResult, CSharpResolver state, AstNode invocation, CompilationUnit unit, int parameter, bool controlSpace) IEnumerable<ICompletionData> CreateParameterCompletion(MethodGroupResolveResult resolveResult, CSharpResolver state, AstNode invocation, CompilationUnit unit, int parameter, bool controlSpace)
{ {
var result = new CompletionDataWrapper (this); var result = new CompletionDataWrapper(this);
var addedEnums = new HashSet<string> (); var addedEnums = new HashSet<string>();
var addedDelegates = new HashSet<string> (); var addedDelegates = new HashSet<string>();
foreach (var method in resolveResult.Methods) { foreach (var method in resolveResult.Methods) {
if (method.Parameters.Count <= parameter) { if (method.Parameters.Count <= parameter) {
@ -1958,13 +1970,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
addedEnums.Add(resolvedType.ReflectionName); addedEnums.Add(resolvedType.ReflectionName);
AddEnumMembers(result, resolvedType, state); AddEnumMembers(result, resolvedType, state);
} else if (resolvedType.Kind == TypeKind.Delegate) { } else if (resolvedType.Kind == TypeKind.Delegate) {
// if (addedDelegates.Contains (resolvedType.DecoratedFullName)) if (addedDelegates.Contains(resolvedType.ReflectionName))
// continue; continue;
// addedDelegates.Add (resolvedType.DecoratedFullName); string parameterDefinition = AddDelegateHandlers(result, resolvedType);
// string parameterDefinition = AddDelegateHandlers (completionList, resolvedType, false, addedDelegates.Count == 1); string varName = "Handle" + method.Parameters [parameter].Type.Name + method.Parameters [parameter].Name;
// string varName = "Handle" + method.Parameters [parameter].ReturnType.Name + method.Parameters [parameter].Name; result.Result.Add(factory.CreateEventCreationCompletionData(varName, resolvedType, null, parameterDefinition, currentMember, currentType));
// result.Add (new EventCreationCompletionData (document, varName, resolvedType, null, parameterDefinition, resolver.Unit.GetMemberAt (location), resolvedType) { AddSemicolon = false });
} }
} }
if (!controlSpace) { if (!controlSpace) {
@ -2515,132 +2525,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return document.GetText(i, endOffset - i); return document.GetText(i, endOffset - i);
} }
bool GetParameterCompletionCommandOffset(out int cpos)
{
// Start calculating the parameter offset from the beginning of the
// current member, instead of the beginning of the file.
cpos = offset - 1;
var mem = currentMember;
if (mem == null || (mem is IType)) {
return false;
}
int startPos = document.GetOffset(mem.Region.BeginLine, mem.Region.BeginColumn);
int parenDepth = 0;
int chevronDepth = 0;
while (cpos > startPos) {
char c = document.GetCharAt(cpos);
if (c == ')') {
parenDepth++;
}
if (c == '>') {
chevronDepth++;
}
if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') {
int p = GetCurrentParameterIndex(cpos + 1, startPos);
if (p != -1) {
cpos++;
return true;
} else {
return false;
}
}
if (c == '(') {
parenDepth--;
}
if (c == '<') {
chevronDepth--;
}
cpos--;
}
return false;
}
int GetCurrentParameterIndex(int offset, int memberStart)
{
int cursor = this.offset;
int i = offset;
if (i > cursor) {
return -1;
}
if (i == cursor) {
return 1;
}
// parameters are 1 based
int index = memberStart + 1;
int parentheses = 0;
int bracket = 0;
bool insideQuote = false, insideString = false, insideSingleLineComment = false, insideMultiLineComment = false;
do {
char c = document.GetCharAt(i - 1);
switch (c) {
case '\\':
if (insideString || insideQuote) {
i++;
}
break;
case '\'':
if (!insideString && !insideSingleLineComment && !insideMultiLineComment) {
insideQuote = !insideQuote;
}
break;
case '"':
if (!insideQuote && !insideSingleLineComment && !insideMultiLineComment) {
insideString = !insideString;
}
break;
case '/':
if (!insideQuote && !insideString && !insideMultiLineComment) {
if (document.GetCharAt(i) == '/') {
insideSingleLineComment = true;
}
if (document.GetCharAt(i) == '*') {
insideMultiLineComment = true;
}
}
break;
case '*':
if (insideMultiLineComment && document.GetCharAt(i) == '/') {
insideMultiLineComment = false;
}
break;
case '\n':
case '\r':
insideSingleLineComment = false;
break;
case '{':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
bracket++;
}
break;
case '}':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
bracket--;
}
break;
case '(':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
parentheses++;
}
break;
case ')':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
parentheses--;
}
break;
case ',':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment && parentheses == 1 && bracket == 0) {
index++;
}
break;
}
i++;
} while (i <= cursor && parentheses >= 0);
return parentheses != 1 || bracket > 0 ? -1 : index;
}
#endregion #endregion
#region Preprocessor #region Preprocessor

286
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -100,76 +100,258 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var provider = MemberProvider ?? new DefaultMemberProvider (this); var provider = MemberProvider ?? new DefaultMemberProvider (this);
provider.GetCurrentMembers (offset, out currentType, out currentMember); provider.GetCurrentMembers (offset, out currentType, out currentMember);
} }
protected bool GetParameterCompletionCommandOffset(out int cpos)
{
// Start calculating the parameter offset from the beginning of the
// current member, instead of the beginning of the file.
cpos = offset - 1;
var mem = currentMember;
if (mem == null || (mem is IType)) {
return false;
}
int startPos = document.GetOffset(mem.Region.BeginLine, mem.Region.BeginColumn);
int parenDepth = 0;
int chevronDepth = 0;
Stack<int> indexStack = new Stack<int>();
while (cpos > startPos) {
char c = document.GetCharAt(cpos);
if (c == ')') {
parenDepth++;
}
if (c == '>') {
chevronDepth++;
}
if (c == '}') {
if (indexStack.Count > 0) {
parenDepth = indexStack.Pop();
} else {
parenDepth = 0;
}
chevronDepth = 0;
}
if (indexStack.Count == 0 && (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<')) {
int p = GetCurrentParameterIndex (cpos + 1, startPos);
if (p != -1) {
cpos++;
return true;
} else {
return false;
}
}
if (c == '(') {
parenDepth--;
}
if (c == '<') {
chevronDepth--;
}
if (c == '{') {
indexStack.Push (parenDepth);
chevronDepth = 0;
}
cpos--;
}
return false;
}
#region Context helper methods protected int GetCurrentParameterIndex (int offset, int memberStart)
protected bool IsInsideCommentOrString ()
{ {
var text = GetMemberTextToCaret (); int cursor = this.offset;
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false; int i = offset;
for (int i = 0; i < text.Item1.Length - 1; i++) { if (i > cursor) {
char ch = text.Item1 [i]; return -1;
char nextCh = text.Item1 [i + 1]; }
if (i == cursor) {
switch (ch) { return 1;
case '/': }
if (inString || inChar || inVerbatimString) // parameters are 1 based
break; int index = memberStart + 1;
if (nextCh == '/') { int parentheses = 0;
int bracket = 0;
bool insideQuote = false, insideString = false, insideSingleLineComment = false, insideMultiLineComment = false;
Stack<int> indexStack = new Stack<int> ();
do {
char c = document.GetCharAt (i - 1);
switch (c) {
case '\\':
if (insideString || insideQuote) {
i++; i++;
inSingleComment = true;
} }
if (nextCh == '*')
inMultiLineComment = true;
break; break;
case '*': case '\'':
if (inString || inChar || inVerbatimString || inSingleComment) if (!insideString && !insideSingleLineComment && !insideMultiLineComment) {
break; insideQuote = !insideQuote;
if (nextCh == '/') {
i++;
inMultiLineComment = false;
} }
break; break;
case '@': case '"':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) if (!insideQuote && !insideSingleLineComment && !insideMultiLineComment) {
break; insideString = !insideString;
if (nextCh == '"') { }
i++; break;
inVerbatimString = true; case '/':
if (!insideQuote && !insideString && !insideMultiLineComment) {
if (document.GetCharAt (i) == '/') {
insideSingleLineComment = true;
}
if (document.GetCharAt (i) == '*') {
insideMultiLineComment = true;
}
}
break;
case '*':
if (insideMultiLineComment && document.GetCharAt (i) == '/') {
insideMultiLineComment = false;
} }
break; break;
case '\n': case '\n':
case '\r': case '\r':
inSingleComment = false; insideSingleLineComment = false;
inString = false;
inChar = false;
break; break;
case '\\': case '{':
if (inString || inChar) if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
i++; bracket++;
indexStack.Push (index);
}
break; break;
case '"': case '}':
if (inSingleComment || inMultiLineComment || inChar) if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
break; bracket--;
if (inVerbatimString) { if (indexStack.Count > 0)
if (nextCh == '"') { index = indexStack.Pop ();
i++;
break;
}
inVerbatimString = false;
break;
} }
inString = !inString;
break; break;
case '\'': case '(':
if (inSingleComment || inMultiLineComment || inString || inVerbatimString) if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
break; parentheses++;
inChar = !inChar; }
break;
case ')':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment) {
parentheses--;
}
break;
case ',':
if (!insideQuote && !insideString && !insideSingleLineComment && !insideMultiLineComment && parentheses == 1 && bracket == 0) {
index++;
}
break; break;
}
i++;
} while (i <= cursor && parentheses >= 0);
Console.WriteLine (indexStack.Count >= 0 || parentheses != 1 || bracket > 0 ? -1 : index);
return indexStack.Count >= 0 || parentheses != 1 || bracket > 0 ? -1 : index;
}
#region Context helper methods
public class MiniLexer
{
readonly string text;
public bool IsFistNonWs = true;
public bool IsInSingleComment = false;
public bool IsInString = false;
public bool IsInVerbatimString = false;
public bool IsInChar = false;
public bool IsInMultiLineComment = false;
public bool IsInPreprocessorDirective = false;
public MiniLexer(string text)
{
this.text = text;
}
public void Parse(Action<char> act = null)
{
Parse(0, text.Length, act);
}
public void Parse(int start, int length, Action<char> act = null)
{
for (int i = start; i < length; i++) {
char ch = text [i];
char nextCh = i + 1 < text.Length ? text [i + 1] : '\0';
switch (ch) {
case '#':
if (IsFistNonWs)
IsInPreprocessorDirective = true;
break;
case '/':
if (IsInString || IsInChar || IsInVerbatimString)
break;
if (nextCh == '/') {
i++;
IsInSingleComment = true;
}
if (nextCh == '*')
IsInMultiLineComment = true;
break;
case '*':
if (IsInString || IsInChar || IsInVerbatimString || IsInSingleComment)
break;
if (nextCh == '/') {
i++;
IsInMultiLineComment = false;
}
break;
case '@':
if (IsInString || IsInChar || IsInVerbatimString || IsInSingleComment || IsInMultiLineComment)
break;
if (nextCh == '"') {
i++;
IsInVerbatimString = true;
}
break;
case '\n':
case '\r':
IsInSingleComment = false;
IsInString = false;
IsInChar = false;
IsFistNonWs = true;
break;
case '\\':
if (IsInString || IsInChar)
i++;
break;
case '"':
if (IsInSingleComment || IsInMultiLineComment || IsInChar)
break;
if (IsInVerbatimString) {
if (nextCh == '"') {
i++;
break;
}
IsInVerbatimString = false;
break;
}
IsInString = !IsInString;
break;
case '\'':
if (IsInSingleComment || IsInMultiLineComment || IsInString || IsInVerbatimString)
break;
IsInChar = !IsInChar;
break;
}
if (act != null)
act(ch);
IsFistNonWs &= ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
} }
} }
}
return inSingleComment || inString || inVerbatimString || inChar || inMultiLineComment;
protected bool IsInsideCommentStringOrDirective()
{
var text = GetMemberTextToCaret();
var lexer = new MiniLexer(text.Item1);
lexer.Parse();
return
lexer.IsInSingleComment ||
lexer.IsInString ||
lexer.IsInVerbatimString ||
lexer.IsInChar ||
lexer.IsInMultiLineComment ||
lexer.IsInPreprocessorDirective;
} }
protected bool IsInsideDocComment () protected bool IsInsideDocComment ()
@ -439,7 +621,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AppendMissingClosingBrackets(wrapper, memberText, appendSemicolon); AppendMissingClosingBrackets(wrapper, memberText, appendSemicolon);
wrapper.Append(afterContinuation); wrapper.Append(afterContinuation);
if (closingBrackets > 0) { if (closingBrackets > 0) {
wrapper.Append(new string ('}', closingBrackets)); wrapper.Append(new string('}', closingBrackets));
} }
using (var stream = new System.IO.StringReader (wrapper.ToString ())) { using (var stream = new System.IO.StringReader (wrapper.ToString ())) {
try { try {

74
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -1,4 +1,4 @@
// //
// CSharpParameterCompletionEngine.cs // CSharpParameterCompletionEngine.cs
// //
// Author: // Author:
@ -105,6 +105,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; //var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var expr = baseUnit.GetNodeAt<AstType>(location.Line, location.Column + 1); var expr = baseUnit.GetNodeAt<AstType>(location.Line, location.Column + 1);
if (expr == null)
return null;
// '>' position // '>' position
return new ExpressionResult((AstNode)expr, baseUnit); return new ExpressionResult((AstNode)expr, baseUnit);
} }
@ -146,7 +148,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
SetOffset(offset); SetOffset(offset);
if (IsInsideCommentOrString()) { if (IsInsideCommentStringOrDirective()) {
return null; return null;
} }
@ -171,6 +173,8 @@ 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, invoke.Unit);
if (createType.Item1.Type.Kind == TypeKind.Unknown)
return null;
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
} }
@ -217,6 +221,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (invoke == null) { if (invoke == null) {
invoke = GetTypeBeforeCursor(); invoke = GetTypeBeforeCursor();
if (invoke != null) { if (invoke != null) {
if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0)
return null;
var typeExpression = ResolveExpression(invoke); var typeExpression = ResolveExpression(invoke);
if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) { if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) {
return null; return null;
@ -226,6 +232,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return null; return null;
} }
if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0)
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, invoke.Unit);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
@ -334,17 +342,37 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return 0; return 0;
} }
var parameter = new Stack<int>(); var parameter = new Stack<int>();
var bracketStack = new Stack<Stack<int>>();
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false; bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false;
for (int i = triggerOffset; i < endOffset; i++) { for (int i = triggerOffset; i < endOffset; i++) {
char ch = document.GetCharAt(i); char ch = document.GetCharAt(i);
char nextCh = i + 1 < document.TextLength ? document.GetCharAt(i + 1) : '\0'; char nextCh = i + 1 < document.TextLength ? document.GetCharAt(i + 1) : '\0';
switch (ch) { switch (ch) {
case '{':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
bracketStack.Push(parameter);
parameter = new Stack<int>();
break;
case '[':
case '(': case '(':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) { if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break; break;
} }
parameter.Push(0); parameter.Push(0);
break; break;
case '}':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (bracketStack.Count > 0) {
parameter = bracketStack.Pop();
} else {
return -1;
}
break;
case ']':
case ')': case ')':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) { if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break; break;
@ -440,51 +468,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
break; break;
} }
} }
if (parameter.Count == 0) { if (parameter.Count == 0 || bracketStack.Count > 0) {
return -1; return -1;
} }
return parameter.Pop() + 1; return parameter.Pop() + 1;
} }
/*
public override bool GetParameterCompletionCommandOffset (out int cpos)
{
// Start calculating the parameter offset from the beginning of the
// current member, instead of the beginning of the file.
cpos = textEditorData.Caret.Offset - 1;
var parsedDocument = Document.ParsedDocument;
if (parsedDocument == null)
return false;
IMember mem = currentMember;
if (mem == null || (mem is IType))
return false;
int startPos = textEditorData.LocationToOffset (mem.Region.BeginLine, mem.Region.BeginColumn);
int parenDepth = 0;
int chevronDepth = 0;
while (cpos > startPos) {
char c = textEditorData.GetCharAt (cpos);
if (c == ')')
parenDepth++;
if (c == '>')
chevronDepth++;
if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') {
int p = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, cpos + 1, startPos);
if (p != -1) {
cpos++;
return true;
} else {
return false;
}
}
if (c == '(')
parenDepth--;
if (c == '<')
chevronDepth--;
cpos--;
}
return false;
}*/
} }
} }

69
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -1,4 +1,4 @@
// //
// AstFormattingVisitor.cs // AstFormattingVisitor.cs
// //
// Author: // Author:
@ -445,6 +445,24 @@ namespace ICSharpCode.NRefactory.CSharp
return i; return i;
} }
int ForceSpacesBeforeRemoveNewLines(AstNode n)
{
if (n == null || n.IsNull) {
return 0;
}
int offset = document.GetOffset(n.StartLocation);
int i = offset - 1;
while (i >= 0) {
char ch = document.GetCharAt(i);
if (!IsSpacing(ch) && ch != '\r' && ch != '\n')
break;
i--;
}
var length = System.Math.Max(0, (offset - 1) - i);
AddChange(i + 1, length, " ");
return i;
}
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{ {
FormatAttributedNode(propertyDeclaration); FormatAttributedNode(propertyDeclaration);
@ -870,8 +888,16 @@ namespace ICSharpCode.NRefactory.CSharp
if (child.Role == Roles.LBrace || child.Role == Roles.RBrace) { if (child.Role == Roles.LBrace || child.Role == Roles.RBrace) {
continue; continue;
} }
FixStatementIndentation(child.StartLocation); if (child is Statement) {
child.AcceptVisitor(this); FixStatementIndentation(child.StartLocation);
child.AcceptVisitor(this);
} else if (child is Comment) {
child.AcceptVisitor(this);
} else {
// pre processor directives at line start, if they are there.
if (child.StartLocation.Column > 1)
FixStatementIndentation(child.StartLocation);
}
} }
if (indent) { if (indent) {
curIndent.Pop (); curIndent.Pop ();
@ -887,7 +913,7 @@ namespace ICSharpCode.NRefactory.CSharp
public override void VisitComment(Comment comment) public override void VisitComment(Comment comment)
{ {
if (comment.StartsLine && !HadErrors && comment.StartLocation.Column > 1) { if (comment.StartsLine && !HadErrors && (!policy.KeepCommentsAtFirstColumn || comment.StartLocation.Column > 1)) {
FixIndentation(comment.StartLocation); FixIndentation(comment.StartLocation);
} }
} }
@ -1404,18 +1430,11 @@ namespace ICSharpCode.NRefactory.CSharp
} }
var lastLoc = variableDeclarationStatement.StartLocation; var lastLoc = variableDeclarationStatement.StartLocation;
foreach (var initializer in variableDeclarationStatement.Variables) { foreach (var initializer in variableDeclarationStatement.Variables) {
var indent = !(initializer.Initializer is AnonymousMethodExpression);
if (indent) {
curIndent.Push(IndentType.Block);
}
if (lastLoc.Line != initializer.StartLocation.Line) { if (lastLoc.Line != initializer.StartLocation.Line) {
FixStatementIndentation(initializer.StartLocation); FixStatementIndentation(initializer.StartLocation);
lastLoc = initializer.StartLocation; lastLoc = initializer.StartLocation;
} }
initializer.AcceptVisitor(this); initializer.AcceptVisitor(this);
if (indent) {
curIndent.Pop ();
}
} }
FormatCommas(variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma); FormatCommas(variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma);
@ -1673,6 +1692,28 @@ namespace ICSharpCode.NRefactory.CSharp
base.VisitArrayCreateExpression(arrayObjectCreateExpression); base.VisitArrayCreateExpression(arrayObjectCreateExpression);
} }
public override void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
{
if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) {
EnforceBraceStyle(policy.ArrayInitializerBraceStyle, arrayInitializerExpression.LBraceToken, arrayInitializerExpression.RBraceToken);
curIndent.Push(IndentType.Block);
foreach (var init in arrayInitializerExpression.Elements) {
FixStatementIndentation(init.StartLocation);
init.AcceptVisitor(this);
}
curIndent.Pop();
} else if (policy.ArrayInitializerWrapping == Wrapping.DoNotWrap) {
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.LBraceToken);
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.RBraceToken);
foreach (var init in arrayInitializerExpression.Elements) {
ForceSpacesBeforeRemoveNewLines(init);
init.AcceptVisitor(this);
}
} else {
base.VisitArrayInitializerExpression(arrayInitializerExpression);
}
}
public override void VisitLambdaExpression(LambdaExpression lambdaExpression) public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
{ {
ForceSpacesAfter(lambdaExpression.ArrowToken, true); ForceSpacesAfter(lambdaExpression.ArrowToken, true);
@ -1681,6 +1722,12 @@ namespace ICSharpCode.NRefactory.CSharp
base.VisitLambdaExpression(lambdaExpression); base.VisitLambdaExpression(lambdaExpression);
} }
public override void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
{
ForceSpacesAfter(namedArgumentExpression.ColonToken, policy.SpaceInNamedArgumentAfterDoubleColon);
base.VisitNamedArgumentExpression(namedArgumentExpression);
}
#endregion #endregion
void ForceSpaceBefore(int offset, bool forceSpace) void ForceSpaceBefore(int offset, bool forceSpace)

159
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs

@ -48,12 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp
AddBraces AddBraces
} }
public enum ArrayInitializerPlacement
{
AlwaysNewLine,
AlwaysSameLine
}
public enum PropertyFormatting public enum PropertyFormatting
{ {
AllowOneLine, AllowOneLine,
@ -61,6 +55,12 @@ namespace ICSharpCode.NRefactory.CSharp
ForceNewLine ForceNewLine
} }
public enum Wrapping {
DoNotWrap,
WrapAlways,
WrapIfTooLong
}
public class CSharpFormattingOptions public class CSharpFormattingOptions
{ {
public string Name { public string Name {
@ -322,11 +322,6 @@ namespace ICSharpCode.NRefactory.CSharp
get; get;
set; set;
} }
public ArrayInitializerPlacement PlaceArrayInitializersOnNewLine {
get;
set;
}
#endregion #endregion
#region Spaces #region Spaces
@ -727,6 +722,10 @@ namespace ICSharpCode.NRefactory.CSharp
set; set;
} }
public bool SpaceInNamedArgumentAfterDoubleColon {
get;
set;
}
#endregion #endregion
#region Blank Lines #region Blank Lines
@ -766,119 +765,31 @@ namespace ICSharpCode.NRefactory.CSharp
} }
#endregion #endregion
public CSharpFormattingOptions ()
#region Keep formatting
public bool KeepCommentsAtFirstColumn {
get;
set;
}
#endregion
#region Wrapping
public Wrapping ArrayInitializerWrapping {
get;
set;
}
public BraceStyle ArrayInitializerBraceStyle {
get;
set;
}
#endregion
internal CSharpFormattingOptions()
{ {
IndentNamespaceBody = true;
IndentClassBody = IndentInterfaceBody = IndentStructBody = IndentEnumBody = true;
IndentMethodBody = IndentPropertyBody = IndentEventBody = true;
IndentBlocks = true;
IndentSwitchBody = false;
IndentCaseBody = true;
IndentBreakStatements = true;
NamespaceBraceStyle = BraceStyle.NextLine;
ClassBraceStyle = InterfaceBraceStyle = StructBraceStyle = EnumBraceStyle = BraceStyle.NextLine;
MethodBraceStyle = ConstructorBraceStyle = DestructorBraceStyle = BraceStyle.NextLine;
AnonymousMethodBraceStyle = BraceStyle.EndOfLine;
PropertyBraceStyle = PropertyGetBraceStyle = PropertySetBraceStyle = BraceStyle.EndOfLine;
AllowPropertyGetBlockInline = AllowPropertySetBlockInline = true;
EventBraceStyle = EventAddBraceStyle = EventRemoveBraceStyle = BraceStyle.EndOfLine;
AllowEventAddBlockInline = AllowEventRemoveBlockInline = true;
StatementBraceStyle = BraceStyle.EndOfLine;
PlaceElseOnNewLine = false;
PlaceCatchOnNewLine = false;
PlaceFinallyOnNewLine = false;
PlaceWhileOnNewLine = false;
PlaceArrayInitializersOnNewLine = ArrayInitializerPlacement.AlwaysSameLine;
SpaceBeforeMethodCallParentheses = true;
SpaceBeforeMethodDeclarationParentheses = true;
SpaceBeforeConstructorDeclarationParentheses = true;
SpaceBeforeDelegateDeclarationParentheses = true;
SpaceAfterMethodCallParameterComma = true;
SpaceAfterConstructorDeclarationParameterComma = true;
SpaceBeforeNewParentheses = true;
SpacesWithinNewParentheses = false;
SpacesBetweenEmptyNewParentheses = false;
SpaceBeforeNewParameterComma = false;
SpaceAfterNewParameterComma = true;
SpaceBeforeIfParentheses = true;
SpaceBeforeWhileParentheses = true;
SpaceBeforeForParentheses = true;
SpaceBeforeForeachParentheses = true;
SpaceBeforeCatchParentheses = true;
SpaceBeforeSwitchParentheses = true;
SpaceBeforeLockParentheses = true;
SpaceBeforeUsingParentheses = true;
SpaceAroundAssignment = true;
SpaceAroundLogicalOperator = true;
SpaceAroundEqualityOperator = true;
SpaceAroundRelationalOperator = true;
SpaceAroundBitwiseOperator = true;
SpaceAroundAdditiveOperator = true;
SpaceAroundMultiplicativeOperator = true;
SpaceAroundShiftOperator = true;
SpaceAroundNullCoalescingOperator = true;
SpacesWithinParentheses = false;
SpaceWithinMethodCallParentheses = false;
SpaceWithinMethodDeclarationParentheses = false;
SpacesWithinIfParentheses = false;
SpacesWithinWhileParentheses = false;
SpacesWithinForParentheses = false;
SpacesWithinForeachParentheses = false;
SpacesWithinCatchParentheses = false;
SpacesWithinSwitchParentheses = false;
SpacesWithinLockParentheses = false;
SpacesWithinUsingParentheses = false;
SpacesWithinCastParentheses = false;
SpacesWithinSizeOfParentheses = false;
SpacesWithinTypeOfParentheses = false;
SpacesWithinCheckedExpressionParantheses = false;
SpaceBeforeConditionalOperatorCondition = true;
SpaceAfterConditionalOperatorCondition = true;
SpaceBeforeConditionalOperatorSeparator = true;
SpaceAfterConditionalOperatorSeparator = true;
SpacesWithinBrackets = false;
SpacesBeforeBrackets = true;
SpaceBeforeBracketComma = false;
SpaceAfterBracketComma = true;
SpaceBeforeForSemicolon = false;
SpaceAfterForSemicolon = true;
SpaceAfterTypecast = false;
AlignEmbeddedIfStatements = true;
AlignEmbeddedUsingStatements = true;
PropertyFormatting = PropertyFormatting.AllowOneLine;
SpaceBeforeMethodDeclarationParameterComma = false;
SpaceAfterMethodDeclarationParameterComma = true;
SpaceBeforeFieldDeclarationComma = false;
SpaceAfterFieldDeclarationComma = true;
SpaceBeforeLocalVariableDeclarationComma = false;
SpaceAfterLocalVariableDeclarationComma = true;
SpaceBeforeIndexerDeclarationBracket = true;
SpaceWithinIndexerDeclarationBracket = false;
SpaceBeforeIndexerDeclarationParameterComma = false;
SpaceAfterIndexerDeclarationParameterComma = true;
BlankLinesBeforeUsings = 0;
BlankLinesAfterUsings = 1;
BlankLinesBeforeFirstDeclaration = 0;
BlankLinesBetweenTypes = 1;
BlankLinesBetweenFields = 0;
BlankLinesBetweenEventFields = 0;
BlankLinesBetweenMembers = 1;
} }
/*public static CSharpFormattingOptions Load (FilePath selectedFile) /*public static CSharpFormattingOptions Load (FilePath selectedFile)
@ -890,7 +801,7 @@ namespace ICSharpCode.NRefactory.CSharp
public static CSharpFormattingOptions Load (System.IO.Stream input) public static CSharpFormattingOptions Load (System.IO.Stream input)
{ {
CSharpFormattingOptions result = new CSharpFormattingOptions (); CSharpFormattingOptions result = FormattingOptionsFactory.CreateMonoOptions ();
result.Name = "noname"; result.Name = "noname";
using (XmlTextReader reader = new XmlTextReader (input)) { using (XmlTextReader reader = new XmlTextReader (input)) {
while (reader.Read ()) { while (reader.Read ()) {

339
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs

@ -0,0 +1,339 @@
//
// FormattingOptionsFactory.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// The formatting options factory creates pre defined formatting option styles.
/// </summary>
public static class FormattingOptionsFactory
{
/// <summary>
/// Creates empty CSharpFormatting options.
/// </summary>
public static CSharpFormattingOptions CreateEmpty()
{
return new CSharpFormattingOptions();
}
/// <summary>
/// Creates mono indent style CSharpFormatting options.
/// </summary>
public static CSharpFormattingOptions CreateMono()
{
return new CSharpFormattingOptions() {
IndentNamespaceBody = true,
IndentClassBody = true,
IndentInterfaceBody = true,
IndentStructBody = true,
IndentEnumBody = true,
IndentMethodBody = true,
IndentPropertyBody = true,
IndentEventBody = true,
IndentBlocks = true,
IndentSwitchBody = false,
IndentCaseBody = true,
IndentBreakStatements = true,
NamespaceBraceStyle = BraceStyle.NextLine,
ClassBraceStyle = BraceStyle.NextLine,
InterfaceBraceStyle = BraceStyle.NextLine,
StructBraceStyle = BraceStyle.NextLine,
EnumBraceStyle = BraceStyle.NextLine,
MethodBraceStyle = BraceStyle.NextLine,
ConstructorBraceStyle = BraceStyle.NextLine,
DestructorBraceStyle = BraceStyle.NextLine,
AnonymousMethodBraceStyle = BraceStyle.EndOfLine,
PropertyBraceStyle = BraceStyle.EndOfLine,
PropertyGetBraceStyle = BraceStyle.EndOfLine,
PropertySetBraceStyle = BraceStyle.EndOfLine,
AllowPropertyGetBlockInline = true,
AllowPropertySetBlockInline = true,
EventBraceStyle = BraceStyle.EndOfLine,
EventAddBraceStyle = BraceStyle.EndOfLine,
EventRemoveBraceStyle = BraceStyle.EndOfLine,
AllowEventAddBlockInline = true,
AllowEventRemoveBlockInline = true,
StatementBraceStyle = BraceStyle.EndOfLine,
PlaceElseOnNewLine = false,
PlaceCatchOnNewLine = false,
PlaceFinallyOnNewLine = false,
PlaceWhileOnNewLine = false,
ArrayInitializerWrapping = Wrapping.WrapIfTooLong,
ArrayInitializerBraceStyle = BraceStyle.EndOfLine,
SpaceBeforeMethodCallParentheses = true,
SpaceBeforeMethodDeclarationParentheses = true,
SpaceBeforeConstructorDeclarationParentheses = true,
SpaceBeforeDelegateDeclarationParentheses = true,
SpaceAfterMethodCallParameterComma = true,
SpaceAfterConstructorDeclarationParameterComma = true,
SpaceBeforeNewParentheses = true,
SpacesWithinNewParentheses = false,
SpacesBetweenEmptyNewParentheses = false,
SpaceBeforeNewParameterComma = false,
SpaceAfterNewParameterComma = true,
SpaceBeforeIfParentheses = true,
SpaceBeforeWhileParentheses = true,
SpaceBeforeForParentheses = true,
SpaceBeforeForeachParentheses = true,
SpaceBeforeCatchParentheses = true,
SpaceBeforeSwitchParentheses = true,
SpaceBeforeLockParentheses = true,
SpaceBeforeUsingParentheses = true,
SpaceAroundAssignment = true,
SpaceAroundLogicalOperator = true,
SpaceAroundEqualityOperator = true,
SpaceAroundRelationalOperator = true,
SpaceAroundBitwiseOperator = true,
SpaceAroundAdditiveOperator = true,
SpaceAroundMultiplicativeOperator = true,
SpaceAroundShiftOperator = true,
SpaceAroundNullCoalescingOperator = true,
SpacesWithinParentheses = false,
SpaceWithinMethodCallParentheses = false,
SpaceWithinMethodDeclarationParentheses = false,
SpacesWithinIfParentheses = false,
SpacesWithinWhileParentheses = false,
SpacesWithinForParentheses = false,
SpacesWithinForeachParentheses = false,
SpacesWithinCatchParentheses = false,
SpacesWithinSwitchParentheses = false,
SpacesWithinLockParentheses = false,
SpacesWithinUsingParentheses = false,
SpacesWithinCastParentheses = false,
SpacesWithinSizeOfParentheses = false,
SpacesWithinTypeOfParentheses = false,
SpacesWithinCheckedExpressionParantheses = false,
SpaceBeforeConditionalOperatorCondition = true,
SpaceAfterConditionalOperatorCondition = true,
SpaceBeforeConditionalOperatorSeparator = true,
SpaceAfterConditionalOperatorSeparator = true,
SpacesWithinBrackets = false,
SpacesBeforeBrackets = true,
SpaceBeforeBracketComma = false,
SpaceAfterBracketComma = true,
SpaceBeforeForSemicolon = false,
SpaceAfterForSemicolon = true,
SpaceAfterTypecast = false,
AlignEmbeddedIfStatements = true,
AlignEmbeddedUsingStatements = true,
PropertyFormatting = PropertyFormatting.AllowOneLine,
SpaceBeforeMethodDeclarationParameterComma = false,
SpaceAfterMethodDeclarationParameterComma = true,
SpaceBeforeFieldDeclarationComma = false,
SpaceAfterFieldDeclarationComma = true,
SpaceBeforeLocalVariableDeclarationComma = false,
SpaceAfterLocalVariableDeclarationComma = true,
SpaceBeforeIndexerDeclarationBracket = true,
SpaceWithinIndexerDeclarationBracket = false,
SpaceBeforeIndexerDeclarationParameterComma = false,
SpaceInNamedArgumentAfterDoubleColon = true,
SpaceAfterIndexerDeclarationParameterComma = true,
BlankLinesBeforeUsings = 0,
BlankLinesAfterUsings = 1,
BlankLinesBeforeFirstDeclaration = 0,
BlankLinesBetweenTypes = 1,
BlankLinesBetweenFields = 0,
BlankLinesBetweenEventFields = 0,
BlankLinesBetweenMembers = 1,
KeepCommentsAtFirstColumn = true,
};
}
/// <summary>
/// Creates sharp develop indent style CSharpFormatting options.
/// </summary>
public static CSharpFormattingOptions CreateSharpDevelop()
{
return new CSharpFormattingOptions() {
IndentNamespaceBody = true,
IndentClassBody = true,
IndentInterfaceBody = true,
IndentStructBody = true,
IndentEnumBody = true,
IndentMethodBody = true,
IndentPropertyBody = true,
IndentEventBody = true,
IndentBlocks = true,
IndentSwitchBody = true,
IndentCaseBody = true,
IndentBreakStatements = true,
NamespaceBraceStyle = BraceStyle.NextLine,
ClassBraceStyle = BraceStyle.NextLine,
InterfaceBraceStyle = BraceStyle.NextLine,
StructBraceStyle = BraceStyle.NextLine,
EnumBraceStyle = BraceStyle.NextLine,
MethodBraceStyle = BraceStyle.NextLine,
ConstructorBraceStyle = BraceStyle.NextLine,
DestructorBraceStyle = BraceStyle.NextLine,
AnonymousMethodBraceStyle = BraceStyle.EndOfLine,
PropertyBraceStyle = BraceStyle.EndOfLine,
PropertyGetBraceStyle = BraceStyle.EndOfLine,
PropertySetBraceStyle = BraceStyle.EndOfLine,
AllowPropertyGetBlockInline = true,
AllowPropertySetBlockInline = true,
EventBraceStyle = BraceStyle.EndOfLine,
EventAddBraceStyle = BraceStyle.EndOfLine,
EventRemoveBraceStyle = BraceStyle.EndOfLine,
AllowEventAddBlockInline = true,
AllowEventRemoveBlockInline = true,
StatementBraceStyle = BraceStyle.EndOfLine,
PlaceElseOnNewLine = false,
PlaceCatchOnNewLine = false,
PlaceFinallyOnNewLine = false,
PlaceWhileOnNewLine = false,
ArrayInitializerWrapping = Wrapping.WrapIfTooLong,
ArrayInitializerBraceStyle = BraceStyle.EndOfLine,
SpaceBeforeMethodCallParentheses = false,
SpaceBeforeMethodDeclarationParentheses = false,
SpaceBeforeConstructorDeclarationParentheses = false,
SpaceBeforeDelegateDeclarationParentheses = false,
SpaceAfterMethodCallParameterComma = true,
SpaceAfterConstructorDeclarationParameterComma = true,
SpaceBeforeNewParentheses = false,
SpacesWithinNewParentheses = false,
SpacesBetweenEmptyNewParentheses = false,
SpaceBeforeNewParameterComma = false,
SpaceAfterNewParameterComma = true,
SpaceBeforeIfParentheses = true,
SpaceBeforeWhileParentheses = true,
SpaceBeforeForParentheses = true,
SpaceBeforeForeachParentheses = true,
SpaceBeforeCatchParentheses = true,
SpaceBeforeSwitchParentheses = true,
SpaceBeforeLockParentheses = true,
SpaceBeforeUsingParentheses = true,
SpaceAroundAssignment = true,
SpaceAroundLogicalOperator = true,
SpaceAroundEqualityOperator = true,
SpaceAroundRelationalOperator = true,
SpaceAroundBitwiseOperator = true,
SpaceAroundAdditiveOperator = true,
SpaceAroundMultiplicativeOperator = true,
SpaceAroundShiftOperator = true,
SpaceAroundNullCoalescingOperator = true,
SpacesWithinParentheses = false,
SpaceWithinMethodCallParentheses = false,
SpaceWithinMethodDeclarationParentheses = false,
SpacesWithinIfParentheses = false,
SpacesWithinWhileParentheses = false,
SpacesWithinForParentheses = false,
SpacesWithinForeachParentheses = false,
SpacesWithinCatchParentheses = false,
SpacesWithinSwitchParentheses = false,
SpacesWithinLockParentheses = false,
SpacesWithinUsingParentheses = false,
SpacesWithinCastParentheses = false,
SpacesWithinSizeOfParentheses = false,
SpacesWithinTypeOfParentheses = false,
SpacesWithinCheckedExpressionParantheses = false,
SpaceBeforeConditionalOperatorCondition = true,
SpaceAfterConditionalOperatorCondition = true,
SpaceBeforeConditionalOperatorSeparator = true,
SpaceAfterConditionalOperatorSeparator = true,
SpacesWithinBrackets = false,
SpacesBeforeBrackets = true,
SpaceBeforeBracketComma = false,
SpaceAfterBracketComma = true,
SpaceBeforeForSemicolon = false,
SpaceAfterForSemicolon = true,
SpaceAfterTypecast = false,
AlignEmbeddedIfStatements = true,
AlignEmbeddedUsingStatements = true,
PropertyFormatting = PropertyFormatting.AllowOneLine,
SpaceBeforeMethodDeclarationParameterComma = false,
SpaceAfterMethodDeclarationParameterComma = true,
SpaceBeforeFieldDeclarationComma = false,
SpaceAfterFieldDeclarationComma = true,
SpaceBeforeLocalVariableDeclarationComma = false,
SpaceAfterLocalVariableDeclarationComma = true,
SpaceBeforeIndexerDeclarationBracket = true,
SpaceWithinIndexerDeclarationBracket = false,
SpaceBeforeIndexerDeclarationParameterComma = false,
SpaceInNamedArgumentAfterDoubleColon = true,
SpaceAfterIndexerDeclarationParameterComma = true,
BlankLinesBeforeUsings = 0,
BlankLinesAfterUsings = 1,
BlankLinesBeforeFirstDeclaration = 0,
BlankLinesBetweenTypes = 1,
BlankLinesBetweenFields = 0,
BlankLinesBetweenEventFields = 0,
BlankLinesBetweenMembers = 1,
KeepCommentsAtFirstColumn = true,
};
}
/// <summary>
/// Creates allman indent style CSharpFormatting options used in Visual Studio.
/// </summary>
public static CSharpFormattingOptions CreateAllman()
{
var baseOptions = CreateSharpDevelop();
baseOptions.AnonymousMethodBraceStyle = BraceStyle.EndOfLine;
baseOptions.PropertyBraceStyle = BraceStyle.EndOfLine;
baseOptions.PropertyGetBraceStyle = BraceStyle.EndOfLine;
baseOptions.PropertySetBraceStyle = BraceStyle.EndOfLine;
baseOptions.EventBraceStyle = BraceStyle.EndOfLine;
baseOptions.EventAddBraceStyle = BraceStyle.EndOfLine;
baseOptions.EventRemoveBraceStyle = BraceStyle.EndOfLine;
baseOptions.StatementBraceStyle = BraceStyle.EndOfLine;
baseOptions.ArrayInitializerBraceStyle = BraceStyle.EndOfLine;
return baseOptions;
}
}
}

216
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/GeneratedCodeSettings.cs

@ -0,0 +1,216 @@
//
// GeneratedCodeSettings.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
public enum GeneratedCodeMember
{
Unknown,
StaticFields,
InstanceFields,
StaticProperties,
InstanceProperties,
Indexer,
Constructors,
StaticMethods,
InstanceMethods,
StaticEvents,
InstanceEvents,
Operators,
NestedTypes
}
public class GeneratedCodeSettings
{
List<GeneratedCodeMember> codeMemberOrder;
public List<GeneratedCodeMember> CodeMemberOrder {
get {
return codeMemberOrder;
}
set {
codeMemberOrder = value;
}
}
public bool GenerateCategoryComments {
get;
set;
}
public bool SubOrderAlphabetical {
get;
set;
}
public void Apply (AstNode rootNode)
{
if (rootNode == null)
throw new ArgumentNullException ("rootNode");
rootNode.AcceptVisitor (new GenerateCodeVisitior (this));
}
public virtual string GetCategoryLabel(GeneratedCodeMember memberCategory)
{
switch (memberCategory) {
case GeneratedCodeMember.StaticFields:
return "Static Fields";
case GeneratedCodeMember.InstanceFields:
return "Fields";
case GeneratedCodeMember.StaticProperties:
return "Static Properties";
case GeneratedCodeMember.InstanceProperties:
return "Properties";
case GeneratedCodeMember.Indexer:
return "Indexer";
case GeneratedCodeMember.Constructors:
return "Constructors";
case GeneratedCodeMember.StaticMethods:
return "Static Methods";
case GeneratedCodeMember.InstanceMethods:
return "Methods";
case GeneratedCodeMember.StaticEvents:
return "Static Events";
case GeneratedCodeMember.InstanceEvents:
return "Events";
case GeneratedCodeMember.Operators:
return "Operators";
case GeneratedCodeMember.NestedTypes:
return "Nested Types";
}
return null;
}
class GenerateCodeVisitior : DepthFirstAstVisitor
{
GeneratedCodeSettings settings;
public GenerateCodeVisitior(GeneratedCodeSettings settings)
{
if (settings == null)
throw new ArgumentNullException("settings");
this.settings = settings;
}
GeneratedCodeMember GetCodeMemberCategory(EntityDeclaration x)
{
bool isStatic = x.HasModifier(Modifiers.Static) || x.HasModifier(Modifiers.Const);
if (x is FieldDeclaration)
return isStatic ? GeneratedCodeMember.StaticFields : GeneratedCodeMember.InstanceFields;
if (x is IndexerDeclaration)
return GeneratedCodeMember.Indexer;
if (x is PropertyDeclaration)
return isStatic ? GeneratedCodeMember.StaticProperties : GeneratedCodeMember.InstanceProperties;
if (x is ConstructorDeclaration || x is DestructorDeclaration)
return GeneratedCodeMember.Constructors;
if (x is MethodDeclaration)
return isStatic ? GeneratedCodeMember.StaticMethods : GeneratedCodeMember.InstanceMethods;
if (x is OperatorDeclaration)
return GeneratedCodeMember.Operators;
if (x is EventDeclaration || x is CustomEventDeclaration)
return isStatic ? GeneratedCodeMember.StaticEvents : GeneratedCodeMember.InstanceEvents;
if (x is TypeDeclaration)
return GeneratedCodeMember.NestedTypes;
return GeneratedCodeMember.Unknown;
}
public override void VisitTypeDeclaration (TypeDeclaration typeDeclaration)
{
if (typeDeclaration.ClassType == ClassType.Enum)
return;
var entities = new List<EntityDeclaration> (typeDeclaration.Members);
entities.Sort ((x, y) => {
int i1 = settings.CodeMemberOrder.IndexOf (GetCodeMemberCategory (x));
int i2 = settings.CodeMemberOrder.IndexOf (GetCodeMemberCategory (y));
if (i1 != i2)
return i1.CompareTo (i2);
if (settings.SubOrderAlphabetical)
return (x.Name ?? "").CompareTo ((y.Name ?? ""));
return entities.IndexOf (x).CompareTo (entities.IndexOf (y));
});
typeDeclaration.Members.Clear ();
typeDeclaration.Members.AddRange (entities);
if (settings.GenerateCategoryComments) {
var curCat = GeneratedCodeMember.Unknown;
foreach (var mem in entities) {
if (mem.NextSibling is EntityDeclaration)
mem.Parent.InsertChildAfter (mem, new UnixNewLine (), Roles.NewLine);
var cat = GetCodeMemberCategory (mem);
if (cat == curCat)
continue;
curCat = cat;
var label = settings.GetCategoryLabel (curCat);
if (string.IsNullOrEmpty (label))
continue;
var cmt = new Comment ("", CommentType.SingleLine);
var cmt2 = new Comment (" " + label, CommentType.SingleLine);
var cmt3 = new Comment ("", CommentType.SingleLine);
mem.Parent.InsertChildsBefore (mem, Roles.Comment, cmt, cmt2, cmt3);
if (cmt.PrevSibling is EntityDeclaration)
mem.Parent.InsertChildBefore (cmt, new UnixNewLine (), Roles.NewLine);
mem.Parent.InsertChildAfter (cmt3, new UnixNewLine (), Roles.NewLine);
}
}
}
}
static Lazy<GeneratedCodeSettings> defaultSettings = new Lazy<GeneratedCodeSettings>(
() => new GeneratedCodeSettings() {
CodeMemberOrder = new List<GeneratedCodeMember>() {
GeneratedCodeMember.StaticFields,
GeneratedCodeMember.InstanceFields,
GeneratedCodeMember.StaticProperties,
GeneratedCodeMember.InstanceProperties,
GeneratedCodeMember.Indexer,
GeneratedCodeMember.Constructors,
GeneratedCodeMember.StaticMethods,
GeneratedCodeMember.InstanceMethods,
GeneratedCodeMember.StaticEvents,
GeneratedCodeMember.InstanceEvents,
GeneratedCodeMember.Operators,
GeneratedCodeMember.NestedTypes
},
GenerateCategoryComments = true,
SubOrderAlphabetical = true
});
public static GeneratedCodeSettings Default {
get {
return defaultSettings.Value;
}
}
}
}

15
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -41,7 +41,8 @@
<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>none</DebugType> <DebugType>PdbOnly</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>
@ -240,6 +241,7 @@
<Compile Include="Parser\mcs\typespec.cs" /> <Compile Include="Parser\mcs\typespec.cs" />
<Compile Include="Parser\mcs\visit.cs" /> <Compile Include="Parser\mcs\visit.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Refactoring\CodeIssues\ExplicitConversionInForEachIssue.cs" />
<Compile Include="Refactoring\DocumentScript.cs" /> <Compile Include="Refactoring\DocumentScript.cs" />
<Compile Include="Refactoring\PatternHelper.cs" /> <Compile Include="Refactoring\PatternHelper.cs" />
<Compile Include="Refactoring\RefactoringAstHelper.cs" /> <Compile Include="Refactoring\RefactoringAstHelper.cs" />
@ -358,6 +360,16 @@
<Compile Include="Refactoring\CodeActions\CreateClassDeclarationAction.cs" /> <Compile Include="Refactoring\CodeActions\CreateClassDeclarationAction.cs" />
<Compile Include="Refactoring\CodeActions\CreateDelegateAction.cs" /> <Compile Include="Refactoring\CodeActions\CreateDelegateAction.cs" />
<Compile Include="Formatter\TextEditorOptions.cs" /> <Compile Include="Formatter\TextEditorOptions.cs" />
<Compile Include="Refactoring\CodeActions\IntroduceConstantAction.cs" />
<Compile Include="Refactoring\CodeActions\ExtractMethod\ExtractMethodAction.cs" />
<Compile Include="Refactoring\CodeActions\ExtractMethod\StaticVisitor.cs" />
<Compile Include="Refactoring\CodeActions\ExtractMethod\VariableLookupVisitor.cs" />
<Compile Include="Refactoring\CodeActions\SpecializedCodeAction.cs" />
<Compile Include="Formatter\GeneratedCodeSettings.cs" />
<Compile Include="Ast\GeneralScope\NewLineNode.cs" />
<Compile Include="Ast\GeneralScope\WhitespaceNode.cs" />
<Compile Include="Ast\GeneralScope\TextNode.cs" />
<Compile Include="Formatter\FormattingOptionsFactory.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> <ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
@ -370,6 +382,7 @@
<Folder Include="Completion\" /> <Folder Include="Completion\" />
<Folder Include="Refactoring\CodeIssues\" /> <Folder Include="Refactoring\CodeIssues\" />
<Folder Include="Refactoring\CodeIssues\InconsistentNamingIssue\" /> <Folder Include="Refactoring\CodeIssues\InconsistentNamingIssue\" />
<Folder Include="Refactoring\CodeActions\ExtractMethod\" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs

@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy of this // 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 // software and associated documentation files (the "Software"), to deal in the Software
@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp
throw new ArgumentNullException("entity"); throw new ArgumentNullException("entity");
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
ConvertEntity(entity, new TextWriterOutputFormatter(writer), new CSharpFormattingOptions()); ConvertEntity(entity, new TextWriterOutputFormatter(writer), FormattingOptionsFactory.CreateMono ());
return writer.ToString(); return writer.ToString();
} }

34
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -111,7 +111,7 @@ namespace ICSharpCode.NRefactory.CSharp
void WriteSpecials(AstNode start, AstNode end) void WriteSpecials(AstNode start, AstNode end)
{ {
for (AstNode pos = start; pos != end; pos = pos.NextSibling) { for (AstNode pos = start; pos != end; pos = pos.NextSibling) {
if (pos.Role == Roles.Comment || pos.Role == Roles.PreProcessorDirective) { if (pos.Role == Roles.Comment || pos.Role == Roles.NewLine || pos.Role == Roles.PreProcessorDirective) {
pos.AcceptVisitor(this); pos.AcceptVisitor(this);
} }
} }
@ -519,6 +519,7 @@ namespace ICSharpCode.NRefactory.CSharp
void WriteEmbeddedStatement(Statement embeddedStatement) void WriteEmbeddedStatement(Statement embeddedStatement)
{ {
if (embeddedStatement.IsNull) { if (embeddedStatement.IsNull) {
NewLine();
return; return;
} }
BlockStatement block = embeddedStatement as BlockStatement; BlockStatement block = embeddedStatement as BlockStatement;
@ -659,7 +660,7 @@ namespace ICSharpCode.NRefactory.CSharp
void PrintInitializerElements(AstNodeCollection<Expression> elements) void PrintInitializerElements(AstNodeCollection<Expression> elements)
{ {
BraceStyle style; BraceStyle style;
if (policy.PlaceArrayInitializersOnNewLine == ArrayInitializerPlacement.AlwaysNewLine) { if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) {
style = BraceStyle.NextLine; style = BraceStyle.NextLine;
} else { } else {
style = BraceStyle.EndOfLine; style = BraceStyle.EndOfLine;
@ -1584,7 +1585,8 @@ namespace ICSharpCode.NRefactory.CSharp
node.AcceptVisitor(this); node.AcceptVisitor(this);
} }
CloseBrace(style); CloseBrace(style);
NewLine(); if (!(blockStatement.Parent is Expression))
NewLine();
EndNode(blockStatement); EndNode(blockStatement);
} }
@ -1694,9 +1696,10 @@ namespace ICSharpCode.NRefactory.CSharp
forStatement.Condition.AcceptVisitor(this); forStatement.Condition.AcceptVisitor(this);
Space(policy.SpaceBeforeForSemicolon); Space(policy.SpaceBeforeForSemicolon);
WriteToken(Roles.Semicolon); WriteToken(Roles.Semicolon);
Space(policy.SpaceAfterForSemicolon); if (forStatement.Iterators.Any()) {
Space(policy.SpaceAfterForSemicolon);
WriteCommaSeparatedList(forStatement.Iterators); WriteCommaSeparatedList(forStatement.Iterators);
}
Space(policy.SpacesWithinForParentheses); Space(policy.SpacesWithinForParentheses);
RPar(); RPar();
@ -2373,7 +2376,24 @@ namespace ICSharpCode.NRefactory.CSharp
formatter.EndNode(comment); formatter.EndNode(comment);
lastWritten = LastWritten.Whitespace; lastWritten = LastWritten.Whitespace;
} }
public void VisitNewLine(NewLineNode newLineNode)
{
formatter.StartNode(newLineNode);
formatter.NewLine();
formatter.EndNode(newLineNode);
}
public void VisitWhitespace(WhitespaceNode whitespaceNode)
{
// unused
}
public void VisitText(TextNode textNode)
{
// unused
}
public void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective) public void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective)
{ {
formatter.StartNode(preProcessorDirective); formatter.StartNode(preProcessorDirective);

21
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy of this // 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 // software and associated documentation files (the "Software"), to deal in the Software
@ -171,7 +171,7 @@ namespace ICSharpCode.NRefactory.CSharp
string MakeSnippet(AstNode node) string MakeSnippet(AstNode node)
{ {
StringWriter w = new StringWriter(); StringWriter w = new StringWriter();
CSharpOutputVisitor v = new CSharpOutputVisitor(w, new CSharpFormattingOptions()); CSharpOutputVisitor v = new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ());
node.AcceptVisitor(v); node.AcceptVisitor(v);
return w.ToString(); return w.ToString();
} }
@ -1244,7 +1244,22 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
return new CodeComment (comment.Content, comment.CommentType == CommentType.Documentation); return new CodeComment (comment.Content, comment.CommentType == CommentType.Documentation);
} }
CodeObject IAstVisitor<CodeObject>.VisitNewLine(NewLineNode newLineNode)
{
throw new NotSupportedException();
}
CodeObject IAstVisitor<CodeObject>.VisitWhitespace(WhitespaceNode whitespaceNode)
{
throw new NotSupportedException();
}
CodeObject IAstVisitor<CodeObject>.VisitText(TextNode textNode)
{
throw new NotSupportedException();
}
CodeObject IAstVisitor<CodeObject>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective) CodeObject IAstVisitor<CodeObject>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
{ {
return new CodeComment ("#" + preProcessorDirective.Type.ToString ().ToLower ()); return new CodeComment ("#" + preProcessorDirective.Type.ToString ().ToLower ());

347
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs

@ -13,6 +13,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.CompilerServices.SymbolWriter; using Mono.CompilerServices.SymbolWriter;
using System.Diagnostics;
#if STATIC #if STATIC
using IKVM.Reflection; using IKVM.Reflection;
@ -25,11 +26,20 @@ using System.Reflection.Emit;
namespace Mono.CSharp { namespace Mono.CSharp {
public abstract class CompilerGeneratedClass : Class public abstract class CompilerGeneratedContainer : ClassOrStruct
{ {
protected CompilerGeneratedClass (TypeContainer parent, MemberName name, Modifiers mod) protected CompilerGeneratedContainer (TypeContainer parent, MemberName name, Modifiers mod)
: base (parent, name, mod | Modifiers.COMPILER_GENERATED, null) : this (parent, name, mod, MemberKind.Class)
{
}
protected CompilerGeneratedContainer (TypeContainer parent, MemberName name, Modifiers mod, MemberKind kind)
: base (parent, name, null, kind)
{ {
Debug.Assert ((mod & Modifiers.AccessibilityMask) != 0);
ModFlags = mod | Modifiers.COMPILER_GENERATED | Modifiers.SEALED;
spec = new TypeSpec (Kind, null, this, null, ModFlags);
} }
protected void CheckMembersDefined () protected void CheckMembersDefined ()
@ -38,6 +48,15 @@ namespace Mono.CSharp {
throw new InternalErrorException ("Helper class already defined!"); throw new InternalErrorException ("Helper class already defined!");
} }
protected override bool DoDefineMembers ()
{
if (Kind == MemberKind.Class && !IsStatic && !PartialContainer.HasInstanceConstructor) {
DefineDefaultConstructor (false);
}
return base.DoDefineMembers ();
}
protected static MemberName MakeMemberName (MemberBase host, string name, int unique_id, TypeParameters tparams, Location loc) protected static MemberName MakeMemberName (MemberBase host, string name, int unique_id, TypeParameters tparams, Location loc)
{ {
string host_name = host == null ? null : host is InterfaceMemberBase ? ((InterfaceMemberBase)host).GetFullName (host.MemberName) : host.MemberName.Name; string host_name = host == null ? null : host is InterfaceMemberBase ? ((InterfaceMemberBase)host).GetFullName (host.MemberName) : host.MemberName.Name;
@ -59,9 +78,17 @@ namespace Mono.CSharp {
{ {
return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X"); return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X");
} }
protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
{
base_type = Compiler.BuiltinTypes.Object;
base_class = null;
return null;
}
} }
public class HoistedStoreyClass : CompilerGeneratedClass public class HoistedStoreyClass : CompilerGeneratedContainer
{ {
public sealed class HoistedField : Field public sealed class HoistedField : Field
{ {
@ -86,8 +113,8 @@ namespace Mono.CSharp {
protected TypeParameterMutator mutator; protected TypeParameterMutator mutator;
public HoistedStoreyClass (TypeDefinition parent, MemberName name, TypeParameters tparams, Modifiers mod) public HoistedStoreyClass (TypeDefinition parent, MemberName name, TypeParameters tparams, Modifiers mods, MemberKind kind)
: base (parent, name, mod | Modifiers.PRIVATE) : base (parent, name, mods | Modifiers.PRIVATE, kind)
{ {
if (tparams != null) { if (tparams != null) {
@ -173,7 +200,7 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec) protected override void DoEmit (EmitContext ec)
{ {
hoisted_this.EmitHoistingAssignment (ec); hoisted_this.EmitAssign (ec, new CompilerGeneratedThis (ec.CurrentType, loc), false, false);
} }
protected override void CloneTo (CloneContext clonectx, Statement target) protected override void CloneTo (CloneContext clonectx, Statement target)
@ -185,7 +212,7 @@ namespace Mono.CSharp {
// Unique storey ID // Unique storey ID
public readonly int ID; public readonly int ID;
public readonly Block OriginalSourceBlock; public readonly ExplicitBlock OriginalSourceBlock;
// A list of StoreyFieldPair with local field keeping parent storey instance // A list of StoreyFieldPair with local field keeping parent storey instance
List<StoreyFieldPair> used_parent_storeys; List<StoreyFieldPair> used_parent_storeys;
@ -193,6 +220,7 @@ namespace Mono.CSharp {
// A list of hoisted parameters // A list of hoisted parameters
protected List<HoistedParameter> hoisted_params; protected List<HoistedParameter> hoisted_params;
List<HoistedParameter> hoisted_local_params;
protected List<HoistedVariable> hoisted_locals; protected List<HoistedVariable> hoisted_locals;
// Hoisted this // Hoisted this
@ -201,9 +229,11 @@ namespace Mono.CSharp {
// Local variable which holds this storey instance // Local variable which holds this storey instance
public Expression Instance; public Expression Instance;
public AnonymousMethodStorey (Block block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name) bool initialize_hoisted_this;
public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind)
: base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation), : base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation),
tparams, Modifiers.SEALED) tparams, 0, kind)
{ {
OriginalSourceBlock = block; OriginalSourceBlock = block;
ID = parent.Module.CounterAnonymousContainers++; ID = parent.Module.CounterAnonymousContainers++;
@ -212,18 +242,10 @@ namespace Mono.CSharp {
public void AddCapturedThisField (EmitContext ec) public void AddCapturedThisField (EmitContext ec)
{ {
TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
Field f = AddCompilerGeneratedField ("<>f__this", type_expr); Field f = AddCompilerGeneratedField ("$this", type_expr);
f.Define ();
hoisted_this = new HoistedThis (this, f); hoisted_this = new HoistedThis (this, f);
// Inflated type instance has to be updated manually initialize_hoisted_this = true;
if (Instance.Type is InflatedTypeSpec) {
var inflator = new TypeParameterInflator (this, Instance.Type, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes);
Instance.Type.MemberCache.AddMember (f.Spec.InflateMember (inflator));
inflator = new TypeParameterInflator (this, f.Parent.CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes);
f.Parent.CurrentType.MemberCache.AddMember (f.Spec.InflateMember (inflator));
}
} }
public Field AddCapturedVariable (string name, TypeSpec type) public Field AddCapturedVariable (string name, TypeSpec type)
@ -283,38 +305,93 @@ namespace Mono.CSharp {
used_parent_storeys.Add (new StoreyFieldPair (storey, f)); used_parent_storeys.Add (new StoreyFieldPair (storey, f));
} }
public void CaptureLocalVariable (ResolveContext ec, LocalVariable local_info) public void CaptureLocalVariable (ResolveContext ec, LocalVariable localVariable)
{ {
ec.CurrentBlock.Explicit.HasCapturedVariable = true; if (this is StateMachine) {
if (ec.CurrentBlock.Explicit != local_info.Block.Explicit) if (ec.CurrentBlock.ParametersBlock != localVariable.Block.ParametersBlock)
AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); ec.CurrentBlock.Explicit.HasCapturedVariable = true;
} else {
ec.CurrentBlock.Explicit.HasCapturedVariable = true;
}
if (local_info.HoistedVariant != null) var hoisted = localVariable.HoistedVariant;
return; if (hoisted != null && hoisted.Storey != this && hoisted.Storey.Kind == MemberKind.Struct) {
// TODO: It's too late the field is defined in HoistedLocalVariable ctor
hoisted.Storey.hoisted_locals.Remove (hoisted);
hoisted = null;
}
if (hoisted == null) {
hoisted = new HoistedLocalVariable (this, localVariable, GetVariableMangledName (localVariable));
localVariable.HoistedVariant = hoisted;
HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info)); if (hoisted_locals == null)
local_info.HoistedVariant = var; hoisted_locals = new List<HoistedVariable> ();
if (hoisted_locals == null) hoisted_locals.Add (hoisted);
hoisted_locals = new List<HoistedVariable> (); }
hoisted_locals.Add (var); if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit)
hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
} }
public void CaptureParameter (ResolveContext ec, ParameterReference param_ref) public void CaptureParameter (ResolveContext ec, ParametersBlock.ParameterInfo parameterInfo, ParameterReference parameterReference)
{ {
ec.CurrentBlock.Explicit.HasCapturedVariable = true; if (!(this is StateMachine)) {
AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); ec.CurrentBlock.Explicit.HasCapturedVariable = true;
}
if (param_ref.GetHoistedVariable (ec) != null) var hoisted = parameterInfo.Parameter.HoistedVariant;
return;
if (parameterInfo.Block.StateMachine is AsyncTaskStorey) {
//
// Another storey in same block exists but state machine does not
// have parameter captured. We need to add it there as well to
// proxy parameter value correctly.
//
if (hoisted == null && parameterInfo.Block.StateMachine != this) {
var storey = parameterInfo.Block.StateMachine;
hoisted = new HoistedParameter (storey, parameterReference);
parameterInfo.Parameter.HoistedVariant = hoisted;
if (storey.hoisted_params == null)
storey.hoisted_params = new List<HoistedParameter> ();
if (hoisted_params == null) storey.hoisted_params.Add (hoisted);
hoisted_params = new List<HoistedParameter> (2); }
//
// Lift captured parameter from value type storey to reference type one. Otherwise
// any side effects would be done on a copy
//
if (hoisted != null && hoisted.Storey != this && hoisted.Storey.Kind == MemberKind.Struct) {
if (hoisted_local_params == null)
hoisted_local_params = new List<HoistedParameter> ();
hoisted_local_params.Add (hoisted);
hoisted = null;
}
}
if (hoisted == null) {
hoisted = new HoistedParameter (this, parameterReference);
parameterInfo.Parameter.HoistedVariant = hoisted;
var expr = new HoistedParameter (this, param_ref); if (hoisted_params == null)
param_ref.Parameter.HoistedVariant = expr; hoisted_params = new List<HoistedParameter> ();
hoisted_params.Add (expr);
hoisted_params.Add (hoisted);
}
//
// Register link between current block and parameter storey. It will
// be used when setting up storey definition to deploy storey reference
// when parameters are used from multiple blocks
//
if (ec.CurrentBlock.Explicit != parameterInfo.Block) {
hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
}
} }
TypeExpr CreateStoreyTypeExpression (EmitContext ec) TypeExpr CreateStoreyTypeExpression (EmitContext ec)
@ -429,7 +506,11 @@ namespace Mono.CSharp {
Instance = fexpr; Instance = fexpr;
} else { } else {
var local = TemporaryVariableReference.Create (source.Type, block, Location); var local = TemporaryVariableReference.Create (source.Type, block, Location);
local.EmitAssign (ec, source); if (source.Type.IsStruct) {
local.LocalInfo.CreateBuilder (ec);
} else {
local.EmitAssign (ec, source);
}
Instance = local; Instance = local;
} }
@ -458,6 +539,7 @@ namespace Mono.CSharp {
FieldExpr f_set_expr = new FieldExpr (fs, Location); FieldExpr f_set_expr = new FieldExpr (fs, Location);
f_set_expr.InstanceExpression = instace_expr; f_set_expr.InstanceExpression = instace_expr;
// TODO: CompilerAssign expression
SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec)); SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec));
if (a.Resolve (rc) != null) if (a.Resolve (rc) != null)
a.EmitStatement (ec); a.EmitStatement (ec);
@ -465,10 +547,10 @@ namespace Mono.CSharp {
} }
// //
// Define hoisted `this' in top-level storey only // Initialize hoisted `this' only once, everywhere else will be
// referenced indirectly
// //
if (OriginalSourceBlock.Explicit.HasCapturedThis && !(Parent is AnonymousMethodStorey)) { if (initialize_hoisted_this) {
AddCapturedThisField (ec);
rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this));
} }
@ -485,9 +567,20 @@ namespace Mono.CSharp {
ec.CurrentAnonymousMethod = ae; ec.CurrentAnonymousMethod = ae;
} }
protected virtual void EmitHoistedParameters (EmitContext ec, IList<HoistedParameter> hoisted) protected virtual void EmitHoistedParameters (EmitContext ec, List<HoistedParameter> hoisted)
{ {
foreach (HoistedParameter hp in hoisted) { foreach (HoistedParameter hp in hoisted) {
//
// Parameters could be proxied via local fields for value type storey
//
if (hoisted_local_params != null) {
var local_param = hoisted_local_params.Find (l => l.Parameter.Parameter == hp.Parameter.Parameter);
var source = new FieldExpr (local_param.Field, Location);
source.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
hp.EmitAssign (ec, source, false, false);
continue;
}
hp.EmitHoistingAssignment (ec); hp.EmitHoistingAssignment (ec);
} }
} }
@ -560,7 +653,12 @@ namespace Mono.CSharp {
} }
public HoistedThis HoistedThis { public HoistedThis HoistedThis {
get { return hoisted_this; } get {
return hoisted_this;
}
set {
hoisted_this = value;
}
} }
public IList<ExplicitBlock> ReferencesFromChildrenBlock { public IList<ExplicitBlock> ReferencesFromChildrenBlock {
@ -628,6 +726,12 @@ namespace Mono.CSharp {
this.field = field; this.field = field;
} }
public AnonymousMethodStorey Storey {
get {
return storey;
}
}
public void AddressOf (EmitContext ec, AddressOp mode) public void AddressOf (EmitContext ec, AddressOp mode)
{ {
GetFieldExpression (ec).AddressOf (ec, mode); GetFieldExpression (ec).AddressOf (ec, mode);
@ -709,7 +813,7 @@ namespace Mono.CSharp {
public class HoistedParameter : HoistedVariable public class HoistedParameter : HoistedVariable
{ {
sealed class HoistedFieldAssign : Assign sealed class HoistedFieldAssign : CompilerAssign
{ {
public HoistedFieldAssign (Expression target, Expression source) public HoistedFieldAssign (Expression target, Expression source)
: base (target, source, source.Location) : base (target, source, source.Location)
@ -740,23 +844,32 @@ namespace Mono.CSharp {
this.parameter = hp.parameter; this.parameter = hp.parameter;
} }
#region Properties
public Field Field { public Field Field {
get { get {
return field; return field;
} }
} }
public ParameterReference Parameter {
get {
return parameter;
}
}
#endregion
public void EmitHoistingAssignment (EmitContext ec) public void EmitHoistingAssignment (EmitContext ec)
{ {
// //
// Remove hoisted redirection to emit assignment from original parameter // Remove hoisted redirection to emit assignment from original parameter
// //
HoistedVariable temp = parameter.Parameter.HoistedVariant; var temp = parameter.Parameter.HoistedVariant;
parameter.Parameter.HoistedVariant = null; parameter.Parameter.HoistedVariant = null;
Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter); var a = new HoistedFieldAssign (GetFieldExpression (ec), parameter);
if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) a.EmitStatement (ec);
a.EmitStatement (ec);
parameter.Parameter.HoistedVariant = temp; parameter.Parameter.HoistedVariant = temp;
} }
@ -782,13 +895,6 @@ namespace Mono.CSharp {
return field; return field;
} }
} }
public void EmitHoistingAssignment (EmitContext ec)
{
SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location));
if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
a.EmitStatement (ec);
}
} }
// //
@ -1003,12 +1109,8 @@ namespace Mono.CSharp {
} }
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); var body = CompatibleMethodBody (ec, tic, null, delegate_type);
if (body != null) { if (body != null) {
if (Block.IsAsync) {
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent.PartialContainer, null, loc);
}
am = body.Compatible (ec, body); am = body.Compatible (ec, body);
} else { } else {
am = null; am = null;
@ -1080,6 +1182,10 @@ namespace Mono.CSharp {
} else { } else {
int errors = ec.Report.Errors; int errors = ec.Report.Errors;
if (Block.IsAsync) {
ec.Report.Error (1989, loc, "Async lambda expressions cannot be converted to expression trees");
}
using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) { using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
am = body.Compatible (ec); am = body.Compatible (ec);
} }
@ -1091,18 +1197,6 @@ namespace Mono.CSharp {
am = CreateExpressionTree (ec, delegate_type); am = CreateExpressionTree (ec, delegate_type);
} }
} else { } else {
if (Block.IsAsync) {
var rt = body.ReturnType;
if (rt.Kind != MemberKind.Void &&
rt != ec.Module.PredefinedTypes.Task.TypeSpec &&
!rt.IsGenericTask) {
ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'",
GetSignatureForError (), type.GetSignatureForError ());
}
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent.PartialContainer, rt, loc);
}
am = body.Compatible (ec); am = body.Compatible (ec);
} }
} catch (CompletionResult) { } catch (CompletionResult) {
@ -1143,7 +1237,7 @@ namespace Mono.CSharp {
for (int i = 0; i < delegate_parameters.Count; i++) { for (int i = 0; i < delegate_parameters.Count; i++) {
Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags; Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags;
if (i_mod == Parameter.Modifier.OUT) { if ((i_mod & Parameter.Modifier.OUT) != 0) {
if (!ec.IsInProbingMode) { if (!ec.IsInProbingMode) {
ec.Report.Error (1688, loc, ec.Report.Error (1688, loc,
"Cannot convert anonymous method block without a parameter list to delegate type `{0}' because it has one or more `out' parameters", "Cannot convert anonymous method block without a parameter list to delegate type `{0}' because it has one or more `out' parameters",
@ -1230,7 +1324,19 @@ namespace Mono.CSharp {
ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block; ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block;
return CompatibleMethodFactory (return_type, delegate_type, p, b); if (b.IsAsync) {
var rt = return_type;
if (rt != null && rt.Kind != MemberKind.Void && rt != ec.Module.PredefinedTypes.Task.TypeSpec && !rt.IsGenericTask) {
ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'",
GetSignatureForError (), delegate_type.GetSignatureForError ());
return null;
}
b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, loc);
}
return CompatibleMethodFactory (return_type ?? InternalType.Arglist, delegate_type, p, b);
} }
protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b) protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b)
@ -1330,6 +1436,15 @@ namespace Mono.CSharp {
public abstract bool IsIterator { get; } public abstract bool IsIterator { get; }
public abstract AnonymousMethodStorey Storey { get; } public abstract AnonymousMethodStorey Storey { get; }
//
// The block that makes up the body for the anonymous method
//
public ParametersBlock Block {
get {
return block;
}
}
public AnonymousExpression Compatible (ResolveContext ec) public AnonymousExpression Compatible (ResolveContext ec)
{ {
return Compatible (ec, this); return Compatible (ec, this);
@ -1403,16 +1518,6 @@ namespace Mono.CSharp {
b = b.Parent == null ? null : b.Parent.Explicit; b = b.Parent == null ? null : b.Parent.Explicit;
} while (b != null); } while (b != null);
} }
//
// The block that makes up the body for the anonymous method
//
public ParametersBlock Block {
get {
return block;
}
}
} }
public class AnonymousMethodBody : AnonymousExpression public class AnonymousMethodBody : AnonymousExpression
@ -1500,19 +1605,49 @@ namespace Mono.CSharp {
// //
Modifiers modifiers; Modifiers modifiers;
if (Block.HasCapturedVariable || Block.HasCapturedThis) { TypeDefinition parent = null;
storey = FindBestMethodStorey ();
var src_block = Block.Original.Explicit;
if (src_block.HasCapturedVariable || src_block.HasCapturedThis) {
parent = storey = FindBestMethodStorey ();
if (storey == null) {
var sm = src_block.ParametersBlock.TopBlock.StateMachine;
//
// Remove hoisted this demand when simple instance method is enough
//
if (src_block.HasCapturedThis) {
src_block.ParametersBlock.TopBlock.RemoveThisReferenceFromChildrenBlock (src_block);
//
// Special case where parent class is used to emit instance method
// because currect storey is of value type (async host) and we don't
// want to create another childer storey to host this reference only
//
if (sm != null && sm.Kind == MemberKind.Struct)
parent = sm.Parent.PartialContainer;
}
//
// For iterators we can host everything in one class
//
if (sm is IteratorStorey)
parent = storey = sm;
}
modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
} else { } else {
if (ec.CurrentAnonymousMethod != null) if (ec.CurrentAnonymousMethod != null)
storey = ec.CurrentAnonymousMethod.Storey; parent = storey = ec.CurrentAnonymousMethod.Storey;
modifiers = Modifiers.STATIC | Modifiers.PRIVATE; modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
} }
var parent = storey != null ? storey : ec.CurrentTypeDefinition.Parent.PartialContainer; if (parent == null)
parent = ec.CurrentTypeDefinition.Parent.PartialContainer;
string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null, string name = CompilerGeneratedContainer.MakeName (parent != storey ? block_name : null,
"m", null, ec.Module.CounterAnonymousMethods++); "m", null, ec.Module.CounterAnonymousMethods++);
MemberName member_name; MemberName member_name;
@ -1570,7 +1705,7 @@ namespace Mono.CSharp {
am_cache = new Field (parent, new TypeExpression (cache_type, loc), am_cache = new Field (parent, new TypeExpression (cache_type, loc),
Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null); new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null);
am_cache.Define (); am_cache.Define ();
parent.AddField (am_cache); parent.AddField (am_cache);
} else { } else {
@ -1610,10 +1745,22 @@ namespace Mono.CSharp {
ec.EmitNull (); ec.EmitNull ();
} else if (storey != null) { } else if (storey != null) {
Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
if (e != null) if (e != null) {
e.Emit (ec); e.Emit (ec);
}
} else { } else {
ec.EmitThis (); ec.EmitThis ();
//
// Special case for value type storey where this is not lifted but
// droped off to parent class
//
for (var b = Block.Parent; b != null; b = b.Parent) {
if (b.ParametersBlock.StateMachine != null) {
ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
break;
}
}
} }
var delegate_method = method.Spec; var delegate_method = method.Spec;
@ -1624,9 +1771,7 @@ namespace Mono.CSharp {
// Mutate anonymous method instance type if we are in nested // Mutate anonymous method instance type if we are in nested
// hoisted generic anonymous method storey // hoisted generic anonymous method storey
// //
if (ec.CurrentAnonymousMethod != null && if (ec.IsAnonymousStoreyMutateRequired) {
ec.CurrentAnonymousMethod.Storey != null &&
ec.CurrentAnonymousMethod.Storey.Mutator != null) {
t = storey.Mutator.Mutate (t); t = storey.Mutator.Mutate (t);
} }
@ -1679,7 +1824,7 @@ namespace Mono.CSharp {
// //
// Anonymous type container // Anonymous type container
// //
public class AnonymousTypeClass : CompilerGeneratedClass public class AnonymousTypeClass : CompilerGeneratedContainer
{ {
public const string ClassNamePrefix = "<>__AnonType"; public const string ClassNamePrefix = "<>__AnonType";
public const string SignatureForError = "anonymous type"; public const string SignatureForError = "anonymous type";
@ -1687,7 +1832,7 @@ namespace Mono.CSharp {
readonly IList<AnonymousTypeParameter> parameters; readonly IList<AnonymousTypeParameter> parameters;
private AnonymousTypeClass (ModuleContainer parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc) private AnonymousTypeClass (ModuleContainer parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc)
: base (parent, name, (parent.Evaluator != null ? Modifiers.PUBLIC : 0) | Modifiers.SEALED) : base (parent, name, parent.Evaluator != null ? Modifiers.PUBLIC : Modifiers.INTERNAL)
{ {
this.parameters = parameters; this.parameters = parameters;
} }
@ -1740,7 +1885,7 @@ namespace Mono.CSharp {
c.Block = new ToplevelBlock (parent.Module.Compiler, c.ParameterInfo, loc); c.Block = new ToplevelBlock (parent.Module.Compiler, c.ParameterInfo, loc);
// //
// Create fields and contructor body with field initialization // Create fields and constructor body with field initialization
// //
bool error = false; bool error = false;
for (int i = 0; i < parameters.Count; ++i) { for (int i = 0; i < parameters.Count; ++i) {

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs

@ -120,10 +120,14 @@ namespace Mono.CSharp
ml.AddressOf (ec, mode); ml.AddressOf (ec, mode);
} }
public Argument EmitToField (EmitContext ec) public Argument EmitToField (EmitContext ec, bool cloneResult)
{ {
var res = Expr.EmitToField (ec); var res = Expr.EmitToField (ec);
return res == Expr ? this : new Argument (res, ArgType); if (cloneResult && res != Expr)
return new Argument (res, ArgType);
Expr = res;
return this;
} }
public string GetSignatureForError () public string GetSignatureForError ()
@ -258,7 +262,7 @@ namespace Mono.CSharp
{ {
foreach (var a in ordered) { foreach (var a in ordered) {
if (prepareAwait) if (prepareAwait)
a.EmitToField (ec); a.EmitToField (ec, false);
else else
a.EmitToVariable (ec); a.EmitToVariable (ec);
} }
@ -440,7 +444,7 @@ namespace Mono.CSharp
LocalTemporary lt; LocalTemporary lt;
foreach (Argument a in args) { foreach (Argument a in args) {
if (prepareAwait) { if (prepareAwait) {
dups.Add (a.EmitToField (ec)); dups.Add (a.EmitToField (ec, true));
continue; continue;
} }

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs

@ -1010,7 +1010,7 @@ namespace Mono.CSharp
// //
// A placeholder class for assembly attributes when emitting module // A placeholder class for assembly attributes when emitting module
// //
class AssemblyAttributesPlaceholder : CompilerGeneratedClass class AssemblyAttributesPlaceholder : CompilerGeneratedContainer
{ {
static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>"; static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>";
public static readonly string AssemblyFieldName = "attributes"; public static readonly string AssemblyFieldName = "attributes";
@ -1018,7 +1018,7 @@ namespace Mono.CSharp
Field assembly; Field assembly;
public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName) public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName)
: base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC) : base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC | Modifiers.INTERNAL)
{ {
assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC, assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC,
new MemberName (AssemblyFieldName), null); new MemberName (AssemblyFieldName), null);

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs

@ -343,7 +343,7 @@ namespace Mono.CSharp {
type = target_type; type = target_type;
if (!(target is IAssignMethod)) { if (!(target is IAssignMethod)) {
Error_ValueAssignment (ec, source); target.Error_ValueAssignment (ec, source);
return null; return null;
} }
@ -488,6 +488,10 @@ namespace Mono.CSharp {
public CompilerAssign (Expression target, Expression source, Location loc) public CompilerAssign (Expression target, Expression source, Location loc)
: base (target, source, loc) : base (target, source, loc)
{ {
if (target.Type != null) {
type = target.Type;
eclass = ExprClass.Value;
}
} }
protected override Expression DoResolve (ResolveContext ec) protected override Expression DoResolve (ResolveContext ec)
@ -568,10 +572,10 @@ namespace Mono.CSharp {
// //
// Emit sequence symbol info even if we are in compiler generated // Emit sequence symbol info even if we are in compiler generated
// block to allow debugging filed initializers when constructor is // block to allow debugging field initializers when constructor is
// compiler generated // compiler generated
// //
if (ec.HasSet (BuilderContext.Options.OmitDebugInfo)) { if (ec.HasSet (BuilderContext.Options.OmitDebugInfo) && ec.HasMethodSymbolBuilder) {
using (ec.With (BuilderContext.Options.OmitDebugInfo, false)) { using (ec.With (BuilderContext.Options.OmitDebugInfo, false)) {
ec.Mark (loc); ec.Mark (loc);
} }
@ -822,7 +826,7 @@ namespace Mono.CSharp {
return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec); return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec);
} }
right.Error_ValueCannotBeConverted (ec, loc, target_type, false); right.Error_ValueCannotBeConverted (ec, target_type, false);
return null; return null;
} }

502
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs

@ -46,6 +46,12 @@ namespace Mono.CSharp
} }
} }
public AwaitStatement Statement {
get {
return stmt;
}
}
protected override void CloneTo (CloneContext clonectx, Expression target) protected override void CloneTo (CloneContext clonectx, Expression target)
{ {
var t = (Await) target; var t = (Await) target;
@ -70,11 +76,6 @@ namespace Mono.CSharp
"The `await' operator cannot be used in the body of a lock statement"); "The `await' operator cannot be used in the body of a lock statement");
} }
if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
rc.Report.Error (1989, loc, "An expression tree cannot contain an await operator");
return null;
}
if (rc.IsUnsafe) { if (rc.IsUnsafe) {
rc.Report.Error (4004, loc, rc.Report.Error (4004, loc,
"The `await' operator cannot be used in an unsafe context"); "The `await' operator cannot be used in an unsafe context");
@ -124,7 +125,7 @@ namespace Mono.CSharp
} }
} }
class AwaitStatement : YieldStatement<AsyncInitializer> public class AwaitStatement : YieldStatement<AsyncInitializer>
{ {
sealed class AwaitableMemberAccess : MemberAccess sealed class AwaitableMemberAccess : MemberAccess
{ {
@ -140,7 +141,13 @@ namespace Mono.CSharp
protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type)
{ {
rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ()); var invocation = LeftExpression as Invocation;
if (invocation != null && invocation.MethodGroup != null && (invocation.MethodGroup.BestCandidate.Modifiers & Modifiers.ASYNC) != 0) {
rc.Report.Error (4008, loc, "Cannot await void method `{0}'. Consider changing method return type to `Task'",
invocation.GetSignatureForError ());
} else {
rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
}
} }
} }
@ -161,7 +168,6 @@ namespace Mono.CSharp
Field awaiter; Field awaiter;
PropertySpec is_completed; PropertySpec is_completed;
MethodSpec on_completed;
MethodSpec get_result; MethodSpec get_result;
TypeSpec type; TypeSpec type;
TypeSpec result_type; TypeSpec result_type;
@ -213,6 +219,8 @@ namespace Mono.CSharp
public void EmitPrologue (EmitContext ec) public void EmitPrologue (EmitContext ec)
{ {
awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (expr.Type, loc);
var fe_awaiter = new FieldExpr (awaiter, loc); var fe_awaiter = new FieldExpr (awaiter, loc);
fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
@ -230,6 +238,10 @@ namespace Mono.CSharp
Arguments dargs = new Arguments (1); Arguments dargs = new Arguments (1);
dargs.Add (new Argument (fe_awaiter)); dargs.Add (new Argument (fe_awaiter));
completed_expr = new DynamicMemberBinder ("IsCompleted", dargs, loc).Resolve (rc); completed_expr = new DynamicMemberBinder ("IsCompleted", dargs, loc).Resolve (rc);
dargs = new Arguments (1);
dargs.Add (new Argument (completed_expr));
completed_expr = new DynamicConversion (ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve (rc);
} else { } else {
var pe = PropertyExpr.CreatePredefined (is_completed, loc); var pe = PropertyExpr.CreatePredefined (is_completed, loc);
pe.InstanceExpression = fe_awaiter; pe.InstanceExpression = fe_awaiter;
@ -252,25 +264,10 @@ namespace Mono.CSharp
ec.AssertEmptyStack (); ec.AssertEmptyStack ();
var storey = (AsyncTaskStorey) machine_initializer.Storey; var storey = (AsyncTaskStorey) machine_initializer.Storey;
var cont_field = storey.EmitContinuationInitialization (ec);
var args = new Arguments (1);
args.Add (new Argument (cont_field));
if (IsDynamic) { if (IsDynamic) {
var rc = new ResolveContext (ec.MemberContext); storey.EmitAwaitOnCompletedDynamic (ec, fe_awaiter);
var mg_expr = new Invocation (new MemberAccess (fe_awaiter, "OnCompleted"), args).Resolve (rc);
ExpressionStatement es = (ExpressionStatement) mg_expr;
es.EmitStatement (ec);
} else { } else {
var mg_completed = MethodGroupExpr.CreatePredefined (on_completed, fe_awaiter.Type, loc); storey.EmitAwaitOnCompleted (ec, fe_awaiter);
mg_completed.InstanceExpression = fe_awaiter;
//
// awaiter.OnCompleted (continuation);
//
mg_completed.EmitCall (ec, args);
} }
// Return ok // Return ok
@ -285,6 +282,8 @@ namespace Mono.CSharp
EmitPrologue (ec); EmitPrologue (ec);
DoEmit (ec); DoEmit (ec);
awaiter.IsAvailableForReuse = true;
if (ResultType.Kind != MemberKind.Void) { if (ResultType.Kind != MemberKind.Void) {
var storey = (AsyncTaskStorey) machine_initializer.Storey; var storey = (AsyncTaskStorey) machine_initializer.Storey;
@ -297,12 +296,18 @@ namespace Mono.CSharp
void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter) void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter)
{ {
rc.Report.Error (4011, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members", rc.Report.Error (4011, loc, "The awaiter type `{0}' must have suitable IsCompleted and GetResult members",
awaiter.GetSignatureForError ()); awaiter.GetSignatureForError ());
} }
public override bool Resolve (BlockContext bc) public override bool Resolve (BlockContext bc)
{ {
if (bc.CurrentBlock is Linq.QueryBlock) {
bc.Report.Error (1995, loc,
"The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause");
return false;
}
if (!base.Resolve (bc)) if (!base.Resolve (bc))
return false; return false;
@ -315,9 +320,6 @@ namespace Mono.CSharp
// //
if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
result_type = type; result_type = type;
awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (type, loc);
expr = new Invocation (new MemberAccess (expr, "GetAwaiter"), args).Resolve (bc); expr = new Invocation (new MemberAccess (expr, "GetAwaiter"), args).Resolve (bc);
return true; return true;
} }
@ -343,8 +345,6 @@ namespace Mono.CSharp
} }
var awaiter_type = ama.Type; var awaiter_type = ama.Type;
awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (awaiter_type, loc);
expr = ama; expr = ama;
// //
@ -358,20 +358,6 @@ namespace Mono.CSharp
return false; return false;
} }
//
// Predefined: OnCompleted (Action)
//
if (bc.Module.PredefinedTypes.Action.Define ()) {
on_completed = MemberCache.FindMember (awaiter_type, MemberFilter.Method ("OnCompleted", 0,
ParametersCompiled.CreateFullyResolved (bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void),
BindingRestriction.InstanceOnly) as MethodSpec;
if (on_completed == null) {
Error_WrongAwaiterPattern (bc, awaiter_type);
return false;
}
}
// //
// Predefined: GetResult () // Predefined: GetResult ()
// //
@ -386,6 +372,16 @@ namespace Mono.CSharp
return false; return false;
} }
//
// Predefined: INotifyCompletion.OnCompleted (System.Action)
//
var nc = bc.Module.PredefinedTypes.INotifyCompletion;
if (nc.Define () && !awaiter_type.ImplementsInterface (nc.TypeSpec, false)) {
bc.Report.Error (4027, loc, "The awaiter type `{0}' must implement interface `{1}'",
awaiter_type.GetSignatureForError (), nc.GetSignatureForError ());
return false;
}
result_type = get_result.ReturnType; result_type = get_result.ReturnType;
return true; return true;
@ -415,12 +411,6 @@ namespace Mono.CSharp
} }
} }
public Block OriginalBlock {
get {
return block.Parent;
}
}
public TypeInferenceContext ReturnTypeInference { public TypeInferenceContext ReturnTypeInference {
get { get {
return return_inference; return return_inference;
@ -429,38 +419,6 @@ namespace Mono.CSharp
#endregion #endregion
public static void Create (IMemberContext context, ParametersBlock block, ParametersCompiled parameters, TypeDefinition host, TypeSpec returnType, Location loc)
{
for (int i = 0; i < parameters.Count; i++) {
Parameter p = parameters[i];
Parameter.Modifier mod = p.ModFlags;
if ((mod & Parameter.Modifier.ISBYREF) != 0) {
host.Compiler.Report.Error (1988, p.Location,
"Async methods cannot have ref or out parameters");
return;
}
if (p is ArglistParameter) {
host.Compiler.Report.Error (4006, p.Location,
"__arglist is not allowed in parameter list of async methods");
return;
}
if (parameters.Types[i].IsPointer) {
host.Compiler.Report.Error (4005, p.Location,
"Async methods cannot have unsafe parameters");
return;
}
}
if (!block.HasAwait) {
host.Compiler.Report.Warning (1998, 1, loc,
"Async block lacks `await' operator and will run synchronously");
}
block.WrapIntoAsyncTask (context, host, returnType);
}
protected override BlockContext CreateBlockContext (ResolveContext rc) protected override BlockContext CreateBlockContext (ResolveContext rc)
{ {
var ctx = base.CreateBlockContext (rc); var ctx = base.CreateBlockContext (rc);
@ -491,37 +449,7 @@ namespace Mono.CSharp
public override void EmitStatement (EmitContext ec) public override void EmitStatement (EmitContext ec)
{ {
var storey = (AsyncTaskStorey) Storey; var storey = (AsyncTaskStorey) Storey;
storey.Instance.Emit (ec); storey.EmitInitializer (ec);
var move_next_entry = storey.StateMachineMethod.Spec;
if (storey.MemberName.Arity > 0) {
move_next_entry = MemberCache.GetMember (storey.Instance.Type, move_next_entry);
}
ec.Emit (OpCodes.Call, move_next_entry);
//
// Emits return <async-storey-instance>.$builder.Task;
//
if (storey.Task != null) {
var builder_field = storey.Builder.Spec;
var task_get = storey.Task.Get;
if (storey.MemberName.Arity > 0) {
builder_field = MemberCache.GetMember (storey.Instance.Type, builder_field);
task_get = MemberCache.GetMember (builder_field.MemberType, task_get);
}
var pe_task = new PropertyExpr (storey.Task, loc) {
InstanceExpression = new FieldExpr (builder_field, loc) {
InstanceExpression = storey.Instance
},
Getter = task_get
};
pe_task.Emit (ec);
}
ec.Emit (OpCodes.Ret); ec.Emit (OpCodes.Ret);
} }
} }
@ -529,30 +457,27 @@ namespace Mono.CSharp
class AsyncTaskStorey : StateMachine class AsyncTaskStorey : StateMachine
{ {
int awaiters; int awaiters;
Field builder, continuation; Field builder;
readonly TypeSpec return_type; readonly TypeSpec return_type;
MethodSpec set_result; MethodSpec set_result;
MethodSpec set_exception; MethodSpec set_exception;
MethodSpec builder_factory;
MethodSpec builder_start;
PropertySpec task; PropertySpec task;
LocalVariable hoisted_return; LocalVariable hoisted_return;
int locals_captured; int locals_captured;
Dictionary<TypeSpec, List<StackField>> stack_fields; Dictionary<TypeSpec, List<Field>> stack_fields;
TypeSpec action; Dictionary<TypeSpec, List<Field>> awaiter_fields;
public AsyncTaskStorey (IMemberContext context, AsyncInitializer initializer, TypeSpec type) public AsyncTaskStorey (ParametersBlock block, IMemberContext context, AsyncInitializer initializer, TypeSpec type)
: base (initializer.OriginalBlock, initializer.Host, context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async") : base (block, initializer.Host, context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async", MemberKind.Struct)
{ {
return_type = type; return_type = type;
awaiter_fields = new Dictionary<TypeSpec, List<Field>> ();
} }
#region Properties #region Properties
public Field Builder {
get {
return builder;
}
}
public LocalVariable HoistedReturn { public LocalVariable HoistedReturn {
get { get {
return hoisted_return; return hoisted_return;
@ -575,34 +500,53 @@ namespace Mono.CSharp
public Field AddAwaiter (TypeSpec type, Location loc) public Field AddAwaiter (TypeSpec type, Location loc)
{ {
return AddCapturedVariable ("$awaiter" + awaiters++.ToString ("X"), type); if (mutator != null)
type = mutator.Mutate (type);
List<Field> existing_fields = null;
if (awaiter_fields.TryGetValue (type, out existing_fields)) {
foreach (var f in existing_fields) {
if (f.IsAvailableForReuse) {
f.IsAvailableForReuse = false;
return f;
}
}
}
var field = AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, Location), true);
field.Define ();
if (existing_fields == null) {
existing_fields = new List<Field> ();
awaiter_fields.Add (type, existing_fields);
}
existing_fields.Add (field);
return field;
} }
public StackField AddCapturedLocalVariable (TypeSpec type) public Field AddCapturedLocalVariable (TypeSpec type)
{ {
if (mutator != null) if (mutator != null)
type = mutator.Mutate (type); type = mutator.Mutate (type);
List<StackField> existing_fields = null; List<Field> existing_fields = null;
if (stack_fields == null) { if (stack_fields == null) {
stack_fields = new Dictionary<TypeSpec, List<StackField>> (); stack_fields = new Dictionary<TypeSpec, List<Field>> ();
} else if (stack_fields.TryGetValue (type, out existing_fields)) { } else if (stack_fields.TryGetValue (type, out existing_fields)) {
foreach (var f in existing_fields) { foreach (var f in existing_fields) {
if (f.CanBeReused) { if (f.IsAvailableForReuse) {
f.CanBeReused = false; f.IsAvailableForReuse = false;
return f; return f;
} }
} }
} }
const Modifiers mod = Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE; var field = AddCompilerGeneratedField ("$stack" + locals_captured++.ToString ("X"), new TypeExpression (type, Location), true);
var field = new StackField (this, new TypeExpression (type, Location), mod, new MemberName ("<s>$" + locals_captured++.ToString ("X"), Location));
AddField (field);
field.Define (); field.Define ();
if (existing_fields == null) { if (existing_fields == null) {
existing_fields = new List<StackField> (); existing_fields = new List<Field> ();
stack_fields.Add (type, existing_fields); stack_fields.Add (type, existing_fields);
} }
@ -613,39 +557,52 @@ namespace Mono.CSharp
protected override bool DoDefineMembers () protected override bool DoDefineMembers ()
{ {
action = Module.PredefinedTypes.Action.Resolve ();
PredefinedType builder_type; PredefinedType builder_type;
PredefinedMember<MethodSpec> bf; PredefinedMember<MethodSpec> bf;
PredefinedMember<MethodSpec> bs;
PredefinedMember<MethodSpec> sr; PredefinedMember<MethodSpec> sr;
PredefinedMember<MethodSpec> se; PredefinedMember<MethodSpec> se;
PredefinedMember<MethodSpec> sm;
bool has_task_return_type = false; bool has_task_return_type = false;
var pred_members = Module.PredefinedMembers; var pred_members = Module.PredefinedMembers;
if (return_type.Kind == MemberKind.Void) { if (return_type.Kind == MemberKind.Void) {
builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder;
bf = pred_members.AsyncVoidMethodBuilderCreate; bf = pred_members.AsyncVoidMethodBuilderCreate;
bs = pred_members.AsyncVoidMethodBuilderStart;
sr = pred_members.AsyncVoidMethodBuilderSetResult; sr = pred_members.AsyncVoidMethodBuilderSetResult;
se = pred_members.AsyncVoidMethodBuilderSetException; se = pred_members.AsyncVoidMethodBuilderSetException;
sm = pred_members.AsyncVoidMethodBuilderSetStateMachine;
} else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) {
builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder;
bf = pred_members.AsyncTaskMethodBuilderCreate; bf = pred_members.AsyncTaskMethodBuilderCreate;
bs = pred_members.AsyncTaskMethodBuilderStart;
sr = pred_members.AsyncTaskMethodBuilderSetResult; sr = pred_members.AsyncTaskMethodBuilderSetResult;
se = pred_members.AsyncTaskMethodBuilderSetException; se = pred_members.AsyncTaskMethodBuilderSetException;
sm = pred_members.AsyncTaskMethodBuilderSetStateMachine;
task = pred_members.AsyncTaskMethodBuilderTask.Get (); task = pred_members.AsyncTaskMethodBuilderTask.Get ();
} else { } else {
builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric;
bf = pred_members.AsyncTaskMethodBuilderGenericCreate; bf = pred_members.AsyncTaskMethodBuilderGenericCreate;
bs = pred_members.AsyncTaskMethodBuilderGenericStart;
sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult;
se = pred_members.AsyncTaskMethodBuilderGenericSetException; se = pred_members.AsyncTaskMethodBuilderGenericSetException;
sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine;
task = pred_members.AsyncTaskMethodBuilderGenericTask.Get (); task = pred_members.AsyncTaskMethodBuilderGenericTask.Get ();
has_task_return_type = true; has_task_return_type = true;
} }
set_result = sr.Get (); set_result = sr.Get ();
set_exception = se.Get (); set_exception = se.Get ();
var builder_factory = bf.Get (); builder_factory = bf.Get ();
if (!builder_type.Define () || set_result == null || builder_factory == null || set_exception == null) { builder_start = bs.Get ();
var istate_machine = Module.PredefinedTypes.IAsyncStateMachine;
var set_statemachine = sm.Get ();
if (!builder_type.Define () || !istate_machine.Define () || set_result == null || builder_factory == null ||
set_exception == null || set_statemachine == null || builder_start == null ||
!Module.PredefinedTypes.INotifyCompletion.Define ()) {
Report.Error (1993, Location, Report.Error (1993, Location,
"Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?");
return base.DoDefineMembers (); return base.DoDefineMembers ();
@ -662,83 +619,206 @@ namespace Mono.CSharp
task_return_type = mutator.Mutate (task_return_type); task_return_type = mutator.Mutate (task_return_type);
bt = bt.MakeGenericType (Module, task_return_type); bt = bt.MakeGenericType (Module, task_return_type);
builder_factory = MemberCache.GetMember<MethodSpec> (bt, builder_factory); set_result = MemberCache.GetMember (bt, set_result);
set_result = MemberCache.GetMember<MethodSpec> (bt, set_result); set_exception = MemberCache.GetMember (bt, set_exception);
set_exception = MemberCache.GetMember<MethodSpec> (bt, set_exception); set_statemachine = MemberCache.GetMember (bt, set_statemachine);
if (task != null) if (task != null)
task = MemberCache.GetMember<PropertySpec> (bt, task); task = MemberCache.GetMember (bt, task);
} }
builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location)); builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location));
var ctor = DefineDefaultConstructor (false); var set_state_machine = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Void, Location),
Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC,
new MemberName ("SetStateMachine"),
ParametersCompiled.CreateFullyResolved (
new Parameter (new TypeExpression (istate_machine.TypeSpec, Location), "stateMachine", Parameter.Modifier.NONE, null, Location),
istate_machine.TypeSpec),
null);
ToplevelBlock block = new ToplevelBlock (Compiler, set_state_machine.ParameterInfo, Location);
block.IsCompilerGenerated = true;
set_state_machine.Block = block;
Members.Add (set_state_machine);
if (!base.DoDefineMembers ()) if (!base.DoDefineMembers ())
return false; return false;
Block block = ctor.Block; //
// Fabricates SetStateMachine method
//
// public void SetStateMachine (IAsyncStateMachine stateMachine)
// {
// $builder.SetStateMachine (stateMachine);
// }
//
var mg = MethodGroupExpr.CreatePredefined (set_statemachine, bt, Location);
mg.InstanceExpression = new FieldExpr (builder, Location);
var mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location); var param_reference = block.GetParameterReference (0, Location);
block.AddStatement ( param_reference.Type = istate_machine.TypeSpec;
new StatementExpression (new SimpleAssign ( param_reference.eclass = ExprClass.Variable;
new FieldExpr (builder, Location),
new Invocation (mg, new Arguments (0)), var args = new Arguments (1);
Location))); args.Add (new Argument (param_reference));
set_state_machine.Block.AddStatement (new StatementExpression (new Invocation (mg, args)));
if (has_task_return_type) { if (has_task_return_type) {
hoisted_return = LocalVariable.CreateCompilerGenerated (bt.TypeArguments[0], block, Location); hoisted_return = LocalVariable.CreateCompilerGenerated (bt.TypeArguments[0], StateMachineMethod.Block, Location);
} }
return true; return true;
} }
public Expression EmitContinuationInitialization (EmitContext ec) public void EmitAwaitOnCompletedDynamic (EmitContext ec, FieldExpr awaiter)
{ {
var critical = Module.PredefinedTypes.ICriticalNotifyCompletion;
if (!critical.Define ()) {
throw new NotImplementedException ();
}
var temp_critical = new LocalTemporary (critical.TypeSpec);
var label_critical = ec.DefineLabel ();
var label_end = ec.DefineLabel ();
// //
// When more than 1 awaiter has been used in the block we // Special path for dynamic awaiters
// introduce class scope field to cache continuation delegate
// //
if (awaiters > 1) { // var awaiter = this.$awaiter as ICriticalNotifyCompletion;
if (continuation == null) { // if (awaiter == null) {
continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true); // var completion = (INotifyCompletion) this.$awaiter;
continuation.Define (); // this.$builder.AwaitOnCompleted (ref completion, ref this);
} // } else {
// this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this);
// }
//
awaiter.Emit (ec);
ec.Emit (OpCodes.Isinst, critical.TypeSpec);
temp_critical.Store (ec);
temp_critical.Emit (ec);
ec.Emit (OpCodes.Brtrue_S, label_critical);
var temp = new LocalTemporary (Module.PredefinedTypes.INotifyCompletion.TypeSpec);
awaiter.Emit (ec);
ec.Emit (OpCodes.Castclass, temp.Type);
temp.Store (ec);
EmitOnCompleted (ec, temp, false);
temp.Release (ec);
ec.Emit (OpCodes.Br_S, label_end);
var fexpr = new FieldExpr (continuation, Location); ec.MarkLabel (label_critical);
fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
// EmitOnCompleted (ec, temp_critical, true);
// if ($continuation == null)
// $continuation = new Action (MoveNext);
//
fexpr.Emit (ec);
var skip_cont_init = ec.DefineLabel (); ec.MarkLabel (label_end);
ec.Emit (OpCodes.Brtrue_S, skip_cont_init);
ec.EmitThis (); temp_critical.Release (ec);
EmitActionLoad (ec); }
ec.Emit (OpCodes.Stfld, continuation.Spec);
ec.MarkLabel (skip_cont_init);
return fexpr; public void EmitAwaitOnCompleted (EmitContext ec, FieldExpr awaiter)
{
bool unsafe_version = false;
if (Module.PredefinedTypes.ICriticalNotifyCompletion.Define ()) {
unsafe_version = awaiter.Type.ImplementsInterface (Module.PredefinedTypes.ICriticalNotifyCompletion.TypeSpec, false);
} }
// EmitOnCompleted (ec, awaiter, unsafe_version);
// Otherwise simply use temporary local variable
//
var field = LocalVariable.CreateCompilerGenerated (action, OriginalSourceBlock, Location);
EmitActionLoad (ec);
field.EmitAssign (ec);
return new LocalVariableReference (field, Location);
} }
void EmitActionLoad (EmitContext ec) void EmitOnCompleted (EmitContext ec, Expression awaiter, bool unsafeVersion)
{ {
ec.EmitThis (); var pm = Module.PredefinedMembers;
ec.Emit (OpCodes.Ldftn, StateMachineMethod.Spec); PredefinedMember<MethodSpec> predefined;
ec.Emit (OpCodes.Newobj, (MethodSpec) MemberCache.FindMember (action, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly)); bool has_task_return_type = false;
if (return_type.Kind == MemberKind.Void) {
predefined = unsafeVersion ? pm.AsyncVoidMethodBuilderOnCompletedUnsafe : pm.AsyncVoidMethodBuilderOnCompleted;
} else if (return_type == Module.PredefinedTypes.Task.TypeSpec) {
predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderOnCompletedUnsafe : pm.AsyncTaskMethodBuilderOnCompleted;
} else {
predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderGenericOnCompletedUnsafe : pm.AsyncTaskMethodBuilderGenericOnCompleted;
has_task_return_type = true;
}
var on_completed = predefined.Resolve (Location);
if (on_completed == null)
return;
if (has_task_return_type)
on_completed = MemberCache.GetMember<MethodSpec> (set_result.DeclaringType, on_completed);
on_completed = on_completed.MakeGenericMethod (this, awaiter.Type, ec.CurrentType);
var mg = MethodGroupExpr.CreatePredefined (on_completed, on_completed.DeclaringType, Location);
mg.InstanceExpression = new FieldExpr (builder, Location) {
InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location)
};
var args = new Arguments (2);
args.Add (new Argument (awaiter, Argument.AType.Ref));
args.Add (new Argument (new CompilerGeneratedThis (CurrentType, Location), Argument.AType.Ref));
mg.EmitCall (ec, args);
}
public void EmitInitializer (EmitContext ec)
{
//
// Some predefined types are missing
//
if (builder == null)
return;
var instance = (TemporaryVariableReference) Instance;
var builder_field = builder.Spec;
if (MemberName.Arity > 0) {
builder_field = MemberCache.GetMember (instance.Type, builder_field);
}
//
// Inflated factory method when task is of generic type
//
if (builder_factory.DeclaringType.IsGeneric) {
var task_return_type = return_type.TypeArguments;
var bt = builder_factory.DeclaringType.MakeGenericType (Module, task_return_type);
builder_factory = MemberCache.GetMember (bt, builder_factory);
builder_start = MemberCache.GetMember (bt, builder_start);
}
//
// stateMachine.$builder = AsyncTaskMethodBuilder<{task-type}>.Create();
//
instance.AddressOf (ec, AddressOp.Store);
ec.Emit (OpCodes.Call, builder_factory);
ec.Emit (OpCodes.Stfld, builder_field);
//
// stateMachine.$builder.Start<{storey-type}>(ref stateMachine);
//
instance.AddressOf (ec, AddressOp.Store);
ec.Emit (OpCodes.Ldflda, builder_field);
if (Task != null)
ec.Emit (OpCodes.Dup);
instance.AddressOf (ec, AddressOp.Store);
ec.Emit (OpCodes.Call, builder_start.MakeGenericMethod (Module, instance.Type));
//
// Emits return stateMachine.$builder.Task;
//
if (Task != null) {
var task_get = Task.Get;
if (MemberName.Arity > 0) {
task_get = MemberCache.GetMember (builder_field.MemberType, task_get);
}
var pe_task = new PropertyExpr (Task, Location) {
InstanceExpression = EmptyExpression.Null, // Comes from the dup above
Getter = task_get
};
pe_task.Emit (ec);
}
} }
public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable) public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable)
@ -747,7 +827,7 @@ namespace Mono.CSharp
// $builder.SetException (Exception) // $builder.SetException (Exception)
// //
var mg = MethodGroupExpr.CreatePredefined (set_exception, set_exception.DeclaringType, Location); var mg = MethodGroupExpr.CreatePredefined (set_exception, set_exception.DeclaringType, Location);
mg.InstanceExpression = new FieldExpr (Builder, Location) { mg.InstanceExpression = new FieldExpr (builder, Location) {
InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location) InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location)
}; };
@ -764,7 +844,7 @@ namespace Mono.CSharp
// $builder.SetResult<return-type> (value); // $builder.SetResult<return-type> (value);
// //
var mg = MethodGroupExpr.CreatePredefined (set_result, set_result.DeclaringType, Location); var mg = MethodGroupExpr.CreatePredefined (set_result, set_result.DeclaringType, Location);
mg.InstanceExpression = new FieldExpr (Builder, Location) { mg.InstanceExpression = new FieldExpr (builder, Location) {
InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location) InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location)
}; };
@ -778,31 +858,57 @@ namespace Mono.CSharp
mg.EmitCall (ec, args); mg.EmitCall (ec, args);
} }
}
class StackField : Field protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
{
public StackField (TypeDefinition parent, FullNamedExpression type, Modifiers mod, MemberName name)
: base (parent, type, mod, name, null)
{ {
} base_type = Compiler.BuiltinTypes.ValueType;
base_class = null;
public bool CanBeReused { get; set; } var istate_machine = Module.PredefinedTypes.IAsyncStateMachine;
if (istate_machine.Define ()) {
return new[] { istate_machine.TypeSpec };
}
return null;
}
} }
class StackFieldExpr : FieldExpr class StackFieldExpr : FieldExpr, IExpressionCleanup
{ {
public StackFieldExpr (Field field) public StackFieldExpr (Field field)
: base (field, Location.Null) : base (field, Location.Null)
{ {
} }
public override void AddressOf (EmitContext ec, AddressOp mode)
{
base.AddressOf (ec, mode);
if (mode == AddressOp.Load) {
var field = (Field) spec.MemberDefinition;
field.IsAvailableForReuse = true;
}
}
public override void Emit (EmitContext ec) public override void Emit (EmitContext ec)
{ {
base.Emit (ec); base.Emit (ec);
var field = (StackField) spec.MemberDefinition; var field = (Field) spec.MemberDefinition;
field.CanBeReused = true; field.IsAvailableForReuse = true;
//
// Release any captured reference type stack variables
// to imitate real stack behavour and help GC stuff early
//
if (TypeSpec.IsReferenceType (type)) {
ec.AddStatementEpilog (this);
}
}
void IExpressionCleanup.EmitCleanup (EmitContext ec)
{
EmitAssign (ec, new NullConstant (type, loc), false, false);
} }
} }
} }

14
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs

@ -902,6 +902,11 @@ namespace Mono.CSharp {
// Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
// //
public bool IsInternalCall () public bool IsInternalCall ()
{
return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
}
public MethodImplOptions GetMethodImplOptions ()
{ {
MethodImplOptions options = 0; MethodImplOptions options = 0;
if (pos_args.Count == 1) { if (pos_args.Count == 1) {
@ -911,7 +916,7 @@ namespace Mono.CSharp {
options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ()); options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
} }
return (options & MethodImplOptions.InternalCall) != 0; return options;
} }
// //
@ -1631,6 +1636,9 @@ namespace Mono.CSharp {
public readonly PredefinedDecimalAttribute DecimalConstant; public readonly PredefinedDecimalAttribute DecimalConstant;
public readonly PredefinedAttribute StructLayout; public readonly PredefinedAttribute StructLayout;
public readonly PredefinedAttribute FieldOffset; public readonly PredefinedAttribute FieldOffset;
public readonly PredefinedAttribute CallerMemberNameAttribute;
public readonly PredefinedAttribute CallerLineNumberAttribute;
public readonly PredefinedAttribute CallerFilePathAttribute;
public PredefinedAttributes (ModuleContainer module) public PredefinedAttributes (ModuleContainer module)
{ {
@ -1682,6 +1690,10 @@ namespace Mono.CSharp {
StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute"); StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute"); FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
// TODO: Should define only attributes which are used for comparison // TODO: Should define only attributes which are used for comparison
const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public | const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly; System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs

@ -149,7 +149,7 @@ namespace Mono.CSharp {
case Binary.Operator.ExclusiveOr: case Binary.Operator.ExclusiveOr:
result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
if (result != null) if (result != null)
result = result.TryReduce (ec, lt, loc); result = result.TryReduce (ec, lt);
return result; return result;
/// ///
@ -158,7 +158,7 @@ namespace Mono.CSharp {
case Binary.Operator.Subtraction: case Binary.Operator.Subtraction:
result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
if (result != null) if (result != null)
result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt), loc); result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt));
return result; return result;
/// ///
@ -340,7 +340,7 @@ namespace Mono.CSharp {
if (result == null) if (result == null)
return null; return null;
result = result.TryReduce (ec, lt, loc); result = result.TryReduce (ec, lt);
if (result == null) if (result == null)
return null; return null;
@ -459,7 +459,7 @@ namespace Mono.CSharp {
if (result == null) if (result == null)
return null; return null;
result = result.TryReduce (ec, lt, loc); result = result.TryReduce (ec, lt);
if (result == null) if (result == null)
return null; return null;

97
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs

@ -85,16 +85,15 @@ namespace Mono.CSharp
} }
} }
#if FULL_AST
// //
// Any unattached attributes during parsing get added here. // Any unattached attributes during parsing get added here. User
// by FULL_AST mode
// //
public Attributes UnattachedAttributes { public Attributes UnattachedAttributes {
get; set; get; set;
} }
#endif
public virtual void AddCompilerGeneratedClass (CompilerGeneratedClass c) public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
{ {
containers.Add (c); containers.Add (c);
} }
@ -747,7 +746,7 @@ namespace Mono.CSharp
base.AddTypeContainer (tc); base.AddTypeContainer (tc);
} }
public override void AddCompilerGeneratedClass (CompilerGeneratedClass c) public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
{ {
members.Add (c); members.Add (c);
@ -1326,7 +1325,7 @@ namespace Mono.CSharp
} }
if (proxy_method == null) { if (proxy_method == null) {
string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count); string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
var base_parameters = new Parameter[method.Parameters.Count]; var base_parameters = new Parameter[method.Parameters.Count];
for (int i = 0; i < base_parameters.Length; ++i) { for (int i = 0; i < base_parameters.Length; ++i) {
var base_param = method.Parameters.FixedParameters[i]; var base_param = method.Parameters.FixedParameters[i];
@ -1958,28 +1957,28 @@ namespace Mono.CSharp
if (OptAttributes != null) if (OptAttributes != null)
OptAttributes.Emit (); OptAttributes.Emit ();
if (!IsTopLevel) { if (!IsCompilerGenerated) {
MemberSpec candidate; if (!IsTopLevel) {
bool overrides = false; MemberSpec candidate;
var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides); bool overrides = false;
if (conflict_symbol == null && candidate == null) { var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
if ((ModFlags & Modifiers.NEW) != 0) if (conflict_symbol == null && candidate == null) {
Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", if ((ModFlags & Modifiers.NEW) != 0)
GetSignatureForError ()); Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
} else { GetSignatureForError ());
if ((ModFlags & Modifiers.NEW) == 0) { } else {
if (candidate == null) if ((ModFlags & Modifiers.NEW) == 0) {
candidate = conflict_symbol; if (candidate == null)
candidate = conflict_symbol;
Report.SymbolRelatedToPreviousError (candidate); Report.SymbolRelatedToPreviousError (candidate);
Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
GetSignatureForError (), candidate.GetSignatureForError ()); GetSignatureForError (), candidate.GetSignatureForError ());
}
} }
} }
}
// Run constraints check on all possible generic types // Run constraints check on all possible generic types
if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
if (base_type != null && base_type_expr != null) { if (base_type != null && base_type_expr != null) {
ConstraintChecker.Check (this, base_type, base_type_expr.Location); ConstraintChecker.Check (this, base_type, base_type_expr.Location);
} }
@ -2355,6 +2354,8 @@ namespace Mono.CSharp
public abstract class ClassOrStruct : TypeDefinition public abstract class ClassOrStruct : TypeDefinition
{ {
public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
SecurityType declarative_security; SecurityType declarative_security;
public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind) public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
@ -2364,7 +2365,19 @@ namespace Mono.CSharp
protected override TypeAttributes TypeAttr { protected override TypeAttributes TypeAttr {
get { get {
return has_static_constructor ? base.TypeAttr : base.TypeAttr | TypeAttributes.BeforeFieldInit; TypeAttributes ta = base.TypeAttr;
if (!has_static_constructor)
ta |= TypeAttributes.BeforeFieldInit;
if (Kind == MemberKind.Class) {
ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
if (IsStatic)
ta |= StaticClassAttribute;
} else {
ta |= TypeAttributes.SequentialLayout;
}
return ta;
} }
} }
@ -2479,8 +2492,8 @@ namespace Mono.CSharp
} }
// TODO: should be sealed public sealed class Class : ClassOrStruct
public class Class : ClassOrStruct { {
const Modifiers AllowedModifiers = const Modifiers AllowedModifiers =
Modifiers.NEW | Modifiers.NEW |
Modifiers.PUBLIC | Modifiers.PUBLIC |
@ -2492,8 +2505,6 @@ namespace Mono.CSharp
Modifiers.STATIC | Modifiers.STATIC |
Modifiers.UNSAFE; Modifiers.UNSAFE;
public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs) public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
: base (parent, name, attrs, MemberKind.Class) : base (parent, name, attrs, MemberKind.Class)
{ {
@ -2687,23 +2698,10 @@ namespace Mono.CSharp
caching_flags |= Flags.Excluded; caching_flags |= Flags.Excluded;
return conditions; return conditions;
} }
//
// FIXME: How do we deal with the user specifying a different
// layout?
//
protected override TypeAttributes TypeAttr {
get {
TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
if (IsStatic)
ta |= StaticClassAttribute;
return ta;
}
}
} }
public sealed class Struct : ClassOrStruct { public sealed class Struct : ClassOrStruct
{
bool is_unmanaged, has_unmanaged_check_done; bool is_unmanaged, has_unmanaged_check_done;
bool InTransit; bool InTransit;
@ -2875,17 +2873,6 @@ namespace Mono.CSharp
return ifaces; return ifaces;
} }
protected override TypeAttributes TypeAttr {
get {
const
TypeAttributes DefaultTypeAttributes =
TypeAttributes.SequentialLayout |
TypeAttributes.Sealed ;
return base.TypeAttr | DefaultTypeAttributes;
}
}
public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
{ {
if ((field.ModFlags & Modifiers.STATIC) == 0) { if ((field.ModFlags & Modifiers.STATIC) == 0) {

42
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs

@ -83,6 +83,8 @@ namespace Mono.CSharp
Label? return_label; Label? return_label;
List<IExpressionCleanup> epilogue_expressions;
public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type, SourceMethodBuilder methodSymbols) public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type, SourceMethodBuilder methodSymbols)
{ {
this.member_context = rc; this.member_context = rc;
@ -137,6 +139,12 @@ namespace Mono.CSharp
} }
} }
public bool HasMethodSymbolBuilder {
get {
return methodSymbols != null;
}
}
public bool HasReturnLabel { public bool HasReturnLabel {
get { get {
return return_label.HasValue; return return_label.HasValue;
@ -190,8 +198,25 @@ namespace Mono.CSharp
} }
} }
public List<IExpressionCleanup> StatementEpilogue {
get {
return epilogue_expressions;
}
}
#endregion #endregion
public void AddStatementEpilog (IExpressionCleanup cleanupExpression)
{
if (epilogue_expressions == null) {
epilogue_expressions = new List<IExpressionCleanup> ();
} else if (epilogue_expressions.Contains (cleanupExpression)) {
return;
}
epilogue_expressions.Add (cleanupExpression);
}
public void AssertEmptyStack () public void AssertEmptyStack ()
{ {
#if STATIC #if STATIC
@ -810,6 +835,17 @@ namespace Mono.CSharp
ig.Emit (OpCodes.Ldarg_0); ig.Emit (OpCodes.Ldarg_0);
} }
public void EmitEpilogue ()
{
if (epilogue_expressions == null)
return;
foreach (var e in epilogue_expressions)
e.EmitCleanup (this);
epilogue_expressions = null;
}
/// <summary> /// <summary>
/// Returns a temporary storage for a variable of type t as /// Returns a temporary storage for a variable of type t as
/// a local variable in the current body. /// a local variable in the current body.
@ -1060,9 +1096,11 @@ namespace Mono.CSharp
return false; return false;
// //
// It's non-virtual and will never be null // It's non-virtual and will never be null and it can be determined
// whether it's known value or reference type by verifier
// //
if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation)) if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation) &&
!instance.Type.IsGenericParameter)
return false; return false;
return true; return true;

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/const.cs

@ -205,7 +205,7 @@ namespace Mono.CSharp {
else if (!(expr is Constant)) else if (!(expr is Constant))
Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ()); Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ());
else else
expr.Error_ValueCannotBeConverted (rc, expr.Location, field.MemberType, false); expr.Error_ValueCannotBeConverted (rc, field.MemberType, false);
} }
expr = c; expr = c;

39
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs

@ -58,7 +58,7 @@ namespace Mono.CSharp {
} }
#endif #endif
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
if (!expl && IsLiteral && if (!expl && IsLiteral &&
BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) && BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
@ -66,7 +66,7 @@ namespace Mono.CSharp {
ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
GetValueAsLiteral (), TypeManager.CSharpName (target)); GetValueAsLiteral (), TypeManager.CSharpName (target));
} else { } else {
base.Error_ValueCannotBeConverted (ec, loc, target, expl); base.Error_ValueCannotBeConverted (ec, target, expl);
} }
} }
@ -74,7 +74,7 @@ namespace Mono.CSharp {
{ {
Constant c = ConvertImplicitly (type); Constant c = ConvertImplicitly (type);
if (c == null) if (c == null)
Error_ValueCannotBeConverted (ec, loc, type, false); Error_ValueCannotBeConverted (ec, type, false);
return c; return c;
} }
@ -160,8 +160,11 @@ namespace Mono.CSharp {
return new NullConstant (t, loc); return new NullConstant (t, loc);
} }
throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", #if STATIC
v, TypeManager.CSharpName (t)); throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ());
#else
return null;
#endif
} }
public override Expression CreateExpressionTree (ResolveContext ec) public override Expression CreateExpressionTree (ResolveContext ec)
@ -251,32 +254,38 @@ namespace Mono.CSharp {
/// <summary> /// <summary>
/// Attempts to do a compile-time folding of a constant cast. /// Attempts to do a compile-time folding of a constant cast.
/// </summary> /// </summary>
public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc) public Constant TryReduce (ResolveContext ec, TypeSpec target_type)
{ {
try { try {
return TryReduce (ec, target_type); return TryReduceConstant (ec, target_type);
} } catch (OverflowException) {
catch (OverflowException) {
if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
ec.Report.Error (221, loc, ec.Report.Error (221, loc,
"Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
GetValueAsLiteral (), target_type.GetSignatureForError ()); GetValueAsLiteral (), target_type.GetSignatureForError ());
} else { } else {
Error_ValueCannotBeConverted (ec, loc, target_type, false); Error_ValueCannotBeConverted (ec, target_type, false);
} }
return New.Constantify (target_type, loc); return New.Constantify (target_type, loc);
} }
} }
Constant TryReduce (ResolveContext ec, TypeSpec target_type) Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
{ {
if (Type == target_type) if (Type == target_type) {
//
// Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10
//
if (IsLiteral)
return CreateConstantFromValue (target_type, GetValue (), loc);
return this; return this;
}
Constant c; Constant c;
if (target_type.IsEnum) { if (target_type.IsEnum) {
c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type));
if (c == null) if (c == null)
return null; return null;
@ -378,11 +387,11 @@ namespace Mono.CSharp {
eclass = ExprClass.Value; eclass = ExprClass.Value;
} }
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
try { try {
ConvertExplicitly (true, target); ConvertExplicitly (true, target);
base.Error_ValueCannotBeConverted (ec, loc, target, expl); base.Error_ValueCannotBeConverted (ec, target, expl);
} }
catch catch
{ {

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs

@ -481,7 +481,7 @@ namespace Mono.CSharp
// or it's a parameter // or it's a parameter
// //
if (CurrentAnonymousMethod is AsyncInitializer) if (CurrentAnonymousMethod is AsyncInitializer)
return CurrentBlock.Explicit.HasAwait; return local.IsParameter || CurrentBlock.Explicit.HasAwait;
return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original; return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
} }

13
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs

@ -495,6 +495,11 @@ namespace Mono.CSharp {
return ImplicitNumericConversion (expr, expr.Type, target_type); return ImplicitNumericConversion (expr, expr.Type, target_type);
} }
public static bool ImplicitNumericConversionExists (TypeSpec expr_type, TypeSpec target_type)
{
return ImplicitNumericConversion (null, expr_type, target_type) != null;
}
static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
{ {
switch (expr_type.BuiltinType) { switch (expr_type.BuiltinType) {
@ -1190,7 +1195,7 @@ namespace Mono.CSharp {
if (s_x != source_type) { if (s_x != source_type) {
var c = source as Constant; var c = source as Constant;
if (c != null) { if (c != null) {
source = c.TryReduce (ec, s_x, loc); source = c.TryReduce (ec, s_x);
} else { } else {
source = implicitOnly ? source = implicitOnly ?
ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
@ -1418,7 +1423,7 @@ namespace Mono.CSharp {
if (e != null) if (e != null)
return e; return e;
source.Error_ValueCannotBeConverted (ec, loc, target_type, false); source.Error_ValueCannotBeConverted (ec, target_type, false);
return null; return null;
} }
@ -2098,7 +2103,7 @@ namespace Mono.CSharp {
if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void) if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
return EmptyCast.Create (expr, target_type); return EmptyCast.Create (expr, target_type);
expr.Error_ValueCannotBeConverted (ec, l, target_type, true); expr.Error_ValueCannotBeConverted (ec, target_type, true);
return null; return null;
} }
@ -2161,7 +2166,7 @@ namespace Mono.CSharp {
if (e != null) if (e != null)
return e; return e;
expr.Error_ValueCannotBeConverted (ec, loc, target_type, true); expr.Error_ValueCannotBeConverted (ec, target_type, true);
return null; return null;
} }
} }

8809
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs

File diff suppressed because it is too large Load Diff

130
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay

@ -400,6 +400,8 @@ outer_declaration
Attributes attrs = (Attributes) $4; Attributes attrs = (Attributes) $4;
report.Error (1730, attrs.Attrs [0].Location, report.Error (1730, attrs.Attrs [0].Location,
"Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations");
current_namespace.UnattachedAttributes = attrs;
} }
} }
| opt_extern_alias_directives opt_using_directives attribute_sections | opt_extern_alias_directives opt_using_directives attribute_sections
@ -618,9 +620,7 @@ namespace_or_type_declaration
current_namespace.DeclarationFound = true; current_namespace.DeclarationFound = true;
} }
| attribute_sections CLOSE_BRACE { | attribute_sections CLOSE_BRACE {
#if FULL_AST
current_namespace.UnattachedAttributes = (Attributes) $1; current_namespace.UnattachedAttributes = (Attributes) $1;
#endif
report.Error (1518, lexer.Location, "Attributes must be attached to class, delegate, enum, interface or struct"); report.Error (1518, lexer.Location, "Attributes must be attached to class, delegate, enum, interface or struct");
lexer.putback ('}'); lexer.putback ('}');
} }
@ -1521,12 +1521,18 @@ fixed_parameter
$$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location);
lbag.AddLocation ($$, parameterModifierLocation); lbag.AddLocation ($$, parameterModifierLocation);
} }
| attribute_sections error
{
Error_SyntaxError (yyToken);
Location l = GetLocation ($2);
$$ = new Parameter (null, null, Parameter.Modifier.NONE, (Attributes) $1, l);
}
| opt_attributes | opt_attributes
opt_parameter_modifier opt_parameter_modifier
parameter_type parameter_type
error error
{ {
Error_SyntaxError (yyToken); Error_SyntaxError (yyToken);
Location l = GetLocation ($4); Location l = GetLocation ($4);
$$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l); $$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l);
lbag.AddLocation ($$, parameterModifierLocation); lbag.AddLocation ($$, parameterModifierLocation);
@ -2536,10 +2542,9 @@ event_accessor_block
; ;
attributes_without_members attributes_without_members
: attribute_sections CLOSE_BRACE { : attribute_sections CLOSE_BRACE
#if FULL_AST {
current_type.UnattachedAttributes = (Attributes) $1; current_type.UnattachedAttributes = (Attributes) $1;
#endif
report.Error (1519, GetLocation ($1), "An attribute is missing member declaration"); report.Error (1519, GetLocation ($1), "An attribute is missing member declaration");
lexer.putback ('}'); lexer.putback ('}');
} }
@ -2565,7 +2570,7 @@ enum_declaration
report.Error (1675, name.Location, "Enums cannot have type parameters"); report.Error (1675, name.Location, "Enums cannot have type parameters");
} }
push_current_container (new Enum (current_container, (TypeExpression) $5, (Modifiers) $2, name, (Attributes) $1), null); push_current_container (new Enum (current_container, (FullNamedExpression) $5, (Modifiers) $2, name, (Attributes) $1), null);
if ($5 != null) { if ($5 != null) {
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($3), savedLocation, GetLocation ($7)); lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($3), savedLocation, GetLocation ($7));
} else { } else {
@ -2600,14 +2605,8 @@ opt_enum_base
: /* empty */ : /* empty */
| COLON type | COLON type
{ {
var te = $2 as TypeExpression; savedLocation = GetLocation ($1);
if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { $$ = $2;
Enum.Error_1008 (GetLocation ($2), report);
$$ = null;
} else {
savedLocation = GetLocation ($1);
$$ = $2;
}
} }
| COLON error | COLON error
{ {
@ -3326,10 +3325,10 @@ argument_list
lbag.AppendTo (list, GetLocation ($2)); lbag.AppendTo (list, GetLocation ($2));
$$ = list; $$ = list;
} }
| argument_list COMMA | argument_list COMMA error
{ {
report.Error (839, GetLocation ($2), "An argument is missing"); Error_SyntaxError (yyToken);
$$ = $1; $$ = $1;
} }
| COMMA error | COMMA error
{ {
@ -3386,10 +3385,12 @@ element_access
} }
| primary_expression OPEN_BRACKET_EXPR expression_list_arguments error | primary_expression OPEN_BRACKET_EXPR expression_list_arguments error
{ {
Error_SyntaxError (yyToken);
$$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); $$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2));
} }
| primary_expression OPEN_BRACKET_EXPR error | primary_expression OPEN_BRACKET_EXPR error
{ {
Error_SyntaxError (yyToken);
$$ = new ElementAccess ((Expression) $1, null, GetLocation ($2)); $$ = new ElementAccess ((Expression) $1, null, GetLocation ($2));
} }
; ;
@ -3530,8 +3531,9 @@ array_creation_expression
} }
| NEW new_expr_type error | NEW new_expr_type error
{ {
Error_SyntaxError (1526, yyToken, "Unexpected symbol"); Error_SyntaxError (yyToken);
$$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); // It can be any of new expression, create the most common one
$$ = new New ((FullNamedExpression) $2, null, GetLocation ($1));
} }
; ;
@ -3899,8 +3901,16 @@ unary_expression
| AWAIT prefixed_unary_expression | AWAIT prefixed_unary_expression
{ {
if (!async_block) { if (!async_block) {
report.Error (1992, GetLocation ($1), if (current_anonymous_method is LambdaExpression) {
"The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier"); report.Error (4034, GetLocation ($1),
"The `await' operator can only be used when its containing lambda expression is marked with the `async' modifier");
} else if (current_anonymous_method is AnonymousMethodExpression) {
report.Error (4035, GetLocation ($1),
"The `await' operator can only be used when its containing anonymous method is marked with the `async' modifier");
} else {
report.Error (4033, GetLocation ($1),
"The `await' operator can only be used when its containing method is marked with the `async' modifier");
}
} else { } else {
current_block.Explicit.RegisterAsyncAwait (); current_block.Explicit.RegisterAsyncAwait ();
} }
@ -4101,6 +4111,11 @@ conditional_expression
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2));
lbag.AddLocation ($$, GetLocation ($4)); lbag.AddLocation ($$, GetLocation ($4));
} }
| null_coalescing_expression INTERR expression error
{
Error_SyntaxError (yyToken);
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2));
}
; ;
assignment_expression assignment_expression
@ -5293,6 +5308,11 @@ switch_label
$$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); $$ = new SwitchLabel ((Expression) $2, GetLocation ($1));
lbag.AddLocation ($$, GetLocation ($3)); lbag.AddLocation ($$, GetLocation ($3));
} }
| CASE constant_expression error
{
Error_SyntaxError (yyToken);
$$ = new SwitchLabel ((Expression) $2, GetLocation ($1));
}
| DEFAULT_COLON | DEFAULT_COLON
{ {
$$ = new SwitchLabel (null, GetLocation ($1)); $$ = new SwitchLabel (null, GetLocation ($1));
@ -5394,7 +5414,7 @@ for_statement_condition
{ {
$$ = $4; $$ = $4;
} }
| opt_for_condition CLOSE_PARENS { | boolean_expression CLOSE_PARENS {
report.Error (1525, GetLocation ($2), "Unexpected symbol ')', expected ';'"); report.Error (1525, GetLocation ($2), "Unexpected symbol ')', expected ';'");
For f = (For) $0; For f = (For) $0;
f.Condition = (BooleanExpression) $1; f.Condition = (BooleanExpression) $1;
@ -5471,6 +5491,7 @@ statement_expression_list
} else { } else {
sl.Add ((Statement) $3); sl.Add ((Statement) $3);
lbag.AppendTo (sl, GetLocation ($2)); lbag.AppendTo (sl, GetLocation ($2));
} }
$$ = sl; $$ = sl;
@ -5485,7 +5506,7 @@ foreach_statement
start_block (GetLocation ($2)); start_block (GetLocation ($2));
current_block.IsCompilerGenerated = true; current_block.IsCompilerGenerated = true;
Foreach f = new Foreach ((Expression) $3, null, null, null, GetLocation ($1)); Foreach f = new Foreach ((Expression) $3, null, null, null, null, GetLocation ($1));
current_block.AddStatement (f); current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2)); lbag.AddStatement (f, GetLocation ($2));
@ -5494,7 +5515,7 @@ foreach_statement
| FOREACH open_parens_any type identifier_inside_body error | FOREACH open_parens_any type identifier_inside_body error
{ {
Error_SyntaxError (yyToken); Error_SyntaxError (yyToken);
start_block (GetLocation ($2)); start_block (GetLocation ($2));
current_block.IsCompilerGenerated = true; current_block.IsCompilerGenerated = true;
@ -5502,7 +5523,7 @@ foreach_statement
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location);
current_block.AddLocalName (li); current_block.AddLocalName (li);
Foreach f = new Foreach ((Expression) $3, li, null, null, GetLocation ($1)); Foreach f = new Foreach ((Expression) $3, li, null, null, null, GetLocation ($1));
current_block.AddStatement (f); current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2)); lbag.AddStatement (f, GetLocation ($2));
@ -5521,12 +5542,12 @@ foreach_statement
{ {
if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($9)); Warning_EmptyStatement (GetLocation ($9));
Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, GetLocation ($1));
current_block.AddStatement (f);
Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, current_block, GetLocation ($1));
lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7)); lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7));
$$ = end_block (GetLocation ($7)); end_block (GetLocation ($7));
$$ = f;
} }
| FOREACH open_parens_any type identifier_inside_body error | FOREACH open_parens_any type identifier_inside_body error
{ {
@ -5535,7 +5556,7 @@ foreach_statement
var lt = $4 as Tokenizer.LocatedToken; var lt = $4 as Tokenizer.LocatedToken;
var li = lt != null ? new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location) : null; var li = lt != null ? new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location) : null;
Foreach f = new Foreach ((Expression) $3, li, null, null, GetLocation ($1)); Foreach f = new Foreach ((Expression) $3, li, null, null, null, GetLocation ($1));
current_block.AddStatement (f); current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2)); lbag.AddStatement (f, GetLocation ($2));
@ -5543,7 +5564,7 @@ foreach_statement
} }
| FOREACH open_parens_any type error | FOREACH open_parens_any type error
{ {
Foreach f = new Foreach ((Expression) $3, null, null, null, GetLocation ($1)); Foreach f = new Foreach ((Expression) $3, null, null, null, null, GetLocation ($1));
current_block.AddStatement (f); current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2)); lbag.AddStatement (f, GetLocation ($2));
@ -5574,6 +5595,11 @@ continue_statement
$$ = new Continue (GetLocation ($1)); $$ = new Continue (GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($2)); lbag.AddStatement ($$, GetLocation ($2));
} }
| CONTINUE error
{
Error_SyntaxError (yyToken);
$$ = new Continue (GetLocation ($1));
}
; ;
goto_statement goto_statement
@ -5601,6 +5627,11 @@ return_statement
$$ = new Return ((Expression) $2, GetLocation ($1)); $$ = new Return ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3)); lbag.AddStatement ($$, GetLocation ($3));
} }
| RETURN error
{
Error_SyntaxError (yyToken);
$$ = new Return (null, GetLocation ($1));
}
; ;
throw_statement throw_statement
@ -5609,6 +5640,11 @@ throw_statement
$$ = new Throw ((Expression) $2, GetLocation ($1)); $$ = new Throw ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3)); lbag.AddStatement ($$, GetLocation ($3));
} }
| THROW error
{
Error_SyntaxError (yyToken);
$$ = new Throw (null, GetLocation ($1));
}
; ;
yield_statement yield_statement
@ -6003,7 +6039,7 @@ from_clause
; ;
query_body query_body
: opt_query_body_clauses select_or_group_clause opt_query_continuation : query_body_clauses select_or_group_clause opt_query_continuation
{ {
Linq.AQueryClause head = (Linq.AQueryClause)$2; Linq.AQueryClause head = (Linq.AQueryClause)$2;
@ -6018,7 +6054,24 @@ query_body
$$ = head; $$ = head;
} }
| opt_query_body_clauses COMPLETE_COMPLETION | select_or_group_clause opt_query_continuation
{
Linq.AQueryClause head = (Linq.AQueryClause)$2;
if ($1 != null) {
Linq.AQueryClause clause = (Linq.AQueryClause)$1;
clause.Tail.Next = head;
head = clause;
}
$$ = head;
}
| query_body_clauses COMPLETE_COMPLETION
| query_body_clauses error
{
report.Error (742, GetLocation ($2), "Unexpected symbol `{0}'. A query body must end with select or group clause", GetSymbolName (yyToken));
$$ = $1;
}
| error | error
{ {
Error_SyntaxError (yyToken); Error_SyntaxError (yyToken);
@ -6063,11 +6116,6 @@ select_or_group_clause
} }
; ;
opt_query_body_clauses
: /* empty */
| query_body_clauses
;
query_body_clauses query_body_clauses
: query_body_clause : query_body_clause
| query_body_clauses query_body_clause | query_body_clauses query_body_clause
@ -6773,10 +6821,10 @@ public void parse ()
report.Error (-25, lexer.Location, "Parsing error"); report.Error (-25, lexer.Location, "Parsing error");
} else { } else {
// Used by compiler-tester to test internal errors // Used by compiler-tester to test internal errors
if (yacc_verbose_flag > 0) if (yacc_verbose_flag > 0 || e is FatalException)
throw; throw;
report.Error (589, lexer.Location, "Internal compiler error during parsing"); report.Error (589, lexer.Location, "Internal compiler error during parsing" + e);
} }
} }
} }

22
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs

@ -137,6 +137,11 @@ namespace Mono.CSharp
pos = 0; pos = 0;
} }
public override string ToString ()
{
return string.Format ("Token '{0}' at {1},{2}", Value, row, column);
}
public Location Location { public Location Location {
get { return new Location (row, column); } get { return new Location (row, column); }
} }
@ -1266,10 +1271,24 @@ namespace Mono.CSharp
int ntoken; int ntoken;
int interrs = 1; int interrs = 1;
int colons = 0; int colons = 0;
int braces = 0;
// //
// All shorcuts failed, do it hard way // All shorcuts failed, do it hard way
// //
while ((ntoken = xtoken ()) != Token.EOF) { while ((ntoken = xtoken ()) != Token.EOF) {
if (ntoken == Token.OPEN_BRACE) {
++braces;
continue;
}
if (ntoken == Token.CLOSE_BRACE) {
--braces;
continue;
}
if (braces != 0)
continue;
if (ntoken == Token.SEMICOLON) if (ntoken == Token.SEMICOLON)
break; break;
@ -1285,7 +1304,7 @@ namespace Mono.CSharp
} }
} }
next_token = colons != interrs ? Token.INTERR_NULLABLE : Token.INTERR; next_token = colons != interrs && braces == 0 ? Token.INTERR_NULLABLE : Token.INTERR;
break; break;
} }
} }
@ -1535,6 +1554,7 @@ namespace Mono.CSharp
#endif #endif
number_pos = 0; number_pos = 0;
var loc = Location; var loc = Location;
bool hasLeadingDot = c == '.';
if (c >= '0' && c <= '9'){ if (c >= '0' && c <= '9'){
if (c == '0'){ if (c == '0'){

17
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs

@ -299,7 +299,8 @@ namespace Mono.CSharp {
PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists
HasStructLayout = 1 << 15, // Has StructLayoutAttribute HasStructLayout = 1 << 15, // Has StructLayoutAttribute
HasInstanceConstructor = 1 << 16, HasInstanceConstructor = 1 << 16,
HasUserOperators = 1 << 17 HasUserOperators = 1 << 17,
CanBeReused = 1 << 18
} }
/// <summary> /// <summary>
@ -425,6 +426,15 @@ namespace Mono.CSharp {
VerifyClsCompliance (); VerifyClsCompliance ();
} }
public bool IsAvailableForReuse {
get {
return (caching_flags & Flags.CanBeReused) != 0;
}
set {
caching_flags = value ? (caching_flags | Flags.CanBeReused) : (caching_flags & ~Flags.CanBeReused);
}
}
public bool IsCompilerGenerated { public bool IsCompilerGenerated {
get { get {
if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0) if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0)
@ -810,6 +820,11 @@ namespace Mono.CSharp {
Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ()); Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ());
} }
public virtual string GetCallerMemberName ()
{
return MemberName.Name;
}
// //
// Returns a string that represents the signature for this // Returns a string that represents the signature for this
// member which should be used in XML documentation. // member which should be used in XML documentation.

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs

@ -220,7 +220,7 @@ namespace Mono.CSharp {
var p = parameters[i]; var p = parameters[i];
compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location), compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location),
p.Name, p.Name,
p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), p.ModFlags & Parameter.Modifier.RefOutMask,
p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
} }
@ -255,7 +255,7 @@ namespace Mono.CSharp {
int out_params = 0; int out_params = 0;
foreach (Parameter p in Parameters.FixedParameters) { foreach (Parameter p in Parameters.FixedParameters) {
if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0)
++out_params; ++out_params;
} }
@ -265,12 +265,12 @@ namespace Mono.CSharp {
int param = 0; int param = 0;
for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
Parameter p = parameters [i]; Parameter p = parameters [i];
if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) if ((p.ModFlags & Parameter.Modifier.RefOutMask) == 0)
continue; continue;
end_params [param++] = new Parameter (new TypeExpression (p.Type, Location), end_params [param++] = new Parameter (new TypeExpression (p.Type, Location),
p.Name, p.Name,
p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), p.ModFlags & Parameter.Modifier.RefOutMask,
p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
} }

112
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs

@ -397,10 +397,15 @@ namespace Mono.CSharp
if (ParsedParameters != null) { if (ParsedParameters != null) {
var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ()); var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ());
foreach (var pp in ParsedParameters) { try {
pp.Resolve (mc); var context = new DocumentationMemberContext (mc, ParsedName ?? MemberName.Null);
foreach (var pp in ParsedParameters) {
pp.Resolve (context);
}
} finally {
mc.Module.Compiler.Report.SetPrinter (old_printer);
} }
mc.Module.Compiler.Report.SetPrinter (old_printer);
} }
if (type != null) { if (type != null) {
@ -433,13 +438,15 @@ namespace Mono.CSharp
if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue) if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue)
continue; continue;
var pm_params = pm.Parameters;
int i; int i;
for (i = 0; i < parsed_param_count; ++i) { for (i = 0; i < parsed_param_count; ++i) {
var pparam = ParsedParameters[i]; var pparam = ParsedParameters[i];
if (i >= pm.Parameters.Count || pparam == null || if (i >= pm_params.Count || pparam == null || pparam.TypeSpec == null ||
pparam.TypeSpec != pm.Parameters.Types[i] || !TypeSpecComparer.Override.IsEqual (pparam.TypeSpec, pm_params.Types[i]) ||
(pparam.Modifier & Parameter.Modifier.SignatureMask) != (pm.Parameters.FixedParameters[i].ModFlags & Parameter.Modifier.SignatureMask)) { (pparam.Modifier & Parameter.Modifier.RefOutMask) != (pm_params.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) {
if (i > parameters_match) { if (i > parameters_match) {
parameters_match = i; parameters_match = i;
@ -459,7 +466,7 @@ namespace Mono.CSharp
continue; continue;
} }
} else { } else {
if (parsed_param_count != pm.Parameters.Count) if (parsed_param_count != pm_params.Count)
continue; continue;
} }
} }
@ -612,6 +619,97 @@ namespace Mono.CSharp
} }
} }
//
// Type lookup of documentation references uses context of type where
// the reference is used but type parameters from cref value
//
sealed class DocumentationMemberContext : IMemberContext
{
readonly MemberCore host;
MemberName contextName;
public DocumentationMemberContext (MemberCore host, MemberName contextName)
{
this.host = host;
this.contextName = contextName;
}
public TypeSpec CurrentType {
get {
return host.CurrentType;
}
}
public TypeParameters CurrentTypeParameters {
get {
return contextName.TypeParameters;
}
}
public MemberCore CurrentMemberDefinition {
get {
return host.CurrentMemberDefinition;
}
}
public bool IsObsolete {
get {
return false;
}
}
public bool IsUnsafe {
get {
return host.IsStatic;
}
}
public bool IsStatic {
get {
return host.IsStatic;
}
}
public ModuleContainer Module {
get {
return host.Module;
}
}
public string GetSignatureForError ()
{
return host.GetSignatureForError ();
}
public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
{
return null;
}
public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
{
if (arity == 0) {
var tp = CurrentTypeParameters;
if (tp != null) {
for (int i = 0; i < tp.Count; ++i) {
var t = tp[i];
if (t.Name == name) {
t.Type.DeclaredPosition = i;
return new TypeParameterExpr (t, loc);
}
}
}
}
return host.Parent.LookupNamespaceOrType (name, arity, mode, loc);
}
public FullNamedExpression LookupNamespaceAlias (string name)
{
throw new NotImplementedException ();
}
}
class DocumentationParameter class DocumentationParameter
{ {
public readonly Parameter.Modifier Modifier; public readonly Parameter.Modifier Modifier;

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs

@ -259,6 +259,12 @@ namespace Mono.CSharp
output_file = output_file_name; output_file = output_file_name;
} else { } else {
output_file_name = Path.GetFileName (output_file); output_file_name = Path.GetFileName (output_file);
if (string.IsNullOrEmpty (Path.GetFileNameWithoutExtension (output_file_name)) ||
output_file_name.IndexOfAny (Path.GetInvalidFileNameChars ()) >= 0) {
Report.Error (2021, "Output file name is not valid");
return false;
}
} }
#if STATIC #if STATIC

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/dynamic.cs

@ -949,7 +949,7 @@ namespace Mono.CSharp
sealed class DynamicSiteClass : HoistedStoreyClass sealed class DynamicSiteClass : HoistedStoreyClass
{ {
public DynamicSiteClass (TypeDefinition parent, MemberBase host, TypeParameters tparams) public DynamicSiteClass (TypeDefinition parent, MemberBase host, TypeParameters tparams)
: base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC) : base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC, MemberKind.Class)
{ {
parent.DynamicSitesCounter++; parent.DynamicSitesCounter++;
} }

146
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

@ -118,6 +118,11 @@ namespace Mono.CSharp {
bool IsFixed { get; } bool IsFixed { get; }
} }
public interface IExpressionCleanup
{
void EmitCleanup (EmitContext ec);
}
/// <remarks> /// <remarks>
/// Base class for expressions /// Base class for expressions
/// </remarks> /// </remarks>
@ -222,8 +227,7 @@ namespace Mono.CSharp {
public static void Error_InvalidExpressionStatement (Report Report, Location loc) public static void Error_InvalidExpressionStatement (Report Report, Location loc)
{ {
Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " + Report.Error (201, loc, "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement");
"expressions can be used as a statement");
} }
public void Error_InvalidExpressionStatement (BlockContext ec) public void Error_InvalidExpressionStatement (BlockContext ec)
@ -236,7 +240,7 @@ namespace Mono.CSharp {
Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
} }
public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public virtual void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
Error_ValueCannotBeConvertedCore (ec, loc, target, expl); Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
} }
@ -316,7 +320,7 @@ namespace Mono.CSharp {
TypeManager.CSharpName (type), name); TypeManager.CSharpName (type), name);
} }
public void Error_ValueAssignment (ResolveContext rc, Expression rhs) public virtual void Error_ValueAssignment (ResolveContext rc, Expression rhs)
{ {
if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) { if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
rc.Report.SymbolRelatedToPreviousError (type); rc.Report.SymbolRelatedToPreviousError (type);
@ -536,38 +540,40 @@ namespace Mono.CSharp {
ec.EmitThis (); ec.EmitThis ();
// Emit original code // Emit original code
EmitToFieldSource (ec); var field = EmitToFieldSource (ec);
if (field == null) {
//
// Store the result to temporary field when we
// cannot load `this' directly
//
var field = ec.GetTemporaryField (type);
if (needs_temporary) {
// //
// Create temporary local (we cannot load `this' before Emit) // Store the result to temporary field when we
// cannot load `this' directly
// //
var temp = ec.GetTemporaryLocal (type); field = ec.GetTemporaryField (type);
ec.Emit (OpCodes.Stloc, temp); if (needs_temporary) {
//
// Create temporary local (we cannot load `this' before Emit)
//
var temp = ec.GetTemporaryLocal (type);
ec.Emit (OpCodes.Stloc, temp);
ec.EmitThis (); ec.EmitThis ();
ec.Emit (OpCodes.Ldloc, temp); ec.Emit (OpCodes.Ldloc, temp);
field.EmitAssignFromStack (ec); field.EmitAssignFromStack (ec);
ec.FreeTemporaryLocal (temp, type); ec.FreeTemporaryLocal (temp, type);
} else { } else {
field.EmitAssignFromStack (ec); field.EmitAssignFromStack (ec);
}
} }
return field; return field;
} }
protected virtual void EmitToFieldSource (EmitContext ec) protected virtual FieldExpr EmitToFieldSource (EmitContext ec)
{ {
// //
// Default implementation calls Emit method // Default implementation calls Emit method
// //
Emit (ec); Emit (ec);
return null;
} }
protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions) protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions)
@ -909,7 +915,7 @@ namespace Mono.CSharp {
converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc); converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc);
if (converted == null) { if (converted == null) {
source.Error_ValueCannotBeConverted (ec, source.loc, btypes.Int, false); source.Error_ValueCannotBeConverted (ec, btypes.Int, false);
return null; return null;
} }
} }
@ -1025,6 +1031,12 @@ namespace Mono.CSharp {
if (es == null) if (es == null)
Error_InvalidExpressionStatement (ec); Error_InvalidExpressionStatement (ec);
if (ec.CurrentAnonymousMethod is AsyncInitializer && !(e is Assign) &&
(e.Type.IsGenericTask || e.Type == ec.Module.PredefinedTypes.Task.TypeSpec)) {
ec.Report.Warning (4014, 1, e.Location,
"The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator");
}
return es; return es;
} }
@ -1926,6 +1938,12 @@ namespace Mono.CSharp {
#region Properties #region Properties
public override bool IsSideEffectFree {
get {
return expr.IsSideEffectFree;
}
}
public Expression OriginalExpression { public Expression OriginalExpression {
get { get {
return orig_expr; return orig_expr;
@ -1998,6 +2016,11 @@ namespace Mono.CSharp {
expr.Emit (ec); expr.Emit (ec);
} }
public override Expression EmitToField (EmitContext ec)
{
return expr.EmitToField(ec);
}
public override void EmitBranchable (EmitContext ec, Label target, bool on_true) public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
{ {
expr.EmitBranchable (ec, target, on_true); expr.EmitBranchable (ec, target, on_true);
@ -2473,6 +2496,12 @@ namespace Mono.CSharp {
ErrorIsInaccesible (rc, e.GetSignatureForError (), loc); ErrorIsInaccesible (rc, e.GetSignatureForError (), loc);
return e; return e;
} }
} else {
var me = MemberLookup (rc, false, rc.CurrentType, Name, Arity, restrictions & ~MemberLookupRestrictions.InvocableOnly, loc) as MemberExpr;
if (me != null) {
me.Error_UnexpectedKind (rc, me, "method group", me.KindName, loc);
return ErrorExpression.Instance;
}
} }
e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc); e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
@ -3330,7 +3359,7 @@ namespace Mono.CSharp {
call.Emit (ec, best_candidate, arguments, loc); call.Emit (ec, best_candidate, arguments, loc);
} }
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
Name, TypeManager.CSharpName (target)); Name, TypeManager.CSharpName (target));
@ -4031,10 +4060,15 @@ namespace Mono.CSharp {
Arguments orig_args = arguments; Arguments orig_args = arguments;
if (arg_count != param_count) { if (arg_count != param_count) {
for (int i = 0; i < pd.Count; ++i) { //
if (pd.FixedParameters[i].HasDefaultValue) { // No arguments expansion when doing exact match for delegates
optional_count = pd.Count - i; //
break; if ((restrictions & Restrictions.CovariantDelegate) == 0) {
for (int i = 0; i < pd.Count; ++i) {
if (pd.FixedParameters[i].HasDefaultValue) {
optional_count = pd.Count - i;
break;
}
} }
} }
@ -4210,7 +4244,8 @@ namespace Mono.CSharp {
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Argument a = arguments[i]; Argument a = arguments[i];
if (a == null) { if (a == null) {
if (!pd.FixedParameters[i].HasDefaultValue) { var fp = pd.FixedParameters[i];
if (!fp.HasDefaultValue) {
arguments = orig_args; arguments = orig_args;
return arg_count * 2 + 2; return arg_count * 2 + 2;
} }
@ -4219,7 +4254,7 @@ namespace Mono.CSharp {
// Get the default value expression, we can use the same expression // Get the default value expression, we can use the same expression
// if the type matches // if the type matches
// //
Expression e = pd.FixedParameters[i].DefaultValue; Expression e = fp.DefaultValue;
if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric || e.Type.IsGenericParameter) { if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric || e.Type.IsGenericParameter) {
// //
// LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
@ -4234,6 +4269,19 @@ namespace Mono.CSharp {
e = e.Resolve (ec); e = e.Resolve (ec);
} }
if ((fp.ModFlags & Parameter.Modifier.CallerMask) != 0) {
//
// LAMESPEC: Attributes can be mixed together with build-in priority
//
if ((fp.ModFlags & Parameter.Modifier.CallerLineNumber) != 0) {
e = new IntLiteral (ec.BuiltinTypes, loc.Row, loc);
} else if ((fp.ModFlags & Parameter.Modifier.CallerFilePath) != 0) {
e = new StringLiteral (ec.BuiltinTypes, loc.NameFullPath, loc);
} else if (ec.MemberContext.CurrentMemberDefinition != null) {
e = new StringLiteral (ec.BuiltinTypes, ec.MemberContext.CurrentMemberDefinition.GetCallerMemberName (), loc);
}
}
arguments[i] = new Argument (e, Argument.AType.Default); arguments[i] = new Argument (e, Argument.AType.Default);
continue; continue;
} }
@ -4264,7 +4312,7 @@ namespace Mono.CSharp {
continue; continue;
} }
} else { } else {
score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt); score = IsArgumentCompatible (ec, a, p_mod, pt);
if (score < 0) if (score < 0)
dynamicArgument = true; dynamicArgument = true;
@ -4325,7 +4373,7 @@ namespace Mono.CSharp {
// Types have to be identical when ref or out modifer // Types have to be identical when ref or out modifer
// is used and argument is not of dynamic type // is used and argument is not of dynamic type
// //
if ((argument.Modifier | param_mod) != 0) { if (((argument.Modifier | param_mod) & Parameter.Modifier.RefOutMask) != 0) {
if (argument.Type != parameter) { if (argument.Type != parameter) {
// //
// Do full equality check after quick path // Do full equality check after quick path
@ -4334,18 +4382,18 @@ namespace Mono.CSharp {
// //
// Using dynamic for ref/out parameter can still succeed at runtime // Using dynamic for ref/out parameter can still succeed at runtime
// //
if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
return -1; return -1;
return 2; return 2;
} }
} }
if (argument.Modifier != param_mod) { if ((argument.Modifier & Parameter.Modifier.RefOutMask) != (param_mod & Parameter.Modifier.RefOutMask)) {
// //
// Using dynamic for ref/out parameter can still succeed at runtime // Using dynamic for ref/out parameter can still succeed at runtime
// //
if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
return -1; return -1;
return 1; return 1;
@ -4718,9 +4766,12 @@ namespace Mono.CSharp {
if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx)) if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx))
return; return;
if (a.Type == InternalType.ErrorType)
return;
if (a is CollectionElementInitializer.ElementInitializerArgument) { if (a is CollectionElementInitializer.ElementInitializerArgument) {
ec.Report.SymbolRelatedToPreviousError (method); ec.Report.SymbolRelatedToPreviousError (method);
if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) { if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.RefOutMask) != 0) {
ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
TypeManager.CSharpSignature (method)); TypeManager.CSharpSignature (method));
return; return;
@ -4730,7 +4781,7 @@ namespace Mono.CSharp {
} else if (IsDelegateInvoke) { } else if (IsDelegateInvoke) {
ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
DelegateType.GetSignatureForError ()); DelegateType.GetSignatureForError ());
} else if (a.Type != InternalType.ErrorType) { } else {
ec.Report.SymbolRelatedToPreviousError (method); ec.Report.SymbolRelatedToPreviousError (method);
ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
method.GetSignatureForError ()); method.GetSignatureForError ());
@ -4739,15 +4790,14 @@ namespace Mono.CSharp {
Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags; Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags;
string index = (idx + 1).ToString (); string index = (idx + 1).ToString ();
if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^ if (((mod & Parameter.Modifier.RefOutMask) ^ (a.Modifier & Parameter.Modifier.RefOutMask)) != 0) {
(a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) { if ((mod & Parameter.Modifier.RefOutMask) == 0)
if ((mod & Parameter.Modifier.ISBYREF) == 0)
ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier", ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
index, Parameter.GetModifierSignature (a.Modifier)); index, Parameter.GetModifierSignature (a.Modifier));
else else
ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier", ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
index, Parameter.GetModifierSignature (mod)); index, Parameter.GetModifierSignature (mod));
} else if (a.Type != InternalType.ErrorType) { } else {
string p1 = a.GetSignatureForError (); string p1 = a.GetSignatureForError ();
string p2 = TypeManager.CSharpName (paramType); string p2 = TypeManager.CSharpName (paramType);
@ -4876,8 +4926,8 @@ namespace Mono.CSharp {
// //
// Types have to be identical when ref or out modifer is used // Types have to be identical when ref or out modifer is used
// //
if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) { if (((a.Modifier | p_mod) & Parameter.Modifier.RefOutMask) != 0) {
if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier) if ((a.Modifier & Parameter.Modifier.RefOutMask) != (p_mod & Parameter.Modifier.RefOutMask))
break; break;
if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt))
@ -5515,7 +5565,7 @@ namespace Mono.CSharp {
base.EmitSideEffect (ec); base.EmitSideEffect (ec);
} }
public void AddressOf (EmitContext ec, AddressOp mode) public virtual void AddressOf (EmitContext ec, AddressOp mode)
{ {
if ((mode & AddressOp.Store) != 0) if ((mode & AddressOp.Store) != 0)
spec.MemberDefinition.SetIsAssigned (); spec.MemberDefinition.SetIsAssigned ();
@ -5942,10 +5992,11 @@ namespace Mono.CSharp {
Emit (ec, false); Emit (ec, false);
} }
protected override void EmitToFieldSource (EmitContext ec) protected override FieldExpr EmitToFieldSource (EmitContext ec)
{ {
has_await_arguments = true; has_await_arguments = true;
Emit (ec, false); Emit (ec, false);
return null;
} }
public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source);
@ -6249,9 +6300,10 @@ namespace Mono.CSharp {
// //
// Don't capture temporary variables except when using // Don't capture temporary variables except when using
// state machine redirection // state machine redirection and block yields
// //
if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod is StateMachineInitializer && ec.IsVariableCapturingRequired) { if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator &&
ec.CurrentBlock.Explicit.HasYield && ec.IsVariableCapturingRequired) {
AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec); AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
storey.CaptureLocalVariable (ec, li); storey.CaptureLocalVariable (ec, li);
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs

@ -162,9 +162,9 @@ namespace Mono.CSharp {
Modifiers.INTERNAL | Modifiers.INTERNAL |
Modifiers.PRIVATE; Modifiers.PRIVATE;
readonly TypeExpr underlying_type_expr; readonly FullNamedExpression underlying_type_expr;
public Enum (TypeContainer parent, TypeExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
: base (parent, name, attrs, MemberKind.Enum) : base (parent, name, attrs, MemberKind.Enum)
{ {
underlying_type_expr = type; underlying_type_expr = type;
@ -181,7 +181,7 @@ namespace Mono.CSharp {
} }
} }
public TypeExpr BaseTypeExpression { public FullNamedExpression BaseTypeExpression {
get { get {
return underlying_type_expr; return underlying_type_expr;
} }

136
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs

@ -103,7 +103,12 @@ namespace Mono.CSharp
protected override Expression DoResolve (ResolveContext ec) protected override Expression DoResolve (ResolveContext ec)
{ {
return expr.Resolve (ec); var res = expr.Resolve (ec);
var constant = res as Constant;
if (constant != null && constant.IsLiteral)
return Constant.CreateConstantFromValue (res.Type, constant.GetValue (), expr.Location);
return res;
} }
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@ -142,10 +147,12 @@ namespace Mono.CSharp
// This routine will attempt to simplify the unary expression when the // This routine will attempt to simplify the unary expression when the
// argument is a constant. // argument is a constant.
// </summary> // </summary>
Constant TryReduceConstant (ResolveContext ec, Constant e) Constant TryReduceConstant (ResolveContext ec, Constant constant)
{ {
if (e is EmptyConstantCast) var e = constant;
return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
while (e is EmptyConstantCast)
e = ((EmptyConstantCast) e).child;
if (e is SideEffectConstant) { if (e is SideEffectConstant) {
Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value); Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
@ -220,7 +227,7 @@ namespace Mono.CSharp
return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location); return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location);
case BuiltinTypeSpec.Type.UInt: case BuiltinTypeSpec.Type.UInt:
UIntLiteral uil = e as UIntLiteral; UIntLiteral uil = constant as UIntLiteral;
if (uil != null) { if (uil != null) {
if (uil.Value == int.MaxValue + (uint) 1) if (uil.Value == int.MaxValue + (uint) 1)
return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location); return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location);
@ -230,13 +237,13 @@ namespace Mono.CSharp
case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.ULong:
ULongLiteral ull = e as ULongLiteral; ULongLiteral ull = constant as ULongLiteral;
if (ull != null && ull.Value == 9223372036854775808) if (ull != null && ull.Value == 9223372036854775808)
return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location); return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location);
return null; return null;
case BuiltinTypeSpec.Type.Float: case BuiltinTypeSpec.Type.Float:
FloatLiteral fl = e as FloatLiteral; FloatLiteral fl = constant as FloatLiteral;
// For better error reporting // For better error reporting
if (fl != null) if (fl != null)
return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location); return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location);
@ -244,7 +251,7 @@ namespace Mono.CSharp
return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location); return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location);
case BuiltinTypeSpec.Type.Double: case BuiltinTypeSpec.Type.Double:
DoubleLiteral dl = e as DoubleLiteral; DoubleLiteral dl = constant as DoubleLiteral;
// For better error reporting // For better error reporting
if (dl != null) if (dl != null)
return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location); return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location);
@ -1687,19 +1694,19 @@ namespace Mono.CSharp
return null; return null;
} }
eclass = ExprClass.Value; if (type.IsPointer && !ec.IsUnsafe) {
UnsafeError (ec, loc);
}
eclass = ExprClass.Value;
Constant c = expr as Constant; Constant c = expr as Constant;
if (c != null) { if (c != null) {
c = c.TryReduce (ec, type, loc); c = c.TryReduce (ec, type);
if (c != null) if (c != null)
return c; return c;
} }
if (type.IsPointer && !ec.IsUnsafe) {
UnsafeError (ec, loc);
}
var res = Convert.ExplicitConversion (ec, expr, type, loc); var res = Convert.ExplicitConversion (ec, expr, type, loc);
if (res == expr) if (res == expr)
return EmptyCast.Create (res, type); return EmptyCast.Create (res, type);
@ -2654,7 +2661,7 @@ namespace Mono.CSharp
return left; return left;
if (left.IsZeroInteger) if (left.IsZeroInteger)
return left.TryReduce (ec, right.Type, loc); return left.TryReduce (ec, right.Type);
break; break;
@ -3929,6 +3936,27 @@ namespace Mono.CSharp
} }
} }
public override Expression EmitToField (EmitContext ec)
{
if ((oper & Operator.LogicalMask) == 0) {
var await_expr = left as Await;
if (await_expr != null && right.IsSideEffectFree) {
await_expr.Statement.EmitPrologue (ec);
left = await_expr.Statement.GetResultExpression (ec);
return this;
}
await_expr = right as Await;
if (await_expr != null && left.IsSideEffectFree) {
await_expr.Statement.EmitPrologue (ec);
right = await_expr.Statement.GetResultExpression (ec);
return this;
}
}
return base.EmitToField (ec);
}
protected override void CloneTo (CloneContext clonectx, Expression t) protected override void CloneTo (CloneContext clonectx, Expression t)
{ {
Binary target = (Binary) t; Binary target = (Binary) t;
@ -4245,7 +4273,7 @@ namespace Mono.CSharp
// //
bool right_contains_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments[1].Expr.ContainsEmitWithAwait (); bool right_contains_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments[1].Expr.ContainsEmitWithAwait ();
if (right_contains_await) { if (right_contains_await) {
arguments[0] = arguments[0].EmitToField (ec); arguments[0] = arguments[0].EmitToField (ec, false);
arguments[0].Expr.Emit (ec); arguments[0].Expr.Emit (ec);
} else { } else {
arguments[0].Expr.Emit (ec); arguments[0].Expr.Emit (ec);
@ -4476,7 +4504,7 @@ namespace Mono.CSharp
// //
converted = GetOperatorTrue (ec, expr, loc); converted = GetOperatorTrue (ec, expr, loc);
if (converted == null) { if (converted == null) {
expr.Error_ValueCannotBeConverted (ec, loc, type, false); expr.Error_ValueCannotBeConverted (ec, type, false);
return null; return null;
} }
@ -4961,22 +4989,25 @@ namespace Mono.CSharp
return this; return this;
} }
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) public override Expression DoResolveLValue (ResolveContext ec, Expression rhs)
{ {
// is out param //
if (right_side == EmptyExpression.OutAccess) // Don't be too pedantic when variable is used as out param or for some broken code
// which uses property/indexer access to run some initialization
//
if (rhs == EmptyExpression.OutAccess || rhs.eclass == ExprClass.PropertyAccess || rhs.eclass == ExprClass.IndexerAccess)
local_info.SetIsUsed (); local_info.SetIsUsed ();
if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) { if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) {
int code; int code;
string msg; string msg;
if (right_side == EmptyExpression.OutAccess) { if (rhs == EmptyExpression.OutAccess) {
code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'"; code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
} else if (right_side == EmptyExpression.LValueMemberAccess) { } else if (rhs == EmptyExpression.LValueMemberAccess) {
code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'"; code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
} else if (right_side == EmptyExpression.LValueMemberOutAccess) { } else if (rhs == EmptyExpression.LValueMemberOutAccess) {
code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'"; code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
} else if (right_side == EmptyExpression.UnaryAddress) { } else if (rhs == EmptyExpression.UnaryAddress) {
code = 459; msg = "Cannot take the address of {1} `{0}'"; code = 459; msg = "Cannot take the address of {1} `{0}'";
} else { } else {
code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'"; code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
@ -4989,7 +5020,7 @@ namespace Mono.CSharp
if (eclass == ExprClass.Unresolved) if (eclass == ExprClass.Unresolved)
DoResolveBase (ec); DoResolveBase (ec);
return base.DoResolveLValue (ec, right_side); return base.DoResolveLValue (ec, rhs);
} }
public override int GetHashCode () public override int GetHashCode ()
@ -5052,11 +5083,11 @@ namespace Mono.CSharp
} }
public override bool IsRef { public override bool IsRef {
get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; } get { return (pi.Parameter.ModFlags & Parameter.Modifier.RefOutMask) != 0; }
} }
bool HasOutModifier { bool HasOutModifier {
get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; } get { return (pi.Parameter.ModFlags & Parameter.Modifier.OUT) != 0; }
} }
public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
@ -5138,7 +5169,7 @@ namespace Mono.CSharp
if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) { if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) {
AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec); AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec);
storey.CaptureParameter (ec, this); storey.CaptureParameter (ec, pi, this);
} }
} }
@ -5249,6 +5280,12 @@ namespace Mono.CSharp
return expr; return expr;
} }
} }
public MethodGroupExpr MethodGroup {
get {
return mg;
}
}
#endregion #endregion
protected override void CloneTo (CloneContext clonectx, Expression t) protected override void CloneTo (CloneContext clonectx, Expression t)
@ -6627,6 +6664,11 @@ namespace Mono.CSharp
} }
public override void Emit (EmitContext ec) public override void Emit (EmitContext ec)
{
EmitToFieldSource (ec);
}
protected sealed override FieldExpr EmitToFieldSource (EmitContext ec)
{ {
if (first_emit != null) { if (first_emit != null) {
first_emit.Emit (ec); first_emit.Emit (ec);
@ -6646,7 +6688,7 @@ namespace Mono.CSharp
ec.EmitArrayNew ((ArrayContainer) type); ec.EmitArrayNew ((ArrayContainer) type);
if (initializers == null) if (initializers == null)
return; return await_stack_field;
if (await_stack_field != null) if (await_stack_field != null)
await_stack_field.EmitAssignFromStack (ec); await_stack_field.EmitAssignFromStack (ec);
@ -6671,11 +6713,10 @@ namespace Mono.CSharp
EmitDynamicInitializers (ec, true, await_stack_field); EmitDynamicInitializers (ec, true, await_stack_field);
} }
if (await_stack_field != null)
await_stack_field.Emit (ec);
if (first_emit_temp != null) if (first_emit_temp != null)
first_emit_temp.Release (ec); first_emit_temp.Release (ec);
return await_stack_field;
} }
public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
@ -6974,15 +7015,7 @@ namespace Mono.CSharp
return null; return null;
AnonymousMethodStorey storey = ae.Storey; AnonymousMethodStorey storey = ae.Storey;
while (storey != null) { return storey != null ? storey.HoistedThis : null;
AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey;
if (temp == null)
return storey.HoistedThis;
storey = temp;
}
return null;
} }
public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous) public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous)
@ -7011,11 +7044,20 @@ namespace Mono.CSharp
var block = ec.CurrentBlock; var block = ec.CurrentBlock;
if (block != null) { if (block != null) {
if (block.ParametersBlock.TopBlock.ThisVariable != null) var top = block.ParametersBlock.TopBlock;
variable_info = block.ParametersBlock.TopBlock.ThisVariable.VariableInfo; if (top.ThisVariable != null)
variable_info = top.ThisVariable.VariableInfo;
AnonymousExpression am = ec.CurrentAnonymousMethod; AnonymousExpression am = ec.CurrentAnonymousMethod;
if (am != null && ec.IsVariableCapturingRequired) { if (am != null && ec.IsVariableCapturingRequired && !block.Explicit.HasCapturedThis) {
//
// Hoisted this is almost like hoisted variable but not exactly. When
// there is no variable hoisted we can simply emit an instance method
// without lifting this into a storey. Unfotunatelly this complicates
// this in other cases because we don't know where this will be hoisted
// until top-level block is fully resolved
//
top.AddThisReferenceFromChildrenBlock (block.Explicit);
am.SetHasThisAccess (); am.SetHasThisAccess ();
} }
} }
@ -9248,11 +9290,15 @@ namespace Mono.CSharp
return this; return this;
} }
public override void Error_ValueAssignment (ResolveContext rc, Expression rhs)
{
}
public override void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc) public override void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
{ {
} }
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs

@ -232,7 +232,7 @@ namespace Mono.CSharp
{ {
if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder); Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder);
} else if (!(Parent is CompilerGeneratedClass) && member_type.HasDynamicElement) { } else if (!Parent.IsCompilerGenerated && member_type.HasDynamicElement) {
Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location); Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
} }

152
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs

@ -11,10 +11,6 @@
// Copyright 2011 Xamarin Inc. // Copyright 2011 Xamarin Inc.
// //
// TODO:
// Flow analysis for Yield.
//
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.CompilerServices.SymbolWriter; using Mono.CompilerServices.SymbolWriter;
@ -160,9 +156,10 @@ namespace Mono.CSharp
Field pc_field; Field pc_field;
StateMachineMethod method; StateMachineMethod method;
int local_name_idx;
protected StateMachine (Block block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name) protected StateMachine (ParametersBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind)
: base (block, parent, host, tparams, name) : base (block, parent, host, tparams, name, kind)
{ {
} }
@ -197,6 +194,14 @@ namespace Mono.CSharp
return base.DoDefineMembers (); return base.DoDefineMembers ();
} }
protected override string GetVariableMangledName (LocalVariable local_info)
{
if (local_info.IsCompilerGenerated)
return base.GetVariableMangledName (local_info);
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
} }
class IteratorStorey : StateMachine class IteratorStorey : StateMachine
@ -399,17 +404,13 @@ namespace Mono.CSharp
TypeExpr iterator_type_expr; TypeExpr iterator_type_expr;
Field current_field; Field current_field;
Field disposing_field; Field disposing_field;
int local_name_idx;
TypeExpr enumerator_type; TypeSpec generic_enumerator_type;
TypeExpr enumerable_type; TypeSpec generic_enumerable_type;
TypeArguments generic_args;
TypeExpr generic_enumerator_type;
TypeExpr generic_enumerable_type;
public IteratorStorey (Iterator iterator) public IteratorStorey (Iterator iterator)
: base (iterator.Container.ParametersBlock, iterator.Host, : base (iterator.Container.ParametersBlock, iterator.Host,
iterator.OriginalMethod as MemberBase, iterator.OriginalMethod.CurrentTypeParameters, "Iterator") iterator.OriginalMethod as MemberBase, iterator.OriginalMethod.CurrentTypeParameters, "Iterator", MemberKind.Class)
{ {
this.Iterator = iterator; this.Iterator = iterator;
} }
@ -437,33 +438,30 @@ namespace Mono.CSharp
mtype = Mutator.Mutate (mtype); mtype = Mutator.Mutate (mtype);
iterator_type_expr = new TypeExpression (mtype, Location); iterator_type_expr = new TypeExpression (mtype, Location);
generic_args = new TypeArguments (iterator_type_expr);
var list = new List<FullNamedExpression> (); var ifaces = new List<TypeSpec> (5);
if (Iterator.IsEnumerable) { if (Iterator.IsEnumerable) {
enumerable_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerable, Location); ifaces.Add (Compiler.BuiltinTypes.IEnumerable);
list.Add (enumerable_type);
if (Module.PredefinedTypes.IEnumerableGeneric.Define ()) { if (Module.PredefinedTypes.IEnumerableGeneric.Define ()) {
generic_enumerable_type = new GenericTypeExpr (Module.PredefinedTypes.IEnumerableGeneric.TypeSpec, generic_args, Location); generic_enumerable_type = Module.PredefinedTypes.IEnumerableGeneric.TypeSpec.MakeGenericType (Module, new[] { mtype });
list.Add (generic_enumerable_type); ifaces.Add (generic_enumerable_type);
} }
} }
enumerator_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerator, Location); ifaces.Add (Compiler.BuiltinTypes.IEnumerator);
list.Add (enumerator_type); ifaces.Add (Compiler.BuiltinTypes.IDisposable);
list.Add (new TypeExpression (Compiler.BuiltinTypes.IDisposable, Location));
var ienumerator_generic = Module.PredefinedTypes.IEnumeratorGeneric; var ienumerator_generic = Module.PredefinedTypes.IEnumeratorGeneric;
if (ienumerator_generic.Define ()) { if (ienumerator_generic.Define ()) {
generic_enumerator_type = new GenericTypeExpr (ienumerator_generic.TypeSpec, generic_args, Location); generic_enumerator_type = ienumerator_generic.TypeSpec.MakeGenericType (Module, new [] { mtype });
list.Add (generic_enumerator_type); ifaces.Add (generic_enumerator_type);
} }
type_bases = list; base_class = null;
return base.ResolveBaseTypes (out base_class); base_type = Compiler.BuiltinTypes.Object;
return ifaces.ToArray ();
} }
protected override bool DoDefineMembers () protected override bool DoDefineMembers ()
@ -497,20 +495,20 @@ namespace Mono.CSharp
var name = new MemberName ("GetEnumerator", null, explicit_iface, Location.Null); var name = new MemberName ("GetEnumerator", null, explicit_iface, Location.Null);
if (generic_enumerator_type != null) { if (generic_enumerator_type != null) {
explicit_iface = new GenericTypeExpr (Module.PredefinedTypes.IEnumerableGeneric.Resolve (), generic_args, Location); explicit_iface = new TypeExpression (generic_enumerable_type, Location);
var gname = new MemberName ("GetEnumerator", null, explicit_iface, Location.Null); var gname = new MemberName ("GetEnumerator", null, explicit_iface, Location.Null);
Method gget_enumerator = GetEnumeratorMethod.Create (this, generic_enumerator_type, gname); Method gget_enumerator = GetEnumeratorMethod.Create (this, new TypeExpression (generic_enumerator_type, Location), gname);
// //
// Just call generic GetEnumerator implementation // Just call generic GetEnumerator implementation
// //
var stmt = new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), null), Location); var stmt = new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), null), Location);
Method get_enumerator = GetEnumeratorMethod.Create (this, enumerator_type, name, stmt); Method get_enumerator = GetEnumeratorMethod.Create (this, new TypeExpression (Compiler.BuiltinTypes.IEnumerator, Location), name, stmt);
Members.Add (get_enumerator); Members.Add (get_enumerator);
Members.Add (gget_enumerator); Members.Add (gget_enumerator);
} else { } else {
Members.Add (GetEnumeratorMethod.Create (this, enumerator_type, name)); Members.Add (GetEnumeratorMethod.Create (this, new TypeExpression (Compiler.BuiltinTypes.IEnumerator, Location), name));
} }
} }
@ -523,7 +521,7 @@ namespace Mono.CSharp
FullNamedExpression explicit_iface; FullNamedExpression explicit_iface;
if (is_generic) { if (is_generic) {
explicit_iface = new GenericTypeExpr (Module.PredefinedTypes.IEnumeratorGeneric.Resolve (), generic_args, Location); explicit_iface = new TypeExpression (generic_enumerator_type, Location);
type = iterator_type_expr; type = iterator_type_expr;
} else { } else {
explicit_iface = new TypeExpression (Module.Compiler.BuiltinTypes.IEnumerator, Location); explicit_iface = new TypeExpression (Module.Compiler.BuiltinTypes.IEnumerator, Location);
@ -564,16 +562,11 @@ namespace Mono.CSharp
reset.Block.AddStatement (new Throw (new New (new TypeExpression (ex_type, Location), null, Location), Location)); reset.Block.AddStatement (new Throw (new New (new TypeExpression (ex_type, Location), null, Location), Location));
} }
protected override void EmitHoistedParameters (EmitContext ec, IList<HoistedParameter> hoisted) protected override void EmitHoistedParameters (EmitContext ec, List<HoistedParameter> hoisted)
{ {
base.EmitHoistedParameters (ec, hoisted); base.EmitHoistedParameters (ec, hoisted);
base.EmitHoistedParameters (ec, hoisted_params_copy); base.EmitHoistedParameters (ec, hoisted_params_copy);
} }
protected override string GetVariableMangledName (LocalVariable local_info)
{
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
} }
public class StateMachineMethod : Method public class StateMachineMethod : Method
@ -705,8 +698,6 @@ namespace Mono.CSharp
protected override Expression DoResolve (ResolveContext ec) protected override Expression DoResolve (ResolveContext ec)
{ {
storey = (StateMachine) block.Parent.ParametersBlock.AnonymousMethodStorey;
var ctx = CreateBlockContext (ec); var ctx = CreateBlockContext (ec);
Block.Resolve (ctx); Block.Resolve (ctx);
@ -733,7 +724,7 @@ namespace Mono.CSharp
public override void Emit (EmitContext ec) public override void Emit (EmitContext ec)
{ {
// //
// Load Iterator storey instance // Load state machine instance
// //
storey.Instance.Emit (ec); storey.Instance.Emit (ec);
} }
@ -752,11 +743,7 @@ namespace Mono.CSharp
iterator_body_end = ec.DefineLabel (); iterator_body_end = ec.DefineLabel ();
if (ec.EmitAccurateDebugInfo && ec.Mark (Block.Original.StartLocation)) { block.EmitEmbedded (ec);
ec.Emit (OpCodes.Nop);
}
block.Emit (ec);
ec.MarkLabel (iterator_body_end); ec.MarkLabel (iterator_body_end);
@ -819,11 +806,7 @@ namespace Mono.CSharp
iterator_body_end = ec.DefineLabel (); iterator_body_end = ec.DefineLabel ();
if (ec.EmitAccurateDebugInfo && ec.Mark (Block.Original.StartLocation)) { block.EmitEmbedded (ec);
ec.Emit (OpCodes.Nop);
}
block.Emit (ec);
ec.MarkLabel (iterator_body_end); ec.MarkLabel (iterator_body_end);
@ -908,16 +891,51 @@ namespace Mono.CSharp
ec.Emit (OpCodes.Stloc, skip_finally); ec.Emit (OpCodes.Stloc, skip_finally);
} }
} }
public void SetStateMachine (StateMachine stateMachine)
{
this.storey = stateMachine;
}
} }
// //
// Iterators are implemented as hidden anonymous block // Iterators are implemented as state machine blocks
// //
public class Iterator : StateMachineInitializer public class Iterator : StateMachineInitializer
{ {
sealed class TryFinallyBlockProxyStatement : Statement
{
TryFinallyBlock block;
Iterator iterator;
public TryFinallyBlockProxyStatement (Iterator iterator, TryFinallyBlock block)
{
this.iterator = iterator;
this.block = block;
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
throw new NotSupportedException ();
}
protected override void DoEmit (EmitContext ec)
{
//
// Restore redirection for any captured variables
//
ec.CurrentAnonymousMethod = iterator;
using (ec.With (BuilderContext.Options.OmitDebugInfo, !ec.HasMethodSymbolBuilder)) {
block.EmitFinallyBody (ec);
}
}
}
public readonly IMethodData OriginalMethod; public readonly IMethodData OriginalMethod;
public readonly bool IsEnumerable; public readonly bool IsEnumerable;
public readonly TypeSpec OriginalIteratorType; public readonly TypeSpec OriginalIteratorType;
int finally_hosts_counter;
public Iterator (ParametersBlock block, IMethodData method, TypeDefinition host, TypeSpec iterator_type, bool is_enumerable) public Iterator (ParametersBlock block, IMethodData method, TypeDefinition host, TypeSpec iterator_type, bool is_enumerable)
: base (block, host, host.Compiler.BuiltinTypes.Bool) : base (block, host, host.Compiler.BuiltinTypes.Bool)
@ -928,7 +946,9 @@ namespace Mono.CSharp
this.type = method.ReturnType; this.type = method.ReturnType;
} }
public Block Container { #region Properties
public ToplevelBlock Container {
get { return OriginalMethod.Block; } get { return OriginalMethod.Block; }
} }
@ -940,6 +960,22 @@ namespace Mono.CSharp
get { return true; } get { return true; }
} }
#endregion
public Method CreateFinallyHost (TryFinallyBlock block)
{
var method = new Method (storey, new TypeExpression (storey.Compiler.BuiltinTypes.Void, loc),
Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, null, "Finally", finally_hosts_counter++), loc),
ParametersCompiled.EmptyReadOnlyParameters, null);
method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc);
method.Block.IsCompilerGenerated = true;
method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
storey.AddMember (method);
return method;
}
public void EmitYieldBreak (EmitContext ec, bool unwind_protect) public void EmitYieldBreak (EmitContext ec, bool unwind_protect)
{ {
ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error);
@ -975,11 +1011,13 @@ namespace Mono.CSharp
public void EmitDispose (EmitContext ec) public void EmitDispose (EmitContext ec)
{ {
if (resume_points == null)
return;
Label end = ec.DefineLabel (); Label end = ec.DefineLabel ();
Label[] labels = null; Label[] labels = null;
int n_resume_points = resume_points == null ? 0 : resume_points.Count; for (int i = 0; i < resume_points.Count; ++i) {
for (int i = 0; i < n_resume_points; ++i) {
ResumableStatement s = resume_points[i]; ResumableStatement s = resume_points[i];
Label ret = s.PrepareForDispose (ec, end); Label ret = s.PrepareForDispose (ec, end);
if (ret.Equals (end) && labels == null) if (ret.Equals (end) && labels == null)
@ -1069,7 +1107,7 @@ namespace Mono.CSharp
for (int i = 0; i < parameters.Count; i++) { for (int i = 0; i < parameters.Count; i++) {
Parameter p = parameters [i]; Parameter p = parameters [i];
Parameter.Modifier mod = p.ModFlags; Parameter.Modifier mod = p.ModFlags;
if ((mod & Parameter.Modifier.ISBYREF) != 0) { if ((mod & Parameter.Modifier.RefOutMask) != 0) {
parent.Compiler.Report.Error (1623, p.Location, parent.Compiler.Report.Error (1623, p.Location,
"Iterators cannot have ref or out parameters"); "Iterators cannot have ref or out parameters");
return; return;
@ -1092,7 +1130,7 @@ namespace Mono.CSharp
parent.Compiler.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators"); parent.Compiler.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators");
} }
method.Block.WrapIntoIterator (method, parent, iterator_type, is_enumerable); method.Block = method.Block.ConvertToIterator (method, parent, iterator_type, is_enumerable);
} }
static bool CheckType (TypeSpec ret, TypeContainer parent, out TypeSpec original_iterator_type, out bool is_enumerable) static bool CheckType (TypeSpec ret, TypeContainer parent, out TypeSpec original_iterator_type, out bool is_enumerable)

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs

@ -81,7 +81,7 @@ namespace Mono.CSharp {
TypeSpec [] ptypes = new TypeSpec [Parameters.Count]; TypeSpec [] ptypes = new TypeSpec [Parameters.Count];
for (int i = 0; i < d_params.Count; i++) { for (int i = 0; i < d_params.Count; i++) {
// D has no ref or out parameters // D has no ref or out parameters
if ((d_params.FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) != 0) if ((d_params.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
return null; return null;
TypeSpec d_param = d_params.Types [i]; TypeSpec d_param = d_params.Types [i];
@ -191,7 +191,7 @@ namespace Mono.CSharp {
return Expr.CreateExpressionTree (ec); return Expr.CreateExpressionTree (ec);
} }
public override void Emit (EmitContext ec) protected override void DoEmit (EmitContext ec)
{ {
if (statement != null) { if (statement != null) {
statement.EmitStatement (ec); statement.EmitStatement (ec);
@ -203,7 +203,7 @@ namespace Mono.CSharp {
return; return;
} }
base.Emit (ec); base.DoEmit (ec);
} }
protected override bool DoResolve (BlockContext ec) protected override bool DoResolve (BlockContext ec)

20
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs

@ -90,6 +90,13 @@ namespace Mono.CSharp.Linq
return rmg; return rmg;
} }
protected override Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
{
ec.Report.Error (1979, loc,
"Query expressions with a source or join sequence of type `dynamic' are not allowed");
return null;
}
#region IErrorHandler Members #region IErrorHandler Members
bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
@ -422,19 +429,6 @@ namespace Mono.CSharp.Linq
public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter) public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
{ {
/*
expr = expr.Resolve (ec);
if (expr == null)
return null;
if (expr.Type == InternalType.Dynamic || expr.Type == TypeManager.void_type) {
ec.Report.Error (1979, expr.Location,
"Query expression with a source or join sequence of type `{0}' is not allowed",
TypeManager.CSharpName (expr.Type));
return null;
}
*/
if (IdentifierType != null) if (IdentifierType != null)
expr = CreateCastExpression (expr); expr = CreateCastExpression (expr);

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs

@ -50,7 +50,7 @@ namespace Mono.CSharp
{ {
} }
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec t, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec t, bool expl)
{ {
if (t.IsGenericParameter) { if (t.IsGenericParameter) {
ec.Report.Error(403, loc, ec.Report.Error(403, loc,
@ -65,7 +65,7 @@ namespace Mono.CSharp
return; return;
} }
base.Error_ValueCannotBeConverted (ec, loc, t, expl); base.Error_ValueCannotBeConverted (ec, t, expl);
} }
public override string GetValueAsLiteral () public override string GetValueAsLiteral ()
@ -253,7 +253,7 @@ namespace Mono.CSharp
{ {
} }
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
{ {
if (target.BuiltinType == BuiltinTypeSpec.Type.Float) { if (target.BuiltinType == BuiltinTypeSpec.Type.Float) {
Error_664 (ec, loc, "float", "f"); Error_664 (ec, loc, "float", "f");
@ -265,7 +265,7 @@ namespace Mono.CSharp
return; return;
} }
base.Error_ValueCannotBeConverted (ec, loc, target, expl); base.Error_ValueCannotBeConverted (ec, target, expl);
} }
static void Error_664 (ResolveContext ec, Location loc, string type, string suffix) static void Error_664 (ResolveContext ec, Location loc, string type, string suffix)

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs

@ -1352,8 +1352,10 @@ namespace Mono.CSharp {
type_a = parameters.Types [ii]; type_a = parameters.Types [ii];
type_b = p_types [ii]; type_b = p_types [ii];
if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) != var a_byref = (pd.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0;
(parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF)) var b_byref = (parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0;
if (a_byref != b_byref)
break; break;
} while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0); } while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0);
@ -1372,7 +1374,9 @@ namespace Mono.CSharp {
// //
if (pd != null && member is MethodCore) { if (pd != null && member is MethodCore) {
ii = method_param_count; ii = method_param_count;
while (ii-- != 0 && parameters.FixedParameters[ii].ModFlags == pd.FixedParameters[ii].ModFlags && while (ii-- != 0 &&
(parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) ==
(pd.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) &&
parameters.ExtensionMethodType == pd.ExtensionMethodType) ; parameters.ExtensionMethodType == pd.ExtensionMethodType) ;
if (ii >= 0) { if (ii >= 0) {

30
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs

@ -19,6 +19,7 @@ using System.Security.Permissions;
using System.Text; using System.Text;
using System.Linq; using System.Linq;
using Mono.CompilerServices.SymbolWriter; using Mono.CompilerServices.SymbolWriter;
using System.Runtime.CompilerServices;
#if NET_2_1 #if NET_2_1
using XmlElement = System.Object; using XmlElement = System.Object;
@ -533,10 +534,13 @@ namespace Mono.CSharp {
} }
if (a.Type == pa.MethodImpl) { if (a.Type == pa.MethodImpl) {
is_external_implementation = a.IsInternalCall (); if ((ModFlags & Modifiers.ASYNC) != 0 && (a.GetMethodImplOptions () & MethodImplOptions.Synchronized) != 0) {
} Report.Error (4015, a.Location, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
GetSignatureForError ());
}
if (a.Type == pa.DllImport) { is_external_implementation = a.IsInternalCall ();
} else if (a.Type == pa.DllImport) {
const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC; const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
if ((ModFlags & extern_static) != extern_static) { if ((ModFlags & extern_static) != extern_static) {
Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'"); Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
@ -633,7 +637,7 @@ namespace Mono.CSharp {
if ((ModFlags & Modifiers.PARTIAL) != 0) { if ((ModFlags & Modifiers.PARTIAL) != 0) {
for (int i = 0; i < parameters.Count; ++i) { for (int i = 0; i < parameters.Count; ++i) {
IParameterData p = parameters.FixedParameters [i]; IParameterData p = parameters.FixedParameters [i];
if (p.ModFlags == Parameter.Modifier.OUT) { if ((p.ModFlags & Parameter.Modifier.OUT) != 0) {
Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier", Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
GetSignatureForError ()); GetSignatureForError ());
} }
@ -888,7 +892,7 @@ namespace Mono.CSharp {
var ac = parameters.Types [0] as ArrayContainer; var ac = parameters.Types [0] as ArrayContainer;
return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String && return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String &&
(parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE; (parameters[0].ModFlags & Parameter.Modifier.RefOutMask) == 0;
} }
public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
@ -936,7 +940,7 @@ namespace Mono.CSharp {
} }
for (int i = 0; i < parameters.Count; ++i) { for (int i = 0; i < parameters.Count; ++i) {
if (parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) { if ((parameters.FixedParameters [i].ModFlags & Parameter.Modifier.OUT) != 0) {
Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ()); Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
return; return;
} }
@ -1192,7 +1196,7 @@ namespace Mono.CSharp {
Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task<T>"); Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task<T>");
} }
AsyncInitializer.Create (this, block, parameters, Parent.PartialContainer, ReturnType, Location); block = (ToplevelBlock) block.ConvertToAsyncTask (this, Parent.PartialContainer, parameters, ReturnType, Location);
ModFlags |= Modifiers.DEBUGGER_HIDDEN; ModFlags |= Modifiers.DEBUGGER_HIDDEN;
} }
} }
@ -1699,6 +1703,11 @@ namespace Mono.CSharp {
return null; return null;
} }
public override string GetCallerMemberName ()
{
return IsStatic ? TypeConstructorName : ConstructorName;
}
public override string GetSignatureForDocumentation () public override string GetSignatureForDocumentation ()
{ {
return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation (); return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation ();
@ -2104,7 +2113,7 @@ namespace Mono.CSharp {
get; get;
set; set;
} }
public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l) public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
: base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters) : base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters)
{ {
@ -2347,6 +2356,11 @@ namespace Mono.CSharp {
return false; return false;
} }
public override string GetCallerMemberName ()
{
return base.GetCallerMemberName ().Substring (prefix.Length);
}
public override string GetSignatureForDocumentation () public override string GetSignatureForDocumentation ()
{ {
// should not be called // should not be called

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/module.cs

@ -36,13 +36,14 @@ namespace Mono.CSharp
// //
// Compiler generated container for static data // Compiler generated container for static data
// //
sealed class StaticDataContainer : CompilerGeneratedClass sealed class StaticDataContainer : CompilerGeneratedContainer
{ {
readonly Dictionary<int, Struct> size_types; readonly Dictionary<int, Struct> size_types;
int fields; int fields;
public StaticDataContainer (ModuleContainer module) public StaticDataContainer (ModuleContainer module)
: base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC) : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null),
Modifiers.STATIC | Modifiers.INTERNAL)
{ {
size_types = new Dictionary<int, Struct> (); size_types = new Dictionary<int, Struct> ();
} }

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs

@ -860,7 +860,7 @@ namespace Mono.CSharp.Nullable
if (lifted_type == null) if (lifted_type == null)
return null; return null;
if (left is UserCast || left is TypeCast) if (left is UserCast || left is EmptyCast || left is OpcodeCast)
left.Type = lifted_type; left.Type = lifted_type;
else else
left = EmptyCast.Create (left, lifted_type); left = EmptyCast.Create (left, lifted_type);
@ -875,7 +875,7 @@ namespace Mono.CSharp.Nullable
if (r is ReducedExpression) if (r is ReducedExpression)
r = ((ReducedExpression) r).OriginalExpression; r = ((ReducedExpression) r).OriginalExpression;
if (r is UserCast || r is TypeCast) if (r is UserCast || r is EmptyCast || r is OpcodeCast)
r.Type = lifted_type; r.Type = lifted_type;
else else
right = EmptyCast.Create (right, lifted_type); right = EmptyCast.Create (right, lifted_type);

126
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs

@ -209,21 +209,23 @@ namespace Mono.CSharp {
[Flags] [Flags]
public enum Modifier : byte { public enum Modifier : byte {
NONE = 0, NONE = 0,
REF = REFMASK | ISBYREF, PARAMS = 1 << 0,
OUT = OUTMASK | ISBYREF, REF = 1 << 1,
PARAMS = 4, OUT = 1 << 2,
// This is a flag which says that it's either REF or OUT. This = 1 << 3,
ISBYREF = 8, CallerMemberName = 1 << 4,
REFMASK = 32, CallerLineNumber = 1 << 5,
OUTMASK = 64, CallerFilePath = 1 << 6,
SignatureMask = REFMASK | OUTMASK,
This = 128 RefOutMask = REF | OUT,
ModifierMask = PARAMS | REF | OUT | This,
CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
} }
static readonly string[] attribute_targets = new string[] { "param" }; static readonly string[] attribute_targets = new string[] { "param" };
FullNamedExpression texpr; FullNamedExpression texpr;
readonly Modifier modFlags; Modifier modFlags;
string name; string name;
Expression default_expr; Expression default_expr;
protected TypeSpec parameter_type; protected TypeSpec parameter_type;
@ -233,7 +235,7 @@ namespace Mono.CSharp {
TemporaryVariableReference expr_tree_variable; TemporaryVariableReference expr_tree_variable;
HoistedVariable hoisted_variant; HoistedParameter hoisted_variant;
public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc) public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
{ {
@ -323,7 +325,7 @@ namespace Mono.CSharp {
return; return;
} }
if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF && if (a.Type == pa.Out && (ModFlags & Modifier.REF) != 0 &&
!OptAttributes.Contains (pa.In)) { !OptAttributes.Contains (pa.In)) {
a.Report.Error (662, a.Location, a.Report.Error (662, a.Location,
"Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither"); "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
@ -332,9 +334,7 @@ namespace Mono.CSharp {
if (a.Type == pa.CLSCompliant) { if (a.Type == pa.CLSCompliant) {
a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead"); a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
} } else if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
if (HasOptionalExpression) { if (HasOptionalExpression) {
a.Report.Error (1745, a.Location, a.Report.Error (1745, a.Location,
"Cannot specify `{0}' attribute on optional parameter `{1}'", "Cannot specify `{0}' attribute on optional parameter `{1}'",
@ -343,6 +343,21 @@ namespace Mono.CSharp {
if (a.Type == pa.DefaultParameterValue) if (a.Type == pa.DefaultParameterValue)
return; return;
} else if (a.Type == pa.CallerMemberNameAttribute) {
if ((modFlags & Modifier.CallerMemberName) == 0) {
a.Report.Error (4022, a.Location,
"The CallerMemberName attribute can only be applied to parameters with default value");
}
} else if (a.Type == pa.CallerLineNumberAttribute) {
if ((modFlags & Modifier.CallerLineNumber) == 0) {
a.Report.Error (4020, a.Location,
"The CallerLineNumber attribute can only be applied to parameters with default value");
}
} else if (a.Type == pa.CallerFilePathAttribute) {
if ((modFlags & Modifier.CallerFilePath) == 0) {
a.Report.Error (4021, a.Location,
"The CallerFilePath attribute can only be applied to parameters with default value");
}
} }
base.ApplyAttributeBuilder (a, ctor, cdata, pa); base.ApplyAttributeBuilder (a, ctor, cdata, pa);
@ -372,15 +387,15 @@ namespace Mono.CSharp {
return null; return null;
this.idx = index; this.idx = index;
if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) { if ((modFlags & Parameter.Modifier.RefOutMask) != 0 && parameter_type.IsSpecialRuntimeType) {
rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
GetSignatureForError ()); GetSignatureForError ());
return null; return null;
} }
TypeManager.CheckTypeVariance (parameter_type, TypeManager.CheckTypeVariance (parameter_type,
(modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant,
rc); rc);
if (parameter_type.IsStatic) { if (parameter_type.IsStatic) {
@ -397,6 +412,54 @@ namespace Mono.CSharp {
return parameter_type; return parameter_type;
} }
void ResolveCallerAttributes (ResolveContext rc)
{
var pa = rc.Module.PredefinedAttributes;
TypeSpec caller_type;
foreach (var attr in attributes.Attrs) {
var atype = attr.ResolveType ();
if (atype == null)
continue;
if (atype == pa.CallerMemberNameAttribute) {
caller_type = rc.BuiltinTypes.String;
if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
rc.Report.Error (4019, attr.Location,
"The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
}
modFlags |= Modifier.CallerMemberName;
continue;
}
if (atype == pa.CallerLineNumberAttribute) {
caller_type = rc.BuiltinTypes.Int;
if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
rc.Report.Error (4017, attr.Location,
"The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
}
modFlags |= Modifier.CallerLineNumber;
continue;
}
if (atype == pa.CallerFilePathAttribute) {
caller_type = rc.BuiltinTypes.String;
if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
rc.Report.Error (4018, attr.Location,
"The CallerFilePath attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
}
modFlags |= Modifier.CallerFilePath;
continue;
}
}
}
public void ResolveDefaultValue (ResolveContext rc) public void ResolveDefaultValue (ResolveContext rc)
{ {
// //
@ -404,14 +467,17 @@ namespace Mono.CSharp {
// //
if (default_expr != null) { if (default_expr != null) {
((DefaultParameterValueExpression)default_expr).Resolve (rc, this); ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
if (attributes != null)
ResolveCallerAttributes (rc);
return; return;
} }
if (attributes == null) if (attributes == null)
return; return;
var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter); var pa = rc.Module.PredefinedAttributes;
var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue); var def_attr = attributes.Search (pa.DefaultParameterValue);
if (def_attr != null) { if (def_attr != null) {
if (def_attr.Resolve () == null) if (def_attr.Resolve () == null)
return; return;
@ -466,6 +532,7 @@ namespace Mono.CSharp {
return; return;
} }
var opt_attr = attributes.Search (pa.OptionalParameter);
if (opt_attr != null) { if (opt_attr != null) {
default_expr = EmptyExpression.MissingValue; default_expr = EmptyExpression.MissingValue;
} }
@ -482,7 +549,7 @@ namespace Mono.CSharp {
// //
// Hoisted parameter variant // Hoisted parameter variant
// //
public HoistedVariable HoistedVariant { public HoistedParameter HoistedVariant {
get { get {
return hoisted_variant; return hoisted_variant;
} }
@ -611,7 +678,7 @@ namespace Mono.CSharp {
public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec) public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
{ {
if ((modFlags & Modifier.ISBYREF) != 0) if ((modFlags & Modifier.RefOutMask) != 0)
ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
@ -636,7 +703,7 @@ namespace Mono.CSharp {
public void EmitAddressOf (EmitContext ec) public void EmitAddressOf (EmitContext ec)
{ {
if ((ModFlags & Modifier.ISBYREF) != 0) { if ((ModFlags & Modifier.RefOutMask) != 0) {
ec.EmitArgumentLoad (idx); ec.EmitArgumentLoad (idx);
} else { } else {
ec.EmitArgumentAddress (idx); ec.EmitArgumentAddress (idx);
@ -701,7 +768,7 @@ namespace Mono.CSharp {
} }
public Parameter.Modifier ModFlags { public Parameter.Modifier ModFlags {
get { return modifiers & ~Parameter.Modifier.This; } get { return modifiers; }
} }
public string Name { public string Name {
@ -750,7 +817,7 @@ namespace Mono.CSharp {
public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags) public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
{ {
return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ? return (modFlags & Parameter.Modifier.OUT) != 0 ?
ParameterAttributes.Out : ParameterAttributes.None; ParameterAttributes.Out : ParameterAttributes.None;
} }
@ -773,7 +840,7 @@ namespace Mono.CSharp {
for (int i = 0; i < types.Length; ++i) { for (int i = 0; i < types.Length; ++i) {
types[i] = Types[i].GetMetaInfo (); types[i] = Types[i].GetMetaInfo ();
if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0) if ((FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == 0)
continue; continue;
// TODO MemberCache: Should go to MetaInfo getter // TODO MemberCache: Should go to MetaInfo getter
@ -808,7 +875,7 @@ namespace Mono.CSharp {
sb.Append (types [i].GetSignatureForDocumentation ()); sb.Append (types [i].GetSignatureForDocumentation ());
if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) if ((parameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
sb.Append ("@"); sb.Append ("@");
} }
sb.Append (")"); sb.Append (")");
@ -1027,8 +1094,7 @@ namespace Mono.CSharp {
var a_type = a.Types[i]; var a_type = a.Types[i];
var b_type = b.Types[i]; var b_type = b.Types[i];
if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) { if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
res |= 1; res |= 1;
continue; continue;

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs

@ -305,11 +305,10 @@ namespace Mono.CSharp {
// //
// First check exact modifiers match // First check exact modifiers match
// //
const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; if ((cp[pi].ModFlags & Parameter.Modifier.RefOutMask) == (tp[pi].ModFlags & Parameter.Modifier.RefOutMask))
if ((cp[pi].ModFlags & ref_out) == (tp[pi].ModFlags & ref_out))
continue; continue;
if ((cp[pi].ModFlags & tp[pi].ModFlags & Parameter.Modifier.ISBYREF) != 0) { if (((cp[pi].ModFlags | tp[pi].ModFlags) & Parameter.Modifier.RefOutMask) == Parameter.Modifier.RefOutMask) {
ref_only_difference = true; ref_only_difference = true;
continue; continue;
} }
@ -557,8 +556,7 @@ namespace Mono.CSharp {
// //
// First check exact ref/out match // First check exact ref/out match
// //
const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out))
continue; continue;
modifiers_match = false; modifiers_match = false;
@ -566,7 +564,7 @@ namespace Mono.CSharp {
// //
// Different in ref/out only // Different in ref/out only
// //
if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) { if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) {
if (similar_candidate == null) { if (similar_candidate == null) {
if (!candidate.IsPublic) if (!candidate.IsPublic)
break; break;

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs

@ -55,7 +55,8 @@ namespace Mono.CSharp {
2002, 2023, 2029, 2002, 2023, 2029,
3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009, 3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
3021, 3022, 3023, 3024, 3026, 3027 3021, 3022, 3023, 3024, 3026, 3027,
4014
}; };
static HashSet<int> AllWarningsHashSet; static HashSet<int> AllWarningsHashSet;

567
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs

File diff suppressed because it is too large Load Diff

153
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs

@ -228,6 +228,9 @@ namespace Mono.CSharp
public readonly PredefinedType Action; public readonly PredefinedType Action;
public readonly PredefinedType Task; public readonly PredefinedType Task;
public readonly PredefinedType TaskGeneric; public readonly PredefinedType TaskGeneric;
public readonly PredefinedType IAsyncStateMachine;
public readonly PredefinedType INotifyCompletion;
public readonly PredefinedType ICriticalNotifyCompletion;
public PredefinedTypes (ModuleContainer module) public PredefinedTypes (ModuleContainer module)
{ {
@ -276,6 +279,9 @@ namespace Mono.CSharp
AsyncTaskMethodBuilderGeneric = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder", 1); AsyncTaskMethodBuilderGeneric = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder", 1);
Task = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task"); Task = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task");
TaskGeneric = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task", 1); TaskGeneric = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task", 1);
IAsyncStateMachine = new PredefinedType (module, MemberKind.Interface, "System.Runtime.CompilerServices", "IAsyncStateMachine");
INotifyCompletion = new PredefinedType (module, MemberKind.Interface, "System.Runtime.CompilerServices", "INotifyCompletion");
ICriticalNotifyCompletion = new PredefinedType (module, MemberKind.Interface, "System.Runtime.CompilerServices", "ICriticalNotifyCompletion");
// //
// Define types which are used for comparison. It does not matter // Define types which are used for comparison. It does not matter
@ -312,16 +318,28 @@ namespace Mono.CSharp
{ {
public readonly PredefinedMember<MethodSpec> ActivatorCreateInstance; public readonly PredefinedMember<MethodSpec> ActivatorCreateInstance;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderCreate; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderCreate;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderStart;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetResult; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetResult;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetException; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetException;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetStateMachine;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderOnCompleted;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderOnCompletedUnsafe;
public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderTask; public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderTask;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericCreate; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericCreate;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericStart;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetResult; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetResult;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetException; public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetException;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetStateMachine;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericOnCompleted;
public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericOnCompletedUnsafe;
public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderGenericTask; public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderGenericTask;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderCreate; public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderCreate;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderStart;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetException; public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetException;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetResult; public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetResult;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetStateMachine;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderOnCompleted;
public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderOnCompletedUnsafe;
public readonly PredefinedMember<MethodSpec> DebuggerBrowsableAttributeCtor; public readonly PredefinedMember<MethodSpec> DebuggerBrowsableAttributeCtor;
public readonly PredefinedMember<MethodSpec> DecimalCtor; public readonly PredefinedMember<MethodSpec> DecimalCtor;
public readonly PredefinedMember<MethodSpec> DecimalCtorInt; public readonly PredefinedMember<MethodSpec> DecimalCtorInt;
@ -363,6 +381,8 @@ namespace Mono.CSharp
var atypes = module.PredefinedAttributes; var atypes = module.PredefinedAttributes;
var btypes = module.Compiler.BuiltinTypes; var btypes = module.Compiler.BuiltinTypes;
var tp = new TypeParameter (0, new MemberName ("T"), null, null, Variance.None);
ActivatorCreateInstance = new PredefinedMember<MethodSpec> (module, types.Activator, ActivatorCreateInstance = new PredefinedMember<MethodSpec> (module, types.Activator,
MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null)); MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null));
@ -372,10 +392,52 @@ namespace Mono.CSharp
AsyncTaskMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder, AsyncTaskMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void));
AsyncTaskMethodBuilderSetStateMachine = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
"SetStateMachine", MemberKind.Method, () => new[] {
types.IAsyncStateMachine.TypeSpec
}, btypes.Void);
AsyncTaskMethodBuilderSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder, AsyncTaskMethodBuilderSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Method ("SetException", 0, MemberFilter.Method ("SetException", 0,
ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void)); ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void));
AsyncTaskMethodBuilderOnCompleted = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Method ("AwaitOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncTaskMethodBuilderOnCompletedUnsafe = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Method ("AwaitUnsafeOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncTaskMethodBuilderStart = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Method ("Start", 1,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
}, false),
btypes.Void));
AsyncTaskMethodBuilderTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilder, AsyncTaskMethodBuilderTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilder,
MemberFilter.Property ("Task", null)); MemberFilter.Property ("Task", null));
@ -385,12 +447,54 @@ namespace Mono.CSharp
AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric, AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
"SetResult", MemberKind.Method, () => new TypeSpec[] { "SetResult", MemberKind.Method, () => new TypeSpec[] {
types.AsyncTaskMethodBuilderGeneric.TypeSpec.MemberDefinition.TypeParameters[0] types.AsyncTaskMethodBuilderGeneric.TypeSpec.MemberDefinition.TypeParameters[0]
}); }, btypes.Void);
AsyncTaskMethodBuilderGenericSetStateMachine = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
"SetStateMachine", MemberKind.Method, () => new[] {
types.IAsyncStateMachine.TypeSpec
}, btypes.Void);
AsyncTaskMethodBuilderGenericSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric, AsyncTaskMethodBuilderGenericSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("SetException", 0, MemberFilter.Method ("SetException", 0,
ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void)); ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void));
AsyncTaskMethodBuilderGenericOnCompleted = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("AwaitOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncTaskMethodBuilderGenericOnCompletedUnsafe = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("AwaitUnsafeOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncTaskMethodBuilderGenericStart = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("Start", 1,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
}, false),
btypes.Void));
AsyncTaskMethodBuilderGenericTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilderGeneric, AsyncTaskMethodBuilderGenericTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Property ("Task", null)); MemberFilter.Property ("Task", null));
@ -403,6 +507,48 @@ namespace Mono.CSharp
AsyncVoidMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder, AsyncVoidMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void));
AsyncVoidMethodBuilderSetStateMachine = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
"SetStateMachine", MemberKind.Method, () => new[] {
types.IAsyncStateMachine.TypeSpec
}, btypes.Void);
AsyncVoidMethodBuilderOnCompleted = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
MemberFilter.Method ("AwaitOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncVoidMethodBuilderOnCompletedUnsafe = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
MemberFilter.Method ("AwaitUnsafeOnCompleted", 2,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
new ParameterData (null, Parameter.Modifier.REF)
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
new TypeParameterSpec (1, tp, SpecialConstraint.None, Variance.None, null)
}, false),
btypes.Void));
AsyncVoidMethodBuilderStart = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
MemberFilter.Method ("Start", 1,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.REF),
},
new[] {
new TypeParameterSpec (0, tp, SpecialConstraint.None, Variance.None, null),
}, false),
btypes.Void));
DebuggerBrowsableAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DebuggerBrowsable, DebuggerBrowsableAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DebuggerBrowsable,
MemberFilter.Constructor (null)); MemberFilter.Constructor (null));
@ -464,7 +610,6 @@ namespace Mono.CSharp
false), false),
btypes.Int)); btypes.Int));
var tp = new TypeParameter(0, new MemberName("T"), null, null, Variance.None);
InterlockedCompareExchange_T = new PredefinedMember<MethodSpec> (module, types.Interlocked, InterlockedCompareExchange_T = new PredefinedMember<MethodSpec> (module, types.Interlocked,
MemberFilter.Method ("CompareExchange", 1, MemberFilter.Method ("CompareExchange", 1,
new ParametersImported ( new ParametersImported (
@ -743,8 +888,8 @@ namespace Mono.CSharp
}; };
} }
public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, Func<TypeSpec[]> typesBuilder) public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, Func<TypeSpec[]> typesBuilder, TypeSpec returnType)
: this (module, type, new MemberFilter (name, 0, kind, null, null)) : this (module, type, new MemberFilter (name, 0, kind, null, returnType))
{ {
filter_builder = typesBuilder; filter_builder = typesBuilder;
} }

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs

@ -1061,8 +1061,7 @@ namespace Mono.CSharp
if (!IsEqual (a.Types[i], b.Types[i])) if (!IsEqual (a.Types[i], b.Types[i]))
return false; return false;
const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
return false; return false;
} }

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs

@ -2,7 +2,7 @@
// visit.cs: Visitors for parsed dom // visit.cs: Visitors for parsed dom
// //
// Authors: Mike Krüger (mkrueger@novell.com) // Authors: Mike Krüger (mkrueger@novell.com)
// Marek Safar (marek.safar@gmail.com) // Marek Safar (marek.safar@gmail.com)
// //
// Dual licensed under the terms of the MIT X11 or GNU GPL // Dual licensed under the terms of the MIT X11 or GNU GPL
// //
@ -26,16 +26,15 @@ namespace Mono.CSharp
foreach (var container in mc.Containers) { foreach (var container in mc.Containers) {
container.Accept (this); container.Accept (this);
} }
} }
void VisitTypeDefinition (TypeDefinition tc) void VisitTypeDefinition (TypeDefinition tc)
{ {
foreach (var container in tc.Members) { foreach (var member in tc.Members) {
container.Accept (this); member.Accept (this);
} }
} }
public virtual void Visit (NamespaceContainer ns) public virtual void Visit (NamespaceContainer ns)
{ {
} }

27
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs

@ -34,12 +34,13 @@ using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using System.ComponentModel.Design; using System.ComponentModel.Design;
using ICSharpCode.NRefactory.CSharp.Analysis;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
public abstract class BaseRefactoringContext : IServiceProvider public abstract class BaseRefactoringContext : IServiceProvider
{ {
protected readonly CSharpAstResolver resolver; readonly CSharpAstResolver resolver;
readonly CancellationToken cancellationToken; readonly CancellationToken cancellationToken;
public virtual bool Supports(Version version) public virtual bool Supports(Version version)
@ -65,6 +66,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
public CSharpAstResolver Resolver {
get {
return resolver;
}
}
public virtual CSharpParsedFile ParsedFile { public virtual CSharpParsedFile ParsedFile {
get { get {
return resolver.ParsedFile; return resolver.ParsedFile;
@ -113,7 +120,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return resolver.GetConversion(expression, cancellationToken); return resolver.GetConversion(expression, cancellationToken);
} }
#endregion #endregion
#region Code Analyzation
/// <summary>
/// Creates a new definite assignment analysis object with a given root statement.
/// </summary>
/// <returns>
/// The definite assignment analysis object.
/// </returns>
/// <param name='root'>
/// The root statement.
/// </param>
public DefiniteAssignmentAnalysis CreateDefiniteAssignmentAnalysis (Statement root)
{
return new DefiniteAssignmentAnalysis (root, resolver, CancellationToken);
}
#endregion
/// <summary> /// <summary>
/// Translates the english input string to the context language. /// Translates the english input string to the context language.
/// </summary> /// </summary>

18
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeAction.cs

@ -27,18 +27,36 @@ using System;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
/// <summary>
/// A code action provides a code transformation with a description.
/// </summary>
public class CodeAction public class CodeAction
{ {
/// <summary>
/// Gets the description.
/// </summary>
public string Description { public string Description {
get; get;
private set; private set;
} }
/// <summary>
/// Gets the code transformation.
/// </summary>
public Action<Script> Run { public Action<Script> Run {
get; get;
private set; private set;
} }
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction"/> class.
/// </summary>
/// <param name='description'>
/// The description.
/// </param>
/// <param name='action'>
/// The code transformation.
/// </param>
public CodeAction (string description, Action<Script> action) public CodeAction (string description, Action<Script> action)
{ {
if (action == null) { if (action == null) {

29
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CheckIfParameterIsNullAction.cs

@ -33,40 +33,25 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// Creates a 'if (param == null) throw new System.ArgumentNullException ();' contruct for a parameter. /// Creates a 'if (param == null) throw new System.ArgumentNullException ();' contruct for a parameter.
/// </summary> /// </summary>
[ContextAction("Check if parameter is null", Description = "Checks function parameter is not null.")] [ContextAction("Check if parameter is null", Description = "Checks function parameter is not null.")]
public class CheckIfParameterIsNullAction : ICodeActionProvider public class CheckIfParameterIsNullAction : SpecializedCodeAction<ParameterDeclaration>
{ {
public IEnumerable<CodeAction> GetActions(RefactoringContext context) protected override CodeAction GetAction(RefactoringContext context, ParameterDeclaration parameter)
{ {
var parameter = GetParameterDeclaration(context);
if (parameter == null) {
yield break;
}
var bodyStatement = parameter.Parent.GetChildByRole(Roles.Body); var bodyStatement = parameter.Parent.GetChildByRole(Roles.Body);
if (bodyStatement == null)
if (bodyStatement == null) { return null;
yield break;
}
var type = context.ResolveType(parameter.Type); var type = context.ResolveType(parameter.Type);
if (type.IsReferenceType == false || HasNullCheck(parameter)) { if (type.IsReferenceType == false || HasNullCheck(parameter))
yield break; return null;
}
yield return new CodeAction (context.TranslateString("Add null check for parameter"), script => { return new CodeAction (context.TranslateString("Add null check for parameter"), script => {
var statement = new IfElseStatement () { var statement = new IfElseStatement () {
Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()), Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()),
TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name))) TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name)))
}; };
script.AddTo(bodyStatement, statement); script.AddTo(bodyStatement, statement);
}); });
} }
static ParameterDeclaration GetParameterDeclaration (RefactoringContext context)
{
return context.GetNode<ICSharpCode.NRefactory.CSharp.ParameterDeclaration> ();
}
static bool HasNullCheck (ParameterDeclaration parameter) static bool HasNullCheck (ParameterDeclaration parameter)
{ {

13
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertDecToHexAction.cs

@ -37,16 +37,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public IEnumerable<CodeAction> GetActions(RefactoringContext context) public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{ {
var pexpr = context.GetNode<PrimitiveExpression>(); var pexpr = context.GetNode<PrimitiveExpression>();
if (pexpr == null || pexpr.LiteralValue.StartsWith("0X", System.StringComparison.OrdinalIgnoreCase)) { if (pexpr == null || pexpr.LiteralValue.StartsWith("0X", System.StringComparison.OrdinalIgnoreCase))
yield break; yield break;
}
if (!((pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) || var value = pexpr.Value;
(pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte))) { if (value is string)
yield break; yield break;
}
yield return new CodeAction(context.TranslateString("Convert dec to hex"), script => { yield return new CodeAction(context.TranslateString("Convert dec to hex"), script => {
script.Replace(pexpr, new PrimitiveExpression (pexpr.Value, string.Format("0x{0:x}", pexpr.Value))); script.Replace(pexpr, new PrimitiveExpression (value, string.Format("0x{0:x}", value)));
}); });
} }
} }

105
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs

@ -27,6 +27,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
@ -71,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var result = node is SimpleType ? var result = node is SimpleType ?
CreateClassFromType(context, (SimpleType)node) : CreateClassFromType(context, (SimpleType)node) :
CreateClassFromObjectCreation(context, (ObjectCreateExpression)node); CreateClassFromObjectCreation(context, (ObjectCreateExpression)node);
return AddBaseTypesAccordingToNamingRules(context, service, result); return AddBaseTypesAccordingToNamingRules(context, service, result);
} }
@ -115,9 +116,109 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}; };
decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, createExpression.Arguments)); decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, createExpression.Arguments));
} }
var guessedType = CreateFieldAction.GuessType(context, createExpression);
if (guessedType.Kind == TypeKind.Interface || guessedType.Kind == TypeKind.Class && guessedType.GetDefinition ().IsAbstract) {
result.BaseTypes.Add(context.CreateShortType(guessedType));
AddImplementation(context, result, guessedType);
}
return result; return result;
} }
static Modifiers GetModifiers(IEntity property)
{
if (property.DeclaringType.Kind == TypeKind.Interface)
return Modifiers.Public;
switch (property.Accessibility) {
case Accessibility.Public:
return Modifiers.Public | Modifiers.Override;
case Accessibility.Protected:
return Modifiers.Protected | Modifiers.Override;
case Accessibility.Internal:
return Modifiers.Internal | Modifiers.Override;
case Accessibility.ProtectedOrInternal:
// TODO: oops
return Modifiers.Internal | Modifiers.Protected | Modifiers.Override;
case Accessibility.ProtectedAndInternal:
// TODO: oops
return Modifiers.Internal | Modifiers.Protected | Modifiers.Override;
}
return Modifiers.Override;
}
static void AddImplementation(RefactoringContext context, TypeDeclaration result, ICSharpCode.NRefactory.TypeSystem.IType guessedType)
{
foreach (var property in guessedType.GetProperties ()) {
if (!property.IsAbstract)
continue;
if (property.IsIndexer) {
var indexerDecl = new IndexerDeclaration() {
ReturnType = context.CreateShortType(property.ReturnType),
Modifiers = GetModifiers(property),
Name = property.Name
};
indexerDecl.Parameters.AddRange(ConvertParameters(context, property.Parameters));
if (property.CanGet)
indexerDecl.Getter = new Accessor();
if (property.CanSet)
indexerDecl.Setter = new Accessor();
result.AddChild(indexerDecl, Roles.TypeMemberRole);
continue;
}
var propDecl = new PropertyDeclaration() {
ReturnType = context.CreateShortType(property.ReturnType),
Modifiers = GetModifiers (property),
Name = property.Name
};
if (property.CanGet)
propDecl.Getter = new Accessor();
if (property.CanSet)
propDecl.Setter = new Accessor();
result.AddChild(propDecl, Roles.TypeMemberRole);
}
foreach (var method in guessedType.GetMethods ()) {
if (!method.IsAbstract)
continue;
var decl = new MethodDeclaration() {
ReturnType = context.CreateShortType(method.ReturnType),
Modifiers = GetModifiers (method),
Name = method.Name,
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
decl.Parameters.AddRange(ConvertParameters(context, method.Parameters));
result.AddChild(decl, Roles.TypeMemberRole);
}
foreach (var evt in guessedType.GetEvents ()) {
if (!evt.IsAbstract)
continue;
var decl = new EventDeclaration() {
ReturnType = context.CreateShortType(evt.ReturnType),
Modifiers = GetModifiers (evt),
Name = evt.Name
};
result.AddChild(decl, Roles.TypeMemberRole);
}
}
static IEnumerable<ParameterDeclaration> ConvertParameters(RefactoringContext context, IList<IParameter> parameters)
{
foreach (var param in parameters) {
ParameterModifier mod = ParameterModifier.None;
if (param.IsOut) {
mod = ParameterModifier.Out;
} else if (param.IsRef) {
mod = ParameterModifier.Ref;
} else if (param.IsParams) {
mod = ParameterModifier.Params;
}
yield return new ParameterDeclaration(context.CreateShortType(param.Type), param.Name, mod);
}
}
static TypeDeclaration AddBaseTypesAccordingToNamingRules(RefactoringContext context, NamingConventionService service, TypeDeclaration result) static TypeDeclaration AddBaseTypesAccordingToNamingRules(RefactoringContext context, NamingConventionService service, TypeDeclaration result)
{ {
if (service.HasValidRule(result.Name, AffectedEntity.CustomAttributes, Modifiers.Public)) { if (service.HasValidRule(result.Name, AffectedEntity.CustomAttributes, Modifiers.Public)) {

52
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs

@ -95,13 +95,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return -1; return -1;
} }
static IEnumerable<IType> GetAllValidTypesFromInvokation(RefactoringContext context, InvocationExpression invoke, AstNode parameter) static IEnumerable<IType> GetAllValidTypesFromInvokation(CSharpAstResolver resolver, InvocationExpression invoke, AstNode parameter)
{ {
int index = GetArgumentIndex(invoke.Arguments, parameter); int index = GetArgumentIndex(invoke.Arguments, parameter);
if (index < 0) if (index < 0)
yield break; yield break;
var targetResult = context.Resolve(invoke.Target); var targetResult = resolver.Resolve(invoke.Target);
if (targetResult is MethodGroupResolveResult) { if (targetResult is MethodGroupResolveResult) {
foreach (var method in ((MethodGroupResolveResult)targetResult).Methods) { foreach (var method in ((MethodGroupResolveResult)targetResult).Methods) {
if (index < method.Parameters.Count) { if (index < method.Parameters.Count) {
@ -111,13 +111,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
static IEnumerable<IType> GetAllValidTypesFromObjectCreation(RefactoringContext context, ObjectCreateExpression invoke, AstNode parameter) static IEnumerable<IType> GetAllValidTypesFromObjectCreation(CSharpAstResolver resolver, ObjectCreateExpression invoke, AstNode parameter)
{ {
int index = GetArgumentIndex(invoke.Arguments, parameter); int index = GetArgumentIndex(invoke.Arguments, parameter);
if (index < 0) if (index < 0)
yield break; yield break;
var targetResult = context.Resolve(invoke.Type); var targetResult = resolver.Resolve(invoke.Type);
if (targetResult is TypeResolveResult) { if (targetResult is TypeResolveResult) {
var type = ((TypeResolveResult)targetResult).Type; var type = ((TypeResolveResult)targetResult).Type;
if (type.Kind == TypeKind.Delegate && index == 0) { if (type.Kind == TypeKind.Delegate && index == 0) {
@ -131,13 +131,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
internal static IEnumerable<IType> GetValidTypes(RefactoringContext context, Expression expr) internal static IEnumerable<IType> GetValidTypes(CSharpAstResolver resolver, Expression expr)
{ {
if (expr.Parent is DirectionExpression) { if (expr.Parent is DirectionExpression) {
var parent = expr.Parent.Parent; var parent = expr.Parent.Parent;
if (parent is InvocationExpression) { if (parent is InvocationExpression) {
var invoke = (InvocationExpression)parent; var invoke = (InvocationExpression)parent;
return GetAllValidTypesFromInvokation(context, invoke, expr.Parent); return GetAllValidTypesFromInvokation(resolver, invoke, expr.Parent);
} }
} }
@ -145,7 +145,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var parent = expr.Parent; var parent = expr.Parent;
if (parent is ObjectCreateExpression) { if (parent is ObjectCreateExpression) {
var invoke = (ObjectCreateExpression)parent; var invoke = (ObjectCreateExpression)parent;
return GetAllValidTypesFromObjectCreation(context, invoke, expr); return GetAllValidTypesFromObjectCreation(resolver, invoke, expr);
} }
} }
@ -153,59 +153,73 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var parent = expr.Parent; var parent = expr.Parent;
if (parent is InvocationExpression) { if (parent is InvocationExpression) {
var invoke = (InvocationExpression)parent; var invoke = (InvocationExpression)parent;
return GetAllValidTypesFromInvokation(context, invoke, expr); return GetAllValidTypesFromInvokation(resolver, invoke, expr);
} }
} }
if (expr.Parent is VariableInitializer) { if (expr.Parent is VariableInitializer) {
var initializer = (VariableInitializer)expr.Parent; var initializer = (VariableInitializer)expr.Parent;
return new [] { context.Resolve(initializer).Type }; return new [] { resolver.Resolve(initializer).Type };
} }
if (expr.Parent is CastExpression) { if (expr.Parent is CastExpression) {
var cast = (CastExpression)expr.Parent; var cast = (CastExpression)expr.Parent;
return new [] { context.Resolve(cast.Type).Type }; return new [] { resolver.Resolve(cast.Type).Type };
} }
if (expr.Parent is AsExpression) { if (expr.Parent is AsExpression) {
var cast = (AsExpression)expr.Parent; var cast = (AsExpression)expr.Parent;
return new [] { context.Resolve(cast.Type).Type }; return new [] { resolver.Resolve(cast.Type).Type };
} }
if (expr.Parent is AssignmentExpression) { if (expr.Parent is AssignmentExpression) {
var assign = (AssignmentExpression)expr.Parent; var assign = (AssignmentExpression)expr.Parent;
var other = assign.Left == expr ? assign.Right : assign.Left; var other = assign.Left == expr ? assign.Right : assign.Left;
return new [] { context.Resolve(other).Type }; return new [] { resolver.Resolve(other).Type };
} }
if (expr.Parent is BinaryOperatorExpression) { if (expr.Parent is BinaryOperatorExpression) {
var assign = (BinaryOperatorExpression)expr.Parent; var assign = (BinaryOperatorExpression)expr.Parent;
var other = assign.Left == expr ? assign.Right : assign.Left; var other = assign.Left == expr ? assign.Right : assign.Left;
return new [] { context.Resolve(other).Type }; return new [] { resolver.Resolve(other).Type };
} }
if (expr.Parent is ReturnStatement) { if (expr.Parent is ReturnStatement) {
var state = context.GetResolverStateBefore(expr); var state = resolver.GetResolverStateBefore(expr);
if (state != null) if (state != null)
return new [] { state.CurrentMember.ReturnType }; return new [] { state.CurrentMember.ReturnType };
} }
if (expr.Parent is YieldReturnStatement) { if (expr.Parent is YieldReturnStatement) {
var state = context.GetResolverStateBefore(expr); var state = resolver.GetResolverStateBefore(expr);
if (state != null && (state.CurrentMember.ReturnType is ParameterizedType)) { if (state != null && (state.CurrentMember.ReturnType is ParameterizedType)) {
var pt = (ParameterizedType)state.CurrentMember.ReturnType; var pt = (ParameterizedType)state.CurrentMember.ReturnType;
if (pt.FullName == "System.Collections.Generic.IEnumerable") { if (pt.FullName == "System.Collections.Generic.IEnumerable") {
return new [] { pt.TypeArguments.First () }; return new [] { pt.TypeArguments.First() };
} }
} }
} }
if (expr.Parent is UnaryOperatorExpression) {
var uop = (UnaryOperatorExpression)expr.Parent;
switch (uop.Operator) {
case UnaryOperatorType.Not:
return new [] { resolver.Compilation.FindType(KnownTypeCode.Boolean) };
case UnaryOperatorType.Minus:
case UnaryOperatorType.Plus:
case UnaryOperatorType.Increment:
case UnaryOperatorType.Decrement:
case UnaryOperatorType.PostIncrement:
case UnaryOperatorType.PostDecrement:
return new [] { resolver.Compilation.FindType(KnownTypeCode.Int32) };
}
}
return Enumerable.Empty<IType>(); return Enumerable.Empty<IType>();
} }
static readonly IType[] emptyTypes = new IType[0]; static readonly IType[] emptyTypes = new IType[0];
internal static AstType GuessAstType(RefactoringContext context, Expression expr) internal static AstType GuessAstType(RefactoringContext context, Expression expr)
{ {
var type = GetValidTypes(context, expr).ToArray(); var type = GetValidTypes(context.Resolver, expr).ToArray();
var typeInference = new TypeInference(context.Compilation); var typeInference = new TypeInference(context.Compilation);
typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults; typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults;
var inferedType = typeInference.FindTypeInBounds(type, emptyTypes); var inferedType = typeInference.FindTypeInBounds(type, emptyTypes);
@ -216,7 +230,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
internal static IType GuessType(RefactoringContext context, Expression expr) internal static IType GuessType(RefactoringContext context, Expression expr)
{ {
var type = GetValidTypes(context, expr).ToArray(); var type = GetValidTypes(context.Resolver, expr).ToArray();
var typeInference = new TypeInference(context.Compilation); var typeInference = new TypeInference(context.Compilation);
typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults; typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults;
var inferedType = typeInference.FindTypeInBounds(type, emptyTypes); var inferedType = typeInference.FindTypeInBounds(type, emptyTypes);

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateIndexerAction.cs

@ -43,6 +43,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield break; yield break;
var state = context.GetResolverStateBefore(indexer); var state = context.GetResolverStateBefore(indexer);
if (state.CurrentTypeDefinition == null)
yield break;
var guessedType = CreateFieldAction.GuessAstType(context, indexer); var guessedType = CreateFieldAction.GuessAstType(context, indexer);
bool createInOtherType = false; bool createInOtherType = false;

136
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs

@ -40,6 +40,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var identifier = context.GetNode<IdentifierExpression>(); var identifier = context.GetNode<IdentifierExpression>();
if (identifier != null && !(identifier.Parent is InvocationExpression && ((InvocationExpression)identifier.Parent).Target == identifier)) if (identifier != null && !(identifier.Parent is InvocationExpression && ((InvocationExpression)identifier.Parent).Target == identifier))
return GetActionsFromIdentifier(context, identifier); return GetActionsFromIdentifier(context, identifier);
var memberReference = context.GetNode<MemberReferenceExpression>();
if (memberReference != null && !(memberReference.Parent is InvocationExpression && ((InvocationExpression)memberReference.Parent).Target == memberReference))
return GetActionsFromMemberReferenceExpression(context, memberReference);
var invocation = context.GetNode<InvocationExpression>(); var invocation = context.GetNode<InvocationExpression>();
if (invocation != null) if (invocation != null)
@ -47,7 +51,54 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return Enumerable.Empty<CodeAction>(); return Enumerable.Empty<CodeAction>();
} }
public IEnumerable<CodeAction> GetActionsFromIdentifier(RefactoringContext context, IdentifierExpression identifier) IEnumerable<CodeAction> GetActionsFromMemberReferenceExpression(RefactoringContext context, MemberReferenceExpression invocation)
{
if (!(context.Resolve(invocation).IsError))
yield break;
var methodName = invocation.MemberName;
var guessedType = CreateFieldAction.GuessType(context, invocation);
if (guessedType.Kind != TypeKind.Delegate)
yield break;
var invocationMethod = guessedType.GetDelegateInvokeMethod();
var state = context.GetResolverStateBefore(invocation);
if (state.CurrentTypeDefinition == null)
yield break;
ResolveResult targetResolveResult = context.Resolve(invocation.Target);
bool createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
bool isStatic;
if (createInOtherType) {
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
isStatic = targetResolveResult is TypeResolveResult;
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface)
yield break;
} else {
if (state.CurrentMember == null)
yield break;
isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
}
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
// if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic)) {
// yield break;
// }
yield return CreateAction(
context,
methodName,
context.CreateShortType(invocationMethod.ReturnType),
invocationMethod.Parameters.Select(parameter => new ParameterDeclaration(context.CreateShortType(parameter.Type), parameter.Name) {
ParameterModifier = GetModifiers(parameter)
}),
createInOtherType,
isStatic,
targetResolveResult);
}
IEnumerable<CodeAction> GetActionsFromIdentifier(RefactoringContext context, IdentifierExpression identifier)
{ {
if (!(context.Resolve(identifier).IsError)) if (!(context.Resolve(identifier).IsError))
yield break; yield break;
@ -65,39 +116,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic)) if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic))
yield break; yield break;
yield return new CodeAction(context.TranslateString("Create delegate handler"), script => { yield return CreateAction(
var decl = new MethodDeclaration() { context,
ReturnType = context.CreateShortType(invocationMethod.ReturnType), methodName,
Name = methodName, context.CreateShortType(invocationMethod.ReturnType),
Body = new BlockStatement() { invocationMethod.Parameters.Select(parameter => new ParameterDeclaration(context.CreateShortType(parameter.Type), parameter.Name) {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"))) ParameterModifier = GetModifiers(parameter)
} }),
}; false,
if (isStatic) isStatic,
decl.Modifiers |= Modifiers.Static; null);
foreach (var parameter in invocationMethod.Parameters) {
decl.Parameters.Add(new ParameterDeclaration(context.CreateShortType (parameter.Type), parameter.Name) {
ParameterModifier = GetModifiers(parameter)
});
}
script.InsertWithCursor(context.TranslateString("Create delegate handler"), decl, Script.InsertPosition.Before);
});
} }
static ParameterModifier GetModifiers(IParameter parameter) IEnumerable<CodeAction> GetActionsFromInvocation(RefactoringContext context, InvocationExpression invocation)
{
if (parameter.IsOut)
return ParameterModifier.Out;
if (parameter.IsRef)
return ParameterModifier.Ref;
if (parameter.IsParams)
return ParameterModifier.Params;
return ParameterModifier.None;
}
public IEnumerable<CodeAction> GetActionsFromInvocation(RefactoringContext context, InvocationExpression invocation)
{ {
if (!(context.Resolve(invocation.Target).IsError)) if (!(context.Resolve(invocation.Target).IsError))
yield break; yield break;
@ -106,6 +137,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (methodName == null) if (methodName == null)
yield break; yield break;
var state = context.GetResolverStateBefore(invocation); var state = context.GetResolverStateBefore(invocation);
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
var guessedType = invocation.Parent is ExpressionStatement ? new PrimitiveType("void") : CreateFieldAction.GuessAstType(context, invocation); var guessedType = invocation.Parent is ExpressionStatement ? new PrimitiveType("void") : CreateFieldAction.GuessAstType(context, invocation);
bool createInOtherType = false; bool createInOtherType = false;
@ -123,8 +156,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface) if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface)
yield break; yield break;
} else { } else {
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic; isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
} }
@ -133,15 +164,40 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// yield break; // yield break;
// } // }
yield return new CodeAction(context.TranslateString("Create method"), script => {
yield return CreateAction(
context,
methodName,
guessedType,
GenerateParameters(context, invocation.Arguments),
createInOtherType,
isStatic,
targetResolveResult);
}
static ParameterModifier GetModifiers(IParameter parameter)
{
if (parameter.IsOut)
return ParameterModifier.Out;
if (parameter.IsRef)
return ParameterModifier.Ref;
if (parameter.IsParams)
return ParameterModifier.Params;
return ParameterModifier.None;
}
static CodeAction CreateAction(RefactoringContext context, string methodName, AstType returnType, IEnumerable<ParameterDeclaration> parameters, bool createInOtherType, bool isStatic, ResolveResult targetResolveResult)
{
return new CodeAction(context.TranslateString("Create method"), script => {
var decl = new MethodDeclaration() { var decl = new MethodDeclaration() {
ReturnType = guessedType, ReturnType = returnType,
Name = methodName, Name = methodName,
Body = new BlockStatement() { Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"))) new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
} }
}; };
decl.Parameters.AddRange(GenerateParameters (context, invocation.Arguments)); decl.Parameters.AddRange(parameters);
if (isStatic) if (isStatic)
decl.Modifiers |= Modifiers.Static; decl.Modifiers |= Modifiers.Static;
@ -267,6 +323,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
case "System.Char": case "System.Char":
return "ch"; return "ch";
case "System.Double":
case "System.Decimal":
return "d";
case "System.Single":
return "f";
case "System.String": case "System.String":
return "str"; return "str";
@ -282,7 +343,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return returnType.Name; return returnType.Name;
} }
string GetMethodName(InvocationExpression invocation) string GetMethodName(InvocationExpression invocation)
{ {
if (invocation.Target is IdentifierExpression) if (invocation.Target is IdentifierExpression)

11
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs

@ -1,4 +1,4 @@
// //
// CreateProperty.cs // CreateProperty.cs
// //
// Author: // Author:
@ -56,6 +56,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (guessedType == null) if (guessedType == null)
yield break; yield break;
var state = context.GetResolverStateBefore(identifier); var state = context.GetResolverStateBefore(identifier);
if (state.CurrentTypeDefinition == null)
yield break;
bool createInOtherType = false; bool createInOtherType = false;
ResolveResult targetResolveResult = null; ResolveResult targetResolveResult = null;
@ -64,15 +66,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition()); createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
} }
bool isStatic; bool isStatic = targetResolveResult is TypeResolveResult;
if (createInOtherType) { if (createInOtherType) {
isStatic = targetResolveResult is TypeResolveResult;
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface) if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface)
yield break; yield break;
} else { } else {
if (state.CurrentMember == null || state.CurrentTypeDefinition == null) if (state.CurrentMember == null)
yield break; yield break;
isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic; isStatic |= state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
} }
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); // var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));

186
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/ExtractMethodAction.cs

@ -0,0 +1,186 @@
//
// ExtractMethodAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Analysis;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
[ContextAction("Extract method", Description = "Creates a new method out of selected text.")]
public class ExtractMethodAction : ICodeActionProvider
{
public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
if (!context.IsSomethingSelected)
yield break;
var selected = new List<AstNode>(context.GetSelectedNodes());
if (selected.Count == 0)
yield break;
if (selected.Count == 1 && selected [0] is Expression) {
var codeAction = CreateFromExpression(context, (Expression)selected [0]);
if (codeAction == null)
yield break;
yield return codeAction;
}
foreach (var node in selected) {
if (!(node is Statement))
yield break;
}
var action = CreateFromStatements (context, new List<Statement> (selected.OfType<Statement> ()));
if (action != null)
yield return action;
}
CodeAction CreateFromExpression(RefactoringContext context, Expression expression)
{
var resolveResult = context.Resolve(expression);
if (resolveResult.IsError)
return null;
return new CodeAction(context.TranslateString("Extract method"), script => {
string methodName = "NewMethod";
var method = new MethodDeclaration() {
ReturnType = context.CreateShortType(resolveResult.Type),
Name = methodName,
Body = new BlockStatement() {
new ReturnStatement(expression.Clone())
}
};
if (!StaticVisitor.UsesNotStaticMember(context, expression))
method.Modifiers |= Modifiers.Static;
script.InsertWithCursor(context.TranslateString("Extract method"), method, Script.InsertPosition.Before);
var target = new IdentifierExpression(methodName);
script.Replace(expression, new InvocationExpression(target));
// script.Link(target, method.NameToken);
});
}
CodeAction CreateFromStatements(RefactoringContext context, List<Statement> statements)
{
if (!(statements [0].Parent is Statement))
return null;
return new CodeAction(context.TranslateString("Extract method"), script => {
string methodName = "NewMethod";
var method = new MethodDeclaration() {
ReturnType = new PrimitiveType("void"),
Name = methodName,
Body = new BlockStatement()
};
bool usesNonStaticMember = false;
foreach (Statement node in statements) {
usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
method.Body.Add(node.Clone());
}
if (!usesNonStaticMember)
method.Modifiers |= Modifiers.Static;
var target = new IdentifierExpression(methodName);
var invocation = new InvocationExpression(target);
var usedVariables = VariableLookupVisitor.Analyze(context, statements);
var extractedCodeAnalysis = new DefiniteAssignmentAnalysis((Statement)statements [0].Parent, context.Resolver, context.CancellationToken);
var lastStatement = statements [statements.Count - 1];
extractedCodeAnalysis.SetAnalyzedRange(statements [0], lastStatement);
var statusAfterMethod = new List<Tuple<IVariable, DefiniteAssignmentStatus>>();
foreach (var variable in usedVariables) {
extractedCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
statusAfterMethod.Add(Tuple.Create(variable, extractedCodeAnalysis.GetStatusAfter(lastStatement)));
}
var stmt = statements [0].GetParent<BlockStatement>();
while (stmt.GetParent<BlockStatement> () != null) {
stmt = stmt.GetParent<BlockStatement>();
}
var wholeCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
var statusBeforeMethod = new Dictionary<IVariable, DefiniteAssignmentStatus>();
foreach (var variable in usedVariables) {
wholeCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
}
var afterCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
var statusAtEnd = new Dictionary<IVariable, DefiniteAssignmentStatus>();
afterCodeAnalysis.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);
foreach (var variable in usedVariables) {
afterCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
}
var beforeVisitor = new VariableLookupVisitor(context);
beforeVisitor.SetAnalyzedRange(stmt, statements [0], true, false);
stmt.AcceptVisitor(beforeVisitor);
var afterVisitor = new VariableLookupVisitor(context);
afterVisitor.SetAnalyzedRange(lastStatement, stmt, false, true);
stmt.AcceptVisitor(afterVisitor);
foreach (var status in statusAfterMethod) {
if (!beforeVisitor.UsedVariables.Contains(status.Item1) && !afterVisitor.UsedVariables.Contains(status.Item1))
continue;
Expression argumentExpression = new IdentifierExpression(status.Item1.Name);
ParameterModifier mod;
switch (status.Item2) {
case DefiniteAssignmentStatus.AssignedAfterTrueExpression:
case DefiniteAssignmentStatus.AssignedAfterFalseExpression:
case DefiniteAssignmentStatus.PotentiallyAssigned:
mod = ParameterModifier.Ref;
argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
break;
case DefiniteAssignmentStatus.DefinitelyAssigned:
if (statusBeforeMethod [status.Item1] != DefiniteAssignmentStatus.PotentiallyAssigned)
goto case DefiniteAssignmentStatus.PotentiallyAssigned;
mod = ParameterModifier.Out;
argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
break;
// case DefiniteAssignmentStatus.Unassigned:
default:
mod = ParameterModifier.None;
break;
}
method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(status.Item1.Type), status.Item1.Name, mod));
invocation.Arguments.Add(argumentExpression);
}
foreach (var node in statements.Skip (1)) {
script.Remove(node);
}
script.Replace(statements [0], new ExpressionStatement(invocation));
script.InsertWithCursor(context.TranslateString("Extract method"), method, Script.InsertPosition.Before);
//script.Link(target, method.NameToken);
});
}
}
}

85
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/StaticVisitor.cs

@ -0,0 +1,85 @@
//
// StaticVisitor.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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 ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
class StaticVisitor : DepthFirstAstVisitor
{
readonly RefactoringContext context;
public bool UsesNonStaticMember = false;
StaticVisitor(RefactoringContext context)
{
this.context = context;
}
public static bool UsesNotStaticMember(RefactoringContext context, AstNode node)
{
var visitor = new StaticVisitor(context);
node.AcceptVisitor(visitor);
return visitor.UsesNonStaticMember;
}
protected override void VisitChildren(AstNode node)
{
if (UsesNonStaticMember)
return;
base.VisitChildren(node);
}
public override void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
{
UsesNonStaticMember = true;
base.VisitThisReferenceExpression(thisReferenceExpression);
}
public override void VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
{
UsesNonStaticMember = true;
base.VisitBaseReferenceExpression(baseReferenceExpression);
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
var resolveResult = context.Resolve(identifierExpression);
if (resolveResult is MemberResolveResult) {
var memberResult = (MemberResolveResult)resolveResult;
if (!memberResult.Member.IsStatic)
UsesNonStaticMember = true;
} else if (resolveResult is MethodGroupResolveResult) {
var methodGroupResolveResult = (MethodGroupResolveResult)resolveResult;
if (methodGroupResolveResult.Methods.Any(m => !m.IsStatic))
UsesNonStaticMember = true;
}
}
}
}

97
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/VariableLookupVisitor.cs

@ -0,0 +1,97 @@
//
// VariableLookupVisitor.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// 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.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
class VariableLookupVisitor : DepthFirstAstVisitor
{
readonly RefactoringContext context;
public List<IVariable> UsedVariables = new List<IVariable> ();
TextLocation startLocation = TextLocation.Empty;
TextLocation endLocation = TextLocation.Empty;
public VariableLookupVisitor (RefactoringContext context)
{
this.context = context;
}
public void SetAnalyzedRange(AstNode start, AstNode end, bool startInclusive = true, bool endInclusive = true)
{
if (start == null)
throw new ArgumentNullException("start");
if (end == null)
throw new ArgumentNullException("end");
startLocation = startInclusive ? start.StartLocation : start.EndLocation;
endLocation = endInclusive ? end.EndLocation : end.StartLocation;
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation) {
var result = context.Resolve(identifierExpression);
var local = result as LocalResolveResult;
if (local != null && !UsedVariables.Contains(local.Variable))
UsedVariables.Add(local.Variable);
}
}
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
{
base.VisitVariableDeclarationStatement(variableDeclarationStatement);
foreach (var varDecl in variableDeclarationStatement.Variables) {
if (startLocation.IsEmpty || startLocation <= varDecl.StartLocation && varDecl.EndLocation <= endLocation) {
var result = context.Resolve(varDecl);
var local = result as LocalResolveResult;
if (local != null && !UsedVariables.Contains(local.Variable))
UsedVariables.Add(local.Variable);
}
}
}
public static List<IVariable> Analyze(RefactoringContext context, Expression expression)
{
var visitor = new VariableLookupVisitor(context);
expression.AcceptVisitor(visitor);
return visitor.UsedVariables;
}
public static List<IVariable> Analyze(RefactoringContext context, List<Statement> statements)
{
var visitor = new VariableLookupVisitor(context);
statements.ForEach(stmt => stmt.AcceptVisitor(visitor));
return visitor.UsedVariables;
}
}
}

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/GeneratePropertyAction.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
public IEnumerable<CodeAction> GetActions(RefactoringContext context) public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{ {
var initializer = GetVariableInitializer(context); var initializer = context.GetNode<VariableInitializer>();
if (initializer == null || !initializer.NameToken.Contains(context.Location.Line, context.Location.Column)) { if (initializer == null || !initializer.NameToken.Contains(context.Location.Line, context.Location.Column)) {
yield break; yield break;
} }
@ -92,10 +92,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)); ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name));
} }
VariableInitializer GetVariableInitializer (RefactoringContext context)
{
return context.GetNode<VariableInitializer> ();
}
} }
} }

89
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs

@ -0,0 +1,89 @@
//
// IntroduceConstantAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Introduce constant", Description = "Creates a constant for a non constant primitive expression.")]
public class IntroduceConstantAction : ICodeActionProvider
{
public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var pexpr = context.GetNode<PrimitiveExpression>();
if (pexpr == null)
yield break;
var statement = context.GetNode<Statement>();
if (statement == null) {
yield break;
}
var resolveResult = context.Resolve(pexpr);
yield return new CodeAction(context.TranslateString("Create local constant"), script => {
string name = CreateMethodDeclarationAction.CreateBaseName(pexpr, resolveResult.Type);
var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
if (service != null)
name = service.CheckName(context, name, AffectedEntity.LocalConstant);
var initializer = new VariableInitializer(name, pexpr.Clone());
var decl = new VariableDeclarationStatement() {
Type = context.CreateShortType(resolveResult.Type),
Modifiers = Modifiers.Const,
Variables = { initializer }
};
script.InsertBefore(statement, decl);
var variableUsage = new IdentifierExpression(name);
script.Replace(pexpr, variableUsage);
script.Link(initializer.NameToken, variableUsage);
});
yield return new CodeAction(context.TranslateString("Create constant field"), script => {
string name = CreateMethodDeclarationAction.CreateBaseName(pexpr, resolveResult.Type);
var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
if (service != null)
name = service.CheckName(context, name, AffectedEntity.ConstantField);
var initializer = new VariableInitializer(name, pexpr.Clone());
var decl = new FieldDeclaration() {
ReturnType = context.CreateShortType(resolveResult.Type),
Modifiers = Modifiers.Const,
Variables = { initializer }
};
var variableUsage = new IdentifierExpression(name);
script.Replace(pexpr, variableUsage);
// script.Link(initializer.NameToken, variableUsage);
script.InsertWithCursor(context.TranslateString("Create constant"), decl, Script.InsertPosition.Before);
});
}
}
}

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveBackingStoreAction.cs

@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
newProperty.Getter.Body = BlockStatement.Null; newProperty.Getter.Body = BlockStatement.Null;
newProperty.Setter.Body = BlockStatement.Null; newProperty.Setter.Body = BlockStatement.Null;
yield return new CodeAction(context.TranslateString("Remove backing store"), script => { yield return new CodeAction(context.TranslateString("Convert to auto property"), script => {
script.Rename((IEntity)field, newProperty.Name); script.Rename((IEntity)field, newProperty.Name);
script.Remove (context.RootNode.GetNodeAt<FieldDeclaration> (field.Region.Begin)); script.Remove (context.RootNode.GetNodeAt<FieldDeclaration> (field.Region.Begin));
script.Replace (property, newProperty); script.Replace (property, newProperty);

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveBracesAction.cs

@ -47,14 +47,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}); });
} }
static BlockStatement GetBlockStatement (RefactoringContext context) static BlockStatement GetBlockStatement(RefactoringContext context)
{ {
var block = context.GetNode<BlockStatement> (); var block = context.GetNode<BlockStatement>();
if (block == null || block.LBraceToken.IsNull || block.RBraceToken.IsNull) if (block == null || block.LBraceToken.IsNull || block.RBraceToken.IsNull)
return null; return null;
if (!(block.Parent is Statement)) if (!(block.LBraceToken.IsInside(context.Location) || block.RBraceToken.IsInside(context.Location)))
return null; return null;
if (block.Statements.Count != 1) if (!(block.Parent is Statement) || block.Parent is TryCatchStatement)
return null;
if (block.Statements.Count != 1 || block.Statements.First () is VariableDeclarationStatement)
return null; return null;
return block; return block;
} }

38
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SpecializedCodeAction.cs

@ -0,0 +1,38 @@
using System;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// A specialized code action creates a code action assoziated with one special type of ast nodes.
/// </summary>
public abstract class SpecializedCodeAction<T> : ICodeActionProvider where T : AstNode
{
/// <summary>
/// Gets the action for the specified ast node.
/// </summary>
/// <returns>
/// The code action. May return <c>null</c>, if no action can be provided.
/// </returns>
/// <param name='context'>
/// The refactoring conext.
/// </param>
/// <param name='node'>
/// The AstNode it's ensured that the node is always != null, if called.
/// </param>
protected abstract CodeAction GetAction(RefactoringContext context, T node);
#region ICodeActionProvider implementation
public System.Collections.Generic.IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<T>();
if (node == null)
yield break;
var action = GetAction(context, node);
if (action == null)
yield break;
yield return action;
}
#endregion
}
}

49
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs

@ -1,4 +1,4 @@
// //
// InspectionIssue.cs // InspectionIssue.cs
// //
// Author: // Author:
@ -29,28 +29,58 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
/// <summary>
/// A code issue marks a region of text with an issue and can provide solution actions for this issue.
/// </summary>
public class CodeIssue public class CodeIssue
{ {
/// <summary>
/// Gets the desription of the issue.
/// </summary>
public string Desription { public string Desription {
get; get;
private set; private set;
} }
/// <summary>
/// Gets the issue start location.
/// </summary>
public TextLocation Start { public TextLocation Start {
get; get;
private set; private set;
} }
/// <summary>
/// Gets the issue end location.
/// </summary>
public TextLocation End { public TextLocation End {
get; get;
private set; private set;
} }
/// <summary>
/// Gets a list of potential solutions for the issue.
/// </summary>
public IList<CodeAction> Actions { public IList<CodeAction> Actions {
get; get;
private set; private set;
} }
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.Refactoring.CodeIssue"/> class.
/// </summary>
/// <param name='description'>
/// The desription of the issue.
/// </param>
/// <param name='start'>
/// The issue start location.
/// </param>
/// <param name='end'>
/// the issue end location.
/// </param>
/// <param name='actions'>
/// A list of potential solutions for the issue.
/// </param>
public CodeIssue(string description, TextLocation start, TextLocation end, IEnumerable<CodeAction> actions = null) public CodeIssue(string description, TextLocation start, TextLocation end, IEnumerable<CodeAction> actions = null)
{ {
Desription = description; Desription = description;
@ -62,6 +92,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Actions = EmptyList<CodeAction>.Instance; Actions = EmptyList<CodeAction>.Instance;
} }
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.Refactoring.CodeIssue"/> class.
/// </summary>
/// <param name='description'>
/// The desription of the issue.
/// </param>
/// <param name='start'>
/// The issue start location.
/// </param>
/// <param name='end'>
/// the issue end location.
/// </param>
/// <param name='action'>
/// A potential solution for the issue.
/// </param>
public CodeIssue(string description, TextLocation start, TextLocation end, CodeAction action) : this (description, start, end, action != null ? new [] { action } : null) public CodeIssue(string description, TextLocation start, TextLocation end, CodeAction action) : this (description, start, end, action != null ? new [] { action } : null)
{ {
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ConditionalToNullCoalescingIssue.cs

@ -55,11 +55,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
), ),
}; };
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

71
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExplicitConversionInForEachIssue.cs

@ -0,0 +1,71 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[IssueDescription("Incorrect element type in foreach over generic collection",
Description= "Detects hidden explicit conversions in foreach loops.",
Category = IssueCategories.CodeQualityIssues,
Severity = Severity.Warning)]
public class ExplicitConversionInForEachIssue : ICodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor(context).GetIssues();
}
class GatherVisitor : GatherVisitorBase
{
CSharpConversions conversions;
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
{
}
public override void VisitForeachStatement(ForeachStatement foreachStatement)
{
base.VisitForeachStatement(foreachStatement);
var rr = ctx.Resolve(foreachStatement) as ForEachResolveResult;
if (rr == null)
return;
if (rr.ElementType.Kind == TypeKind.Unknown)
return;
if (ReflectionHelper.GetTypeCode(rr.ElementType) == TypeCode.Object)
return;
if (conversions == null) {
conversions = CSharpConversions.Get(ctx.Compilation);
}
Conversion c = conversions.ImplicitConversion(rr.ElementType, rr.ElementVariable.Type);
if (c.IsValid)
return;
var csResolver = ctx.GetResolverStateBefore(foreachStatement);
var builder = new TypeSystemAstBuilder(csResolver);
AstType elementType = builder.ConvertType(rr.ElementType);
AstType variableType = foreachStatement.VariableType;
string text = ctx.TranslateString("Collection element type '{0}' is not implicitly convertible to '{1}'");
AddIssue(variableType, string.Format(text, elementType.GetText(), variableType.GetText()));
}
}
}
}

23
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/GatherVisitorBase.cs

@ -29,17 +29,38 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp namespace ICSharpCode.NRefactory.CSharp
{ {
/// <summary>
/// A base class for writing issue provider visitor implementations.
/// </summary>
class GatherVisitorBase : DepthFirstAstVisitor class GatherVisitorBase : DepthFirstAstVisitor
{ {
protected readonly BaseRefactoringContext ctx; protected readonly BaseRefactoringContext ctx;
public readonly List<CodeIssue> FoundIssues = new List<CodeIssue> (); public readonly List<CodeIssue> FoundIssues = new List<CodeIssue> ();
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.GatherVisitorBase"/> class.
/// </summary>
/// <param name='ctx'>
/// The refactoring context.
/// </param>
public GatherVisitorBase (BaseRefactoringContext ctx) public GatherVisitorBase (BaseRefactoringContext ctx)
{ {
this.ctx = ctx; this.ctx = ctx;
} }
/// <summary>
/// Gets all the issues using the context root node as base.
/// </summary>
/// <returns>
/// The issues.
/// </returns>
public IEnumerable<CodeIssue> GetIssues()
{
ctx.RootNode.AcceptVisitor(this);
return FoundIssues;
}
protected override void VisitChildren (AstNode node) protected override void VisitChildren (AstNode node)
{ {
if (ctx.CancellationToken.IsCancellationRequested) if (ctx.CancellationToken.IsCancellationRequested)

14
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/DefaultRules.cs

@ -1,4 +1,4 @@
// //
// DefaultRules.cs // DefaultRules.cs
// //
// Author: // Author:
@ -73,6 +73,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
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,
NamingStyle = NamingStyle.PascalCase, NamingStyle = NamingStyle.PascalCase,
IncludeInstanceMembers = false IncludeInstanceMembers = false
}; };
@ -94,7 +95,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Name = "Fields (Private)", Name = "Fields (Private)",
NamingStyle = NamingStyle.CamelCase, NamingStyle = NamingStyle.CamelCase,
AllowedPrefixes = new [] { "_", "m_" }, AllowedPrefixes = new [] { "_", "m_" },
VisibilityMask = Modifiers.Private 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) { yield return new NamingRule(AffectedEntity.ReadonlyField) {

22
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/NamingConventionService.cs

@ -35,6 +35,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
get; get;
} }
public string CheckName(RefactoringContext ctx, string name, AffectedEntity entity, Modifiers accessibilty = Modifiers.Private, bool isStatic = false)
{
foreach (var rule in Rules) {
if (!rule.AffectedEntity.HasFlag(entity)) {
continue;
}
if (!rule.VisibilityMask.HasFlag(accessibilty)) {
continue;
}
if (isStatic && !rule.IncludeStaticEntities || !isStatic && !rule.IncludeInstanceMembers) {
continue;
}
if (!rule.IsValid(name)) {
IList<string> suggestedNames;
var msg = rule.GetErrorMessage(ctx, name, out suggestedNames);
if (suggestedNames.Any ())
return suggestedNames [0];
}
}
return name;
}
public bool IsValidName(string name, AffectedEntity entity, Modifiers accessibilty = Modifiers.Private, bool isStatic = false) public bool IsValidName(string name, AffectedEntity entity, Modifiers accessibilty = Modifiers.Private, bool isStatic = false)
{ {
foreach (var rule in Rules) { foreach (var rule in Rules) {

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/NotImplementedExceptionIssue.cs

@ -37,11 +37,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
[IssueDescription("Show NotImplementedExceptions", Description="Shows NotImplementedException throws in the quick task bar.", Category = IssueCategories.Notifications, Severity = Severity.Suggestion, IssueMarker = IssueMarker.None)] [IssueDescription("Show NotImplementedExceptions", Description="Shows NotImplementedException throws in the quick task bar.", Category = IssueCategories.Notifications, Severity = Severity.Suggestion, IssueMarker = IssueMarker.None)]
public class NotImplementedExceptionIssue : ICodeIssueProvider public class NotImplementedExceptionIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantInternalIssue.cs

@ -1,4 +1,4 @@
// //
// RedundantInternalInspector.cs // RedundantInternalInspector.cs
// //
// Author: // Author:
@ -34,18 +34,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// <summary> /// <summary>
/// Finds redundant internal modifiers. /// Finds redundant internal modifiers.
/// </summary> /// </summary>
[IssueDescription("Remove redunant 'internal' modifier", [IssueDescription("Remove redundant 'internal' modifier",
Description="Removes 'internal' modifiers that are not required.", Description="Removes 'internal' modifiers that are not required.",
Category = IssueCategories.Redundancies, Category = IssueCategories.Redundancies,
Severity = Severity.Hint, Severity = Severity.Hint,
IssueMarker = IssueMarker.GrayOut)] IssueMarker = IssueMarker.GrayOut)]
public class RedundantInternalIssue : ICodeIssueProvider public class RedundantInternalIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

52
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantNamespaceUsageIssue.cs

@ -1,6 +1,6 @@
// //
// RedundantNamespaceUsageInspector.cs // RedundantNamespaceUsageInspector.cs
// //
// Author: // Author:
// Mike Krüger <mkrueger@xamarin.com> // Mike Krüger <mkrueger@xamarin.com>
// //
@ -37,17 +37,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// Finds redundant namespace usages. /// Finds redundant namespace usages.
/// </summary> /// </summary>
[IssueDescription("Remove redundant namespace usages", [IssueDescription("Remove redundant namespace usages",
Description = "Removes namespace usages that are obsolete.", Description = "Removes namespace usages that are obsolete.",
Category = IssueCategories.Redundancies, Category = IssueCategories.Redundancies,
Severity = Severity.Hint, Severity = Severity.Hint,
IssueMarker = IssueMarker.GrayOut)] IssueMarker = IssueMarker.GrayOut)]
public class RedundantNamespaceUsageIssue : ICodeIssueProvider public class RedundantNamespaceUsageIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase
@ -62,24 +60,40 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
{ {
base.VisitMemberReferenceExpression(memberReferenceExpression); base.VisitMemberReferenceExpression(memberReferenceExpression);
HandleMemberReference(
var result = ctx.Resolve(memberReferenceExpression.Target); memberReferenceExpression, memberReferenceExpression.Target, memberReferenceExpression.MemberNameToken, memberReferenceExpression.TypeArguments, SimpleNameLookupMode.Expression,
script => {
script.Replace(memberReferenceExpression, RefactoringAstHelper.RemoveTarget(memberReferenceExpression));
});
}
public override void VisitMemberType(MemberType memberType)
{
base.VisitMemberType(memberType);
HandleMemberReference(
memberType, memberType.Target, memberType.MemberNameToken, memberType.TypeArguments, SimpleNameLookupMode.Type,
script => {
script.Replace(memberType, RefactoringAstHelper.RemoveTarget(memberType));
});
}
void HandleMemberReference(AstNode wholeNode, AstNode targetNode, Identifier memberName, IEnumerable<AstType> typeArguments, SimpleNameLookupMode mode, Action<Script> action)
{
var result = ctx.Resolve(targetNode);
if (!(result is NamespaceResolveResult)) { if (!(result is NamespaceResolveResult)) {
return; return;
} }
var wholeResult = ctx.Resolve(memberReferenceExpression); var wholeResult = ctx.Resolve(wholeNode);
if (!(wholeResult is TypeResolveResult)) { if (!(wholeResult is TypeResolveResult)) {
return; return;
} }
var state = ctx.GetResolverStateBefore(memberReferenceExpression); var state = ctx.GetResolverStateBefore(wholeNode);
var lookupName = state.LookupSimpleNameOrTypeName(memberReferenceExpression.MemberName, new List<IType> (), SimpleNameLookupMode.Expression); var resolvedTypeArguments = typeArguments.Select(ctx.ResolveType).ToList();
var lookupName = state.LookupSimpleNameOrTypeName(memberName.Name, resolvedTypeArguments, mode);
if (lookupName is TypeResolveResult && !lookupName.IsError && wholeResult.Type.Equals(lookupName.Type)) { if (lookupName is TypeResolveResult && !lookupName.IsError && wholeResult.Type.Equals(lookupName.Type)) {
AddIssue(memberReferenceExpression.StartLocation, memberReferenceExpression.MemberNameToken.StartLocation, ctx.TranslateString("Remove redundant namespace usage"), script => { AddIssue(wholeNode.StartLocation, memberName.StartLocation, ctx.TranslateString("Remove redundant namespace usage"), action);
script.Replace(memberReferenceExpression, RefactoringAstHelper.RemoveTarget(memberReferenceExpression));
}
);
} }
} }
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantPrivateIssue.cs

@ -41,11 +41,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IssueMarker = IssueMarker.GrayOut)] IssueMarker = IssueMarker.GrayOut)]
public class RedundantPrivateIssue : ICodeIssueProvider public class RedundantPrivateIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantThisIssue.cs

@ -45,11 +45,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IssueMarker = IssueMarker.GrayOut)] IssueMarker = IssueMarker.GrayOut)]
public class RedundantThisIssue : ICodeIssueProvider public class RedundantThisIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

76
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantUsingIssue.cs

@ -1,6 +1,6 @@
// //
// RedundantUsingInspector.cs // RedundantUsingInspector.cs
// //
// Author: // Author:
// Mike Krüger <mkrueger@xamarin.com> // Mike Krüger <mkrueger@xamarin.com>
// //
@ -38,13 +38,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// Finds redundant using declarations. /// Finds redundant using declarations.
/// </summary> /// </summary>
[IssueDescription("Remove unused usings", [IssueDescription("Remove unused usings",
Description = "Removes used declarations that are not required.", Description = "Removes used declarations that are not required.",
Category = IssueCategories.Redundancies, Category = IssueCategories.Redundancies,
Severity = Severity.Hint, Severity = Severity.Hint,
IssueMarker = IssueMarker.GrayOut)] IssueMarker = IssueMarker.GrayOut)]
public class RedundantUsingIssue : ICodeIssueProvider public class RedundantUsingIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) List<string> namespacesToKeep = new List<string>();
/// <summary>
/// The list of namespaces that should be kept even if they are not being used.
/// Used in SharpDevelop to always keep the "System" namespace around.
/// </summary>
public IList<string> NamespacesToKeep {
get { return namespacesToKeep; }
}
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor); context.RootNode.AcceptVisitor (visitor);
@ -55,22 +65,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase
{ {
readonly RedundantUsingIssue inspector; readonly RedundantUsingIssue inspector;
Dictionary<UsingDeclaration, bool> usingDeclarations = new Dictionary<UsingDeclaration, bool> (); Dictionary<UsingDeclaration, bool> isInUse = new Dictionary<UsingDeclaration, bool>();
Dictionary<string, UsingDeclaration> namespaceToUsingDecl = new Dictionary<string, UsingDeclaration>();
Stack<List<UsingDeclaration>> usingStack = new Stack<List<UsingDeclaration>> ();
public GatherVisitor (BaseRefactoringContext ctx, RedundantUsingIssue inspector) : base (ctx) public GatherVisitor (BaseRefactoringContext ctx, RedundantUsingIssue inspector) : base (ctx)
{ {
this.inspector = inspector; this.inspector = inspector;
usingStack.Push (new List<UsingDeclaration> ());
} }
public void Collect() public void Collect()
{ {
foreach (var u in usingDeclarations.Where (u => !u.Value)) { foreach (var u in isInUse.Where (u => !u.Value)) {
var decl = u.Key; var decl = u.Key;
AddIssue(decl, ctx.TranslateString("Remove redundant usings"), script => { AddIssue(decl, ctx.TranslateString("Remove redundant usings"), script => {
foreach (var u2 in usingDeclarations.Where (a => !a.Value)) { foreach (var u2 in isInUse.Where (a => !a.Value)) {
script.Remove (u2.Key); script.Remove (u2.Key);
} }
} }
@ -81,30 +89,35 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration) public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
{ {
base.VisitUsingDeclaration(usingDeclaration); base.VisitUsingDeclaration(usingDeclaration);
usingDeclarations [usingDeclaration] = false; var nrr = ctx.Resolve(usingDeclaration.Import) as NamespaceResolveResult;
usingStack.Peek().Add(usingDeclaration); if (nrr != null) {
isInUse[usingDeclaration] = inspector.namespacesToKeep.Contains(nrr.NamespaceName);
namespaceToUsingDecl[nrr.NamespaceName] = usingDeclaration;
}
} }
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{ {
usingStack.Push(new List<UsingDeclaration> (usingStack.Peek())); var oldNamespaceToUsingDecl = new Dictionary<string, UsingDeclaration>(namespaceToUsingDecl);
base.VisitNamespaceDeclaration(namespaceDeclaration); base.VisitNamespaceDeclaration(namespaceDeclaration);
usingStack.Pop(); namespaceToUsingDecl = oldNamespaceToUsingDecl;
} }
void UseNamespace(string ns) void UseNamespace(string ns)
{ {
foreach (var u in usingStack.Peek ()) { UsingDeclaration decl;
if (u.Namespace == ns) { if (namespaceToUsingDecl.TryGetValue(ns, out decl)) {
usingDeclarations [u] = true; isInUse[decl] = true;
}
} }
} }
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression) public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{ {
base.VisitIdentifierExpression(identifierExpression); base.VisitIdentifierExpression(identifierExpression);
UseNamespace(ctx.Resolve(identifierExpression).Type.Namespace); var trr = ctx.Resolve(identifierExpression) as TypeResolveResult;
if (trr != null) {
UseNamespace(trr.Type.Namespace);
}
} }
public override void VisitSimpleType(SimpleType simpleType) public override void VisitSimpleType(SimpleType simpleType)
@ -116,13 +129,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override void VisitInvocationExpression (InvocationExpression invocationExpression) public override void VisitInvocationExpression (InvocationExpression invocationExpression)
{ {
base.VisitInvocationExpression (invocationExpression); base.VisitInvocationExpression (invocationExpression);
var mg = ctx.Resolve (invocationExpression) as CSharpInvocationResolveResult; UseExtensionMethod(ctx.Resolve(invocationExpression));
if (mg == null || !mg.IsExtensionMethodInvocation) { }
return;
void UseExtensionMethod(ResolveResult rr)
{
var mg = rr as CSharpInvocationResolveResult;
if (mg != null && mg.IsExtensionMethodInvocation) {
UseNamespace (mg.Member.DeclaringType.Namespace);
} }
UseNamespace (mg.Member.DeclaringType.Namespace);
} }
public override void VisitQueryExpression(QueryExpression queryExpression)
{
base.VisitQueryExpression(queryExpression);
foreach (var clause in queryExpression.Clauses) {
UseExtensionMethod(ctx.Resolve(clause));
}
}
} }
} }
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StringIsNullOrEmptyIssue.cs

@ -70,11 +70,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
), ),
}; };
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/UseVarKeywordIssue.cs

@ -43,11 +43,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IssueMarker = IssueMarker.None)] IssueMarker = IssueMarker.None)]
public class UseVarKeywordIssue : ICodeIssueProvider public class UseVarKeywordIssue : ICodeIssueProvider
{ {
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
var visitor = new GatherVisitor (context, this); return new GatherVisitor(context, this).GetIssues();
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ICodeIssueProvider.cs

@ -28,8 +28,17 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
/// <summary>
/// The code issue provider gets a list of all code issues in a compilation unit.
/// </summary>
public interface ICodeIssueProvider public interface ICodeIssueProvider
{ {
/// <summary>
/// Gets all code issues inside a compilation unit.
/// </summary>
/// <param name='context'>
/// The refactoring context of the issues to get.
/// </param>
IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context); IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context);
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public virtual AstType CreateShortType (IType fullType) public virtual AstType CreateShortType (IType fullType)
{ {
var csResolver = resolver.GetResolverStateBefore(GetNode()); var csResolver = Resolver.GetResolverStateBefore(GetNode());
var builder = new TypeSystemAstBuilder(csResolver); var builder = new TypeSystemAstBuilder(csResolver);
return builder.ConvertType(fullType); return builder.ConvertType(fullType);
} }

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs

@ -26,7 +26,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs

@ -85,6 +85,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
CSharpAstResolver resolver = new CSharpAstResolver(compilation, cu, parsedFile); CSharpAstResolver resolver = new CSharpAstResolver(compilation, cu, parsedFile);
resolver.ApplyNavigator(new NodeListResolveVisitorNavigator(node), cancellationToken);
ResolveResult rr = resolver.Resolve(node, cancellationToken); ResolveResult rr = resolver.Resolve(node, cancellationToken);
if (rr is MethodGroupResolveResult && parentInvocation != null) if (rr is MethodGroupResolveResult && parentInvocation != null)
return resolver.Resolve(parentInvocation); return resolver.Resolve(parentInvocation);

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

@ -3608,6 +3608,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
return null; return null;
} }
ResolveResult IAstVisitor<ResolveResult>.VisitNewLine (NewLineNode comment)
{
return null;
}
ResolveResult IAstVisitor<ResolveResult>.VisitWhitespace(WhitespaceNode whitespaceNode)
{
return null;
}
ResolveResult IAstVisitor<ResolveResult>.VisitText(TextNode textNode)
{
return null;
}
ResolveResult IAstVisitor<ResolveResult>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective) ResolveResult IAstVisitor<ResolveResult>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
{ {

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs

@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy of this // 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 // software and associated documentation files (the "Software"), to deal in the Software
@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
// 2. Output // 2. Output
StringWriter w = new StringWriter(); StringWriter w = new StringWriter();
cu.AcceptVisitor(new CSharpOutputVisitor(w, new CSharpFormattingOptions())); cu.AcceptVisitor(new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ()));
string generatedCode = w.ToString().TrimEnd(); string generatedCode = w.ToString().TrimEnd();
// 3. Compare output with original (modulo whitespaces) // 3. Compare output with original (modulo whitespaces)

32
src/Libraries/NRefactory/ICSharpCode.NRefactory.ConsistencyCheck/Xml/IncrementalXmlParserTests.cs

@ -182,7 +182,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
CompareResults(obj1.Children, obj2.Children); CompareResults(obj1.Children, obj2.Children);
} }
sealed class ValidationVisitor : IAXmlVisitor sealed class ValidationVisitor : AXmlVisitor
{ {
readonly ITextSource textSource; readonly ITextSource textSource;
@ -191,19 +191,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
this.textSource = textSource; this.textSource = textSource;
} }
public void Visit(IList<AXmlObject> objects) public override void VisitTag(AXmlTag tag)
{
for (int i = 0; i < objects.Count; i++) {
objects[i].AcceptVisitor(this);
}
}
public void VisitDocument(AXmlDocument document)
{
Visit(document.Children);
}
public void VisitTag(AXmlTag tag)
{ {
if (textSource.GetText(tag.StartOffset, tag.OpeningBracket.Length) != tag.OpeningBracket) if (textSource.GetText(tag.StartOffset, tag.OpeningBracket.Length) != tag.OpeningBracket)
throw new InvalidOperationException(); throw new InvalidOperationException();
@ -211,24 +199,14 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
throw new InvalidOperationException(); throw new InvalidOperationException();
if (textSource.GetText(tag.EndOffset - tag.ClosingBracket.Length, tag.ClosingBracket.Length) != tag.ClosingBracket) if (textSource.GetText(tag.EndOffset - tag.ClosingBracket.Length, tag.ClosingBracket.Length) != tag.ClosingBracket)
throw new InvalidOperationException(); throw new InvalidOperationException();
Visit(tag.Children); base.VisitTag(tag);
} }
public void VisitAttribute(AXmlAttribute attribute) public override void VisitAttribute(AXmlAttribute attribute)
{ {
if (textSource.GetText(attribute.NameSegment) != attribute.Name) if (textSource.GetText(attribute.NameSegment) != attribute.Name)
throw new InvalidOperationException(); throw new InvalidOperationException();
Visit(attribute.Children); base.VisitAttribute(attribute);
}
public void VisitText(AXmlText text)
{
Visit(text.Children);
}
public void VisitElement(AXmlElement element)
{
Visit(element.Children);
} }
} }
} }

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.GtkDemo/gtk-gui/ICSharpCode.NRefactory.GtkDemo.MainWindow.cs

@ -5,12 +5,19 @@ namespace ICSharpCode.NRefactory.GtkDemo
public partial class MainWindow public partial class MainWindow
{ {
private global::Gtk.VBox vbox1; private global::Gtk.VBox vbox1;
private global::Gtk.ScrolledWindow scrolledwindow1; private global::Gtk.ScrolledWindow scrolledwindow1;
private global::Gtk.TextView textview1; private global::Gtk.TextView textview1;
private global::Gtk.HBox hbox1; private global::Gtk.HBox hbox1;
private global::Gtk.Button buttonParse; private global::Gtk.Button buttonParse;
private global::Gtk.Button buttonGenerate; private global::Gtk.Button buttonGenerate;
private global::Gtk.ScrolledWindow GtkScrolledWindow1; private global::Gtk.ScrolledWindow GtkScrolledWindow1;
private global::Gtk.TreeView treeviewNodes; private global::Gtk.TreeView treeviewNodes;
protected virtual void Build () protected virtual void Build ()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save