Browse Source

Update to NRefactory 5.4

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
2c75fada90
  1. 5
      NRefactory/.gitattributes
  2. 1
      NRefactory/.gitignore
  3. 27
      NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/AssemblyInfo.cs
  4. 69
      NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/ICSharpCode.NRefactory.CSharp.AstVerifier.csproj
  5. 83
      NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/Main.cs
  6. 65
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/AnnotationNames.cs
  7. 88
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  8. 157
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DeclarationSpace/LocalDeclarationSpace.cs
  9. 138
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DeclarationSpace/LocalDeclarationSpaceVisitor.cs
  10. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  11. 2215
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueAnalysis.cs
  12. 84
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueStatus.cs
  13. 140
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs
  14. 691
      NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs
  15. 282
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  16. 19
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNodeCollection.cs
  17. 73
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs
  18. 102
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs
  19. 36
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs
  20. 115
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpUtil.cs
  21. 44
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs
  22. 43
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs
  23. 30
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DocumentationReference.cs
  24. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ErrorNode.cs
  25. 3
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs
  26. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayCreateExpression.cs
  27. 5
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs
  28. 70
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AsExpression.cs
  29. 67
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs
  30. 66
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs
  31. 72
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CastExpression.cs
  32. 67
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ConditionalExpression.cs
  33. 54
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs
  34. 37
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs
  35. 78
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IsExpression.cs
  36. 8
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs
  37. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/MemberReferenceExpression.cs
  38. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs
  39. 10
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NullReferenceExpression.cs
  40. 78
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs
  41. 89
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs
  42. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs
  43. 5
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs
  44. 19
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Attribute.cs
  45. 15
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/AttributeSection.cs
  46. 9
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs
  47. 6
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs
  48. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/DelegateDeclaration.cs
  49. 111
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NamespaceDeclaration.cs
  50. 109
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NewLineNode.cs
  51. 81
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs
  52. 22
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs
  53. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs
  54. 27
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingDeclaration.cs
  55. 14
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs
  56. 13
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs
  57. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs
  58. 37
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs
  59. 11
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs
  60. 13
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs
  61. 34
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs
  62. 14
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs
  63. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BreakStatement.cs
  64. 10
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/DoWhileStatement.cs
  65. 2
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/LabelStatement.cs
  66. 35
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs
  67. 5
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs
  68. 10
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/WhileStatement.cs
  69. 45
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxExtensions.cs
  70. 21
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs
  71. 32
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TokenRole.cs
  72. 25
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs
  73. 25
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs
  74. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/DestructorDeclaration.cs
  75. 10
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EntityDeclaration.cs
  76. 10
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs
  77. 31
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EventDeclaration.cs
  78. 20
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FieldDeclaration.cs
  79. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs
  80. 12
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/IndexerDeclaration.cs
  81. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MethodDeclaration.cs
  82. 6
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs
  83. 17
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs
  84. 4
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/PropertyDeclaration.cs
  85. 17
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs
  86. 1201
      NRefactory/ICSharpCode.NRefactory.CSharp/Ast/old_ObservableAstVisitor.cs
  87. 16
      NRefactory/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
  88. 216
      NRefactory/ICSharpCode.NRefactory.CSharp/CombineQueryExpressions.cs
  89. 2544
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  90. 418
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  91. 268
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  92. 179
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  93. 9
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs
  94. 28
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs
  95. 9
      NRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs
  96. 2181
      NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  97. 159
      NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormatter.cs
  98. 218
      NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs
  99. 514
      NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/ConstructFixer.cs
  100. 169
      NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingChanges.cs
  101. Some files were not shown because too many files have changed in this diff Show More

5
NRefactory/.gitattributes vendored

@ -1,2 +1,3 @@ @@ -1,2 +1,3 @@
*.sln -crlf
*.csproj -crlf
*.cs text diff=csharp
*.sln text eol=crlf
*.csproj text eol=crlf

1
NRefactory/.gitignore vendored

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
bin
obj
*.suo
/lib/*.dll
/ICSharpCode.NRefactory.Tests/PartCover/*
_ReSharper*/*

27
NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/AssemblyInfo.cs

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("ICSharpCode.NRefactory.CSharp.AstVerifier")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mike")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

69
NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/ICSharpCode.NRefactory.CSharp.AstVerifier.csproj

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{961DADFA-7CE6-429F-BC22-47630D6DB826}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ICSharpCode.NRefactory.CSharp.AstVerifier</RootNamespace>
<AssemblyName>AstVerifier</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
</Project>

83
NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/Main.cs

@ -1,83 +0,0 @@ @@ -1,83 +0,0 @@
using System;
using System.IO;
namespace ICSharpCode.NRefactory.CSharp.AstVerifier
{
class MainClass
{
static bool IsMatch (string src1, string src2, out int i, out int j)
{
i = 0;
j = 0;
while (i < src1.Length && j < src2.Length) {
char c1 = src1 [i];
char c2 = src2 [j];
if (char.IsWhiteSpace (c1)) {
i++;
continue;
}
if (char.IsWhiteSpace (c2)) {
j++;
continue;
}
if (c1 != c2)
return false;
i++;
j++;
}
while (i < src1.Length && char.IsWhiteSpace (src1[i])) {
i++;
}
while (j < src2.Length && char.IsWhiteSpace (src2[j])) {
j++;
}
return i == src1.Length && j == src2.Length;
}
public static void Main (string[] args)
{
if (args.Length == 0) {
Console.WriteLine ("Usage: AstVerifier [-v|-verbose] [Directory]");
return;
}
string directory = args[args.Length - 1];
bool verboseOutput = args.Length > 1 && (args[0] == "-v" || args[0] == "-verbose");
try {
if (!Directory.Exists (directory)) {
Console.WriteLine ("Directory not found.");
return;
}
} catch (IOException) {
Console.WriteLine ("Exception while trying to access the directory.");
return;
}
int failed = 0, passed = 0;
Console.WriteLine ("search in " + directory);
foreach (var file in Directory.GetFileSystemEntries (directory, "*", SearchOption.AllDirectories)) {
if (!file.EndsWith (".cs"))
continue;
string text = File.ReadAllText (file);
var unit = SyntaxTree.Parse (text, file);
if (unit == null)
continue;
string generated = unit.GetText ();
int i, j;
if (!IsMatch (text, generated, out i, out j)) {
if (i > 0 && j > 0 && verboseOutput) {
Console.WriteLine ("fail :" + file + "----original:");
Console.WriteLine (text.Substring (0, Math.Min (text.Length, i + 1)));
Console.WriteLine ("----generated:");
Console.WriteLine (generated.Substring (0, Math.Min (generated.Length, j + 1)));
}
failed++;
} else {
passed++;
}
}
Console.WriteLine ("{0} passed, {1} failed", passed, failed);
}
}
}

65
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs → NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/AnnotationNames.cs

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
//
// EmptyExpression.cs
//
// Annotations.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
// Copyright (c) 2013 Luís Reis
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -23,57 +23,26 @@ @@ -23,57 +23,26 @@
// 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>
/// Type&lt;[EMPTY]&gt;
/// </summary>
public class EmptyExpression : Expression
public static class AnnotationNames
{
TextLocation location;
//Used const instead of readonly to allow values to be used in switch cases.
public override TextLocation StartLocation {
get {
return location;
}
}
public override TextLocation EndLocation {
get {
return location;
}
}
public const string AssertionMethodAttribute = "JetBrains.Annotations.AssertionMethodAttribute";
public const string AssertionConditionAttribute = "JetBrains.Annotations.AssertionConditionAttribute";
public const string AssertionConditionTypeAttribute = "JetBrains.Annotations.AssertionConditionType";
public EmptyExpression ()
{
}
public const string AssertionConditionTypeIsTrue = "JetBrains.Annotations.AssertionConditionType.IS_TRUE";
public const string AssertionConditionTypeIsFalse = "JetBrains.Annotations.AssertionConditionType.IS_FALSE";
public const string AssertionConditionTypeIsNull = "JetBrains.Annotations.AssertionConditionType.IS_NULL";
public const string AssertionConditionTypeIsNotNull = "JetBrains.Annotations.AssertionConditionType.IS_NOT_NULL";
public EmptyExpression (TextLocation location)
{
this.location = location;
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitEmptyExpression (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitEmptyExpression (this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitEmptyExpression (this, data);
}
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
var o = other as EmptyExpression;
return o != null;
}
public const string NotNullAttribute = "JetBrains.Annotations.NotNullAttribute";
public const string CanBeNullAttribute = "JetBrains.Annotations.CanBeNullAttribute";
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -26,6 +26,7 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem; @@ -26,6 +26,7 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Analysis
{
@ -248,6 +249,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -248,6 +249,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
#region Create*Node
ControlFlowNode CreateStartNode(Statement statement)
{
if (statement.IsNull)
return null;
ControlFlowNode node = CreateNode(null, statement, ControlFlowNodeType.StartNode);
nodes.Add(node);
return node;
@ -294,6 +297,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -294,6 +297,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <returns>The constant value of the expression; or null if the expression is not a constant.</returns>
ResolveResult EvaluateConstant(Expression expr)
{
if (expr.IsNull)
return null;
if (EvaluateOnlyPrimitiveConstants) {
if (!(expr is PrimitiveExpression || expr is NullReferenceExpression))
return null;
@ -336,6 +341,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -336,6 +341,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
internal ControlFlowEdge Connect(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type = ControlFlowEdgeType.Normal)
{
if (from == null || to == null)
return null;
ControlFlowEdge edge = builder.CreateEdge(from, to, type);
from.Outgoing.Add(edge);
to.Incoming.Add(edge);
@ -354,8 +361,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -354,8 +361,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
protected override ControlFlowNode VisitChildren(AstNode node, ControlFlowNode data)
{
// We have overrides for all possible expressions and should visit expressions only.
throw new NotImplementedException();
// We have overrides for all possible statements and should visit statements only.
throw new NotSupportedException();
}
public override ControlFlowNode VisitBlockStatement(BlockStatement blockStatement, ControlFlowNode data)
@ -406,22 +413,20 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -406,22 +413,20 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
public override ControlFlowNode VisitIfElseStatement(IfElseStatement ifElseStatement, ControlFlowNode data)
{
bool? cond = builder.EvaluateCondition(ifElseStatement.Condition);
ControlFlowNode trueBegin = builder.CreateStartNode(ifElseStatement.TrueStatement);
if (cond != false)
Connect(data, trueBegin, ControlFlowEdgeType.ConditionTrue);
ControlFlowNode trueEnd = ifElseStatement.TrueStatement.AcceptVisitor(this, trueBegin);
ControlFlowNode falseEnd;
if (ifElseStatement.FalseStatement.IsNull) {
falseEnd = null;
} else {
ControlFlowNode falseBegin = builder.CreateStartNode(ifElseStatement.FalseStatement);
if (cond != true)
Connect(data, falseBegin, ControlFlowEdgeType.ConditionFalse);
falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin);
}
ControlFlowNode falseBegin = builder.CreateStartNode(ifElseStatement.FalseStatement);
if (cond != true)
Connect(data, falseBegin, ControlFlowEdgeType.ConditionFalse);
ControlFlowNode falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin);
// (if no else statement exists, both falseBegin and falseEnd will be null)
ControlFlowNode end = builder.CreateEndNode(ifElseStatement);
if (trueEnd != null)
Connect(trueEnd, end);
Connect(trueEnd, end);
if (falseEnd != null) {
Connect(falseEnd, end);
} else if (cond != true) {
@ -599,8 +604,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -599,8 +604,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
ControlFlowNode bodyStart = builder.CreateStartNode(forStatement.EmbeddedStatement);
ControlFlowNode bodyEnd = forStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart);
if (bodyEnd != null)
Connect(bodyEnd, iteratorStart);
Connect(bodyEnd, iteratorStart);
breakTargets.Pop();
continueTargets.Pop();
@ -743,5 +747,57 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -743,5 +747,57 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return CreateConnectedEndNode(fixedStatement, bodyEnd);
}
}
/// <summary>
/// Debugging helper that exports a control flow graph.
/// </summary>
public static GraphVizGraph ExportGraph(IList<ControlFlowNode> nodes)
{
GraphVizGraph g = new GraphVizGraph();
GraphVizNode[] n = new GraphVizNode[nodes.Count];
Dictionary<ControlFlowNode, int> dict = new Dictionary<ControlFlowNode, int>();
for (int i = 0; i < n.Length; i++) {
dict.Add(nodes[i], i);
n[i] = new GraphVizNode(i);
string name = "#" + i + " = ";
switch (nodes[i].Type) {
case ControlFlowNodeType.StartNode:
case ControlFlowNodeType.BetweenStatements:
name += nodes[i].NextStatement.DebugToString();
break;
case ControlFlowNodeType.EndNode:
name += "End of " + nodes[i].PreviousStatement.DebugToString();
break;
case ControlFlowNodeType.LoopCondition:
name += "Condition in " + nodes[i].NextStatement.DebugToString();
break;
default:
name += "?";
break;
}
n[i].label = name;
g.AddNode(n[i]);
}
for (int i = 0; i < n.Length; i++) {
foreach (ControlFlowEdge edge in nodes[i].Outgoing) {
GraphVizEdge ge = new GraphVizEdge(i, dict[edge.To]);
if (edge.IsLeavingTryFinally)
ge.style = "dashed";
switch (edge.Type) {
case ControlFlowEdgeType.ConditionTrue:
ge.color = "green";
break;
case ControlFlowEdgeType.ConditionFalse:
ge.color = "red";
break;
case ControlFlowEdgeType.Jump:
ge.color = "blue";
break;
}
g.AddEdge(ge);
}
}
return g;
}
}
}

157
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DeclarationSpace/LocalDeclarationSpace.cs

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
//
// LovalVariableDeclarationSpace.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2013 Simon Lindgren
//
// 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 ICSharpCode.NRefactory.Utils;
using System.Collections.Generic;
using System.Linq;
using System;
namespace ICSharpCode.NRefactory.CSharp.Analysis
{
/// <summary>
/// Represents a declaration space. (§3.3)
/// </summary>
public class LocalDeclarationSpace
{
/// <summary>
/// Maps from variable name to the declarations in this declaration space.
/// </summary>
/// <remarks>
/// This maps from variable name
/// </remarks>
MultiDictionary<string, AstNode> declarations = new MultiDictionary<string, AstNode> ();
public LocalDeclarationSpace()
{
Children = new List<LocalDeclarationSpace> ();
}
/// <summary>
/// The child declaration spaces.
/// </summary>
public IList<LocalDeclarationSpace> Children {
get;
private set;
}
/// <summary>
/// The parent declaration space.
/// </summary>
/// <value>The parent.</value>
public LocalDeclarationSpace Parent {
get;
private set;
}
/// <summary>
/// The names declared in this declaration space, excluding child spaces.
/// </summary>
/// <value>The declared names.</value>
public ICollection<string> DeclaredNames {
get {
return declarations.Keys;
}
}
/// <summary>
/// Get all nodes declaring the name specified in <paramref name="name"/>.
/// </summary>
/// <returns>The declaring nodes.</returns>
/// <param name="name">The declaration name.</param>
public IEnumerable<AstNode> GetNameDeclarations(string name)
{
return declarations [name].Concat(Children.SelectMany(child => child.GetNameDeclarations(name)));
}
/// <summary>
/// Adds a child declaration space.
/// </summary>
/// <param name="child">The <see cref="LocalDeclarationSpace"/> to add.</param>
public void AddChildSpace(LocalDeclarationSpace child)
{
if (child == null)
throw new ArgumentNullException("child");
if (Children.Contains(child))
throw new InvalidOperationException("the child was already added");
Children.Add(child);
child.Parent = this;
}
/// <summary>
/// Adds a new declaration to the declaration space.
/// </summary>
/// <param name="name">The name of the declared variable.</param>
/// <param name="node">A node associated with the declaration.</param>
public void AddDeclaration(string name, AstNode node)
{
if (name == null)
throw new ArgumentNullException("name");
if (node == null)
throw new ArgumentNullException("node");
declarations.Add(name, node);
}
/// <summary>
/// Determines if the name exists in the this declaration space.
/// </summary>
/// <returns><c>true</c>, if the name specified in <paramref name="name"/> is used in this variable declaration space, <c>false</c> otherwise.</returns>
/// <param name="name">The name to look for.</param>
/// <param name="includeChildren">When <c>true</c>, child declaration spaces are included in the search.</param>
public bool ContainsName(string name, bool includeChildren)
{
if (name == null)
throw new ArgumentNullException("name");
if (declarations.Keys.Contains(name))
return true;
return includeChildren && Children.Any(child => child.ContainsName(name, true));
}
/// <summary>
/// Determines whether the name specified in <paramref name="name"/> is used in surrouding code.
/// </summary>
/// <returns><c>true</c> if the name is used, <c>false</c> otherwise.</returns>
/// <param name="name">The name to check.</param>
/// <remarks>
/// Contrary to <see cref="ContainsName"/>, this method also checks parent declaration spaces
/// for name conflicts. Typically, this will be the right method to use when determining if a name can be used.
/// </remarks>
public bool IsNameUsed(string name)
{
if (name == null)
throw new ArgumentNullException("name");
return IsNameUsedBySelfOrParent(name) || Children.Any(child => child.ContainsName(name, true));
}
bool IsNameUsedBySelfOrParent(string name)
{
if (declarations.Keys.Contains(name))
return true;
return Parent != null && Parent.IsNameUsedBySelfOrParent(name);
}
}
}

138
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DeclarationSpace/LocalDeclarationSpaceVisitor.cs

@ -0,0 +1,138 @@ @@ -0,0 +1,138 @@
//
// LocalDeclarationSpaceVisitor.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2013 Simon Lindgren
//
// 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.Analysis
{
public class LocalDeclarationSpaceVisitor : DepthFirstAstVisitor
{
LocalDeclarationSpace currentDeclarationSpace;
Dictionary<AstNode, LocalDeclarationSpace> nodeDeclarationSpaces = new Dictionary<AstNode, LocalDeclarationSpace>();
public LocalDeclarationSpace GetDeclarationSpace(AstNode node)
{
if (node == null)
throw new ArgumentNullException("node");
while (node != null) {
LocalDeclarationSpace declarationSpace;
if (nodeDeclarationSpaces.TryGetValue(node, out declarationSpace))
return declarationSpace;
node = node.Parent;
}
return null;
}
#region Visitor
void AddDeclaration(string name, AstNode node)
{
if (currentDeclarationSpace != null)
currentDeclarationSpace.AddDeclaration(name, node);
}
public override void VisitVariableInitializer(VariableInitializer variableInitializer)
{
AddDeclaration(variableInitializer.Name, variableInitializer);
base.VisitVariableInitializer(variableInitializer);
}
public override void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
{
AddDeclaration(parameterDeclaration.Name, parameterDeclaration);
base.VisitParameterDeclaration(parameterDeclaration);
}
void VisitNewDeclarationSpace(AstNode node)
{
var oldDeclarationSpace = currentDeclarationSpace;
currentDeclarationSpace = new LocalDeclarationSpace();
if (oldDeclarationSpace != null)
oldDeclarationSpace.AddChildSpace(currentDeclarationSpace);
VisitChildren(node);
nodeDeclarationSpaces.Add(node, currentDeclarationSpace);
currentDeclarationSpace = oldDeclarationSpace;
}
#region Declaration space creating nodes
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
VisitNewDeclarationSpace(methodDeclaration);
}
public override void VisitBlockStatement(BlockStatement blockStatement)
{
VisitNewDeclarationSpace(blockStatement);
}
public override void VisitSwitchStatement(SwitchStatement switchStatement)
{
VisitNewDeclarationSpace(switchStatement);
}
public override void VisitForeachStatement(ForeachStatement foreachStatement)
{
AddDeclaration(foreachStatement.VariableName, foreachStatement);
VisitNewDeclarationSpace(foreachStatement);
}
public override void VisitForStatement(ForStatement forStatement)
{
VisitNewDeclarationSpace(forStatement);
}
public override void VisitUsingStatement(UsingStatement usingStatement)
{
VisitNewDeclarationSpace(usingStatement);
}
public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
{
VisitNewDeclarationSpace(lambdaExpression);
}
public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
{
VisitNewDeclarationSpace(anonymousMethodExpression);
}
public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
{
AddDeclaration(eventDeclaration.Name, eventDeclaration);
}
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
{
VisitNewDeclarationSpace(eventDeclaration);
}
#endregion
#endregion
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

2215
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueAnalysis.cs

File diff suppressed because it is too large Load Diff

84
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueStatus.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
//
// NullValueAnalysis.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis
//
// 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.Analysis
{
/// <summary>
/// Represents the null value status of a variable at a specific location.
/// </summary>
public enum NullValueStatus
{
/// <summary>
/// The value of the variable is unknown, possibly due to limitations
/// of the null value analysis.
/// </summary>
Unknown = 0,
/// <summary>
/// The value of the variable is unknown and even assigning it to a
/// value won't change its state, since it has been captured by a lambda
/// that may change it at any time (potentially even from a different thread).
/// Only going out of scope and creating a new variable may change the value
/// of this variable.
/// </summary>
CapturedUnknown,
/// <summary>
/// This variable is potentially unassigned.
/// </summary>
Unassigned,
/// <summary>
/// The value of the variable is provably null.
/// </summary>
DefinitelyNull,
/// <summary>
/// The value of the variable might or might not be null
/// </summary>
PotentiallyNull,
/// <summary>
/// The value of the variable is provably not null
/// </summary>
DefinitelyNotNull,
/// <summary>
/// The position of this node is unreachable, therefore the value
/// of the variable is not meaningful.
/// Alternatively, it might mean no local variable exists with the requested name.
/// </summary>
UnreachableOrInexistent,
/// <summary>
/// The analyser has encountered an error when attempting to find the value
/// of this variable.
/// </summary>
Error
}
public static class NullValueStatusExtensions
{
public static bool IsDefiniteValue (this NullValueStatus self) {
return self == NullValueStatus.DefinitelyNull || self == NullValueStatus.DefinitelyNotNull;
}
}
}

140
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -18,10 +18,12 @@ @@ -18,10 +18,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Analysis
{
@ -34,32 +36,37 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -34,32 +36,37 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
HashSet<Statement> reachableEndPoints = new HashSet<Statement>();
HashSet<ControlFlowNode> visitedNodes = new HashSet<ControlFlowNode>();
Stack<ControlFlowNode> stack = new Stack<ControlFlowNode>();
RecursiveDetectorVisitor recursiveDetectorVisitor = null;
private ReachabilityAnalysis() {}
public static ReachabilityAnalysis Create(Statement statement, CSharpAstResolver resolver = null, CancellationToken cancellationToken = default(CancellationToken))
public static ReachabilityAnalysis Create(Statement statement, CSharpAstResolver resolver = null, RecursiveDetectorVisitor recursiveDetectorVisitor = null, CancellationToken cancellationToken = default(CancellationToken))
{
var cfgBuilder = new ControlFlowGraphBuilder();
var cfg = cfgBuilder.BuildControlFlowGraph(statement, resolver, cancellationToken);
return Create(cfg, cancellationToken);
return Create(cfg, recursiveDetectorVisitor, cancellationToken);
}
internal static ReachabilityAnalysis Create(Statement statement, Func<AstNode, CancellationToken, ResolveResult> resolver, CSharpTypeResolveContext typeResolveContext, CancellationToken cancellationToken)
{
var cfgBuilder = new ControlFlowGraphBuilder();
var cfg = cfgBuilder.BuildControlFlowGraph(statement, resolver, typeResolveContext, cancellationToken);
return Create(cfg, cancellationToken);
return Create(cfg, null, cancellationToken);
}
public static ReachabilityAnalysis Create(IList<ControlFlowNode> controlFlowGraph, CancellationToken cancellationToken = default(CancellationToken))
public static ReachabilityAnalysis Create(IList<ControlFlowNode> controlFlowGraph, RecursiveDetectorVisitor recursiveDetectorVisitor = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (controlFlowGraph == null)
throw new ArgumentNullException("controlFlowGraph");
ReachabilityAnalysis ra = new ReachabilityAnalysis();
ra.stack.Push(controlFlowGraph[0]);
while (ra.stack.Count > 0) {
cancellationToken.ThrowIfCancellationRequested();
ra.MarkReachable(ra.stack.Pop());
ra.recursiveDetectorVisitor = recursiveDetectorVisitor;
// Analysing a null node can result in an empty control flow graph
if (controlFlowGraph.Count > 0) {
ra.stack.Push(controlFlowGraph[0]);
while (ra.stack.Count > 0) {
cancellationToken.ThrowIfCancellationRequested();
ra.MarkReachable(ra.stack.Pop());
}
}
ra.stack = null;
ra.visitedNodes = null;
@ -68,15 +75,32 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -68,15 +75,32 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
void MarkReachable(ControlFlowNode node)
{
if (node.PreviousStatement != null)
if (node.PreviousStatement != null) {
if (node.PreviousStatement is LabelStatement) {
reachableStatements.Add(node.PreviousStatement);
}
reachableEndPoints.Add(node.PreviousStatement);
if (node.NextStatement != null)
}
if (node.NextStatement != null) {
reachableStatements.Add(node.NextStatement);
if (IsRecursive(node.NextStatement)) {
return;
}
}
foreach (var edge in node.Outgoing) {
if (visitedNodes.Add(edge.To))
stack.Push(edge.To);
}
}
bool IsRecursive(Statement statement)
{
return recursiveDetectorVisitor != null && statement.AcceptVisitor(recursiveDetectorVisitor);
}
public IEnumerable<Statement> ReachableStatements {
get { return reachableStatements; }
}
public bool IsReachable(Statement statement)
{
@ -87,5 +111,99 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -87,5 +111,99 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
{
return reachableEndPoints.Contains(statement);
}
public class RecursiveDetectorVisitor : DepthFirstAstVisitor<bool>
{
public override bool VisitConditionalExpression(ConditionalExpression conditionalExpression)
{
if (conditionalExpression.Condition.AcceptVisitor(this))
return true;
if (!conditionalExpression.TrueExpression.AcceptVisitor(this))
return false;
return conditionalExpression.FalseExpression.AcceptVisitor(this);
}
public override bool VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
{
if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) {
return binaryOperatorExpression.Left.AcceptVisitor(this);
}
return base.VisitBinaryOperatorExpression(binaryOperatorExpression);
}
public override bool VisitIfElseStatement(IfElseStatement ifElseStatement)
{
if (ifElseStatement.Condition.AcceptVisitor(this))
return true;
if (!ifElseStatement.TrueStatement.AcceptVisitor(this))
return false;
//No need to worry about null ast nodes, since AcceptVisitor will just
//return false in those cases
return ifElseStatement.FalseStatement.AcceptVisitor(this);
}
public override bool VisitForeachStatement(ForeachStatement foreachStatement)
{
//Even if the body is always recursive, the function may stop if the collection
// is empty.
return foreachStatement.InExpression.AcceptVisitor(this);
}
public override bool VisitForStatement(ForStatement forStatement)
{
if (forStatement.Initializers.Any(initializer => initializer.AcceptVisitor(this)))
return true;
return forStatement.Condition.AcceptVisitor(this);
}
public override bool VisitSwitchStatement(SwitchStatement switchStatement)
{
if (switchStatement.Expression.AcceptVisitor(this)) {
return true;
}
bool foundDefault = false;
foreach (var section in switchStatement.SwitchSections) {
foundDefault = foundDefault || section.CaseLabels.Any(label => label.Expression.IsNull);
if (!section.AcceptVisitor(this))
return false;
}
return foundDefault;
}
public override bool VisitBlockStatement(BlockStatement blockStatement)
{
//If the block has a recursive statement, then that statement will be visited
//individually by the CFG construction algorithm later.
return false;
}
protected override bool VisitChildren(AstNode node)
{
return VisitNodeList(node.Children);
}
bool VisitNodeList(IEnumerable<AstNode> nodes) {
return nodes.Any(node => node.AcceptVisitor(this));
}
public override bool VisitQueryExpression(QueryExpression queryExpression)
{
//We only care about the first from clause because:
//in "from x in Method() select x", Method() might be recursive
//but in "from x in Bar() from y in Method() select x + y", even if Method() is recursive
//Bar might still be empty.
var queryFromClause = queryExpression.Clauses.OfType<QueryFromClause>().FirstOrDefault();
if (queryFromClause == null)
return true;
return queryFromClause.AcceptVisitor(this);
}
}
}
}

691
NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs

@ -0,0 +1,691 @@ @@ -0,0 +1,691 @@
// Copyright (c) 2010-2013 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 System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Completion;
using System.Collections.ObjectModel;
namespace ICSharpCode.NRefactory.CSharp.Analysis
{
/// <summary>
/// C# Semantic highlighter.
/// </summary>
public abstract class SemanticHighlightingVisitor<TColor> : DepthFirstAstVisitor
{
protected CancellationToken cancellationToken = default (CancellationToken);
protected TColor defaultTextColor;
protected TColor referenceTypeColor;
protected TColor valueTypeColor;
protected TColor interfaceTypeColor;
protected TColor enumerationTypeColor;
protected TColor typeParameterTypeColor;
protected TColor delegateTypeColor;
protected TColor methodCallColor;
protected TColor methodDeclarationColor;
protected TColor eventDeclarationColor;
protected TColor eventAccessColor;
protected TColor propertyDeclarationColor;
protected TColor propertyAccessColor;
protected TColor fieldDeclarationColor;
protected TColor fieldAccessColor;
protected TColor variableDeclarationColor;
protected TColor variableAccessColor;
protected TColor parameterDeclarationColor;
protected TColor parameterAccessColor;
protected TColor valueKeywordColor;
protected TColor externAliasKeywordColor;
protected TColor varKeywordTypeColor;
/// <summary>
/// Used for 'in' modifiers on type parameters.
/// </summary>
/// <remarks>
/// 'in' may have a different color when used with 'foreach'.
/// 'out' is not colored by semantic highlighting, as syntax highlighting can already detect it as a parameter modifier.
/// </remarks>
protected TColor parameterModifierColor;
/// <summary>
/// Used for inactive code (excluded by preprocessor or ConditionalAttribute)
/// </summary>
protected TColor inactiveCodeColor;
protected TColor stringFormatItemColor;
protected TColor syntaxErrorColor;
protected TextLocation regionStart;
protected TextLocation regionEnd;
protected CSharpAstResolver resolver;
bool isInAccessorContainingValueParameter;
protected abstract void Colorize(TextLocation start, TextLocation end, TColor color);
#region Colorize helper methods
protected void Colorize(Identifier identifier, ResolveResult rr)
{
if (identifier.IsNull)
return;
if (rr.IsError) {
Colorize(identifier, syntaxErrorColor);
return;
}
if (rr is TypeResolveResult) {
if (blockDepth > 0 && identifier.Name == "var" && rr.Type.Kind != TypeKind.Null && rr.Type.Name != "var" ) {
Colorize(identifier, varKeywordTypeColor);
return;
}
TColor color;
if (TryGetTypeHighlighting (rr.Type.Kind, out color)) {
Colorize(identifier, color);
}
return;
}
var mrr = rr as MemberResolveResult;
if (mrr != null) {
TColor color;
if (TryGetMemberColor (mrr.Member, out color)) {
Colorize(identifier, color);
return;
}
}
if (rr is MethodGroupResolveResult) {
Colorize (identifier, methodCallColor);
return;
}
var localResult = rr as LocalResolveResult;
if (localResult != null) {
if (localResult.Variable is IParameter) {
Colorize (identifier, parameterAccessColor);
} else {
Colorize (identifier, variableAccessColor);
}
}
VisitIdentifier(identifier); // un-colorize contextual keywords
}
protected void Colorize(AstNode node, TColor color)
{
if (node.IsNull)
return;
Colorize(node.StartLocation, node.EndLocation, color);
}
#endregion
protected override void VisitChildren(AstNode node)
{
for (var child = node.FirstChild; child != null; child = child.NextSibling) {
if (child.StartLocation < regionEnd && child.EndLocation > regionStart)
child.AcceptVisitor(this);
}
}
/// <summary>
/// Visit all children of <c>node</c> until (but excluding) <c>end</c>.
/// If <c>end</c> is a null node, nothing will be visited.
/// </summary>
protected void VisitChildrenUntil(AstNode node, AstNode end)
{
if (end.IsNull)
return;
Debug.Assert(node == end.Parent);
for (var child = node.FirstChild; child != end; child = child.NextSibling) {
cancellationToken.ThrowIfCancellationRequested();
if (child.StartLocation < regionEnd && child.EndLocation > regionStart)
child.AcceptVisitor(this);
}
}
/// <summary>
/// Visit all children of <c>node</c> after (excluding) <c>start</c>.
/// If <c>start</c> is a null node, all children will be visited.
/// </summary>
protected void VisitChildrenAfter(AstNode node, AstNode start)
{
Debug.Assert(start.IsNull || start.Parent == node);
for (var child = (start.IsNull ? node.FirstChild : start.NextSibling); child != null; child = child.NextSibling) {
cancellationToken.ThrowIfCancellationRequested();
if (child.StartLocation < regionEnd && child.EndLocation > regionStart)
child.AcceptVisitor(this);
}
}
public override void VisitIdentifier(Identifier identifier)
{
switch (identifier.Name) {
case "add":
case "async":
case "await":
case "get":
case "partial":
case "remove":
case "set":
case "where":
case "yield":
case "from":
case "select":
case "group":
case "into":
case "orderby":
case "join":
case "let":
case "on":
case "equals":
case "by":
case "ascending":
case "descending":
case "dynamic":
case "var":
// Reset color of contextual keyword to default if it's used as an identifier.
// Note that this method does not get called when 'var' or 'dynamic' is used as a type,
// because types get highlighted with valueTypeColor/referenceTypeColor instead.
Colorize(identifier, defaultTextColor);
break;
case "global":
// Reset color of 'global' keyword to default unless its used as part of 'global::'.
MemberType parentMemberType = identifier.Parent as MemberType;
if (parentMemberType == null || !parentMemberType.IsDoubleColon)
Colorize(identifier, defaultTextColor);
break;
}
// "value" is handled in VisitIdentifierExpression()
// "alias" is handled in VisitExternAliasDeclaration()
}
public override void VisitSimpleType(SimpleType simpleType)
{
var identifierToken = simpleType.IdentifierToken;
VisitChildrenUntil(simpleType, identifierToken);
Colorize(identifierToken, resolver.Resolve(simpleType, cancellationToken));
VisitChildrenAfter(simpleType, identifierToken);
}
public override void VisitMemberType(MemberType memberType)
{
var memberNameToken = memberType.MemberNameToken;
VisitChildrenUntil(memberType, memberNameToken);
Colorize(memberNameToken, resolver.Resolve(memberType, cancellationToken));
VisitChildrenAfter(memberType, memberNameToken);
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
var identifier = identifierExpression.IdentifierToken;
VisitChildrenUntil(identifierExpression, identifier);
if (isInAccessorContainingValueParameter && identifierExpression.Identifier == "value") {
Colorize(identifier, valueKeywordColor);
} else {
Colorize(identifier, resolver.Resolve(identifierExpression, cancellationToken));
}
VisitChildrenAfter(identifierExpression, identifier);
}
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
{
var memberNameToken = memberReferenceExpression.MemberNameToken;
VisitChildrenUntil(memberReferenceExpression, memberNameToken);
ResolveResult rr = resolver.Resolve(memberReferenceExpression, cancellationToken);
Colorize(memberNameToken, rr);
VisitChildrenAfter(memberReferenceExpression, memberNameToken);
}
void HighlightStringFormatItems(PrimitiveExpression expr)
{
if (!(expr.Value is string))
return;
int line = expr.StartLocation.Line;
int col = expr.StartLocation.Column;
TextLocation start = TextLocation.Empty;
for (int i = 0; i < expr.LiteralValue.Length; i++) {
char ch = expr.LiteralValue [i];
if (NewLine.GetDelimiterType(ch, i + 1 < expr.LiteralValue.Length ? expr.LiteralValue [i + 1] : '\0') != UnicodeNewline.Unknown) {
line++;
col = 1;
continue;
}
if (ch == '{' && start.IsEmpty) {
char next = i + 1 < expr.LiteralValue.Length ? expr.LiteralValue [i + 1] : '\0';
if (next == '{') {
i++;
col += 2;
continue;
}
start = new TextLocation(line, col);
}
col++;
if (ch == '}' &&!start.IsEmpty) {
char next = i + 1 < expr.LiteralValue.Length ? expr.LiteralValue [i + 1] : '\0';
if (next == '}') {
i++;
col += 2;
continue;
}
Colorize(start, new TextLocation(line, col), stringFormatItemColor);
start = TextLocation.Empty;
}
}
}
public override void VisitInvocationExpression(InvocationExpression invocationExpression)
{
Expression target = invocationExpression.Target;
if (target is IdentifierExpression || target is MemberReferenceExpression || target is PointerReferenceExpression) {
var invocationRR = resolver.Resolve(invocationExpression, cancellationToken) as CSharpInvocationResolveResult;
if (invocationRR != null) {
if (invocationExpression.Parent is ExpressionStatement && (IsInactiveConditionalMethod(invocationRR.Member) || IsEmptyPartialMethod(invocationRR.Member))) {
// mark the whole invocation statement as inactive code
Colorize(invocationExpression.Parent, inactiveCodeColor);
return;
}
Expression fmtArgumets;
IList<Expression> args;
if (invocationRR.Arguments.Count > 1 && FormatStringHelper.TryGetFormattingParameters(invocationRR, invocationExpression, out fmtArgumets, out args, null)) {
var expr = invocationExpression.Arguments.First() as PrimitiveExpression;
if (expr != null)
HighlightStringFormatItems(expr);
}
}
VisitChildrenUntil(invocationExpression, target);
// highlight the method call
var identifier = target.GetChildByRole(Roles.Identifier);
VisitChildrenUntil(target, identifier);
if (invocationRR != null && !invocationRR.IsDelegateInvocation) {
Colorize(identifier, methodCallColor);
} else {
ResolveResult targetRR = resolver.Resolve(target, cancellationToken);
Colorize(identifier, targetRR);
}
VisitChildrenAfter(target, identifier);
VisitChildrenAfter(invocationExpression, target);
} else {
VisitChildren(invocationExpression);
}
}
#region IsInactiveConditional helper methods
bool IsInactiveConditionalMethod(IParameterizedMember member)
{
if (member.SymbolKind != SymbolKind.Method || member.ReturnType.Kind != TypeKind.Void)
return false;
foreach (var baseMember in InheritanceHelper.GetBaseMembers(member, false)) {
if (IsInactiveConditional (baseMember.Attributes))
return true;
}
return IsInactiveConditional(member.Attributes);
}
static bool IsEmptyPartialMethod(IParameterizedMember member)
{
if (member.SymbolKind != SymbolKind.Method || member.ReturnType.Kind != TypeKind.Void)
return false;
var method = (IMethod)member;
return method.IsPartial && !method.HasBody;
}
bool IsInactiveConditional(IList<IAttribute> attributes)
{
bool hasConditionalAttribute = false;
foreach (var attr in attributes) {
if (attr.AttributeType.Name == "ConditionalAttribute" && attr.AttributeType.Namespace == "System.Diagnostics" && attr.PositionalArguments.Count == 1) {
string symbol = attr.PositionalArguments[0].ConstantValue as string;
if (symbol != null) {
hasConditionalAttribute = true;
var cu = this.resolver.RootNode as SyntaxTree;
if (cu != null) {
if (cu.ConditionalSymbols.Contains(symbol))
return false; // conditional is active
}
}
}
}
return hasConditionalAttribute;
}
#endregion
public override void VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration)
{
var aliasToken = externAliasDeclaration.AliasToken;
VisitChildrenUntil(externAliasDeclaration, aliasToken);
Colorize (aliasToken, externAliasKeywordColor);
VisitChildrenAfter(externAliasDeclaration, aliasToken);
}
public override void VisitAccessor(Accessor accessor)
{
isInAccessorContainingValueParameter = accessor.Role != PropertyDeclaration.GetterRole;
try {
VisitChildren(accessor);
} finally {
isInAccessorContainingValueParameter = false;
}
}
bool CheckInterfaceImplementation (EntityDeclaration entityDeclaration)
{
var result = resolver.Resolve (entityDeclaration, cancellationToken) as MemberResolveResult;
if (result == null)
return false;
if (result.Member.ImplementedInterfaceMembers.Count == 0) {
Colorize (entityDeclaration.NameToken, syntaxErrorColor);
return false;
}
return true;
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
var nameToken = methodDeclaration.NameToken;
VisitChildrenUntil(methodDeclaration, nameToken);
if (!methodDeclaration.PrivateImplementationType.IsNull) {
if (!CheckInterfaceImplementation (methodDeclaration)) {
VisitChildrenAfter(methodDeclaration, nameToken);
return;
}
}
Colorize(nameToken, methodDeclarationColor);
VisitChildrenAfter(methodDeclaration, nameToken);
}
public override void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
{
var nameToken = parameterDeclaration.NameToken;
VisitChildrenUntil(parameterDeclaration, nameToken);
Colorize(nameToken, parameterDeclarationColor);
VisitChildrenAfter(parameterDeclaration, nameToken);
}
public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
{
var nameToken = eventDeclaration.NameToken;
VisitChildrenUntil(eventDeclaration, nameToken);
Colorize(nameToken, eventDeclarationColor);
VisitChildrenAfter(eventDeclaration, nameToken);
}
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
{
var nameToken = eventDeclaration.NameToken;
VisitChildrenUntil(eventDeclaration, nameToken);
if (!eventDeclaration.PrivateImplementationType.IsNull) {
if (!CheckInterfaceImplementation (eventDeclaration)) {
VisitChildrenAfter(eventDeclaration, nameToken);
return;
}
}
Colorize(nameToken, eventDeclarationColor);
VisitChildrenAfter(eventDeclaration, nameToken);
}
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
var nameToken = propertyDeclaration.NameToken;
VisitChildrenUntil(propertyDeclaration, nameToken);
if (!propertyDeclaration.PrivateImplementationType.IsNull) {
if (!CheckInterfaceImplementation (propertyDeclaration)) {
VisitChildrenAfter(propertyDeclaration, nameToken);
return;
}
}
Colorize(nameToken, propertyDeclarationColor);
VisitChildrenAfter(propertyDeclaration, nameToken);
}
public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
{
base.VisitIndexerDeclaration(indexerDeclaration);
if (!indexerDeclaration.PrivateImplementationType.IsNull) {
CheckInterfaceImplementation (indexerDeclaration);
}
}
public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
{
fieldDeclaration.ReturnType.AcceptVisitor (this);
foreach (var init in fieldDeclaration.Variables) {
Colorize (init.NameToken, fieldDeclarationColor);
init.Initializer.AcceptVisitor (this);
}
}
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
{
fixedFieldDeclaration.ReturnType.AcceptVisitor (this);
foreach (var init in fixedFieldDeclaration.Variables) {
Colorize (init.NameToken, fieldDeclarationColor);
init.CountExpression.AcceptVisitor (this);
}
}
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
HandleConstructorOrDestructor(constructorDeclaration);
}
public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
{
HandleConstructorOrDestructor(destructorDeclaration);
}
void HandleConstructorOrDestructor(AstNode constructorDeclaration)
{
Identifier nameToken = constructorDeclaration.GetChildByRole(Roles.Identifier);
VisitChildrenUntil(constructorDeclaration, nameToken);
var currentTypeDef = resolver.GetResolverStateBefore(constructorDeclaration).CurrentTypeDefinition;
if (currentTypeDef != null && nameToken.Name == currentTypeDef.Name) {
TColor color;
if (TryGetTypeHighlighting (currentTypeDef.Kind, out color))
Colorize(nameToken, color);
}
VisitChildrenAfter(constructorDeclaration, nameToken);
}
bool TryGetMemberColor(IMember member, out TColor color)
{
switch (member.SymbolKind) {
case SymbolKind.Field:
color = fieldAccessColor;
return true;
case SymbolKind.Property:
color = propertyAccessColor;
return true;
case SymbolKind.Event:
color = eventAccessColor;
return true;
case SymbolKind.Method:
color = methodCallColor;
return true;
case SymbolKind.Constructor:
case SymbolKind.Destructor:
return TryGetTypeHighlighting (member.DeclaringType.Kind, out color);
default:
color = default (TColor);
return false;
}
}
TColor GetTypeHighlighting (ClassType classType)
{
switch (classType) {
case ClassType.Class:
return referenceTypeColor;
case ClassType.Struct:
return valueTypeColor;
case ClassType.Interface:
return interfaceTypeColor;
case ClassType.Enum:
return enumerationTypeColor;
default:
throw new InvalidOperationException ("Unknown class type :" + classType);
}
}
bool TryGetTypeHighlighting (TypeKind kind, out TColor color)
{
switch (kind) {
case TypeKind.Class:
color = referenceTypeColor;
return true;
case TypeKind.Struct:
color = valueTypeColor;
return true;
case TypeKind.Interface:
color = interfaceTypeColor;
return true;
case TypeKind.Enum:
color = enumerationTypeColor;
return true;
case TypeKind.TypeParameter:
color = typeParameterTypeColor;
return true;
case TypeKind.Delegate:
color = delegateTypeColor;
return true;
case TypeKind.Unknown:
case TypeKind.Null:
color = syntaxErrorColor;
return true;
default:
color = default (TColor);
return false;
}
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
var nameToken = typeDeclaration.NameToken;
VisitChildrenUntil(typeDeclaration, nameToken);
Colorize(nameToken, GetTypeHighlighting (typeDeclaration.ClassType));
VisitChildrenAfter(typeDeclaration, nameToken);
}
public override void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
{
if (typeParameterDeclaration.Variance == VarianceModifier.Contravariant)
Colorize(typeParameterDeclaration.VarianceToken, parameterModifierColor);
// bool isValueType = false;
// if (typeParameterDeclaration.Parent != null) {
// foreach (var constraint in typeParameterDeclaration.Parent.GetChildrenByRole(Roles.Constraint)) {
// if (constraint.TypeParameter.Identifier == typeParameterDeclaration.Name) {
// isValueType = constraint.BaseTypes.OfType<PrimitiveType>().Any(p => p.Keyword == "struct");
// }
// }
// }
var nameToken = typeParameterDeclaration.NameToken;
VisitChildrenUntil(typeParameterDeclaration, nameToken);
Colorize(nameToken, typeParameterTypeColor); /*isValueType ? valueTypeColor : referenceTypeColor*/
VisitChildrenAfter(typeParameterDeclaration, nameToken);
}
public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
{
var nameToken = delegateDeclaration.NameToken;
VisitChildrenUntil(delegateDeclaration, nameToken);
Colorize(nameToken, delegateTypeColor);
VisitChildrenAfter(delegateDeclaration, nameToken);
}
public override void VisitVariableInitializer(VariableInitializer variableInitializer)
{
var nameToken = variableInitializer.NameToken;
VisitChildrenUntil(variableInitializer, nameToken);
if (variableInitializer.Parent is FieldDeclaration) {
Colorize(nameToken, fieldDeclarationColor);
} else if (variableInitializer.Parent is EventDeclaration) {
Colorize(nameToken, eventDeclarationColor);
} else {
Colorize(nameToken, variableDeclarationColor);
}
VisitChildrenAfter(variableInitializer, nameToken);
}
public override void VisitComment(Comment comment)
{
if (comment.CommentType == CommentType.InactiveCode) {
Colorize(comment, inactiveCodeColor);
}
}
public override void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective)
{
}
public override void VisitAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute)
{
ITypeDefinition attrDef = resolver.Resolve(attribute.Type, cancellationToken).Type.GetDefinition();
if (attrDef != null && IsInactiveConditional(attrDef.Attributes)) {
Colorize(attribute, inactiveCodeColor);
} else {
VisitChildren(attribute);
}
}
public override void VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression)
{
foreach (var a in arrayInitializerExpression.Elements) {
var namedElement = a as NamedExpression;
if (namedElement != null) {
var result = resolver.Resolve (namedElement, cancellationToken);
if (result.IsError)
Colorize (namedElement.NameToken, syntaxErrorColor);
namedElement.Expression.AcceptVisitor (this);
} else {
a.AcceptVisitor (this);
}
}
}
int blockDepth;
public override void VisitBlockStatement(BlockStatement blockStatement)
{
blockDepth++;
base.VisitBlockStatement(blockStatement);
blockDepth--;
}
}
}

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

@ -31,10 +31,11 @@ using System.Diagnostics; @@ -31,10 +31,11 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
public abstract class AstNode : AbstractAnnotatable, ICSharpCode.NRefactory.TypeSystem.IFreezable, PatternMatching.INode
public abstract class AstNode : AbstractAnnotatable, ICSharpCode.NRefactory.TypeSystem.IFreezable, PatternMatching.INode, ICloneable
{
// the Root role must be available when creating the null nodes, so we can't put it in the Roles class
internal static readonly Role<AstNode> RootRole = new Role<AstNode> ("Root");
@ -58,16 +59,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,16 +59,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
@ -192,6 +194,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -192,6 +194,12 @@ namespace ICSharpCode.NRefactory.CSharp
return child.EndLocation;
}
}
public DomRegion Region {
get {
return new DomRegion (StartLocation, EndLocation);
}
}
/// <summary>
/// Gets the region from StartLocation to EndLocation for this node.
@ -223,6 +231,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -223,6 +231,10 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
internal uint RoleIndex {
get { return flags & roleIndexMask; }
}
void SetRole(Role role)
{
flags = (flags & ~roleIndexMask) | role.Index;
@ -286,31 +298,67 @@ namespace ICSharpCode.NRefactory.CSharp @@ -286,31 +298,67 @@ namespace ICSharpCode.NRefactory.CSharp
}
/// <summary>
/// Gets all descendants of this node (excluding this node itself).
/// Gets all descendants of this node (excluding this node itself) in pre-order.
/// </summary>
public IEnumerable<AstNode> Descendants {
get { return GetDescendants(false); }
get { return GetDescendantsImpl(false); }
}
/// <summary>
/// Gets all descendants of this node (including this node itself).
/// Gets all descendants of this node (including this node itself) in pre-order.
/// </summary>
public IEnumerable<AstNode> DescendantsAndSelf {
get { return GetDescendants(true); }
get { return GetDescendantsImpl(true); }
}
IEnumerable<AstNode> GetDescendants(bool includeSelf)
static bool IsInsideRegion(DomRegion region, AstNode pos)
{
if (region.IsEmpty)
return true;
var nodeRegion = pos.Region;
return region.IntersectsWith(nodeRegion) || region.OverlapsWith(nodeRegion);
}
public IEnumerable<AstNode> DescendantNodes (Func<AstNode, bool> descendIntoChildren = null)
{
if (includeSelf)
yield return this;
return GetDescendantsImpl(false, new DomRegion (), descendIntoChildren);
}
public IEnumerable<AstNode> DescendantNodes (DomRegion region, Func<AstNode, bool> descendIntoChildren = null)
{
return GetDescendantsImpl(false, region, descendIntoChildren);
}
public IEnumerable<AstNode> DescendantNodesAndSelf (Func<AstNode, bool> descendIntoChildren = null)
{
return GetDescendantsImpl(true, new DomRegion (), descendIntoChildren);
}
public IEnumerable<AstNode> DescendantNodesAndSelf (DomRegion region, Func<AstNode, bool> descendIntoChildren = null)
{
return GetDescendantsImpl(true, region, descendIntoChildren);
}
IEnumerable<AstNode> GetDescendantsImpl(bool includeSelf, DomRegion region = new DomRegion (), Func<AstNode, bool> descendIntoChildren = null)
{
if (includeSelf) {
if (IsInsideRegion (region, this))
yield return this;
if (descendIntoChildren != null && !descendIntoChildren(this))
yield break;
}
Stack<AstNode> nextStack = new Stack<AstNode>();
nextStack.Push(null);
AstNode pos = firstChild;
while (pos != null) {
// Remember next before yielding pos.
// This allows removing/replacing nodes while iterating through the list.
if (pos.nextSibling != null)
nextStack.Push(pos.nextSibling);
yield return pos;
if (pos.firstChild != null)
if (IsInsideRegion(region, pos))
yield return pos;
if (pos.firstChild != null && (descendIntoChildren == null || descendIntoChildren(pos)))
pos = pos.firstChild;
else
pos = nextStack.Pop();
@ -337,7 +385,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -337,7 +385,12 @@ namespace ICSharpCode.NRefactory.CSharp
{
return Ancestors.OfType<T>().FirstOrDefault();
}
public AstNode GetParent(Func<AstNode, bool> pred)
{
return Ancestors.FirstOrDefault(pred);
}
public AstNodeCollection<T> GetChildrenByRole<T> (Role<T> role) where T : AstNode
{
return new AstNodeCollection<T> (this, role);
@ -359,6 +412,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -359,6 +412,8 @@ namespace ICSharpCode.NRefactory.CSharp
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child == this)
throw new ArgumentException ("Cannot add a node to itself as a child.", "child");
if (child.parent != null)
throw new ArgumentException ("Node is already used in another tree.", "child");
if (child.IsFrozen)
@ -366,10 +421,24 @@ namespace ICSharpCode.NRefactory.CSharp @@ -366,10 +421,24 @@ namespace ICSharpCode.NRefactory.CSharp
AddChildUnsafe (child, role);
}
public void AddChildWithExistingRole (AstNode child)
{
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child == this)
throw new ArgumentException ("Cannot add a node to itself as a child.", "child");
if (child.parent != null)
throw new ArgumentException ("Node is already used in another tree.", "child");
if (child.IsFrozen)
throw new ArgumentException ("Cannot add a frozen node.", "child");
AddChildUnsafe (child, child.Role);
}
/// <summary>
/// Adds a child without performing any safety checks.
/// </summary>
void AddChildUnsafe (AstNode child, Role role)
internal void AddChildUnsafe (AstNode child, Role role)
{
child.parent = this;
child.SetRole(role);
@ -405,7 +474,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -405,7 +474,7 @@ namespace ICSharpCode.NRefactory.CSharp
InsertChildBeforeUnsafe (nextSibling, child, role);
}
void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role)
internal void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role)
{
child.parent = this;
child.SetRole(role);
@ -566,6 +635,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -566,6 +635,11 @@ namespace ICSharpCode.NRefactory.CSharp
return copy;
}
object ICloneable.Clone()
{
return Clone();
}
public abstract void AcceptVisitor (IAstVisitor visitor);
public abstract T AcceptVisitor<T> (IAstVisitor<T> visitor);
@ -612,6 +686,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -612,6 +686,19 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
/// <summary>
/// Gets the next node which fullfills a given predicate
/// </summary>
/// <returns>The next node.</returns>
/// <param name="pred">The predicate.</param>
public AstNode GetNextNode (Func<AstNode, bool> pred)
{
var next = GetNextNode();
while (next != null && !pred (next))
next = next.GetNextNode();
return next;
}
public AstNode GetPrevNode ()
{
if (PrevSibling != null)
@ -620,6 +707,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -620,6 +707,19 @@ namespace ICSharpCode.NRefactory.CSharp
return Parent.GetPrevNode ();
return null;
}
/// <summary>
/// Gets the previous node which fullfills a given predicate
/// </summary>
/// <returns>The next node.</returns>
/// <param name="pred">The predicate.</param>
public AstNode GetPrevNode (Func<AstNode, bool> pred)
{
var prev = GetPrevNode();
while (prev != null && !pred (prev))
prev = prev.GetPrevNode();
return prev;
}
// filters all non c# nodes (comments, white spaces or pre processor directives)
public AstNode GetCSharpNodeBefore (AstNode node)
{
@ -631,6 +731,32 @@ namespace ICSharpCode.NRefactory.CSharp @@ -631,6 +731,32 @@ namespace ICSharpCode.NRefactory.CSharp
}
return null;
}
/// <summary>
/// Gets the next sibling which fullfills a given predicate
/// </summary>
/// <returns>The next node.</returns>
/// <param name="pred">The predicate.</param>
public AstNode GetNextSibling (Func<AstNode, bool> pred)
{
var next = NextSibling;
while (next != null && !pred (next))
next = next.NextSibling;
return next;
}
/// <summary>
/// Gets the next sibling which fullfills a given predicate
/// </summary>
/// <returns>The next node.</returns>
/// <param name="pred">The predicate.</param>
public AstNode GetPrevSibling (Func<AstNode, bool> pred)
{
var prev = PrevSibling;
while (prev != null && !pred (prev))
prev = prev.PrevSibling;
return prev;
}
#region GetNodeAt
/// <summary>
@ -652,20 +778,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -652,20 +778,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
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)
while (node.LastChild != null) {
var child = node.LastChild;
while (child != null && child.StartLocation > location)
child = child.prevSibling;
if (child != null && location < child.EndLocation) {
if (pred == null || pred (child))
result = child;
node = child;
} else {
// found no better child node - therefore the parent is the right one.
break;
}
}
return result;
}
@ -689,20 +813,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -689,20 +813,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
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)
while (node.LastChild != null) {
var child = node.LastChild;
while (child != null && child.StartLocation > location)
child = child.prevSibling;
if (child != null && location < child.EndLocation) {
if (child is T)
result = (T)child;
node = child;
} else {
// found no better child node - therefore the parent is the right one.
break;
}
}
return result;
}
@ -729,20 +851,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -729,20 +851,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
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)
while (node.LastChild != null) {
var child = node.LastChild;
while (child != null && child.StartLocation > location)
child = child.prevSibling;
if (child != null && location <= child.EndLocation) {
if (pred == null || pred (child))
result = child;
node = child;
} else {
// found no better child node - therefore the parent is the right one.
break;
}
}
return result;
}
@ -766,20 +886,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -766,20 +886,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
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)
while (node.LastChild != null) {
var child = node.LastChild;
while (child != null && child.StartLocation > location)
child = child.prevSibling;
if (child != null && location <= child.EndLocation) {
if (child is T)
result = (T)child;
node = child;
} else {
// found no better child node - therefore the parent is the right one.
break;
}
}
return result;
}
@ -798,11 +916,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -798,11 +916,17 @@ namespace ICSharpCode.NRefactory.CSharp
return this;
}
/// <summary>
/// Returns the root nodes of all subtrees that are fully contained in the specified region.
/// </summary>
public IEnumerable<AstNode> GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn)
{
return GetNodesBetween (new TextLocation (startLine, startColumn), new TextLocation (endLine, endColumn));
}
/// <summary>
/// Returns the root nodes of all subtrees that are fully contained between <paramref name="start"/> and <paramref name="end"/> (inclusive).
/// </summary>
public IEnumerable<AstNode> GetNodesBetween (TextLocation start, TextLocation end)
{
AstNode node = this;
@ -811,11 +935,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -811,11 +935,11 @@ namespace ICSharpCode.NRefactory.CSharp
if (start <= node.StartLocation && node.EndLocation <= end) {
// Remember next before yielding node.
// This allows iteration to continue when the caller removes/replaces the node.
next = node.NextSibling;
next = node.GetNextNode();
yield return node;
} else {
if (node.EndLocation <= start) {
next = node.NextSibling;
next = node.GetNextNode();
} else {
next = node.FirstChild;
}
@ -826,14 +950,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -826,14 +950,19 @@ namespace ICSharpCode.NRefactory.CSharp
node = next;
}
}
[Obsolete("Use ToString(options).")]
public string GetText (CSharpFormattingOptions formattingOptions = null)
{
return ToString(formattingOptions);
}
/// <summary>
/// Gets the node as formatted C# output.
/// </summary>
/// <param name='formattingOptions'>
/// Formatting options.
/// </param>
public virtual string GetText (CSharpFormattingOptions formattingOptions = null)
public virtual string ToString (CSharpFormattingOptions formattingOptions)
{
if (IsNull)
return "";
@ -841,7 +970,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -841,7 +970,12 @@ namespace ICSharpCode.NRefactory.CSharp
AcceptVisitor (new CSharpOutputVisitor (w, formattingOptions ?? FormattingOptionsFactory.CreateMono ()));
return w.ToString ();
}
public sealed override string ToString()
{
return ToString(null);
}
/// <summary>
/// Returns true, if the given coordinates (line, column) are in the node.
/// </summary>
@ -897,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -897,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
if (IsNull)
return "Null";
string text = GetText();
string text = ToString();
text = text.TrimEnd().Replace("\t", "").Replace(Environment.NewLine, " ");
if (text.Length > 100)
return text.Substring(0, 97) + "...";

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -28,7 +28,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -28,7 +28,11 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Represents the children of an AstNode that have a specific role.
/// </summary>
public class AstNodeCollection<T> : ICollection<T> where T : AstNode
public class AstNodeCollection<T> : ICollection<T>
#if NET_4_5
, IReadOnlyCollection<T>
#endif
where T : AstNode
{
readonly AstNode node;
readonly Role<T> role;
@ -46,8 +50,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -46,8 +50,9 @@ namespace ICSharpCode.NRefactory.CSharp
public int Count {
get {
int count = 0;
uint roleIndex = role.Index;
for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) {
if (cur.Role == role)
if (cur.RoleIndex == roleIndex)
count++;
}
return count;
@ -103,7 +108,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -103,7 +108,7 @@ namespace ICSharpCode.NRefactory.CSharp
public bool Contains(T element)
{
return element != null && element.Parent == node && element.Role == role;
return element != null && element.Parent == node && element.RoleIndex == role.Index;
}
public bool Remove(T element)
@ -159,13 +164,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -159,13 +164,14 @@ namespace ICSharpCode.NRefactory.CSharp
public IEnumerator<T> GetEnumerator()
{
uint roleIndex = role.Index;
AstNode next;
for (AstNode cur = node.FirstChild; cur != null; cur = next) {
Debug.Assert(cur.Parent == node);
// Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list.
next = cur.NextSibling;
if (cur.Role == role)
if (cur.RoleIndex == roleIndex)
yield return (T)cur;
}
}
@ -210,13 +216,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -210,13 +216,14 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public void AcceptVisitor(IAstVisitor visitor)
{
uint roleIndex = role.Index;
AstNode next;
for (AstNode cur = node.FirstChild; cur != null; cur = next) {
Debug.Assert(cur.Parent == node);
// Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list.
next = cur.NextSibling;
if (cur.Role == role)
if (cur.RoleIndex == roleIndex)
cur.AcceptVisitor(visitor);
}
}

73
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -58,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp
return other == null || other.IsNull;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
return SpecialType.UnknownType;
}
@ -99,7 +100,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -99,7 +100,7 @@ namespace ICSharpCode.NRefactory.CSharp
return visitor.VisitPatternPlaceholder (this, child, data);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
throw new NotSupportedException();
}
@ -125,8 +126,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -125,8 +126,18 @@ namespace ICSharpCode.NRefactory.CSharp
return (AstType)base.Clone();
}
/// <summary>
/// Gets whether this type is a SimpleType "var".
/// </summary>
public bool IsVar()
{
SimpleType st = this as SimpleType;
return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0;
}
/// <summary>
/// Create an ITypeReference for this AstType.
/// Uses the context (ancestors of this node) to determine the correct <see cref="NameLookupMode"/>.
/// </summary>
/// <remarks>
/// The resulting type reference will read the context information from the
@ -135,7 +146,42 @@ namespace ICSharpCode.NRefactory.CSharp @@ -135,7 +146,42 @@ namespace ICSharpCode.NRefactory.CSharp
/// For resolving simple names, the current namespace and usings from the CurrentUsingScope
/// (on CSharpTypeResolveContext only) is used.
/// </remarks>
public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type);
public ITypeReference ToTypeReference(InterningProvider interningProvider = null)
{
return ToTypeReference(GetNameLookupMode(), interningProvider);
}
/// <summary>
/// Create an ITypeReference for this AstType.
/// </summary>
/// <remarks>
/// The resulting type reference will read the context information from the
/// <see cref="ITypeResolveContext"/>:
/// For resolving type parameters, the CurrentTypeDefinition/CurrentMember is used.
/// For resolving simple names, the current namespace and usings from the CurrentUsingScope
/// (on CSharpTypeResolveContext only) is used.
/// </remarks>
public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null);
/// <summary>
/// Gets the name lookup mode from the context (looking at the ancestors of this <see cref="AstType"/>).
/// </summary>
public NameLookupMode GetNameLookupMode()
{
AstType outermostType = this;
while (outermostType.Parent is AstType)
outermostType = (AstType)outermostType.Parent;
if (outermostType.Parent is UsingDeclaration || outermostType.Parent is UsingAliasDeclaration) {
return NameLookupMode.TypeInUsingDeclaration;
} else if (outermostType.Role == Roles.BaseType) {
// Use BaseTypeReference for a type's base type, and for a constraint on a type.
// Do not use it for a constraint on a method.
if (outermostType.Parent is TypeDeclaration || (outermostType.Parent is Constraint && outermostType.Parent.Parent is TypeDeclaration))
return NameLookupMode.BaseTypeReference;
}
return NameLookupMode.Type;
}
/// <summary>
/// Creates a pointer type from this type by nesting it in a <see cref="ComposedType"/>.
@ -215,5 +261,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -215,5 +261,20 @@ namespace ICSharpCode.NRefactory.CSharp
{
return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments);
}
/// <summary>
/// Creates a simple AstType from a dotted name.
/// Does not support generics, arrays, etc. - just simple dotted names,
/// e.g. namespace names.
/// </summary>
public static AstType Create(string dottedName)
{
string[] parts = dottedName.Split('.');
AstType type = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
type = new MemberType(type, parts[i]);
}
return type;
}
}
}

102
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs

@ -40,14 +40,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,14 +40,14 @@ namespace ICSharpCode.NRefactory.CSharp
this.modifier = value;
}
}
protected override int TokenLength {
public override TextLocation EndLocation {
get {
return GetModifierName (modifier).Length;
return new TextLocation (StartLocation.Line, StartLocation.Column + GetModifierLength (Modifier));
}
}
public override string GetText (CSharpFormattingOptions formattingOptions = null)
public override string ToString(CSharpFormattingOptions formattingOptions)
{
return GetModifierName (Modifier);
}
@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return allModifiers; }
}
public CSharpModifierToken (TextLocation location, Modifiers modifier) : base (location)
public CSharpModifierToken (TextLocation location, Modifiers modifier) : base (location, null)
{
this.Modifier = modifier;
}
@ -124,5 +124,95 @@ namespace ICSharpCode.NRefactory.CSharp @@ -124,5 +124,95 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for Modifiers");
}
}
public static int GetModifierLength(Modifiers modifier)
{
switch (modifier) {
case Modifiers.Private:
return "private".Length;
case Modifiers.Internal:
return "internal".Length;
case Modifiers.Protected:
return "protected".Length;
case Modifiers.Public:
return "public".Length;
case Modifiers.Abstract:
return "abstract".Length;
case Modifiers.Virtual:
return "virtual".Length;
case Modifiers.Sealed:
return "sealed".Length;
case Modifiers.Static:
return "static".Length;
case Modifiers.Override:
return "override".Length;
case Modifiers.Readonly:
return "readonly".Length;
case Modifiers.Const:
return "const".Length;
case Modifiers.New:
return "new".Length;
case Modifiers.Partial:
return "partial".Length;
case Modifiers.Extern:
return "extern".Length;
case Modifiers.Volatile:
return "volatile".Length;
case Modifiers.Unsafe:
return "unsafe".Length;
case Modifiers.Async:
return "async".Length;
case Modifiers.Any:
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return "any".Length;
default:
throw new NotSupportedException("Invalid value for Modifiers");
}
}
public static Modifiers GetModifierValue(string modifier)
{
switch (modifier) {
case "private":
return Modifiers.Private;
case "internal":
return Modifiers.Internal;
case "protected":
return Modifiers.Protected;
case "public":
return Modifiers.Public;
case "abstract":
return Modifiers.Abstract;
case "virtual":
return Modifiers.Virtual;
case "sealed":
return Modifiers.Sealed;
case "static":
return Modifiers.Static;
case "override":
return Modifiers.Override;
case "readonly":
return Modifiers.Readonly;
case "const":
return Modifiers.Const;
case "new":
return Modifiers.New;
case "partial":
return Modifiers.Partial;
case "extern":
return Modifiers.Extern;
case "volatile":
return Modifiers.Volatile;
case "unsafe":
return Modifiers.Unsafe;
case "async":
return Modifiers.Async;
case "any":
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return Modifiers.Any;
default:
throw new NotSupportedException("Invalid value for Modifiers");
}
}
}
}

36
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs

@ -44,22 +44,23 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,22 +44,23 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public NullCSharpTokenNode () : base (TextLocation.Empty)
public NullCSharpTokenNode () : base (TextLocation.Empty, null)
{
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -80,12 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,12 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp
return startLocation;
}
}
protected virtual int TokenLength {
int TokenLength {
get {
if (!(Role is TokenRole))
return 0;
return ((TokenRole)Role).Length;
return TokenRole.TokenLengths [(int)(this.flags >> AstNodeFlagsUsedBits)];
}
}
@ -94,17 +93,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -94,17 +93,17 @@ namespace ICSharpCode.NRefactory.CSharp
return new TextLocation (StartLocation.Line, StartLocation.Column + TokenLength);
}
}
public CSharpTokenNode (TextLocation location)
public CSharpTokenNode (TextLocation location, TokenRole role)
{
this.startLocation = location;
if (role != null)
this.flags |= role.TokenIndex << AstNodeFlagsUsedBits;
}
public override string GetText (CSharpFormattingOptions formattingOptions = null)
public override string ToString(CSharpFormattingOptions formattingOptions)
{
if (!(Role is TokenRole))
return null;
return ((TokenRole)Role).Token;
return TokenRole.Tokens [(int)(this.flags >> AstNodeFlagsUsedBits)];
}
public override void AcceptVisitor (IAstVisitor visitor)
@ -127,11 +126,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -127,11 +126,6 @@ namespace ICSharpCode.NRefactory.CSharp
CSharpTokenNode o = other as CSharpTokenNode;
return o != null && !o.IsNull && !(o is CSharpModifierToken);
}
public override string ToString ()
{
return string.Format ("[CSharpTokenNode: StartLocation={0}, EndLocation={1}, Role={2}]", StartLocation, EndLocation, Role);
}
}
}

115
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpUtil.cs

@ -25,51 +25,87 @@ @@ -25,51 +25,87 @@
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp
{
public static class CSharpUtil
{
public static Expression InvertCondition (Expression condition)
/// <summary>
/// Inverts a boolean condition. Note: The condition object can be frozen (from AST) it's cloned internally.
/// </summary>
/// <param name="condition">The condition to invert.</param>
public static Expression InvertCondition(Expression condition)
{
return InvertConditionInternal (condition.Clone ());
return InvertConditionInternal(condition);
}
static Expression InvertConditionInternal (Expression condition)
static Expression InvertConditionInternal(Expression condition)
{
if (condition is ParenthesizedExpression) {
((ParenthesizedExpression)condition).Expression = InvertCondition (((ParenthesizedExpression)condition).Expression);
return condition;
return new ParenthesizedExpression(InvertCondition(((ParenthesizedExpression)condition).Expression));
}
if (condition is UnaryOperatorExpression) {
var uOp = (UnaryOperatorExpression)condition;
if (uOp.Operator == UnaryOperatorType.Not)
return uOp.Expression;
return new UnaryOperatorExpression (UnaryOperatorType.Not, uOp);
if (uOp.Operator == UnaryOperatorType.Not) {
if (!(uOp.Parent is Expression))
return GetInnerMostExpression(uOp.Expression).Clone();
return uOp.Expression.Clone();
}
return new UnaryOperatorExpression(UnaryOperatorType.Not, uOp.Clone());
}
if (condition is BinaryOperatorExpression) {
var bOp = (BinaryOperatorExpression)condition;
var negatedOp = NegateRelationalOperator (bOp.Operator);
if (negatedOp == BinaryOperatorType.Any)
return new UnaryOperatorExpression (UnaryOperatorType.Not, new ParenthesizedExpression (condition));
bOp.Operator = negatedOp;
return bOp;
if ((bOp.Operator == BinaryOperatorType.ConditionalAnd) || (bOp.Operator == BinaryOperatorType.ConditionalOr)) {
return new BinaryOperatorExpression(InvertCondition(bOp.Left), NegateConditionOperator(bOp.Operator), InvertCondition(bOp.Right));
} else if ((bOp.Operator == BinaryOperatorType.Equality) || (bOp.Operator == BinaryOperatorType.InEquality) || (bOp.Operator == BinaryOperatorType.GreaterThan)
|| (bOp.Operator == BinaryOperatorType.GreaterThanOrEqual) || (bOp.Operator == BinaryOperatorType.LessThan) ||
(bOp.Operator == BinaryOperatorType.LessThanOrEqual)) {
return new BinaryOperatorExpression(bOp.Left.Clone(), NegateRelationalOperator(bOp.Operator), bOp.Right.Clone());
} else {
var negatedOp = NegateRelationalOperator(bOp.Operator);
if (negatedOp == BinaryOperatorType.Any)
return new UnaryOperatorExpression(UnaryOperatorType.Not, new ParenthesizedExpression(condition.Clone()));
bOp = (BinaryOperatorExpression)bOp.Clone();
bOp.Operator = negatedOp;
return bOp;
}
}
if (condition is ConditionalExpression) {
var cEx = condition as ConditionalExpression;
cEx.Condition = InvertCondition (cEx.Condition);
var cEx = condition.Clone() as ConditionalExpression;
cEx.Condition = InvertCondition(cEx.Condition);
return cEx;
}
if (condition is PrimitiveExpression) {
var pex = condition as PrimitiveExpression;
if (pex.Value is bool) {
return new PrimitiveExpression (!((bool)pex.Value));
return new PrimitiveExpression(!((bool)pex.Value));
}
}
return new UnaryOperatorExpression (UnaryOperatorType.Not, condition);
return new UnaryOperatorExpression(UnaryOperatorType.Not, AddParensForUnaryExpressionIfRequired(condition.Clone()));
}
/// <summary>
/// When negating an expression this is required, otherwise you would end up with
/// a or b -> !a or b
/// </summary>
internal static Expression AddParensForUnaryExpressionIfRequired(Expression expression)
{
if ((expression is BinaryOperatorExpression) ||
(expression is AssignmentExpression) ||
(expression is CastExpression) ||
(expression is AsExpression) ||
(expression is IsExpression) ||
(expression is LambdaExpression) ||
(expression is ConditionalExpression)) {
return new ParenthesizedExpression(expression);
}
return expression;
}
/// <summary>
@ -78,7 +114,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -78,7 +114,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <returns>
/// negation of the specified relational operator, or BinaryOperatorType.Any if it's not a relational operator
/// </returns>
public static BinaryOperatorType NegateRelationalOperator (BinaryOperatorType op)
public static BinaryOperatorType NegateRelationalOperator(BinaryOperatorType op)
{
switch (op) {
case BinaryOperatorType.GreaterThan:
@ -93,9 +129,52 @@ namespace ICSharpCode.NRefactory.CSharp @@ -93,9 +129,52 @@ namespace ICSharpCode.NRefactory.CSharp
return BinaryOperatorType.GreaterThanOrEqual;
case BinaryOperatorType.LessThanOrEqual:
return BinaryOperatorType.GreaterThan;
case BinaryOperatorType.ConditionalOr:
return BinaryOperatorType.ConditionalAnd;
case BinaryOperatorType.ConditionalAnd:
return BinaryOperatorType.ConditionalOr;
}
return BinaryOperatorType.Any;
}
/// <summary>
/// Returns true, if the specified operator is a relational operator
/// </summary>
public static bool IsRelationalOperator(BinaryOperatorType op)
{
return NegateRelationalOperator(op) != BinaryOperatorType.Any;
}
/// <summary>
/// Get negation of the condition operator
/// </summary>
/// <returns>
/// negation of the specified condition operator, or BinaryOperatorType.Any if it's not a condition operator
/// </returns>
public static BinaryOperatorType NegateConditionOperator(BinaryOperatorType op)
{
switch (op) {
case BinaryOperatorType.ConditionalOr:
return BinaryOperatorType.ConditionalAnd;
case BinaryOperatorType.ConditionalAnd:
return BinaryOperatorType.ConditionalOr;
}
return BinaryOperatorType.Any;
}
public static bool AreConditionsEqual(Expression cond1, Expression cond2)
{
if (cond1 == null || cond2 == null)
return false;
return GetInnerMostExpression(cond1).IsMatch(GetInnerMostExpression(cond2));
}
public static Expression GetInnerMostExpression(Expression target)
{
while (target is ParenthesizedExpression)
target = ((ParenthesizedExpression)target).Expression;
return target;
}
}
}

44
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs

@ -47,7 +47,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,7 +47,13 @@ namespace ICSharpCode.NRefactory.CSharp
return !GetChildByRole(NullableRole).IsNull;
}
set {
SetChildByRole(NullableRole, value ? new CSharpTokenNode(TextLocation.Empty) : null);
SetChildByRole(NullableRole, value ? new CSharpTokenNode(TextLocation.Empty, null) : null);
}
}
public CSharpTokenNode NullableSpecifierToken {
get {
return GetChildByRole(NullableRole);
}
}
@ -64,7 +70,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -64,7 +70,7 @@ namespace ICSharpCode.NRefactory.CSharp
d--;
}
while (d < value) {
InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(TextLocation.Empty), PointerRole);
InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(TextLocation.Empty, PointerRole), PointerRole);
d++;
}
}
@ -73,12 +79,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -73,12 +79,16 @@ namespace ICSharpCode.NRefactory.CSharp
public AstNodeCollection<ArraySpecifier> ArraySpecifiers {
get { return GetChildrenByRole (ArraySpecifierRole); }
}
public AstNodeCollection<CSharpTokenNode> PointerTokens {
get { return GetChildrenByRole (PointerRole); }
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitComposedType (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitComposedType (this);
@ -92,10 +102,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -92,10 +102,12 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
ComposedType o = other as ComposedType;
return o != null && this.HasNullableSpecifier == o.HasNullableSpecifier && this.PointerRank == o.PointerRank && this.ArraySpecifiers.DoMatch(o.ArraySpecifiers, match);
return o != null && this.HasNullableSpecifier == o.HasNullableSpecifier && this.PointerRank == o.PointerRank
&& this.BaseType.DoMatch(o.BaseType, match)
&& this.ArraySpecifiers.DoMatch(o.ArraySpecifiers, match);
}
public override string ToString()
public override string ToString(CSharpFormattingOptions formattingOptions)
{
StringBuilder b = new StringBuilder();
b.Append(this.BaseType.ToString());
@ -126,18 +138,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -126,18 +138,20 @@ namespace ICSharpCode.NRefactory.CSharp
return this;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
ITypeReference t = this.BaseType.ToTypeReference(lookupMode);
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
ITypeReference t = this.BaseType.ToTypeReference(lookupMode, interningProvider);
if (this.HasNullableSpecifier) {
t = NullableType.Create(t);
t = interningProvider.Intern(NullableType.Create(t));
}
int pointerRank = this.PointerRank;
for (int i = 0; i < pointerRank; i++) {
t = new PointerTypeReference(t);
t = interningProvider.Intern(new PointerTypeReference(t));
}
foreach (var a in this.ArraySpecifiers.Reverse()) {
t = new ArrayTypeReference(t, a.Dimensions);
t = interningProvider.Intern(new ArrayTypeReference(t, a.Dimensions));
}
return t;
}
@ -176,7 +190,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -176,7 +190,7 @@ namespace ICSharpCode.NRefactory.CSharp
d--;
}
while (d < value) {
InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(TextLocation.Empty), Roles.Comma);
InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(TextLocation.Empty, Roles.Comma), Roles.Comma);
d++;
}
}
@ -190,7 +204,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -190,7 +204,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitArraySpecifier (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitArraySpecifier (this);
@ -206,8 +220,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -206,8 +220,8 @@ namespace ICSharpCode.NRefactory.CSharp
ArraySpecifier o = other as ArraySpecifier;
return o != null && this.Dimensions == o.Dimensions;
}
public override string ToString()
public override string ToString(CSharpFormattingOptions formattingOptions)
{
return "[" + new string(',', this.Dimensions - 1) + "]";
}

43
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs

@ -44,6 +44,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,6 +44,14 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public virtual void VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
}
public virtual void VisitSyntaxTree (SyntaxTree syntaxTree)
{
VisitChildren (syntaxTree);
@ -613,12 +621,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -613,12 +621,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
VisitChildren (namedExpression);
}
public virtual void VisitEmptyExpression (EmptyExpression emptyExpression)
{
VisitChildren (emptyExpression);
}
public virtual void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern)
{
VisitChildren (placeholder);
@ -642,6 +645,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -642,6 +645,15 @@ namespace ICSharpCode.NRefactory.CSharp
return default (T);
}
public virtual T VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default (T);
}
public virtual T VisitSyntaxTree (SyntaxTree unit)
{
return VisitChildren (unit);
@ -1212,11 +1224,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1212,11 +1224,6 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (namedExpression);
}
public virtual T VisitEmptyExpression (EmptyExpression emptyExpression)
{
return VisitChildren (emptyExpression);
}
public virtual T VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern)
{
return VisitChildren (placeholder);
@ -1240,6 +1247,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1240,6 +1247,15 @@ namespace ICSharpCode.NRefactory.CSharp
return default (S);
}
public virtual S VisitNullNode(AstNode nullNode, T data)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default (S);
}
public virtual S VisitSyntaxTree (SyntaxTree unit, T data)
{
return VisitChildren (unit, data);
@ -1810,11 +1826,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1810,11 +1826,6 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (namedExpression, data);
}
public virtual S VisitEmptyExpression (EmptyExpression emptyExpression, T data)
{
return VisitChildren (emptyExpression, data);
}
public virtual S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data)
{
return VisitChildren (placeholder, data);

30
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DocumentationReference.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -29,29 +29,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -29,29 +29,29 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<AstType> DeclaringTypeRole = new Role<AstType>("DeclaringType", AstType.Null);
public static readonly Role<AstType> ConversionOperatorReturnTypeRole = new Role<AstType>("ConversionOperatorReturnType", AstType.Null);
EntityType entityType;
SymbolKind symbolKind;
OperatorType operatorType;
bool hasParameterList;
/// <summary>
/// Gets/Sets the entity type.
/// Possible values are:
/// <c>EntityType.Operator</c> for operators,
/// <c>EntityType.Indexer</c> for indexers,
/// <c>EntityType.TypeDefinition</c> for references to primitive types,
/// and <c>EntityType.None</c> for everything else.
/// <c>SymbolKind.Operator</c> for operators,
/// <c>SymbolKind.Indexer</c> for indexers,
/// <c>SymbolKind.TypeDefinition</c> for references to primitive types,
/// and <c>SymbolKind.None</c> for everything else.
/// </summary>
public EntityType EntityType {
get { return entityType; }
public SymbolKind SymbolKind {
get { return symbolKind; }
set {
ThrowIfFrozen();
entityType = value;
symbolKind = value;
}
}
/// <summary>
/// Gets/Sets the operator type.
/// This property is only used when EntityType==Operator.
/// This property is only used when SymbolKind==Operator.
/// </summary>
public OperatorType OperatorType {
get { return operatorType; }
@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Gets/sets the member name.
/// This property is only used when EntityType==None.
/// This property is only used when SymbolKind==None.
/// </summary>
public string MemberName {
get { return GetChildByRole(Roles.Identifier).Name; }
@ -95,7 +95,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -95,7 +95,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Gets/Sets the return type of conversion operators.
/// This property is only used when EntityType==Operator and OperatorType is explicit or implicit.
/// This property is only used when SymbolKind==Operator and OperatorType is explicit or implicit.
/// </summary>
public AstType ConversionOperatorReturnType {
get { return GetChildByRole(ConversionOperatorReturnTypeRole); }
@ -113,16 +113,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -113,16 +113,16 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match)
{
DocumentationReference o = other as DocumentationReference;
if (!(o != null && this.EntityType == o.EntityType && this.HasParameterList == o.HasParameterList))
if (!(o != null && this.SymbolKind == o.SymbolKind && this.HasParameterList == o.HasParameterList))
return false;
if (this.EntityType == EntityType.Operator) {
if (this.SymbolKind == SymbolKind.Operator) {
if (this.OperatorType != o.OperatorType)
return false;
if (this.OperatorType == OperatorType.Implicit || this.OperatorType == OperatorType.Explicit) {
if (!this.ConversionOperatorReturnType.DoMatch(o.ConversionOperatorReturnType, match))
return false;
}
} else if (this.EntityType == EntityType.None) {
} else if (this.SymbolKind == SymbolKind.None) {
if (!MatchString(this.MemberName, o.MemberName))
return false;
if (!this.TypeArguments.DoMatch(o.TypeArguments, match))

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ErrorNode.cs

@ -78,8 +78,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -78,8 +78,8 @@ namespace ICSharpCode.NRefactory.CSharp
var o = other as ErrorNode;
return o != null;
}
public override string ToString ()
public override string ToString(CSharpFormattingOptions formattingOptions)
{
return "[ErrorNode]";
}

3
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs

@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp
bool hasParameterList;
public bool HasParameterList {
get { return hasParameterList; }
get { return hasParameterList || Parameters.Any(); }
set { ThrowIfFrozen(); hasParameterList = value; }
}
@ -80,6 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,6 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp
public AnonymousMethodExpression (BlockStatement body, IEnumerable<ParameterDeclaration> parameters = null)
{
if (parameters != null) {
hasParameterList = true;
foreach (var parameter in parameters) {
AddChild (parameter, Roles.Parameter);
}

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayCreateExpression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

5
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs

@ -72,16 +72,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -72,16 +72,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

70
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AsExpression.cs

@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
// 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.Collections.Generic;
using System;
namespace ICSharpCode.NRefactory.CSharp
{
@ -56,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -56,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp
AddChild (expression, Roles.Expression);
AddChild (type, Roles.Type);
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitAsExpression (this);
@ -77,6 +79,72 @@ namespace ICSharpCode.NRefactory.CSharp @@ -77,6 +79,72 @@ namespace ICSharpCode.NRefactory.CSharp
AsExpression o = other as AsExpression;
return o != null && this.Expression.DoMatch(o.Expression, match) && this.Type.DoMatch(o.Type, match);
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
}

67
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs

@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -201,6 +202,72 @@ namespace ICSharpCode.NRefactory.CSharp @@ -201,6 +202,72 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for AssignmentOperatorType");
}
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
public enum AssignmentOperatorType

66
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs

@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -200,6 +201,71 @@ namespace ICSharpCode.NRefactory.CSharp @@ -200,6 +201,71 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for BinaryOperatorType");
}
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
public enum BinaryOperatorType

72
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CastExpression.cs

@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
// 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.Collections.Generic;
using System;
namespace ICSharpCode.NRefactory.CSharp
{
@ -52,13 +54,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,13 +54,13 @@ namespace ICSharpCode.NRefactory.CSharp
public CastExpression ()
{
}
public CastExpression (AstType castToType, Expression expression)
{
AddChild (castToType, Roles.Type);
AddChild (expression, Roles.Expression);
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitCastExpression (this);
@ -79,6 +81,72 @@ namespace ICSharpCode.NRefactory.CSharp @@ -79,6 +81,72 @@ namespace ICSharpCode.NRefactory.CSharp
CastExpression o = other as CastExpression;
return o != null && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match);
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
}

67
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ConditionalExpression.cs

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
// 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.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -91,5 +92,71 @@ namespace ICSharpCode.NRefactory.CSharp @@ -91,5 +92,71 @@ namespace ICSharpCode.NRefactory.CSharp
ConditionalExpression o = other as ConditionalExpression;
return o != null && this.Condition.DoMatch(o.Condition, match) && this.TrueExpression.DoMatch(o.TrueExpression, match) && this.FalseExpression.DoMatch(o.FalseExpression, match);
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
}

54
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs

@ -27,6 +27,42 @@ using System; @@ -27,6 +27,42 @@ using System;
namespace ICSharpCode.NRefactory.CSharp
{
[Obsolete("This class is obsolete. Remove all referencing code.")]
public class EmptyExpression : AstNode
{
#region implemented abstract members of AstNode
public override void AcceptVisitor(IAstVisitor visitor)
{
throw new NotImplementedException();
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
throw new NotImplementedException();
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
throw new NotImplementedException();
}
protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match)
{
throw new NotImplementedException();
}
public override NodeType NodeType {
get {
throw new NotImplementedException();
}
}
#endregion
}
public class ErrorExpression : Expression
{
TextLocation location;
@ -43,6 +79,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,6 +79,11 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public string Error {
get;
private set;
}
public ErrorExpression ()
{
}
@ -51,7 +92,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -51,7 +92,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
this.location = location;
}
public ErrorExpression (string error)
{
this.Error = error;
}
public ErrorExpression (string error, TextLocation location)
{
this.location = location;
this.Error = error;
}
public override void AcceptVisitor (IAstVisitor visitor)
{
// nothing

37
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -43,16 +43,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,16 +43,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -118,13 +119,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -118,13 +119,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
return (Expression)base.Clone();
}
// Make debugging easier by giving Expressions a ToString() implementation
public override string ToString()
{
return DebugToString();
}
public Expression ReplaceWith(Func<Expression, Expression> replaceFunction)
{
if (replaceFunction == null)
@ -136,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -136,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an member reference expression using this expression as target.
/// </summary>
public MemberReferenceExpression Member(string memberName)
public virtual MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
@ -144,7 +139,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -144,7 +139,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an indexer expression using this expression as target.
/// </summary>
public IndexerExpression Indexer(IEnumerable<Expression> arguments)
public virtual IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = this;
@ -155,7 +150,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -155,7 +150,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an indexer expression using this expression as target.
/// </summary>
public IndexerExpression Indexer(params Expression[] arguments)
public virtual IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = this;
@ -166,7 +161,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -166,7 +161,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an invocation expression using this expression as target.
/// </summary>
public InvocationExpression Invoke(string methodName, IEnumerable<Expression> arguments)
public virtual InvocationExpression Invoke(string methodName, IEnumerable<Expression> arguments)
{
return Invoke(methodName, null, arguments);
}
@ -174,7 +169,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -174,7 +169,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an invocation expression using this expression as target.
/// </summary>
public InvocationExpression Invoke(string methodName, params Expression[] arguments)
public virtual InvocationExpression Invoke(string methodName, params Expression[] arguments)
{
return Invoke(methodName, null, arguments);
}
@ -182,7 +177,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -182,7 +177,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an invocation expression using this expression as target.
/// </summary>
public InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
public virtual InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
@ -197,7 +192,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -197,7 +192,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an invocation expression using this expression as target.
/// </summary>
public InvocationExpression Invoke(IEnumerable<Expression> arguments)
public virtual InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = this;
@ -208,7 +203,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -208,7 +203,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Builds an invocation expression using this expression as target.
/// </summary>
public InvocationExpression Invoke(params Expression[] arguments)
public virtual InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = this;
@ -216,17 +211,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -216,17 +211,17 @@ namespace ICSharpCode.NRefactory.CSharp
return ie;
}
public CastExpression CastTo(AstType type)
public virtual CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = this };
}
public AsExpression CastAs(AstType type)
public virtual AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = this };
}
public IsExpression IsType(AstType type)
public virtual IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = this };
}

78
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IsExpression.cs

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
// 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.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -46,6 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -46,6 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole(Roles.Type); }
set { SetChildByRole(Roles.Type, value); }
}
public IsExpression()
{
}
public IsExpression (Expression expression, AstType type)
{
AddChild (expression, Roles.Expression);
AddChild (type, Roles.Type);
}
public override void AcceptVisitor (IAstVisitor visitor)
{
@ -67,6 +79,72 @@ namespace ICSharpCode.NRefactory.CSharp @@ -67,6 +79,72 @@ namespace ICSharpCode.NRefactory.CSharp
IsExpression o = other as IsExpression;
return o != null && this.Expression.DoMatch(o.Expression, match) && this.Type.DoMatch(o.Type, match);
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
}

8
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs

@ -44,10 +44,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,10 +44,18 @@ namespace ICSharpCode.NRefactory.CSharp
set { ThrowIfFrozen(); isAsync = value; }
}
public CSharpTokenNode LParToken {
get { return GetChildByRole (Roles.LPar); }
}
public AstNodeCollection<ParameterDeclaration> Parameters {
get { return GetChildrenByRole (Roles.Parameter); }
}
public CSharpTokenNode RParToken {
get { return GetChildByRole (Roles.RPar); }
}
public CSharpTokenNode ArrowToken {
get { return GetChildByRole (ArrowRole); }
}

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/MemberReferenceExpression.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp
public MemberReferenceExpression (Expression target, string memberName, params AstType[] arguments) : this (target, memberName, (IEnumerable<AstType>)arguments)
{
}
}
public override void AcceptVisitor (IAstVisitor visitor)
{

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

10
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NullReferenceExpression.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
// NullReferenceExpression.cs
//
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
@ -38,6 +38,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,6 +38,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.location = value;
}
public override TextLocation EndLocation {
get {
return new TextLocation (location.Line, location.Column + "null".Length);
@ -57,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -57,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitNullReferenceExpression (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitNullReferenceExpression (this);

78
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
// PrimitiveExpression.cs
//
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
@ -42,10 +42,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,10 +42,22 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.startLocation = value;
this.endLocation = null;
}
string literalValue;
TextLocation? endLocation;
public override TextLocation EndLocation {
get {
return new TextLocation (StartLocation.Line, StartLocation.Column + literalValue.Length);
if (!endLocation.HasValue) {
endLocation = value is string ? AdvanceLocation (StartLocation, literalValue ?? "") :
new TextLocation (StartLocation.Line, StartLocation.Column + (literalValue ?? "").Length);
}
return endLocation.Value;
}
}
@ -53,46 +65,56 @@ namespace ICSharpCode.NRefactory.CSharp @@ -53,46 +65,56 @@ namespace ICSharpCode.NRefactory.CSharp
public object Value {
get { return this.value; }
set {
ThrowIfFrozen();
set {
ThrowIfFrozen();
this.value = value;
literalValue = null;
}
}
/// <remarks>Never returns null.</remarks>
public string LiteralValue {
get { return literalValue ?? ""; }
}
/// <remarks>Can be null.</remarks>
public string UnsafeLiteralValue {
get { return literalValue; }
set {
if (value == null)
throw new ArgumentNullException();
ThrowIfFrozen();
literalValue = value;
}
}
public void SetValue(object value, string literalValue)
{
if (value == null)
throw new ArgumentNullException();
ThrowIfFrozen();
this.value = value;
this.literalValue = literalValue;
}
public PrimitiveExpression (object value)
{
this.Value = value;
this.literalValue = "";
this.literalValue = null;
}
public PrimitiveExpression (object value, string literalValue)
{
this.Value = value;
this.literalValue = literalValue ?? "";
this.literalValue = literalValue;
}
public PrimitiveExpression (object value, TextLocation startLocation, string literalValue)
{
this.Value = value;
this.startLocation = startLocation;
this.literalValue = literalValue ?? "";
this.literalValue = literalValue;
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitPrimitiveExpression (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitPrimitiveExpression (this);
@ -102,6 +124,34 @@ namespace ICSharpCode.NRefactory.CSharp @@ -102,6 +124,34 @@ namespace ICSharpCode.NRefactory.CSharp
{
return visitor.VisitPrimitiveExpression (this, data);
}
unsafe static TextLocation AdvanceLocation(TextLocation startLocation, string str)
{
int line = startLocation.Line;
int col = startLocation.Column;
fixed (char* start = str) {
char* p = start;
char* endPtr = start + str.Length;
while (p < endPtr) {
var nl = NewLine.GetDelimiterLength(*p, () => {
char* nextp = p + 1;
if (nextp < endPtr)
return *nextp;
return '\0';
});
if (nl > 0) {
line++;
col = 1;
if (nl == 2)
p++;
} else {
col++;
}
p++;
}
}
return new TextLocation (line, col);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{

89
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -38,16 +38,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,16 +38,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -81,6 +82,72 @@ namespace ICSharpCode.NRefactory.CSharp @@ -81,6 +82,72 @@ namespace ICSharpCode.NRefactory.CSharp
QueryExpression o = other as QueryExpression;
return o != null && !o.IsNull && this.Clauses.DoMatch(o.Clauses, match);
}
#region Builder methods
public override MemberReferenceExpression Member(string memberName)
{
return new MemberReferenceExpression { Target = this, MemberName = memberName };
}
public override IndexerExpression Indexer(IEnumerable<Expression> arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override IndexerExpression Indexer(params Expression[] arguments)
{
IndexerExpression expr = new IndexerExpression();
expr.Target = new ParenthesizedExpression(this);
expr.Arguments.AddRange(arguments);
return expr;
}
public override InvocationExpression Invoke(string methodName, IEnumerable<AstType> typeArguments, IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
MemberReferenceExpression mre = new MemberReferenceExpression();
mre.Target = new ParenthesizedExpression(this);
mre.MemberName = methodName;
mre.TypeArguments.AddRange(typeArguments);
ie.Target = mre;
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(IEnumerable<Expression> arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override InvocationExpression Invoke(params Expression[] arguments)
{
InvocationExpression ie = new InvocationExpression();
ie.Target = new ParenthesizedExpression(this);
ie.Arguments.AddRange(arguments);
return ie;
}
public override CastExpression CastTo(AstType type)
{
return new CastExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override AsExpression CastAs(AstType type)
{
return new AsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
public override IsExpression IsType(AstType type)
{
return new IsExpression { Type = type, Expression = new ParenthesizedExpression(this) };
}
#endregion
}
public abstract class QueryClause : AstNode
@ -118,6 +185,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -118,6 +185,10 @@ namespace ICSharpCode.NRefactory.CSharp
set { SetChildByRole(PrecedingQueryRole, value); }
}
public CSharpTokenNode IntoKeyword {
get { return GetChildByRole (IntoKeywordRole); }
}
public string Identifier {
get {
return GetChildByRole (Roles.Identifier).Name;
@ -158,6 +229,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -158,6 +229,10 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly TokenRole FromKeywordRole = new TokenRole ("from");
public static readonly TokenRole InKeywordRole = new TokenRole ("in");
public CSharpTokenNode FromKeyword {
get { return GetChildByRole (FromKeywordRole); }
}
public AstType Type {
get { return GetChildByRole (Roles.Type); }
set { SetChildByRole (Roles.Type, value); }
@ -176,6 +251,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -176,6 +251,10 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole(Roles.Identifier); }
}
public CSharpTokenNode InKeyword {
get { return GetChildByRole (InKeywordRole); }
}
public Expression Expression {
get { return GetChildByRole (Roles.Expression); }
set { SetChildByRole (Roles.Expression, value); }

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

5
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs

@ -62,9 +62,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -62,9 +62,10 @@ namespace ICSharpCode.NRefactory.CSharp
public CSharpTokenNode OperatorToken {
get { return GetChildByRole (GetOperatorRole (Operator)); }
}
static Expression NoUnaryExpressionError = new ErrorExpression ("No unary expression");
public Expression Expression {
get { return GetChildByRole (Roles.Expression); }
get { return GetChildByRole (Roles.Expression) ?? NoUnaryExpressionError; }
set { SetChildByRole (Roles.Expression, value); }
}

19
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Attribute.cs

@ -43,11 +43,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,11 +43,19 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole (Roles.Type); }
set { SetChildByRole (Roles.Type, value); }
}
public CSharpTokenNode LParToken {
get { return GetChildByRole (Roles.LPar); }
}
public AstNodeCollection<Expression> Arguments {
get { return base.GetChildrenByRole (Roles.Argument); }
}
public CSharpTokenNode RParToken {
get { return GetChildByRole (Roles.RPar); }
}
// HasArgumentList == false: [Empty]
public bool HasArgumentList {
get;
@ -74,13 +82,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -74,13 +82,12 @@ namespace ICSharpCode.NRefactory.CSharp
Attribute o = other as Attribute;
return o != null && this.Type.DoMatch (o.Type, match) && this.Arguments.DoMatch (o.Arguments, match);
}
public override string ToString ()
public override string ToString(CSharpFormattingOptions formattingOptions)
{
if (IsNull)
return "Null";
else
return GetText();
return base.ToString(formattingOptions);
}
}
}

15
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/AttributeSection.cs

@ -135,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -135,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
AttributeSection o = other as AttributeSection;
return o != null && this.AttributeTarget == o.AttributeTarget && this.Attributes.DoMatch(o.Attributes, match);
return o != null && MatchString(this.AttributeTarget, o.AttributeTarget) && this.Attributes.DoMatch(o.Attributes, match);
}
public AttributeSection()
@ -171,17 +171,4 @@ namespace ICSharpCode.NRefactory.CSharp @@ -171,17 +171,4 @@ namespace ICSharpCode.NRefactory.CSharp
// }
// }
}
public enum AttributeTarget {
None,
Assembly,
Module,
Type,
Param,
Field,
Return,
Method,
Unknown
}
}

9
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs

@ -65,6 +65,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -65,6 +65,15 @@ namespace ICSharpCode.NRefactory.CSharp
set { ThrowIfFrozen(); commentType = value; }
}
/// <summary>
/// Returns true if the <see cref="CommentType"/> is Documentation or MultiLineDocumentation.
/// </summary>
public bool IsDocumentation {
get {
return commentType == CommentType.Documentation || commentType == CommentType.MultiLineDocumentation;
}
}
bool startsLine;
public bool StartsLine {

6
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs

@ -41,7 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,7 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp
return NodeType.Unknown;
}
}
public CSharpTokenNode WhereKeyword {
get { return GetChildByRole (Roles.WhereKeyword); }
}
public SimpleType TypeParameter {
get {
return GetChildByRole (Roles.ConstraintTypeParameter);

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/DelegateDeclaration.cs

@ -37,8 +37,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,8 +37,8 @@ namespace ICSharpCode.NRefactory.CSharp
get { return NodeType.TypeDeclaration; }
}
public override EntityType EntityType {
get { return EntityType.TypeDefinition; }
public override SymbolKind SymbolKind {
get { return SymbolKind.TypeDefinition; }
}
public CSharpTokenNode DelegateToken {

111
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NamespaceDeclaration.cs

@ -23,10 +23,10 @@ @@ -23,10 +23,10 @@
// 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.Collections.Generic;
using System.Linq;
using System.Text;
using System;
namespace ICSharpCode.NRefactory.CSharp
{
@ -36,36 +36,42 @@ namespace ICSharpCode.NRefactory.CSharp @@ -36,36 +36,42 @@ namespace ICSharpCode.NRefactory.CSharp
public class NamespaceDeclaration : AstNode
{
public static readonly Role<AstNode> MemberRole = SyntaxTree.MemberRole;
public static readonly Role<AstType> NamespaceNameRole = new Role<AstType>("NamespaceName", AstType.Null);
public override NodeType NodeType {
get {
return NodeType.Unknown;
}
}
public CSharpTokenNode NamespaceToken {
get { return GetChildByRole (Roles.NamespaceKeyword); }
get { return GetChildByRole(Roles.NamespaceKeyword); }
}
public AstType NamespaceName {
get { return GetChildByRole(NamespaceNameRole) ?? AstType.Null; }
set { SetChildByRole(NamespaceNameRole, value); }
}
public string Name {
get {
StringBuilder builder = new StringBuilder ();
foreach (Identifier identifier in GetChildrenByRole (Roles.Identifier)) {
if (builder.Length > 0)
builder.Append ('.');
builder.Append (identifier.Name);
}
return builder.ToString ();
return UsingDeclaration.ConstructNamespace(NamespaceName);
}
set {
GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident)));
var arr = value.Split('.');
NamespaceName = ConstructType(arr, arr.Length - 1);
}
}
public AstNodeCollection<Identifier> Identifiers {
get { return GetChildrenByRole (Roles.Identifier); }
static AstType ConstructType(string[] arr, int i)
{
if (i < 0 || i >= arr.Length)
throw new ArgumentOutOfRangeException("i");
if (i == 0)
return new SimpleType(arr[i]);
return new MemberType(ConstructType(arr, i - 1), arr[i]);
}
/// <summary>
/// Gets the full namespace name (including any parent namespaces)
/// </summary>
@ -73,65 +79,80 @@ namespace ICSharpCode.NRefactory.CSharp @@ -73,65 +79,80 @@ namespace ICSharpCode.NRefactory.CSharp
get {
NamespaceDeclaration parentNamespace = Parent as NamespaceDeclaration;
if (parentNamespace != null)
return BuildQualifiedName (parentNamespace.FullName, Name);
return BuildQualifiedName(parentNamespace.FullName, Name);
return Name;
}
}
public IEnumerable<string> Identifiers {
get {
var result = new Stack<string>();
AstType type = NamespaceName;
while (type is MemberType) {
var mt = (MemberType)type;
result.Push(mt.MemberName);
type = mt.Target;
}
if (type is SimpleType)
result.Push(((SimpleType)type).Identifier);
return result;
}
}
public CSharpTokenNode LBraceToken {
get { return GetChildByRole (Roles.LBrace); }
get { return GetChildByRole(Roles.LBrace); }
}
public AstNodeCollection<AstNode> Members {
get { return GetChildrenByRole(MemberRole); }
}
public CSharpTokenNode RBraceToken {
get { return GetChildByRole (Roles.RBrace); }
get { return GetChildByRole(Roles.RBrace); }
}
public NamespaceDeclaration ()
public NamespaceDeclaration()
{
}
public NamespaceDeclaration (string name)
public NamespaceDeclaration(string name)
{
this.Name = name;
}
public static string BuildQualifiedName (string name1, string name2)
public static string BuildQualifiedName(string name1, string name2)
{
if (string.IsNullOrEmpty (name1))
if (string.IsNullOrEmpty(name1))
return name2;
if (string.IsNullOrEmpty (name2))
if (string.IsNullOrEmpty(name2))
return name1;
return name1 + "." + name2;
}
public void AddMember (AstNode child)
public void AddMember(AstNode child)
{
AddChild (child, MemberRole);
AddChild(child, MemberRole);
}
public override void AcceptVisitor (IAstVisitor visitor)
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitNamespaceDeclaration (this);
visitor.VisitNamespaceDeclaration(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
return visitor.VisitNamespaceDeclaration (this);
return visitor.VisitNamespaceDeclaration(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitNamespaceDeclaration (this, data);
return visitor.VisitNamespaceDeclaration(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
NamespaceDeclaration o = other as NamespaceDeclaration;
return o != null && MatchString(this.Name, o.Name) && this.Members.DoMatch(o.Members, match);
}
}
};
} ;

109
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NewLineNode.cs

@ -1,16 +1,11 @@ @@ -1,16 +1,11 @@
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 sealed class NewLineNode : AstNode
{
public override NodeType NodeType {
get {
@ -18,8 +13,31 @@ namespace ICSharpCode.NRefactory.CSharp @@ -18,8 +13,31 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public abstract NewLineType NewLineType {
get;
const uint newLineMask = 0xfu << AstNodeFlagsUsedBits;
static readonly UnicodeNewline[] newLineTypes = {
UnicodeNewline.Unknown,
UnicodeNewline.LF,
UnicodeNewline.CRLF,
UnicodeNewline.CR,
UnicodeNewline.NEL,
UnicodeNewline.VT,
UnicodeNewline.FF,
UnicodeNewline.LS,
UnicodeNewline.PS
};
public UnicodeNewline NewLineType {
get {
return newLineTypes[(flags & newLineMask) >> AstNodeFlagsUsedBits];
}
set {
ThrowIfFrozen();
int pos = Array.IndexOf(newLineTypes, value);
if (pos < 0)
pos = 0;
flags &= ~newLineMask; // clear old newline type
flags |= (uint)pos << AstNodeFlagsUsedBits;
}
}
TextLocation startLocation;
@ -44,6 +62,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,6 +62,11 @@ namespace ICSharpCode.NRefactory.CSharp
this.startLocation = startLocation;
}
public sealed override string ToString(CSharpFormattingOptions formattingOptions)
{
return NewLine.GetString (NewLineType);
}
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitNewLine (this);
@ -58,74 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,74 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp
{
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)
protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match)
{
var o = other as MacNewLine;
return o != null;
return other is NewLineNode;
}
}
}

81
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs

@ -24,6 +24,8 @@ @@ -24,6 +24,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
@ -45,6 +47,85 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,6 +47,85 @@ namespace ICSharpCode.NRefactory.CSharp
Pragma = 11,
Line = 12
}
public class LinePreprocessorDirective : PreProcessorDirective
{
public int LineNumber {
get;
set;
}
public string FileName {
get;
set;
}
public LinePreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base (PreProcessorDirectiveType.Line, startLocation, endLocation)
{
}
public LinePreprocessorDirective(string argument = null) : base (PreProcessorDirectiveType.Line, argument)
{
}
}
public class PragmaWarningPreprocessorDirective : PreProcessorDirective
{
public static readonly Role<PrimitiveExpression> WarningRole = new Role<PrimitiveExpression> ("Warning");
public static readonly TokenRole PragmaKeywordRole = new TokenRole ("#pragma");
public static readonly TokenRole WarningKeywordRole = new TokenRole ("warning");
public static readonly TokenRole DisableKeywordRole = new TokenRole ("disable");
public static readonly TokenRole RestoreKeywordRole = new TokenRole ("restore");
public bool Disable {
get {
return !DisableToken.IsNull;
}
}
public CSharpTokenNode PragmaToken {
get { return GetChildByRole (PragmaKeywordRole); }
}
public CSharpTokenNode WarningToken {
get { return GetChildByRole (WarningKeywordRole); }
}
public CSharpTokenNode DisableToken {
get { return GetChildByRole (DisableKeywordRole); }
}
public CSharpTokenNode RestoreToken {
get { return GetChildByRole (RestoreKeywordRole); }
}
public AstNodeCollection<PrimitiveExpression> Warnings {
get { return GetChildrenByRole(WarningRole); }
}
public override TextLocation EndLocation {
get {
var child = LastChild;
if (child == null)
return base.EndLocation;
return child.EndLocation;
}
}
public PragmaWarningPreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base (PreProcessorDirectiveType.Pragma, startLocation, endLocation)
{
}
public PragmaWarningPreprocessorDirective(string argument = null) : base (PreProcessorDirectiveType.Pragma, argument)
{
}
public bool IsDefined(int pragmaWarning)
{
return Warnings.Select(w => (int)w.Value).Any(n => n == pragmaWarning);
}
}
public class PreProcessorDirective : AstNode
{

22
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs

@ -47,8 +47,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,8 +47,8 @@ namespace ICSharpCode.NRefactory.CSharp
get { return NodeType.TypeDeclaration; }
}
public override EntityType EntityType {
get { return EntityType.TypeDefinition; }
public override SymbolKind SymbolKind {
get { return SymbolKind.TypeDefinition; }
}
ClassType classType;
@ -78,9 +78,25 @@ namespace ICSharpCode.NRefactory.CSharp @@ -78,9 +78,25 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public CSharpTokenNode LChevronToken {
get { return GetChildByRole (Roles.LChevron); }
}
public AstNodeCollection<TypeParameterDeclaration> TypeParameters {
get { return GetChildrenByRole (Roles.TypeParameter); }
}
public CSharpTokenNode RChevronToken {
get { return GetChildByRole (Roles.RChevron); }
}
public CSharpTokenNode ColonToken {
get {
return GetChildByRole(Roles.Colon);
}
}
public AstNodeCollection<AstType> BaseTypes {
get { return GetChildrenByRole(Roles.BaseType); }
@ -93,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -93,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp
public CSharpTokenNode LBraceToken {
get { return GetChildByRole (Roles.LBrace); }
}
public AstNodeCollection<EntityDeclaration> Members {
get { return GetChildrenByRole (Roles.TypeMemberRole); }
}

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

27
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingDeclaration.cs

@ -27,6 +27,7 @@ @@ -27,6 +27,7 @@
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -54,7 +55,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -54,7 +55,29 @@ namespace ICSharpCode.NRefactory.CSharp
}
public string Namespace {
get { return this.Import.ToString(); }
get { return ConstructNamespace (Import); }
}
internal static string ConstructNamespace (AstType type)
{
var stack = new Stack<string>();
while (type is MemberType) {
var mt = (MemberType)type;
stack.Push(mt.MemberName);
type = mt.Target;
if (mt.IsDoubleColon) {
stack.Push("::");
} else {
stack.Push(".");
}
}
if (type is SimpleType)
stack.Push(((SimpleType)type).Identifier);
var result = new StringBuilder();
while (stack.Count > 0)
result.Append(stack.Pop());
return result.ToString();
}
public CSharpTokenNode SemicolonToken {
@ -67,7 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -67,7 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp
public UsingDeclaration (string nameSpace)
{
AddChild (new SimpleType (nameSpace), ImportRole);
AddChild (AstType.Create (nameSpace), ImportRole);
}
public UsingDeclaration (AstType import)

14
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -59,8 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -59,8 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp
void VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression);
void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression);
void VisitUncheckedExpression(UncheckedExpression uncheckedExpression);
void VisitEmptyExpression (EmptyExpression emptyExpression);
void VisitQueryExpression(QueryExpression queryExpression);
void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause);
void VisitQueryFromClause(QueryFromClause queryFromClause);
@ -148,6 +147,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -148,6 +147,7 @@ namespace ICSharpCode.NRefactory.CSharp
void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode);
void VisitIdentifier(Identifier identifier);
void VisitNullNode(AstNode nullNode);
void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern);
}
@ -190,8 +190,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -190,8 +190,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression);
S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression);
S VisitUncheckedExpression(UncheckedExpression uncheckedExpression);
S VisitEmptyExpression (EmptyExpression emptyExpression);
S VisitQueryExpression(QueryExpression queryExpression);
S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause);
S VisitQueryFromClause(QueryFromClause queryFromClause);
@ -279,6 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -279,6 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode);
S VisitIdentifier(Identifier identifier);
S VisitNullNode(AstNode nullNode);
S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern);
}
@ -321,8 +321,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -321,8 +321,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data);
S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data);
S VisitUncheckedExpression(UncheckedExpression uncheckedExpression, T data);
S VisitEmptyExpression (EmptyExpression emptyExpression, T data);
S VisitQueryExpression(QueryExpression queryExpression, T data);
S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data);
S VisitQueryFromClause(QueryFromClause queryFromClause, T data);
@ -410,6 +409,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -410,6 +409,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data);
S VisitIdentifier(Identifier identifier, T data);
S VisitNullNode(AstNode nullNode, T data);
S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data);
}
}

13
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs

@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -83,6 +84,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -83,6 +84,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.startLocation = value;
}
const uint verbatimBit = 1u << AstNodeFlagsUsedBits;
public bool IsVerbatim {
@ -127,7 +134,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -127,7 +134,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (string.IsNullOrEmpty(name))
return Identifier.Null;
if (name[0] == '@')
return new Identifier (name.Substring (1), location) { IsVerbatim = true };
return new Identifier (name.Substring (1), new TextLocation (location.Line, location.Column + 1)) { IsVerbatim = true };
else
return new Identifier (name, location);
}

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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

37
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs

@ -115,46 +115,35 @@ namespace ICSharpCode.NRefactory.CSharp @@ -115,46 +115,35 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
MemberType o = other as MemberType;
return o != null && this.IsDoubleColon == o.IsDoubleColon && MatchString(this.MemberName, o.MemberName) && this.Target.DoMatch(o.Target, match);
return o != null && this.IsDoubleColon == o.IsDoubleColon
&& MatchString(this.MemberName, o.MemberName) && this.Target.DoMatch(o.Target, match)
&& this.TypeArguments.DoMatch(o.TypeArguments, match);
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
b.Append(this.Target);
if (IsDoubleColon)
b.Append("::");
else
b.Append('.');
b.Append(this.MemberName);
if (this.TypeArguments.Any()) {
b.Append('<');
b.Append(string.Join(", ", this.TypeArguments));
b.Append('>');
}
return b.ToString();
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
TypeOrNamespaceReference t;
if (this.IsDoubleColon) {
SimpleType st = this.Target as SimpleType;
if (st != null) {
t = new AliasNamespaceReference(st.Identifier);
t = interningProvider.Intern(new AliasNamespaceReference(interningProvider.Intern(st.Identifier)));
} else {
t = null;
}
} else {
t = this.Target.ToTypeReference(lookupMode) as TypeOrNamespaceReference;
t = this.Target.ToTypeReference(lookupMode, interningProvider) as TypeOrNamespaceReference;
}
if (t == null)
return SpecialType.UnknownType;
var typeArguments = new List<ITypeReference>();
foreach (var ta in this.TypeArguments) {
typeArguments.Add(ta.ToTypeReference(lookupMode));
typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider));
}
return new MemberTypeOrNamespaceReference(t, this.MemberName, typeArguments, lookupMode);
string memberName = interningProvider.Intern(this.MemberName);
return interningProvider.Intern(new MemberTypeOrNamespaceReference(t, memberName, interningProvider.InternList(typeArguments), lookupMode));
}
}
}

11
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs

@ -44,6 +44,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,6 +44,10 @@ namespace ICSharpCode.NRefactory.CSharp
if (leave != null)
leave(node);
}
void IAstVisitor.VisitNullNode(AstNode nullNode)
{
}
public event Action<SyntaxTree> EnterSyntaxTree, LeaveSyntaxTree;
@ -842,13 +846,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -842,13 +846,6 @@ namespace ICSharpCode.NRefactory.CSharp
Visit(EnterNamedExpression, LeaveNamedExpression, namedExpression);
}
public event Action<EmptyExpression> EnterEmptyExpression, LeaveEmptyExpression;
void IAstVisitor.VisitEmptyExpression(EmptyExpression emptyExpression)
{
Visit(EnterEmptyExpression, LeaveEmptyExpression, emptyExpression);
}
void IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern)
{
}

13
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs

@ -71,6 +71,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -71,6 +71,13 @@ namespace ICSharpCode.NRefactory.CSharp
return location;
}
}
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.location = value;
}
public override TextLocation EndLocation {
get {
return new TextLocation (location.Line, location.Column + keyword.Length);
@ -97,13 +104,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -97,13 +104,13 @@ namespace ICSharpCode.NRefactory.CSharp
PrimitiveType o = other as PrimitiveType;
return o != null && MatchString(this.Keyword, o.Keyword);
}
public override string ToString()
public override string ToString(CSharpFormattingOptions formattingOptions)
{
return Keyword;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
KnownTypeCode typeCode = GetTypeCodeForPrimitiveType(this.Keyword);
if (typeCode == KnownTypeCode.None)

34
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs

@ -49,16 +49,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,16 +49,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -66,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -66,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp
return other == null || other.IsNull;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
return SpecialType.UnknownType;
}
@ -130,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -130,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitSimpleType (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitSimpleType (this);
@ -147,28 +148,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -147,28 +148,21 @@ namespace ICSharpCode.NRefactory.CSharp
return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match);
}
public override string ToString()
{
StringBuilder b = new StringBuilder(this.Identifier);
if (this.TypeArguments.Any()) {
b.Append('<');
b.Append(string.Join(", ", this.TypeArguments));
b.Append('>');
}
return b.ToString();
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type)
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
var typeArguments = new List<ITypeReference>();
foreach (var ta in this.TypeArguments) {
typeArguments.Add(ta.ToTypeReference(lookupMode));
typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider));
}
if (typeArguments.Count == 0 && string.IsNullOrEmpty(this.Identifier)) {
string identifier = interningProvider.Intern(this.Identifier);
if (typeArguments.Count == 0 && string.IsNullOrEmpty(identifier)) {
// empty SimpleType is used for typeof(List<>).
return SpecialType.UnboundTypeArgument;
}
return new SimpleTypeOrNamespaceReference(this.Identifier, typeArguments, lookupMode);
var t = new SimpleTypeOrNamespaceReference(identifier, interningProvider.InternList(typeArguments), lookupMode);
return interningProvider.Intern(t);
}
}
}

14
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs

@ -47,16 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,16 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -150,11 +151,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -150,11 +151,6 @@ namespace ICSharpCode.NRefactory.CSharp
AddChild(statement, StatementRole);
}
public void Add(Expression expression)
{
AddChild(new ExpressionStatement(expression), StatementRole);
}
IEnumerator<Statement> IEnumerable<Statement>.GetEnumerator()
{
return this.Statements.GetEnumerator();

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BreakStatement.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp
public CSharpTokenNode SemicolonToken {
get { return GetChildByRole (Roles.Semicolon); }
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitBreakStatement (this);

10
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/DoWhileStatement.cs

@ -84,6 +84,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -84,6 +84,16 @@ namespace ICSharpCode.NRefactory.CSharp
DoWhileStatement o = other as DoWhileStatement;
return o != null && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match) && this.Condition.DoMatch(o.Condition, match);
}
public DoWhileStatement()
{
}
public DoWhileStatement(Expression condition, Statement embeddedStatement)
{
this.Condition = condition;
this.EmbeddedStatement = embeddedStatement;
}
}
}

2
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/LabelStatement.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp
set { SetChildByRole (Roles.Identifier, value); }
}
public CSharpTokenNode Colon {
public CSharpTokenNode ColonToken {
get { return GetChildByRole (Roles.Colon); }
}

35
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs

@ -1,5 +1,20 @@ @@ -1,5 +1,20 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
// Copyright (c) 2010-2013 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;
@ -27,16 +42,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -27,16 +42,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -107,11 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -107,11 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp
public override NodeType NodeType {
get { return NodeType.Statement; }
}
// Make debugging easier by giving Statements a ToString() implementation
public override string ToString()
public static implicit operator Statement (Expression type)
{
return DebugToString();
return new ExpressionStatement(type);
}
}
}

5
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs

@ -104,16 +104,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -104,16 +104,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

10
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/WhileStatement.cs

@ -75,5 +75,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -75,5 +75,15 @@ namespace ICSharpCode.NRefactory.CSharp
WhileStatement o = other as WhileStatement;
return o != null && this.Condition.DoMatch(o.Condition, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match);
}
public WhileStatement()
{
}
public WhileStatement(Expression condition, Statement embeddedStatement)
{
this.Condition = condition;
this.EmbeddedStatement = embeddedStatement;
}
}
}

45
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxExtensions.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
// Copyright (c) 2013 Daniel Grunwald
//
// 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>
/// Extension methods for the syntax tree.
/// </summary>
public static class SyntaxExtensions
{
public static bool IsComparisonOperator(this OperatorType operatorType)
{
switch (operatorType) {
case OperatorType.Equality:
case OperatorType.Inequality:
case OperatorType.GreaterThan:
case OperatorType.LessThan:
case OperatorType.GreaterThanOrEqual:
case OperatorType.LessThanOrEqual:
return true;
default:
return false;
}
}
}
}

21
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs

@ -105,27 +105,34 @@ namespace ICSharpCode.NRefactory.CSharp @@ -105,27 +105,34 @@ namespace ICSharpCode.NRefactory.CSharp
{
}
public IEnumerable<TypeDeclaration> GetTypes(bool includeInnerTypes = false)
/// <summary>
/// Gets all defined types in this syntax tree.
/// </summary>
/// <returns>
/// A list containing <see cref="TypeDeclaration"/> or <see cref="DelegateDeclaration"/> nodes.
/// </returns>
public IEnumerable<EntityDeclaration> GetTypes(bool includeInnerTypes = false)
{
Stack<AstNode> nodeStack = new Stack<AstNode> ();
nodeStack.Push(this);
while (nodeStack.Count > 0) {
var curNode = nodeStack.Pop();
if (curNode is TypeDeclaration) {
yield return (TypeDeclaration)curNode;
if (curNode is TypeDeclaration || curNode is DelegateDeclaration) {
yield return (EntityDeclaration)curNode;
}
foreach (var child in curNode.Children) {
if (!(child is Statement || child is Expression) &&
(child.Role != Roles.TypeMemberRole || (child is TypeDeclaration && includeInnerTypes)))
(child.Role != Roles.TypeMemberRole || ((child is TypeDeclaration || child is DelegateDeclaration) && includeInnerTypes)))
nodeStack.Push (child);
}
}
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
SyntaxTree o = other as SyntaxTree;
return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match);
return o != null && this.Members.DoMatch(o.Members, match);
}
public override void AcceptVisitor (IAstVisitor visitor)
@ -157,24 +164,28 @@ namespace ICSharpCode.NRefactory.CSharp @@ -157,24 +164,28 @@ namespace ICSharpCode.NRefactory.CSharp
public static SyntaxTree Parse (string program, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var parser = new CSharpParser (settings);
return parser.Parse (program, fileName);
}
public static SyntaxTree Parse (TextReader reader, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var parser = new CSharpParser (settings);
return parser.Parse (reader, fileName);
}
public static SyntaxTree Parse (Stream stream, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var parser = new CSharpParser (settings);
return parser.Parse (stream, fileName);
}
public static SyntaxTree Parse (ITextSource textSource, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var parser = new CSharpParser (settings);
return parser.Parse (textSource, fileName);
}

32
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TokenRole.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
@ -7,6 +8,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -7,6 +8,17 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public sealed class TokenRole : Role<CSharpTokenNode>
{
internal readonly static List<string> Tokens = new List<string> ();
internal readonly static List<int> TokenLengths = new List<int> ();
internal readonly uint TokenIndex;
static TokenRole ()
{
// null token
Tokens.Add ("");
TokenLengths.Add (0);
}
/// <summary>
/// Gets the token as string. Note that the token Name and Token value may differ.
/// </summary>
@ -22,11 +34,27 @@ namespace ICSharpCode.NRefactory.CSharp @@ -22,11 +34,27 @@ namespace ICSharpCode.NRefactory.CSharp
get;
private set;
}
public TokenRole (string token) : base (token, CSharpTokenNode.Null)
public TokenRole(string token) : base (token, CSharpTokenNode.Null)
{
this.Token = token;
this.Length = token.Length;
bool found = false;
for (int i = 0; i < Tokens.Count; i++) {
var existingToken = Tokens [i];
if (existingToken == token) {
TokenIndex = (uint)i;
found = true;
break;
}
}
if (!found) {
TokenIndex = (uint)Tokens.Count;
Tokens.Add (token);
TokenLengths.Add (this.Length);
}
}
}
}

25
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs

@ -45,16 +45,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,16 +45,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -67,8 +68,24 @@ namespace ICSharpCode.NRefactory.CSharp @@ -67,8 +68,24 @@ namespace ICSharpCode.NRefactory.CSharp
get { return NodeType.Unknown; }
}
public override EntityType EntityType {
get { return EntityType.Method; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Method; }
}
/// <summary>
/// Gets the 'get'/'set'/'add'/'remove' keyword
/// </summary>
public CSharpTokenNode Keyword {
get {
for (AstNode child = this.FirstChild; child != null; child = child.NextSibling) {
if (child.Role == PropertyDeclaration.GetKeywordRole || child.Role == PropertyDeclaration.SetKeywordRole
|| child.Role == CustomEventDeclaration.AddKeywordRole || child.Role == CustomEventDeclaration.RemoveKeywordRole)
{
return (CSharpTokenNode)child;
}
}
return CSharpTokenNode.Null;
}
}
public BlockStatement Body {

25
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs

@ -32,8 +32,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -32,8 +32,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
public static readonly Role<ConstructorInitializer> InitializerRole = new Role<ConstructorInitializer>("Initializer", ConstructorInitializer.Null);
public override EntityType EntityType {
get { return EntityType.Constructor; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Constructor; }
}
public CSharpTokenNode LParToken {
@ -86,6 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -86,6 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
public enum ConstructorInitializerType {
Any,
Base,
This
}
@ -112,16 +113,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -112,16 +113,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -141,6 +143,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -141,6 +143,15 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public CSharpTokenNode Keyword {
get {
if (ConstructorInitializerType == ConstructorInitializerType.Base)
return GetChildByRole(BaseKeywordRole);
else
return GetChildByRole(ThisKeywordRole);
}
}
public CSharpTokenNode LParToken {
get { return GetChildByRole (Roles.LPar); }
}
@ -171,7 +182,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -171,7 +182,9 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
ConstructorInitializer o = other as ConstructorInitializer;
return o != null && !o.IsNull && this.ConstructorInitializerType == o.ConstructorInitializerType && this.Arguments.DoMatch(o.Arguments, match);
return o != null && !o.IsNull
&& (this.ConstructorInitializerType == ConstructorInitializerType.Any || this.ConstructorInitializerType == o.ConstructorInitializerType)
&& this.Arguments.DoMatch(o.Arguments, match);
}
}
}

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/DestructorDeclaration.cs

@ -36,8 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -36,8 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole (TildeRole); }
}
public override EntityType EntityType {
get { return EntityType.Destructor; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Destructor; }
}
public CSharpTokenNode LParToken {

10
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EntityDeclaration.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return NodeType.Member; }
}
public abstract NRefactory.TypeSystem.EntityType EntityType { get; }
public abstract NRefactory.TypeSystem.SymbolKind SymbolKind { get; }
public AstNodeCollection<AttributeSection> Attributes {
get { return base.GetChildrenByRole (AttributeRole); }
@ -71,7 +71,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -71,7 +71,11 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole (Roles.Type); }
set { SetChildByRole(Roles.Type, value); }
}
public CSharpTokenNode SemicolonToken {
get { return GetChildByRole (Roles.Semicolon); }
}
internal static Modifiers GetModifiers(AstNode node)
{
Modifiers m = 0;

10
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs

@ -33,10 +33,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,10 +33,14 @@ namespace ICSharpCode.NRefactory.CSharp
{
public static readonly Role<Expression> InitializerRole = new Role<Expression>("Initializer", Expression.Null);
public override EntityType EntityType {
get { return EntityType.Field; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Field; }
}
public CSharpTokenNode AssignToken {
get { return GetChildByRole (Roles.Assign); }
}
public Expression Initializer {
get { return GetChildByRole (InitializerRole); }
set { SetChildByRole (InitializerRole, value); }

31
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EventDeclaration.cs

@ -24,7 +24,10 @@ @@ -24,7 +24,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
@ -33,14 +36,32 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,14 +36,32 @@ namespace ICSharpCode.NRefactory.CSharp
{
public static readonly TokenRole EventKeywordRole = new TokenRole ("event");
public override EntityType EntityType {
get { return EntityType.Event; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Event; }
}
public CSharpTokenNode EventToken {
get { return GetChildByRole (EventKeywordRole); }
}
public AstNodeCollection<VariableInitializer> Variables {
get { return GetChildrenByRole (Roles.Variable); }
}
// Hide .Name and .NameToken from users; the actual field names
// are stored in the VariableInitializer.
[EditorBrowsable(EditorBrowsableState.Never)]
public override string Name {
get { return string.Empty; }
set { throw new NotSupportedException(); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
set { throw new NotSupportedException(); }
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitEventDeclaration (this);
@ -73,8 +94,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -73,8 +94,8 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<Accessor> AddAccessorRole = new Role<Accessor>("AddAccessor", Accessor.Null);
public static readonly Role<Accessor> RemoveAccessorRole = new Role<Accessor>("RemoveAccessor", Accessor.Null);
public override EntityType EntityType {
get { return EntityType.Event; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Event; }
}
/// <summary>

20
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FieldDeclaration.cs

@ -24,20 +24,36 @@ @@ -24,20 +24,36 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.ComponentModel;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
public class FieldDeclaration : EntityDeclaration
{
public override EntityType EntityType {
get { return EntityType.Field; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Field; }
}
public AstNodeCollection<VariableInitializer> Variables {
get { return GetChildrenByRole (Roles.Variable); }
}
// Hide .Name and .NameToken from users; the actual field names
// are stored in the VariableInitializer.
[EditorBrowsable(EditorBrowsableState.Never)]
public override string Name {
get { return string.Empty; }
set { throw new NotSupportedException(); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
set { throw new NotSupportedException(); }
}
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitFieldDeclaration (this);

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs

@ -33,8 +33,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,8 +33,8 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly TokenRole FixedKeywordRole = new TokenRole ("fixed");
public static readonly Role<FixedVariableInitializer> VariableRole = new Role<FixedVariableInitializer> ("FixedVariable");
public override EntityType EntityType {
get { return EntityType.Field; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Field; }
}
public CSharpTokenNode FixedToken {

12
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/IndexerDeclaration.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.ComponentModel;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
@ -35,8 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -35,8 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<Accessor> GetterRole = PropertyDeclaration.GetterRole;
public static readonly Role<Accessor> SetterRole = PropertyDeclaration.SetterRole;
public override EntityType EntityType {
get { return EntityType.Indexer; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Indexer; }
}
/// <summary>
@ -53,14 +54,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -53,14 +54,19 @@ namespace ICSharpCode.NRefactory.CSharp
set { throw new NotSupportedException(); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
set { throw new NotSupportedException(); }
}
public CSharpTokenNode LBracketToken {
get { return GetChildByRole (Roles.LBracket); }
}
public CSharpTokenNode ThisToken {
get { return GetChildByRole (ThisKeywordRole); }
}
public AstNodeCollection<ParameterDeclaration> Parameters {
get { return GetChildrenByRole (Roles.Parameter); }

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MethodDeclaration.cs

@ -30,8 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -30,8 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
public class MethodDeclaration : EntityDeclaration
{
public override EntityType EntityType {
get { return EntityType.Method; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Method; }
}
/// <summary>

6
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.ComponentModel;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
@ -105,8 +106,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -105,8 +106,8 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly TokenRole ExplicitRole = new TokenRole ("explicit");
public static readonly TokenRole ImplicitRole = new TokenRole ("implicit");
public override EntityType EntityType {
get { return EntityType.Operator; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Operator; }
}
OperatorType operatorType;
@ -250,6 +251,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -250,6 +251,7 @@ namespace ICSharpCode.NRefactory.CSharp
set { throw new NotSupportedException(); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
set { throw new NotSupportedException(); }

17
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs

@ -88,7 +88,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -88,7 +88,11 @@ namespace ICSharpCode.NRefactory.CSharp
SetChildByRole (Roles.Identifier, value);
}
}
public CSharpTokenNode AssignToken {
get { return GetChildByRole (Roles.Assign); }
}
public Expression DefaultExpression {
get { return GetChildByRole (Roles.Expression); }
set { SetChildByRole (Roles.Expression, value); }
@ -127,6 +131,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -127,6 +131,17 @@ namespace ICSharpCode.NRefactory.CSharp
Name = name;
ParameterModifier = modifier;
}
public ParameterDeclaration(string name, ParameterModifier modifier = ParameterModifier.None)
{
Name = name;
ParameterModifier = modifier;
}
public new ParameterDeclaration Clone()
{
return (ParameterDeclaration)base.Clone();
}
}
}

4
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/PropertyDeclaration.cs

@ -34,8 +34,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -34,8 +34,8 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<Accessor> GetterRole = new Role<Accessor>("Getter", Accessor.Null);
public static readonly Role<Accessor> SetterRole = new Role<Accessor>("Setter", Accessor.Null);
public override EntityType EntityType {
get { return EntityType.Property; }
public override SymbolKind SymbolKind {
get { return SymbolKind.Property; }
}
/// <summary>

17
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs

@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
@ -163,15 +164,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -163,15 +164,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
return visitor.VisitVariableInitializer (this, data);
}
public override string ToString()
{
if (this.Initializer.IsNull)
return "[VariableInitializer " + this.Name + "]";
else
return "[VariableInitializer " + this.Name + " = " + this.Initializer.ToString() + "]";
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
VariableInitializer o = other as VariableInitializer;

1201
NRefactory/ICSharpCode.NRefactory.CSharp/Ast/old_ObservableAstVisitor.cs

File diff suppressed because it is too large Load Diff

16
NRefactory/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class CSharpProjectContent : IProjectContent
{
string assemblyName;
string fullAssemblyName;
string projectFileName;
string location;
Dictionary<string, IUnresolvedFile> unresolvedFiles;
@ -48,6 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,6 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected CSharpProjectContent(CSharpProjectContent pc)
{
this.assemblyName = pc.assemblyName;
this.fullAssemblyName = pc.fullAssemblyName;
this.projectFileName = pc.projectFileName;
this.location = pc.location;
this.unresolvedFiles = new Dictionary<string, IUnresolvedFile>(pc.unresolvedFiles, Platform.FileNameComparer);
@ -71,6 +73,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -71,6 +73,10 @@ namespace ICSharpCode.NRefactory.CSharp
get { return assemblyName; }
}
public string FullAssemblyName {
get { return fullAssemblyName; }
}
public string Location {
get { return location; }
}
@ -128,10 +134,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -128,10 +134,16 @@ namespace ICSharpCode.NRefactory.CSharp
return new CSharpProjectContent(this);
}
/// <summary>
/// Sets both the short and the full assembly names.
/// </summary>
/// <param name="newAssemblyName">New full assembly name.</param>
public IProjectContent SetAssemblyName(string newAssemblyName)
{
CSharpProjectContent pc = Clone();
pc.assemblyName = newAssemblyName;
pc.fullAssemblyName = newAssemblyName;
int pos = newAssemblyName != null ? newAssemblyName.IndexOf(',') : -1;
pc.assemblyName = pos < 0 ? newAssemblyName : newAssemblyName.Substring(0, pos);
return pc;
}

216
NRefactory/ICSharpCode.NRefactory.CSharp/CombineQueryExpressions.cs

@ -0,0 +1,216 @@ @@ -0,0 +1,216 @@
//
// CombineQueryExpressions.cs
//
// Modified by Luís Reis <luiscubal@gmail.com> (Copyright (C) 2013)
//
// Copyright header of the original version follows:
//
// Copyright (c) 2011 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.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// Combines query expressions and removes transparent identifiers.
/// </summary>
public class CombineQueryExpressions
{
static readonly InvocationExpression castPattern = new InvocationExpression {
Target = new MemberReferenceExpression {
Target = new AnyNode("inExpr"),
MemberName = "Cast",
TypeArguments = { new AnyNode("targetType") }
}};
public string CombineQuery(AstNode node, AstNode rootQuery = null)
{
if (rootQuery == null) {
rootQuery = node;
}
QueryExpression query = node as QueryExpression;
if (query != null) {
string continuationIdentifier = null;
foreach (var clause in query.Clauses) {
var continuation = clause as QueryContinuationClause;
if (continuation != null) {
CombineQuery(continuation.PrecedingQuery);
}
var from = clause as QueryFromClause;
if (from != null) {
continuationIdentifier = CombineQuery(from.Expression, rootQuery);
}
}
QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
QueryExpression innerQuery = fromClause.Expression as QueryExpression;
if (innerQuery != null) {
continuationIdentifier = continuationIdentifier ?? ((QueryFromClause)innerQuery.Clauses.First()).Identifier;
string transparentIdentifier;
if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, continuationIdentifier, out transparentIdentifier)) {
RemoveTransparentIdentifierReferences(rootQuery, transparentIdentifier);
} else if (fromClause.Type.IsNull) {
QueryContinuationClause continuation = new QueryContinuationClause();
continuation.PrecedingQuery = innerQuery.Detach();
continuation.Identifier = fromClause.Identifier;
fromClause.ReplaceWith(continuation);
}
return transparentIdentifier;
} else {
Match m = castPattern.Match(fromClause.Expression);
if (m.Success) {
fromClause.Type = m.Get<AstType>("targetType").Single().Detach();
fromClause.Expression = m.Get<Expression>("inExpr").Single().Detach();
}
}
}
return null;
}
static readonly QuerySelectClause selectTransparentIdentifierPattern = new QuerySelectClause {
Expression = new AnonymousTypeCreateExpression {
Initializers = {
new AnyNode("nae1"),
new AnyNode("nae2")
}
}
};
bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, string continuationIdentifier, out string transparentIdentifier)
{
transparentIdentifier = fromClause.Identifier;
Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
if (!match.Success)
return false;
QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
Expression nae1 = match.Get<Expression>("nae1").SingleOrDefault();
string nae1Name = ExtractExpressionName(ref nae1);
if (nae1Name == null)
return false;
Expression nae2 = match.Get<Expression>("nae2").SingleOrDefault();
string nae2Name = ExtractExpressionName(ref nae2);
if (nae1Name == null)
return false;
bool introduceLetClause = true;
var nae1Identifier = nae1 as IdentifierExpression;
var nae2Identifier = nae2 as IdentifierExpression;
if (nae1Identifier != null && nae2Identifier != null && nae1Identifier.Identifier == nae1Name && nae2Identifier.Identifier == nae2Name) {
introduceLetClause = false;
}
if (nae1Name != continuationIdentifier) {
if (nae2Name == continuationIdentifier) {
//Members are in reversed order
string tempName = nae1Name;
Expression tempNae = nae1;
nae1Name = nae2Name;
nae1 = nae2;
nae2Name = tempName;
nae2 = tempNae;
} else {
return false;
}
}
if (introduceLetClause && innerQuery.Clauses.OfType<QueryFromClause>().Any(from => from.Identifier == nae2Name)) {
return false;
}
if (introduceLetClause && innerQuery.Clauses.OfType<QueryJoinClause>().Any(join => join.JoinIdentifier == nae2Name)) {
return false;
}
// from * in (from x in ... select new { x = x, y = expr }) ...
// =>
// from x in ... let y = expr ...
fromClause.Remove();
selectClause.Remove();
// Move clauses from innerQuery to query
QueryClause insertionPos = null;
foreach (var clause in innerQuery.Clauses) {
query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
}
if (introduceLetClause) {
query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = nae2Name, Expression = nae2.Detach() });
}
return true;
}
/// <summary>
/// Removes all occurrences of transparent identifiers
/// </summary>
void RemoveTransparentIdentifierReferences(AstNode node, string transparentIdentifier)
{
foreach (AstNode child in node.Children) {
RemoveTransparentIdentifierReferences(child, transparentIdentifier);
}
MemberReferenceExpression mre = node as MemberReferenceExpression;
if (mre != null) {
IdentifierExpression ident = mre.Target as IdentifierExpression;
if (ident != null && ident.Identifier == transparentIdentifier) {
IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
mre.TypeArguments.MoveTo(newIdent.TypeArguments);
newIdent.CopyAnnotationsFrom(mre);
newIdent.RemoveAnnotations<PropertyDeclaration>(); // remove the reference to the property of the anonymous type
mre.ReplaceWith(newIdent);
return;
} else if (mre.MemberName == transparentIdentifier) {
var newVar = mre.Target.Detach();
newVar.CopyAnnotationsFrom(mre);
newVar.RemoveAnnotations<PropertyDeclaration>(); // remove the reference to the property of the anonymous type
mre.ReplaceWith(newVar);
return;
}
}
}
string ExtractExpressionName(ref Expression expr)
{
NamedExpression namedExpr = expr as NamedExpression;
if (namedExpr != null) {
expr = namedExpr.Expression;
return namedExpr.Name;
}
IdentifierExpression identifier = expr as IdentifierExpression;
if (identifier != null) {
return identifier.Identifier;
}
MemberReferenceExpression memberRef = expr as MemberReferenceExpression;
if (memberRef != null) {
return memberRef.MemberName;
}
return null;
}
}
}

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

File diff suppressed because it is too large Load Diff

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

@ -62,6 +62,16 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -62,6 +62,16 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return compilation;
}
}
Version languageVersion = new Version (5, 0);
public Version LanguageVersion {
get {
return languageVersion;
}
set {
languageVersion = value;
}
}
#endregion
protected CSharpCompletionEngineBase(IProjectContent content, ICompletionContextProvider completionContextProvider, CSharpTypeResolveContext ctx)
@ -99,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -99,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// current member, instead of the beginning of the file.
cpos = offset - 1;
var mem = currentMember;
if (mem == null || (mem is IType)) {
if (mem == null || (mem is IType) || IsInsideCommentStringOrDirective ()) {
return false;
}
int startPos = document.GetOffset (mem.Region.BeginLine, mem.Region.BeginColumn);
@ -146,143 +156,169 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -146,143 +156,169 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return false;
}
public int GetCurrentParameterIndex (int triggerOffset, int endOffset)
public int GetCurrentParameterIndex(int triggerOffset, int endOffset)
{
char lastChar = document.GetCharAt (endOffset - 1);
if (lastChar == '(' || lastChar == '<') {
return 0;
}
List<string> list;
return GetCurrentParameterIndex (triggerOffset, endOffset, out list);
}
public int GetCurrentParameterIndex (int triggerOffset, int endOffset, out List<string> usedNamedParameters)
{
usedNamedParameters =new List<string> ();
var parameter = new Stack<int> ();
var bracketStack = new Stack<Stack<int>> ();
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false;
var word = new StringBuilder ();
bool foundCharAfterOpenBracket = false;
for (int i = triggerOffset; i < endOffset; i++) {
char ch = document.GetCharAt (i);
char nextCh = i + 1 < document.TextLength ? document.GetCharAt (i + 1) : '\0';
if (ch == ':') {
usedNamedParameters.Add (word.ToString ());
word.Length = 0;
} else if (char.IsLetterOrDigit (ch) || ch =='_') {
word.Append (ch);
} else if (char.IsWhiteSpace (ch)) {
} else {
word.Length = 0;
}
if (!char.IsWhiteSpace(ch) && parameter.Count > 0)
foundCharAfterOpenBracket = true;
switch (ch) {
case '{':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
bracketStack.Push (parameter);
parameter = new Stack<int> ();
break;
case '[':
case '(':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '{':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
bracketStack.Push (parameter);
parameter = new Stack<int> ();
break;
}
parameter.Push (0);
break;
case '}':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '[':
case '(':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
parameter.Push (0);
break;
}
if (bracketStack.Count > 0) {
parameter = bracketStack.Pop ();
} else {
return -1;
}
break;
case ']':
case ')':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '}':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (bracketStack.Count > 0) {
parameter = bracketStack.Pop ();
} else {
return -1;
}
break;
}
if (parameter.Count > 0) {
parameter.Pop ();
} else {
return -1;
}
break;
case '<':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case ']':
case ')':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (parameter.Count > 0) {
parameter.Pop ();
} else {
return -1;
}
break;
}
parameter.Push (0);
break;
case '>':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '<':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
parameter.Push (0);
break;
}
if (parameter.Count > 0) {
parameter.Pop ();
}
break;
case ',':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '=':
if (nextCh == '>') {
i++;
continue;
}
break;
}
if (parameter.Count > 0) {
parameter.Push (parameter.Pop () + 1);
}
break;
case '/':
if (inString || inChar || inVerbatimString) {
case '>':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (parameter.Count > 0) {
parameter.Pop ();
}
break;
}
if (nextCh == '/') {
i++;
inSingleComment = true;
}
if (nextCh == '*') {
inMultiLineComment = true;
}
break;
case '*':
if (inString || inChar || inVerbatimString || inSingleComment) {
case ',':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (parameter.Count > 0) {
parameter.Push (parameter.Pop () + 1);
}
break;
}
if (nextCh == '/') {
i++;
inMultiLineComment = false;
}
break;
case '@':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
case '/':
if (inString || inChar || inVerbatimString) {
break;
}
if (nextCh == '/') {
i++;
inSingleComment = true;
}
if (nextCh == '*') {
inMultiLineComment = true;
}
break;
}
if (nextCh == '"') {
i++;
inVerbatimString = true;
}
break;
case '\n':
case '\r':
inSingleComment = false;
inString = false;
inChar = false;
break;
case '\\':
if (inString || inChar) {
i++;
}
break;
case '"':
if (inSingleComment || inMultiLineComment || inChar) {
case '*':
if (inString || inChar || inVerbatimString || inSingleComment) {
break;
}
if (nextCh == '/') {
i++;
inMultiLineComment = false;
}
break;
}
if (inVerbatimString) {
case '@':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) {
break;
}
if (nextCh == '"') {
i++;
inVerbatimString = true;
}
break;
case '\\':
if (inString || inChar) {
i++;
}
break;
case '"':
if (inSingleComment || inMultiLineComment || inChar) {
break;
}
inVerbatimString = false;
if (inVerbatimString) {
if (nextCh == '"') {
i++;
break;
}
inVerbatimString = false;
break;
}
inString = !inString;
break;
}
inString = !inString;
break;
case '\'':
if (inSingleComment || inMultiLineComment || inString || inVerbatimString) {
case '\'':
if (inSingleComment || inMultiLineComment || inString || inVerbatimString) {
break;
}
inChar = !inChar;
break;
default:
if (NewLine.IsNewLine(ch)) {
inSingleComment = false;
inString = false;
inChar = false;
}
break;
}
inChar = !inChar;
break;
}
}
if (parameter.Count == 0 || bracketStack.Count > 0) {
if (parameter.Count != 1 || bracketStack.Count > 0) {
return -1;
}
if (!foundCharAfterOpenBracket)
return 0;
return parameter.Pop() + 1;
}
@ -291,12 +327,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -291,12 +327,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{
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 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)
@ -304,12 +340,27 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -304,12 +340,27 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
this.text = text;
}
public void Parse(Action<char> act = null)
/// <summary>
/// Parsing all text and calling act delegate on almost every character.
/// Skipping begining of comments, begining of verbatim strings and escaped characters.
/// </summary>
/// <param name="act">Return true to abort parsing. Integer argument represent offset in text.</param>
/// <returns>True if aborted.</returns>
public bool Parse(Func<char, int, bool> act = null)
{
Parse(0, text.Length, act);
return Parse(0, text.Length, act);
}
public void Parse(int start, int length, Action<char> act = null)
/// <summary>
/// Parsing text from start to start+length and calling act delegate on almost every character.
/// Skipping begining of comments, begining of verbatim strings and escaped characters.
/// </summary>
/// <param name="start">Start offset.</param>
/// <param name="length">Lenght to parse.</param>
/// <param name="act">Return true to abort parsing. Integer argument represent offset in text.</param>
/// <returns>True if aborted.</returns>
public bool Parse(int start, int length, Func<char, int, bool> act = null)
{
for (int i = start; i < length; i++) {
char ch = text [i];
@ -318,16 +369,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -318,16 +369,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
case '#':
if (IsFistNonWs)
IsInPreprocessorDirective = true;
break;
break;
case '/':
if (IsInString || IsInChar || IsInVerbatimString)
if (IsInString || IsInChar || IsInVerbatimString || IsInSingleComment || IsInMultiLineComment)
break;
if (nextCh == '/') {
i++;
IsInSingleComment = true;
IsInPreprocessorDirective = false;
}
if (nextCh == '*')
if (nextCh == '*' && !IsInPreprocessorDirective) {
IsInMultiLineComment = true;
i++;
}
break;
case '*':
if (IsInString || IsInChar || IsInVerbatimString || IsInSingleComment)
@ -377,9 +431,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -377,9 +431,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
break;
}
if (act != null)
act(ch);
if (act (ch, i))
return true;
IsFistNonWs &= ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
}
return false;
}
}
@ -405,11 +461,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -405,11 +461,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
lexer.Parse();
return
lexer.IsInSingleComment ||
lexer.IsInString ||
lexer.IsInVerbatimString ||
lexer.IsInChar ||
lexer.IsInMultiLineComment ||
lexer.IsInPreprocessorDirective;
lexer.IsInString ||
lexer.IsInVerbatimString ||
lexer.IsInChar ||
lexer.IsInMultiLineComment ||
lexer.IsInPreprocessorDirective;
}
protected bool IsInsideDocComment ()
@ -566,12 +622,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -566,12 +622,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
inVerbatimString = true;
}
break;
case '\n':
case '\r':
inSingleComment = false;
inString = false;
inChar = false;
break;
case '\\':
if (inString || inChar)
i++;
@ -595,15 +645,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -595,15 +645,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
inChar = !inChar;
break;
default :
if (NewLine.IsNewLine(ch)) {
inSingleComment = false;
inString = false;
inChar = false;
}
break;
}
}
return bracketStack;
}
public static void AppendMissingClosingBrackets (StringBuilder wrapper, string memberText, bool appendSemicolon)
public static void AppendMissingClosingBrackets (StringBuilder wrapper, bool appendSemicolon)
{
var bracketStack = GetBracketStack (memberText);
var memberText = wrapper.ToString();
var bracketStack = GetBracketStack(memberText);
bool didAppendSemicolon = !appendSemicolon;
//char lastBracket = '\0';
while (bracketStack.Count > 0) {
@ -638,7 +694,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -638,7 +694,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
while (o >= "try".Length) {
char ch = memberText [o];
if (!char.IsWhiteSpace (ch)) {
if (ch == 'y' && memberText [o - 1] == 'r' && memberText [o - 2] == 't') {
if (ch == 'y' && memberText [o - 1] == 'r' && memberText [o - 2] == 't' && (o - 3 < 0 || !char.IsLetterOrDigit(memberText [o - 3]))) {
wrapper.Append ("} catch {}");
didAppendCatch = true;
}
@ -655,17 +711,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -655,17 +711,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.Append (';');
}
protected SyntaxTree ParseStub(string continuation, bool appendSemicolon = true, string afterContinuation = null)
protected StringBuilder CreateWrapper(string continuation, bool appendSemicolon, string afterContinuation, string memberText, TextLocation memberLocation, ref int closingBrackets, ref int generatedLines)
{
var mt = GetMemberTextToCaret();
if (mt == null) {
return null;
}
string memberText = mt.Item1;
var memberLocation = mt.Item2;
int closingBrackets = 1;
int generatedLines = 0;
var wrapper = new StringBuilder();
bool wrapInClass = memberLocation != new TextLocation(1, 1);
if (wrapInClass) {
@ -676,11 +723,26 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -676,11 +723,26 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
wrapper.Append(memberText);
wrapper.Append(continuation);
AppendMissingClosingBrackets(wrapper, memberText, appendSemicolon);
AppendMissingClosingBrackets(wrapper, appendSemicolon);
wrapper.Append(afterContinuation);
if (closingBrackets > 0) {
if (closingBrackets > 0) {
wrapper.Append(new string('}', closingBrackets));
}
return wrapper;
}
protected SyntaxTree ParseStub(string continuation, bool appendSemicolon = true, string afterContinuation = null)
{
var mt = GetMemberTextToCaret();
if (mt == null) {
return null;
}
string memberText = mt.Item1;
var memberLocation = mt.Item2;
int closingBrackets = 1;
int generatedLines = 0;
var wrapper = CreateWrapper(continuation, appendSemicolon, afterContinuation, memberText, memberLocation, ref closingBrackets, ref generatedLines);
var parser = new CSharpParser ();
foreach (var sym in CompletionContextProvider.ConditionalSymbols)
parser.CompilerSettings.ConditionalSymbols.Add (sym);
@ -689,23 +751,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -689,23 +751,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result;
}
// string cachedText = null;
protected virtual void Reset ()
{
// cachedText = null;
memberText = null;
}
Tuple<string, TextLocation> memberText;
protected Tuple<string, TextLocation> GetMemberTextToCaret()
{
return CompletionContextProvider.GetMemberTextToCaret(offset, currentType, currentMember);
if (memberText == null)
memberText = CompletionContextProvider.GetMemberTextToCaret(offset, currentType, currentMember);
return memberText;
}
protected ExpressionResult GetInvocationBeforeCursor(bool afterBracket)
{
SyntaxTree baseUnit;
baseUnit = ParseStub("a", false);
var section = baseUnit.GetNodeAt<AttributeSection>(location.Line, location.Column - 2);
var attr = section != null ? section.Attributes.LastOrDefault() : null;
if (attr != null) {
@ -773,12 +836,26 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -773,12 +836,26 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (ExpressionResult tuple)
protected ExpressionResolveResult ResolveExpression (ExpressionResult tuple)
{
return ResolveExpression (tuple.Node);
}
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(AstNode expr)
protected class ExpressionResolveResult
{
public ResolveResult Result { get; set; }
public CSharpResolver Resolver { get; set; }
public CSharpAstResolver AstResolver { get; set; }
public ExpressionResolveResult(ResolveResult item1, CSharpResolver item2, CSharpAstResolver item3)
{
this.Result = item1;
this.Resolver = item2;
this.AstResolver = item3;
}
}
protected ExpressionResolveResult ResolveExpression(AstNode expr)
{
if (expr == null) {
return null;
@ -796,12 +873,29 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -796,12 +873,29 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (root == null) {
return null;
}
if (root is Accessor)
root = root.Parent;
var csResolver = CompletionContextProvider.GetResolver (GetState(), root);
var curState = GetState();
// current member needs to be in the setter because of the 'value' parameter
if (root is Accessor) {
var prop = curState.CurrentMember as IProperty;
if (prop != null && prop.CanSet && (root.Role == IndexerDeclaration.SetterRole || root.Role == PropertyDeclaration.SetterRole))
curState = curState.WithCurrentMember(prop.Setter);
}
// Rood should be the 'body' - otherwise the state -> current member isn't correct.
var body = root.Children.FirstOrDefault(r => r.Role == Roles.Body);
if (body != null && body.Contains(expr.StartLocation))
root = body;
var csResolver = CompletionContextProvider.GetResolver (curState, root);
var result = csResolver.Resolve(resolveNode);
var state = csResolver.GetResolverStateBefore(resolveNode);
return Tuple.Create(result, state);
if (state.CurrentMember == null)
state = state.WithCurrentMember(curState.CurrentMember);
if (state.CurrentTypeDefinition == null)
state = state.WithCurrentTypeDefinition(curState.CurrentTypeDefinition);
if (state.CurrentUsingScope == null)
state = state.WithCurrentUsingScope(curState.CurrentUsingScope);
return new ExpressionResolveResult(result, state, csResolver);
} catch (Exception e) {
Console.WriteLine(e);
return null;

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

@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (currentMember == null && currentType == null) {
return null;
}
baseUnit = ParseStub("x] = a[1");
baseUnit = ParseStub("x]");
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var mref = baseUnit.GetNodeAt(location, n => n is IndexerExpression);
@ -102,6 +102,23 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -102,6 +102,23 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return new ExpressionResult((AstNode)expr, baseUnit);
}
public ExpressionResult GetMethodTypeArgumentInvocationBeforeCursor()
{
SyntaxTree baseUnit;
if (currentMember == null && currentType == null) {
return null;
}
baseUnit = ParseStub("x>.A ()");
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var expr = baseUnit.GetNodeAt<MemberReferenceExpression>(location.Line, location.Column + 1);
if (expr == null)
return null;
return new ExpressionResult((AstNode)expr, baseUnit);
}
IEnumerable<IMethod> CollectMethods(AstNode resolvedNode, MethodGroupResolveResult resolveResult)
{
var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
@ -109,6 +126,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -109,6 +126,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (resolvedNode is IdentifierExpression && currentMember != null && currentMember.IsStatic || resolveResult.TargetResult is TypeResolveResult) {
onlyStatic = true;
}
var methods = new List<IMethod>();
foreach (var method in resolveResult.Methods) {
if (method.IsConstructor) {
continue;
@ -118,32 +136,140 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -118,32 +136,140 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (onlyStatic && !method.IsStatic) {
continue;
}
yield return method;
if (method.IsShadowing) {
for (int j = 0; j < methods.Count; j++) {
if (ParameterListComparer.Instance.Equals(methods[j].Parameters, method.Parameters)) {
methods.RemoveAt (j);
j--;
}
}
}
methods.Add (method);
}
foreach (var m in methods) {
yield return m;
}
foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) {
foreach (var method in extMethods) {
yield return method;
if (methods.Contains (method))
continue;
yield return new ReducedExtensionMethod (method);
}
}
}
IEnumerable<IProperty> GetAccessibleIndexers(IType type)
{
var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
var properties = new List<IProperty>();
foreach (var property in type.GetProperties ()) {
if (!property.IsIndexer)
continue;
if (!lookup.IsAccessible (property, true))
continue;
if (property.IsShadowing) {
for (int j = 0; j < properties.Count; j++) {
if (ParameterListComparer.Instance.Equals(properties[j].Parameters, property.Parameters)) {
properties.RemoveAt (j);
j--;
}
}
}
properties.Add (property);
}
return properties;
}
public IParameterDataProvider GetParameterDataProvider(int offset, char completionChar)
{
if (offset <= 0) {
//Ignoring completionChar == '\0' because it usually means moving with arrow keys, tab or enter
//we don't want to trigger on those events but it probably should be handled somewhere else
//since our job is to resolve method and not to decide when to display tooltip or not
if (offset <= 0 || completionChar == '\0') {
return null;
}
if (completionChar != '(' && completionChar != '<' && completionChar != '[' && completionChar != ',') {
return null;
SetOffset (offset);
int startOffset;
string text;
if (currentMember == null && currentType == null) {
//In case of attributes parse all file
startOffset = 0;
text = document.Text;
} else {
var memberText = GetMemberTextToCaret ();
text = memberText.Item1;
startOffset = document.GetOffset (memberText.Item2);
}
SetOffset(offset);
if (IsInsideCommentStringOrDirective()) {
var parenStack = new Stack<int> ();
var chevronStack = new Stack<int> ();
var squareStack = new Stack<int> ();
var bracketStack = new Stack<int> ();
var lex = new MiniLexer (text);
bool failed = lex.Parse ((ch, off) => {
if (lex.IsInString || lex.IsInChar || lex.IsInVerbatimString || lex.IsInSingleComment || lex.IsInMultiLineComment || lex.IsInPreprocessorDirective)
return false;
switch (ch) {
case '(':
parenStack.Push (startOffset + off);
break;
case ')':
if (parenStack.Count == 0) {
return true;
}
parenStack.Pop ();
break;
case '<':
chevronStack.Push (startOffset + off);
break;
case '>':
//Don't abort if we don't have macthing '<' for '>' it could be if (i > 0) Foo($
if (chevronStack.Count == 0) {
return false;
}
chevronStack.Pop ();
break;
case '[':
squareStack.Push (startOffset + off);
break;
case ']':
if (squareStack.Count == 0) {
return true;
}
squareStack.Pop ();
break;
case '{':
bracketStack.Push (startOffset + off);
break;
case '}':
if (bracketStack.Count == 0) {
return true;
}
bracketStack.Pop ();
break;
}
return false;
});
if (failed)
return null;
}
int result = -1;
if (parenStack.Count > 0)
result = parenStack.Pop ();
if (squareStack.Count > 0)
result = Math.Max (result, squareStack.Pop ());
if (chevronStack.Count > 0)
result = Math.Max (result, chevronStack.Pop ());
//If we are inside { bracket we don't want to display anything
if (bracketStack.Count > 0 && bracketStack.Pop () > result)
return null;
if (result == -1)
return null;
SetOffset (result + 1);
ResolveResult resolveResult;
switch (completionChar) {
switch (document.GetCharAt (result)) {
case '(':
var invoke = GetInvocationBeforeCursor(true) ?? GetConstructorInitializerBeforeCursor();
if (invoke == null) {
@ -152,7 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -152,7 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (invoke.Node is ConstructorInitializer) {
var init = (ConstructorInitializer)invoke.Node;
if (init.ConstructorInitializerType == ConstructorInitializerType.This) {
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition, init);
} else {
var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface);
if (baseType == null) {
@ -163,23 +289,23 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -163,23 +289,23 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
if (invoke.Node is ObjectCreateExpression) {
var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type);
if (createType.Item1.Type.Kind == TypeKind.Unknown)
if (createType.Result.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.Result.Type);
}
if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression(invoke);
if (attribute == null || attribute.Item1 == null) {
if (attribute == null || attribute.Result == null) {
return null;
}
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Item1.Type);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Result.Type);
}
var invocationExpression = ResolveExpression(invoke);
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) {
if (invocationExpression == null || invocationExpression.Result == null || invocationExpression.Result.IsError) {
return null;
}
resolveResult = invocationExpression.Item1;
resolveResult = invocationExpression.Result;
if (resolveResult is MethodGroupResolveResult) {
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult));
}
@ -189,98 +315,54 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -189,98 +315,54 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member });
}
}
if (resolveResult.Type.Kind == TypeKind.Delegate) {
return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type);
}
//
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
// if (resolveResult is ThisResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
// if (resolveResult is BaseResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
// }
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
// }
//
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
// if (resolveResult is ThisResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
// if (resolveResult is BaseResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
// }
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
// }
break;
case ',':
invoke = GetInvocationBeforeCursor(true) ?? GetIndexerBeforeCursor();
if (invoke == null) {
invoke = GetTypeBeforeCursor();
if (invoke != null) {
if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0)
return null;
var typeExpression = ResolveExpression(invoke);
if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) {
return null;
}
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(typeExpression.Item1.Type));
}
return null;
}
if (GetCurrentParameterIndex(document.GetOffset(invoke.Node.StartLocation), offset) < 0)
return null;
if (invoke.Node is ObjectCreateExpression) {
var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
}
if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression(invoke);
if (attribute == null || attribute.Item1 == null) {
return null;
}
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Item1.Type);
}
invocationExpression = ResolveExpression(invoke);
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) {
return null;
}
resolveResult = invocationExpression.Item1;
if (resolveResult is MethodGroupResolveResult) {
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult));
}
if (resolveResult is MemberResolveResult) {
if (resolveResult.Type.Kind == TypeKind.Delegate) {
return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type);
}
var mr = resolveResult as MemberResolveResult;
if (mr.Member is IMethod) {
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member });
case '<':
invoke = GetMethodTypeArgumentInvocationBeforeCursor();
if (invoke != null) {
var tExpr2 = ResolveExpression(invoke);
if (tExpr2 != null && tExpr2.Result is MethodGroupResolveResult && !tExpr2.Result.IsError) {
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, tExpr2.Result as MethodGroupResolveResult));
}
}
if (resolveResult != null) {
return factory.CreateIndexerParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type, invoke.Node);
}
break;
case '<':
invoke = GetTypeBeforeCursor();
if (invoke == null) {
if (invoke == null || invoke.Node.StartLocation.IsEmpty) {
return null;
}
var tExpr = ResolveExpression(invoke);
if (tExpr == null || tExpr.Item1 == null || tExpr.Item1.IsError) {
if (tExpr == null || tExpr.Result == null || tExpr.Result.IsError) {
return null;
}
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Item1.Type));
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Result.Type));
case '[':
invoke = GetIndexerBeforeCursor();
if (invoke == null) {
return null;
}
if (invoke.Node is ArrayCreateExpression) {
return null;
}
var indexerExpression = ResolveExpression(invoke);
if (indexerExpression == null || indexerExpression.Item1 == null || indexerExpression.Item1.IsError) {
if (indexerExpression == null || indexerExpression.Result == null || indexerExpression.Result.IsError) {
return null;
}
return factory.CreateIndexerParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), indexerExpression.Item1.Type, invoke.Node);
return factory.CreateIndexerParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), indexerExpression.Result.Type, GetAccessibleIndexers (indexerExpression.Result.Type), invoke.Node);
}
return null;
}
@ -320,7 +402,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -320,7 +402,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result;
}
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CompletionDataWrapper.cs
//
// Author:
@ -32,7 +32,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver; @@ -32,7 +32,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
class CompletionDataWrapper
public class CompletionDataWrapper
{
CSharpCompletionEngine completion;
List<ICompletionData> result = new List<ICompletionData> ();
@ -48,6 +48,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -48,6 +48,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return completion.factory;
}
}
internal bool AnonymousDelegateAdded {
get;
set;
}
public CompletionDataWrapper (CSharpCompletionEngine completion)
{
@ -60,17 +65,33 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -60,17 +65,33 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
public void AddCustom (string displayText, string description = null, string completionText = null)
public ICompletionData AddCustom (string displayText, string description = null, string completionText = null)
{
result.Add (Factory.CreateLiteralCompletionData (displayText, description, completionText));
var literalCompletionData = Factory.CreateLiteralCompletionData(displayText, description, completionText);
result.Add(literalCompletionData);
return literalCompletionData;
}
HashSet<string> usedNamespaces = new HashSet<string> ();
bool IsAccessible(MemberLookup lookup, INamespace ns)
{
if (ns.Types.Any (t => lookup.IsAccessible (t, false)))
return true;
foreach (var child in ns.ChildNamespaces)
if (IsAccessible (lookup, child))
return true;
return false;
}
public void AddNamespace (INamespace ns)
public void AddNamespace (MemberLookup lookup, INamespace ns)
{
if (usedNamespaces.Contains (ns.Name))
return;
if (!IsAccessible (lookup, ns)) {
usedNamespaces.Add (ns.Name);
return;
}
usedNamespaces.Add (ns.Name);
result.Add (Factory.CreateNamespaceCompletionData (ns));
}
@ -80,24 +101,57 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -80,24 +101,57 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
result.Add (Factory.CreateLiteralCompletionData (alias));
}
Dictionary<string, ICompletionData> typeDisplayText = new Dictionary<string, ICompletionData> ();
Dictionary<IType, ICompletionData> addedTypes = new Dictionary<IType, ICompletionData> ();
HashSet<string> usedTypes = new HashSet<string> ();
public ICompletionData AddConstructors(IType type, bool showFullName, bool isInAttributeContext = false)
{
return InternalAddType(type, showFullName, isInAttributeContext, true);
}
public ICompletionData AddType(IType type, string shortType)
public ICompletionData AddType(IType type, bool showFullName, bool isInAttributeContext = false)
{
if (type == null || string.IsNullOrEmpty(shortType) || usedTypes.Contains(shortType))
return null;
if (type.Name == "Void" && type.Namespace == "System")
return null;
return InternalAddType(type, showFullName, isInAttributeContext, false);
}
var def = type.GetDefinition ();
if (def != null && def.ParentAssembly != completion.ctx.CurrentAssembly && !def.IsBrowsable ())
ICompletionData InternalAddType(IType type, bool showFullName, bool isInAttributeContext, bool addConstrurs)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.Name == "Void" && type.Namespace == "System" || type.Kind == TypeKind.Unknown)
return null;
usedTypes.Add(shortType);
var iCompletionData = Factory.CreateTypeCompletionData(type, shortType);
result.Add(iCompletionData);
return iCompletionData;
if (addedTypes.ContainsKey (type))
return addedTypes[type];
usedNamespaces.Add(type.Name);
var def = type.GetDefinition();
if (def != null && def.ParentAssembly != completion.ctx.CurrentAssembly) {
switch (completion.EditorBrowsableBehavior) {
case EditorBrowsableBehavior.Ignore:
break;
case EditorBrowsableBehavior.Normal:
var state = def.GetEditorBrowsableState();
if (state != System.ComponentModel.EditorBrowsableState.Always)
return null;
break;
case EditorBrowsableBehavior.IncludeAdvanced:
if (!def.IsBrowsable())
return null;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
ICompletionData usedType;
var data = Factory.CreateTypeCompletionData(type, showFullName, isInAttributeContext, addConstrurs);
var text = data.DisplayText;
if (typeDisplayText.TryGetValue(text, out usedType)) {
usedType.AddOverload(data);
return usedType;
}
typeDisplayText [text] = data;
result.Add(data);
addedTypes[type] = data;
return data;
}
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> ();
@ -134,30 +188,49 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -134,30 +188,49 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
result.Add (Factory.CreateVariableCompletionData (variable));
}
public void AddTypeImport(ITypeDefinition type, bool useFullName, bool addForTypeCreation)
{
result.Add(Factory.CreateImportCompletionData(type, useFullName, addForTypeCreation));
}
public ICompletionData AddMember (IMember member)
{
var newData = Factory.CreateEntityCompletionData (member);
if (member.ParentAssembly != completion.ctx.CurrentAssembly && !member.IsBrowsable ())
return null;
if (member.ParentAssembly != completion.ctx.CurrentAssembly) {
switch (completion.EditorBrowsableBehavior) {
case EditorBrowsableBehavior.Ignore:
break;
case EditorBrowsableBehavior.Normal:
var state = member.GetEditorBrowsableState();
if (state != System.ComponentModel.EditorBrowsableState.Always)
return null;
break;
case EditorBrowsableBehavior.IncludeAdvanced:
if (!member.IsBrowsable())
return null;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
string memberKey = newData.DisplayText;
if (memberKey == null)
return null;
if (member is IMember) {
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition);
}
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition);
List<ICompletionData> existingData;
data.TryGetValue (memberKey, out existingData);
if (existingData != null) {
if (member.SymbolKind == SymbolKind.Field || member.SymbolKind == SymbolKind.Property || member.SymbolKind == SymbolKind.Event)
return null;
var a = member as IEntity;
foreach (var d in existingData) {
if (!(d is IEntityCompletionData))
continue;
var b = ((IEntityCompletionData)d).Entity;
if (a == null || b == null || a.EntityType == b.EntityType) {
if (a == null || b == null || a.SymbolKind == b.SymbolKind) {
d.AddOverload (newData);
return d;
}
@ -201,33 +274,53 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -201,33 +274,53 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var compareCategory = other as TypeCompletionCategory;
if (compareCategory == null)
return -1;
if (Type.ReflectionName == compareCategory.Type.ReflectionName)
return 0;
if (Type.GetAllBaseTypes ().Any (t => t.ReflectionName == compareCategory.Type.ReflectionName))
return -1;
return 1;
int result;
if (Type.ReflectionName == compareCategory.Type.ReflectionName) {
result = 0;
} else if (Type.GetAllBaseTypes().Any(t => t.ReflectionName == compareCategory.Type.ReflectionName)) {
result = -1;
} else if (compareCategory.Type.GetAllBaseTypes().Any(t => t.ReflectionName == Type.ReflectionName)) {
result = 1;
} else {
var d = Type.GetDefinition ();
var ct = compareCategory.Type.GetDefinition();
if (ct.IsStatic && d.IsStatic) {
result = d.FullName.CompareTo (ct.FullName);
} else if (d.IsStatic) {
result = 1;
}else if (ct.IsStatic) {
result = -1;
} else {
result = 0;
}
}
return result;
}
}
HashSet<IType> addedEnums = new HashSet<IType> ();
public void AddEnumMembers (IType resolvedType, CSharpResolver state, string typeString)
public ICompletionData AddEnumMembers (IType resolvedType, CSharpResolver state)
{
if (addedEnums.Contains (resolvedType))
return;
return null;
addedEnums.Add (resolvedType);
if (typeString.Contains(".")) {
AddType(resolvedType, typeString);
}
var result = AddType(resolvedType, true);
foreach (var field in resolvedType.GetFields ()) {
if (field.IsPublic && (field.IsConst || field.IsStatic)) {
Result.Add(Factory.CreateEntityCompletionData(
field,
typeString + "." + field.Name
)
);
Result.Add(Factory.CreateMemberCompletionData(resolvedType, field));
}
}
return result;
}
HashSet<string> anonymousSignatures = new HashSet<string> ();
public bool HasAnonymousDelegateAdded(string signature)
{
return anonymousSignatures.Contains(signature);
}
public void AddAnonymousDelegateAdded(string signature)
{
anonymousSignatures.Add(signature);
}
}
}

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

@ -149,10 +149,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -149,10 +149,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (bracketStack.Count > 0)
bracketStack.Pop ();
break;
case '\r':
case '\n':
isInLineComment = false;
break;
case '/':
if (isInBlockComment) {
if (i > 0 && document.GetCharAt (i - 1) == '*')
@ -173,7 +169,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -173,7 +169,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (!(isInString || isInLineComment || isInBlockComment))
isInChar = !isInChar;
break;
default :
default :
if (NewLine.IsNewLine(ch)) {
isInLineComment = false;
}
break;
}
}

28
NRefactory/ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// ICompletionDataFactory.cs
//
// Author:
@ -35,12 +35,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -35,12 +35,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ICompletionData CreateEntityCompletionData (IEntity entity);
ICompletionData CreateEntityCompletionData (IEntity entity, string text);
ICompletionData CreateTypeCompletionData (IType type, string shortType);
ICompletionData CreateTypeCompletionData (IType type, bool showFullName, bool isInAttributeContext, bool addForTypeCreation);
/// <summary>
/// Creates the member completion data.
/// Form: Type.Member
/// Used for generating enum members Foo.A, Foo.B where the enum 'Foo' is valid.
/// </summary>
ICompletionData CreateMemberCompletionData(IType type, IEntity member);
/// <summary>
/// Creates a generic completion data.
/// </summary>
/// <returns>
/// <param name='title'>
/// The title of the completion data
/// </param>
/// <param name='description'>
@ -57,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -57,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ICompletionData CreateVariableCompletionData (ITypeParameter parameter);
ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType);
ICompletionData CreateEventCreationCompletionData (string delegateMethodName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType);
ICompletionData CreateNewOverrideCompletionData (int declarationBegin, IUnresolvedTypeDefinition type, IMember m);
ICompletionData CreateNewPartialCompletionData (int declarationBegin, IUnresolvedTypeDefinition type, IUnresolvedMember m);
@ -65,5 +72,18 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -65,5 +72,18 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> CreateCodeTemplateCompletionData ();
IEnumerable<ICompletionData> CreatePreProcessorDefinesCompletionData ();
/// <summary>
/// Creates a completion data that adds the required using for the created type.
/// </summary>
/// <param name="type">The type to import</param>
/// <param name="useFullName">If set to true the full name of the type needs to be used.</param>
/// <param name="addForTypeCreation">If true the completion data is used in 'new' context.</param>
ICompletionData CreateImportCompletionData(IType type, bool useFullName, bool addForTypeCreation);
ICompletionData CreateFormatItemCompletionData(string format, string description, object example);
ICompletionData CreateXmlDocCompletionData (string tag, string description = null, string tagInsertionText = null);
}
}

9
NRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs

@ -35,13 +35,20 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -35,13 +35,20 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{
IParameterDataProvider CreateConstructorProvider (int startOffset, IType type);
/// <summary>
/// Creates a constructor provider skipping the parent of thisInitializer.
/// </summary>
IParameterDataProvider CreateConstructorProvider (int startOffset, IType type, AstNode thisInitializer);
IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods);
IParameterDataProvider CreateDelegateDataProvider (int startOffset, IType type);
IParameterDataProvider CreateIndexerParameterDataProvider (int startOffset, IType type, AstNode resolvedNode);
IParameterDataProvider CreateIndexerParameterDataProvider (int startOffset, IType type, IEnumerable<IProperty> accessibleIndexers, AstNode resolvedNode);
IParameterDataProvider CreateTypeParameterDataProvider (int startOffset, IEnumerable<IType> types);
IParameterDataProvider CreateTypeParameterDataProvider (int startOffset, IEnumerable<IMethod> methods);
}
}

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

File diff suppressed because it is too large Load Diff

159
NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormatter.cs

@ -0,0 +1,159 @@ @@ -0,0 +1,159 @@
//
// CSharpFormatter.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 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.Editor;
using System.Threading;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
public enum FormattingMode {
OnTheFly,
Intrusive
}
/// <summary>
/// The C# Formatter generates a set of text replace actions to format a region in a C# document.
/// </summary>
public class CSharpFormatter
{
readonly CSharpFormattingOptions policy;
readonly TextEditorOptions options;
/// <summary>
/// Gets the formatting policy the formatter uses.
/// </summary>
public CSharpFormattingOptions Policy {
get {
return policy;
}
}
/// <summary>
/// Gets the text editor options the formatter uses.
/// Note: If none was specified TextEditorOptions.Default gets used.
/// </summary>
public TextEditorOptions TextEditorOptions {
get {
return options;
}
}
List<DomRegion> formattingRegions = new List<DomRegion> ();
internal TextLocation lastFormattingLocation = new TextLocation(int.MaxValue, int.MaxValue);
/// <summary>
/// Gets the formatting regions. NOTE: Will get changed to IReadOnlyList.
/// </summary>
public IList<DomRegion> FormattingRegions {
get {
return formattingRegions;
}
}
/// <summary>
/// Gets or sets the formatting mode. For on the fly formatting a lightweight formatting mode
/// gives better results.
/// </summary>
public FormattingMode FormattingMode {
get;
set;
}
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.CSharpFormatter"/> class.
/// </summary>
/// <param name="policy">The formatting policy to use.</param>
/// <param name="options">The text editor options (optional). Default is: TextEditorOptions.Default</param>
public CSharpFormatter(CSharpFormattingOptions policy, TextEditorOptions options = null)
{
if (policy == null)
throw new ArgumentNullException("policy");
this.policy = policy;
this.options = options ?? TextEditorOptions.Default;
}
/// <summary>
/// Format the specified document and gives back the formatted text as result.
/// </summary>
public string Format(IDocument document)
{
return InternalFormat (new StringBuilderDocument (document.Text));
}
/// <summary>
/// Format the specified text and gives back the formatted text as result.
/// </summary>
public string Format(string text)
{
return InternalFormat (new StringBuilderDocument (text));
}
string InternalFormat(IDocument document)
{
var syntaxTree = SyntaxTree.Parse (document, document.FileName);
var changes = AnalyzeFormatting(document, syntaxTree);
changes.ApplyChanges();
return document.Text;
}
/// <summary>
/// Analyzes the formatting of a given document and syntax tree.
/// </summary>
/// <param name="document">Document.</param>
/// <param name="syntaxTree">Syntax tree.</param>
/// <param name="token">The cancellation token.</param>
public FormattingChanges AnalyzeFormatting(IDocument document, SyntaxTree syntaxTree, CancellationToken token = default (CancellationToken))
{
if (document == null)
throw new ArgumentNullException("document");
if (syntaxTree == null)
throw new ArgumentNullException("syntaxTree");
var result = new FormattingChanges(document);
var visitor = new FormattingVisitor(this, document, result, token);
syntaxTree.AcceptVisitor(visitor);
return result;
}
/// <summary>
/// Adds a region in the document that should be formatted.
/// </summary>
public void AddFormattingRegion (DomRegion region)
{
formattingRegions.Add(region);
if (formattingRegions.Count == 1) {
lastFormattingLocation = region.End;
} else {
lastFormattingLocation = lastFormattingLocation < region.End ? region.End : lastFormattingLocation;
}
}
}
}

218
NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CSharpFormattingOptions.cs
//
// Author:
@ -41,13 +41,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,13 +41,6 @@ namespace ICSharpCode.NRefactory.CSharp
BannerStyle
}
public enum BraceForcement
{
DoNotChange,
RemoveBraces,
AddBraces
}
public enum PropertyFormatting
{
AllowOneLine,
@ -68,6 +61,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -68,6 +61,17 @@ namespace ICSharpCode.NRefactory.CSharp
SameLine
}
public enum UsingPlacement {
TopOfFile,
InsideNamespace
}
public enum EmptyLineFormatting {
DoNotChange,
Indent,
DoNotIndent
}
public class CSharpFormattingOptions
{
public string Name {
@ -146,21 +150,47 @@ namespace ICSharpCode.NRefactory.CSharp @@ -146,21 +150,47 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool AlignEmbeddedUsingStatements { // tested
public bool AlignEmbeddedStatements { // tested
get;
set;
}
public bool AlignElseInIfStatements {
get;
set;
}
public PropertyFormatting AutoPropertyFormatting { // tested
get;
set;
}
public PropertyFormatting SimplePropertyFormatting { // tested
get;
set;
}
public bool AlignEmbeddedIfStatements { // tested
public EmptyLineFormatting EmptyLineFormatting {
get;
set;
}
public PropertyFormatting PropertyFormatting { // tested
public bool IndentPreprocessorDirectives { // tested
get;
set;
}
public bool AlignToMemberReferenceDot { // TODO!
get;
set;
}
public bool IndentBlocksInsideExpressions {
get;
set;
}
#endregion
#region Braces
@ -224,12 +254,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -224,12 +254,12 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool AllowPropertyGetBlockInline { // tested
public PropertyFormatting SimpleGetBlockFormatting { // tested
get;
set;
}
public bool AllowPropertySetBlockInline { // tested
public PropertyFormatting SimpleSetBlockFormatting { // tested
get;
set;
}
@ -269,41 +299,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -269,41 +299,17 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
#endregion
#region Force Braces
public BraceForcement IfElseBraceForcement { // tested
get;
set;
}
public BraceForcement ForBraceForcement { // tested
get;
set;
}
public BraceForcement ForEachBraceForcement { // tested
get;
set;
}
public BraceForcement WhileBraceForcement { // tested
get;
set;
}
public BraceForcement UsingBraceForcement { // tested
get;
set;
}
public BraceForcement FixedBraceForcement { // tested
get;
set;
bool allowOneLinedArrayInitialziers = true;
public bool AllowOneLinedArrayInitialziers {
get {
return allowOneLinedArrayInitialziers;
}
set {
allowOneLinedArrayInitialziers = value;
}
}
#endregion
#region NewLines
public NewLinePlacement ElseNewLinePlacement { // tested
get;
@ -329,6 +335,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -329,6 +335,16 @@ namespace ICSharpCode.NRefactory.CSharp
get;
set;
}
NewLinePlacement embeddedStatementPlacement = NewLinePlacement.NewLine;
public NewLinePlacement EmbeddedStatementPlacement {
get {
return embeddedStatementPlacement;
}
set {
embeddedStatementPlacement = value;
}
}
#endregion
#region Spaces
@ -434,6 +450,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -434,6 +450,16 @@ namespace ICSharpCode.NRefactory.CSharp
get;
set;
}
public NewLinePlacement NewLineBeforeConstructorInitializerColon {
get;
set;
}
public NewLinePlacement NewLineAfterConstructorInitializerColon {
get;
set;
}
// indexer
public bool SpaceBeforeIndexerDeclarationBracket { // tested
@ -568,7 +594,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -568,7 +594,22 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool SpaceAroundNullCoalescingOperator {
public bool SpaceAroundNullCoalescingOperator { // Tested
get;
set;
}
public bool SpaceAfterUnsafeAddressOfOperator { // Tested
get;
set;
}
public bool SpaceAfterUnsafeAsteriskOfOperator { // Tested
get;
set;
}
public bool SpaceAroundUnsafeArrowOperator { // Tested
get;
set;
}
@ -733,40 +774,60 @@ namespace ICSharpCode.NRefactory.CSharp @@ -733,40 +774,60 @@ namespace ICSharpCode.NRefactory.CSharp
get;
set;
}
public bool RemoveEndOfLineWhiteSpace {
get;
set;
}
public bool SpaceBeforeSemicolon {
get;
set;
}
#endregion
#region Blank Lines
public int BlankLinesBeforeUsings {
public int MinimumBlankLinesBeforeUsings {
get;
set;
}
public int BlankLinesAfterUsings {
public int MinimumBlankLinesAfterUsings {
get;
set;
}
public int BlankLinesBeforeFirstDeclaration {
public int MinimumBlankLinesBeforeFirstDeclaration {
get;
set;
}
public int BlankLinesBetweenTypes {
public int MinimumBlankLinesBetweenTypes {
get;
set;
}
public int BlankLinesBetweenFields {
public int MinimumBlankLinesBetweenFields {
get;
set;
}
public int BlankLinesBetweenEventFields {
public int MinimumBlankLinesBetweenEventFields {
get;
set;
}
public int BlankLinesBetweenMembers {
public int MinimumBlankLinesBetweenMembers {
get;
set;
}
public int MinimumBlankLinesAroundRegion {
get;
set;
}
public int MinimumBlankLinesInsideRegion {
get;
set;
}
@ -803,12 +864,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -803,12 +864,12 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool NewLineAferMethodCallOpenParentheses {
public NewLinePlacement NewLineAferMethodCallOpenParentheses {
get;
set;
}
public bool MethodCallClosingParenthesesOnNewLine {
public NewLinePlacement MethodCallClosingParenthesesOnNewLine {
get;
set;
}
@ -818,12 +879,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -818,12 +879,12 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool NewLineAferIndexerOpenBracket {
public NewLinePlacement NewLineAferIndexerOpenBracket {
get;
set;
}
public bool IndexerClosingBracketOnNewLine {
public NewLinePlacement IndexerClosingBracketOnNewLine {
get;
set;
}
@ -833,12 +894,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -833,12 +894,12 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool NewLineAferMethodDeclarationOpenParentheses {
public NewLinePlacement NewLineAferMethodDeclarationOpenParentheses {
get;
set;
}
public bool MethodDeclarationClosingParenthesesOnNewLine {
public NewLinePlacement MethodDeclarationClosingParenthesesOnNewLine {
get;
set;
}
@ -848,12 +909,45 @@ namespace ICSharpCode.NRefactory.CSharp @@ -848,12 +909,45 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public bool NewLineAferIndexerDeclarationOpenBracket {
public NewLinePlacement NewLineAferIndexerDeclarationOpenBracket {
get;
set;
}
public NewLinePlacement IndexerDeclarationClosingBracketOnNewLine {
get;
set;
}
public bool AlignToFirstIndexerArgument {
get;
set;
}
public bool IndexerDeclarationClosingBracketOnNewLine {
public bool AlignToFirstIndexerDeclarationParameter {
get;
set;
}
public bool AlignToFirstMethodCallArgument {
get;
set;
}
public bool AlignToFirstMethodDeclarationParameter {
get;
set;
}
public NewLinePlacement NewLineBeforeNewQueryClause {
get;
set;
}
#endregion
#region Using Declarations
public UsingPlacement UsingPlacement {
get;
set;
}

514
NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/ConstructFixer.cs

@ -0,0 +1,514 @@ @@ -0,0 +1,514 @@
//
// ConstructFixer.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 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.Editor;
using System.Text;
using System.Reflection;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
abstract class ConstructCompleter
{
public abstract bool TryFix (ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset);
protected AstNode GetLastNonErrorChild (AstNode node)
{
var lastNode = node.LastChild;
while (lastNode is ErrorNode) {
lastNode = lastNode.GetPrevNode(FormattingVisitor.NoWhitespacePredicate);
}
return lastNode;
}
}
class TypeDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var typeDeclaration = syntaxTree.GetNodeAt<TypeDeclaration>(location);
if (typeDeclaration != null) {
if (typeDeclaration.LBraceToken.IsNull && typeDeclaration.RBraceToken.IsNull) {
if (typeDeclaration.Members.Any())
return false;
var lastNode = GetLastNonErrorChild (typeDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (typeDeclaration, fixer.Options.ClassBraceStyle, false, ref newOffset));
return true;
}
}
return false;
}
}
class DelegateDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var typeDeclaration = syntaxTree.GetNodeAt<DelegateDeclaration>(location);
if (typeDeclaration != null) {
if (typeDeclaration.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (typeDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ");\n");
newOffset += ");\n".Length;
return true;
}
}
return false;
}
}
class MethodDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var methodDeclaration = syntaxTree.GetNodeAt<MethodDeclaration>(location);
if (methodDeclaration != null) {
if (!methodDeclaration.LParToken.IsNull && methodDeclaration.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (methodDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ")\n\t{\t\t\n\t}");
newOffset += ")\n\t{\t\t".Length;
return true;
}
}
return false;
}
}
class IfStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<IfElseStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class ForeachStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<ForeachStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class WhileStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<WhileStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class DoWhileStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<DoWhileStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ");");
newOffset = insertionOffset + 2;
return true;
}
}
return false;
}
}
class FixedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<FixedStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class SwitchStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var switchStatement = syntaxTree.GetNodeAt<SwitchStatement>(location);
if (switchStatement != null) {
if (!switchStatement.LParToken.IsNull && switchStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (switchStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (switchStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class InvocationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var invocationExpression = syntaxTree.GetNodeAt<InvocationExpression>(location);
if (invocationExpression != null) {
if (!invocationExpression.LParToken.IsNull && invocationExpression.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (invocationExpression);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
newOffset = insertionOffset;
var text = ")";
newOffset++;
var expressionStatement = invocationExpression.Parent as ExpressionStatement;
if (expressionStatement != null) {
if (expressionStatement.SemicolonToken.IsNull)
text = ");";
newOffset ++;
}
document.Insert(insertionOffset, text);
return true;
}
}
return false;
}
}
class BreakStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<BreakStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
// TODO !!!!
return true;
}
return false;
}
}
class CheckedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<CheckedExpression>(location);
if (stmt != null && stmt.Parent is ExpressionStatement) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, false, ref newOffset));
return true;
}
return false;
}
}
class UncheckedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<UncheckedExpression>(location);
if (stmt != null && stmt.Parent is ExpressionStatement) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, false, ref newOffset));
return true;
}
return false;
}
}
class ExpressionStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var expressionStatement = syntaxTree.GetNodeAt<ExpressionStatement>(location);
if (expressionStatement != null) {
int offset = document.GetOffset(expressionStatement.Expression.EndLocation);
if (expressionStatement.SemicolonToken.IsNull) {
document.Insert(offset, ";");
newOffset = offset + 1;
}
return true;
}
return false;
}
}
class LockStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<LockStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class ReturnStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<ReturnStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
class YieldReturnStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<YieldReturnStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
class ThrowStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<ThrowStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
public class ConstructFixer
{
static readonly ConstructCompleter[] completer = {
new TypeDeclarationCompleter(),
new DelegateDeclarationCompleter (),
new MethodDeclarationCompleter (),
new IfStatementCompleter (),
new ForeachStatementCompleter (),
new WhileStatementCompleter (),
new LockStatementCompleter (),
new FixedStatementCompleter (),
new DoWhileStatementCompleter (),
new SwitchStatementCompleter (),
new BreakStatementCompleter (),
new ThrowStatementCompleter (),
new ReturnStatementCompleter (),
new YieldReturnStatementCompleter (),
new CheckedStatementCompleter (),
new UncheckedStatementCompleter (),
new InvocationCompleter (),
new ExpressionStatementCompleter ()
};
readonly CSharpFormattingOptions options;
readonly TextEditorOptions textEditorOptions;
public CSharpFormattingOptions Options {
get {
return options;
}
}
public ConstructFixer(CSharpFormattingOptions options, TextEditorOptions textEditorOptions)
{
this.options = options;
this.textEditorOptions = textEditorOptions;
}
string GetIndent(AstNode node)
{
if (node == null || node is SyntaxTree)
return "";
if (node is BlockStatement || node is TypeDeclaration || node is NamespaceDeclaration)
return "\t" + GetIndent(node.Parent);
return GetIndent(node.Parent);
}
internal string GenerateBody(AstNode node, BraceStyle braceStyle, bool addClosingBracket, ref int newOffset)
{
StringBuilder result = new StringBuilder();
if (addClosingBracket)
result.Append(")");
var nodeIndent = GetIndent(node.Parent);
switch (braceStyle) {
case BraceStyle.DoNotChange:
case BraceStyle.BannerStyle:
case BraceStyle.EndOfLine:
result.Append(" ");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.EndOfLineWithoutSpace:
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLine:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent);
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLineShifted:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLineShifted2:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t" + "\t");
break;
}
newOffset += result.Length;
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent);
result.Append("}");
return result.ToString();
}
public bool TryFix (IDocument document, int offset, out int newOffset)
{
newOffset = offset;
var syntaxTree = SyntaxTree.Parse(document, "a.cs");
var location = document.GetLocation(offset - 1);
foreach (var c in completer) {
if (c.TryFix(this, syntaxTree, document, location, ref newOffset)) {
return true;
}
}
return false;
}
}
}

169
NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingChanges.cs

@ -0,0 +1,169 @@ @@ -0,0 +1,169 @@
//
// CSharpFormatter.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 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.Editor;
using System.Threading;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// The formatting changes are used to format a specific region inside a document and apply a minimal formatting
/// changeset to a given document. This is useful for a text editor environment.
/// </summary>
public class FormattingChanges
{
readonly IDocument document;
readonly internal List<TextReplaceAction> changes = new List<TextReplaceAction> ();
internal FormattingChanges (IDocument document)
{
if (document == null)
throw new ArgumentNullException("document");
this.document = document;
}
public int Count {
get {
return changes.Count;
}
}
/// <summary>
/// Applies the changes to the input document.
/// </summary>
public void ApplyChanges()
{
ApplyChanges(0, document.TextLength, document.Replace, (o, l, v) => document.GetText(o, l) == v);
}
public void ApplyChanges(int startOffset, int length)
{
ApplyChanges(startOffset, length, document.Replace, (o, l, v) => document.GetText(o, l) == v);
}
/// <summary>
/// Applies the changes to the given Script instance.
/// </summary>
public void ApplyChanges(Script script)
{
ApplyChanges(0, document.TextLength, script.Replace);
}
public void ApplyChanges(int startOffset, int length, Script script)
{
ApplyChanges(startOffset, length, script.Replace);
}
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace, Func<int, int, string, bool> filter = null)
{
int endOffset = startOffset + length;
// Console.WriteLine ("apply:"+ startOffset + "->" + endOffset);
// Console.WriteLine (document.Text.Substring (0, startOffset) + new string ('x',length) + document.Text.Substring (startOffset+ length));
TextReplaceAction previousChange = null;
int delta = 0;
var depChanges = new List<TextReplaceAction> ();
foreach (var change in changes.OrderBy(c => c.Offset)) {
if (previousChange != null) {
if (change.Equals(previousChange)) {
// ignore duplicate changes
continue;
}
if (change.Offset < previousChange.Offset + previousChange.RemovalLength) {
throw new InvalidOperationException ("Detected overlapping changes " + change + "/" + previousChange);
}
}
previousChange = change;
bool skipChange = change.Offset + change.RemovalLength < startOffset || change.Offset > endOffset;
skipChange |= filter != null && filter(change.Offset + delta, change.RemovalLength, change.NewText);
skipChange &= !depChanges.Contains(change);
if (!skipChange) {
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
delta += change.NewText.Length - change.RemovalLength;
if (change.DependsOn != null) {
depChanges.Add(change.DependsOn);
}
}
}
changes.Clear();
}
internal TextReplaceAction AddChange(int offset, int removedChars, string insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", "Should be >= 0");
if (offset >= document.TextLength)
throw new ArgumentOutOfRangeException("offset", "Should be < document.TextLength");
if (removedChars < 0)
throw new ArgumentOutOfRangeException("removedChars", "Should be >= 0");
if (removedChars > offset + document.TextLength)
throw new ArgumentOutOfRangeException("removedChars", "Tried to remove beyond end of text");
if (removedChars == 0 && string.IsNullOrEmpty (insertedText))
return null;
var action = new TextReplaceAction (offset, removedChars, insertedText);
changes.Add(action);
return action;
}
internal sealed class TextReplaceAction
{
internal readonly int Offset;
internal readonly int RemovalLength;
internal readonly string NewText;
internal TextReplaceAction DependsOn;
public TextReplaceAction (int offset, int removalLength, string newText)
{
this.Offset = offset;
this.RemovalLength = removalLength;
this.NewText = newText ?? string.Empty;
}
public override bool Equals(object obj)
{
TextReplaceAction other = obj as TextReplaceAction;
if (other == null) {
return false;
}
return this.Offset == other.Offset && this.RemovalLength == other.RemovalLength && this.NewText == other.NewText;
}
public override int GetHashCode()
{
return 0;
}
public override string ToString()
{
return string.Format("[TextReplaceAction: Offset={0}, RemovalLength={1}, NewText={2}]", Offset, RemovalLength, NewText);
}
}
}
}

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

Loading…
Cancel
Save