Browse Source

Squashed 'NRefactory/' changes from 1e4a1d9..9675caf

9675caf ReadOnlyDocument: rename textBuffer->textSource
97d0964 Fixed GetDelegateInvokeMethod() for parameterized types. Fixed copy constructor of DefaultMethod. Fixed handling of "class" constraint in CecilLoader.
42d4d7d fixed some bugs in use explicit type context action.
79b9582 Fixed failing attribute unit tests.
6fb0a90 Added error indicators for missing closing brackets.
a11458e Worked on attribute resolving. Some tests fail because of wrongly loaded classes in my system. Daniel: Can you check the constructor attribute cases. I think something doesn't work in the Cecil loader on my system. I only get 1 empty constructor for LoaderOptimization & the name on my system is .ctor instead of #ctor.
cf8a412 Use equals.
5c398f2 fixed return types of anonymous type properties. Re-used the var type reference for that.
c458e06 Implemented anonymous types.
19653fa Added identifier token property.
96d1b7f fixed check.
1af72c9 GetResolveableNodeAt is now more selective.
b74fe93 Set compiler errors to parsed file.
b411a2a fixed possible null ref.
7e708a6 Worked on ast formatter tests.
fa55d14 Fix adding assembly attributes to SimpleProjectContent. Fixed MemberLookup.IsInvocable(). Add (ignored) unit tests for user-defined binary operators.
b368465 fixed bug.
99b60b8 Parser change: Interface members are now Accessibiliy.Public. This is a proposal to solve the <interfaceType>.<InferfaceMember>. ... lookup.
dd4f73b Fixed bug in inner type result.
2c2f30d Fixed some issues in the context actions.
b01c263 Implemented brace style formatting.
aceae1f implemented type parameter getmember methods.
2b726d2 Fixed System.Void output.
67fff9f fixed bug in using statement parsing.
ef0d911 Revert "Implemented user defined operator candidates."
9165dfe Implemented user defined operator candidates.
6199ee3 checked outer classes for aceessibility private check.
5fad5f9 Added time stamp to parsed files.
37dbafd fixed mcs bug.
0e1ad6e Started to implement a 'skip bodies' mode for parsing.
62d61ec Implemented GetResolveableNodeAt function.
26946f0 Added DeclarationRegion property to IVariable.
694f373 fix infinite loop.
daf0f21 Fixed some bugs related to conversions of type parameters.
5ae4d60 Conversions: add support for user-defined implicit conversions.
7615720 ResolveVisitor: Handle type arguments on IdentifierExpression and MemberReferenceExpression. Add support for PointerReferenceExpression.
3435eec Add ResolveVisitor.GetResolverStateBefore(AstNode).
5b92717 Add GetMembers() to IType; add ParsedFiles to IProjectContent.
c923833 Fix build errors.
1037d56 fixed some errors.
7fb7783 Make AbstractAnnotatable implement IAnnotatable.
c9d4a5d Rename ITypeResolveContext extension methods to be consistent with the new names of the ITypeResolveContext methods.
350ebaa Fixed NullReferenceException in type inference when passing a "string[]" for a parameter of type "IEnumerable<T>".
823471e Make the end offset of SegmentExtensions.Contains inclusive.
b40610d Simplify nested synchronization of CompositeTypeResolveContext.
991bea4 Added IsVerbatim property again.
484c586 Added easy accessible acceess members.
a883a3d Added constructors that take an error location/added file header.
77d54ee added some constructors.
e8153e0 reduced comment insertion time from O(m log n) to O (m).
44e796a Reduced the memory consumption of identifiers a bit by saving the 'isverbatim' bool. Note: Don't introduce that as virtual property, otherwise the memory saving is lost.
0afc1c6 Updated mcs / included code completion expression lookup.
33d588b Added the ability to specify parser arguments & provided a compiler callback (for getting pre processor directives etc). TODO: Move pre processor directives in the AST.
93b3ebf Implemented type system -> cecil object table.
6a85f0c Renamed GetClass-> GetTypeDefinition;
abec118 fix build.
c6aa05d Addded GetSubTypeDefinitions method. That's like a routine we had in the old MD dom - it's used for example for finding all exceptions in an assembly.
b7fc89c added header.
0cb2388 Separated the annotations from the ast node & added annotations to the project content.
af5e2c6 Added extension method GetMembers on IType.
7e29f61 Fix build (however formatting tests will fail).
9d21d1c Renamed GetClasses -> GetTypes. (GetClasess can give enums, structs & delegates too).
51f924f Renamed ITypeDefinition.InnerClasses -> NestedTypes (for more consistency with IType.GetNestedTypes
224f973 Revert "Moved class type to IType / added type parameter class type for type"
ba335ed Moved class type to IType / added type parameter class type for type parameters.
aa42b1b Added error storage to IParsedFile.
bae8765 Added AstLocation Begin/End properties.
9bc76cf Added naive remove type definition. This won't work for partial types.
bd4fb10 Added cenecllationtoken work around. Mono crashes on default cancellation token.
40147bc Changed CreateShortType implementation a bit.
1ae1b17 Added gettype/member extension methods that are working on a line/column pair.
c744d2f Worked on the way nrefactory contexct actions use the resolver.
1836aa8 Merge branch 'master' of github.com:icsharpcode/NRefactory
1b7906a Worked on context actions.
94b4130 Add IParsedFile to type system.
be5139a Added more context actions.
62988d6 Add TypeSystemAstBuilder: IType --> AstType conversion.
530cb0b mhutch: [NRefactory] Fix const modifier on fields
2b5569d use faster string comparer.
0f5f474 worked on context actions.
c337048 added missing file.
6e1eaf1 Added monodevelop context actions.
3eb2e5d Added patch from mhutch: [NRefactory] Add some name token accessors
7070e47 corrected output of primitive expressions. Primitive expressions contain a literal value which should be preferred ("0x10" vs "16").
13acde3 fix build.
8b606d1 Updated mcs/fixed unit test. string literal constants now contain the real 'literal'.
b2d2678 Rename ITextBuffer -> ITextSource
3048d66 Added some proposals.
21fcd82 Add ISegment and ITextEditor interfaces.
b4bcc80 Add ICSharpCode.Editor assembly.
0afdacd changed to HasModifier.
878dbbf Fixed some issues in resolver; enable resolver unit tests.
d36805c fixed assembly attribute csharp test.
67d9bb5 Fixed attribute on method parameter tests.
3685f49 Fixed TypeSystemConvertVisitor for read-only properties. Added some attribute parser tests.
26986f9 Make sure NamespaceEntry.ClassCount stays consistent with the ordinal typeDict at all times, even when there are name clashes in one of the non-ordinal dictionaries.
ddc55ad fixed variable declaration statement inside for loops wrong semicolon position.
fca4dd0 Added GetTypes method in compilation unit.
0398fd6 Fixed 'GlobalAttributeCSharp' test.
9bcf087 Fixed EnumWithBaseType unit test.
390ed3a Fixed NestedArrays unit test.
1c51b3a Type storage: Fixed handling of namespaces that have sub-namespaces but do not directly contain classes.
07e2896 Make InsertParenthesesVisitorTests independent from indentation of the output.
73a9d8d Merge NRefactory changes from ILSpy.
fb57f7d Fixed several issues in the type system convert visitor.
a697f19 fixed unboundtypeofexpression test.
93117a1 Added MemberNameToken property.
7cd4526 Added some properties to allow easier access for modifiers.
014ecea Pass the parameter to the event handlers.
42717c9 fix missing method.
6144698 removed exception (shouldn't be in production code).
1365588 passed type parameters to the observable ast visitor.
7a5c7f3 fixed possible null reference exception.
6894e6a Primitive expressions now contain the literal value + updated mcs.
790585c Implemented invert condition function.
7f16970 Added token atrribute.
0648470 Fixed membertpe location.
ba4a272 Implemented specific GetNodeAt method.
1feb0fc Added contains method.
d4d9ffd Added observer visitor.
f761813 Fixing switch section output + it's now possible to track node output in the output visitor.
79f1798 Put embedded statments onto next line.
478faf7 added name token property.
d561ccf Merged some changes from monodevelop.
280b79b Fixed return type tokens
8578bad Added easy name token access.
dfea089 added bounds check.
2fa40d8 Fixed special constraint expression parsing.
eb6f6c1 Make ConvertChar and ConvertString public.
b07228e Fixed issues with detection of using statements.
a238bf1 When decompiling a field, also decompile constructors to check whether there's an initializer on the field. When decompiling a constructor, display field initializers outside of the constructor. Closes #3.
3974a80 remove isLastLine from interface - use stack instead; fix null reference if resolve of TypeDefinition fails
7738421 Fixed position of XML comments on nested types.
9a35ee4 Applied some of the optimizations suggested by Kris Vandermotten. #150
5997f81 add foldings to documentation comments; closes #165
fc86a67 Fixed relocation bug.
8fc4139 Fixed relocatable bug/removed some debug messages.
8237448 Renamed interface.
99b4726 fix https://github.com/icsharpcode/ILSpy/issues/177
450be5a Corrected locations for parset expressions/statments/type members.
cb114b8 Fixed blank line formatting bug.
e187185 Merge NRefactory subtree from commit '1e4a1d911cb430db2a4199695ee73dfd89bcc543'
4db670a Merge NRefactory b8330be into ILSpy
f70f6a8 Add SaveIndex/LoadFromIndex methods to XmlDocumentationProvider.
4995f48 New XmlDocumentationProvider implementation:
f3b9d11 When the last statement in a block is a label, add an EmptyStatement so that the generated code is valid.
e68833d Add TestPlugin.
b22b3ec C# OutputVisitor: improve indentation of query expressions
2ca7ec2 Fixed output of NamedArgumentExpression within object initializers.
43e33f8 Fixed InsertParenthesesVisitor for casts of negative primitive expressions.
f3c52a0 Add OperatorDeclaration.GetOperatorType() helper method.
7cbab5e Merge NRefactory a92606c..56fde51

git-subtree-dir: NRefactory
git-subtree-split: 9675caf1e9276391f17536b488148cb668a6cc44
pull/297/head
Daniel Grunwald 14 years ago
parent
commit
1c1420a8d2
  1. 72
      ICSharpCode.Editor/ICSharpCode.Editor.csproj
  2. 141
      ICSharpCode.Editor/IDocument.cs
  3. 30
      ICSharpCode.Editor/IDocumentLine.cs
  4. 55
      ICSharpCode.Editor/ISegment.cs
  5. 102
      ICSharpCode.Editor/ITextAnchor.cs
  6. 100
      ICSharpCode.Editor/ITextEditor.cs
  7. 147
      ICSharpCode.Editor/ITextSource.cs
  8. 68
      ICSharpCode.Editor/LinkedElement.cs
  9. 31
      ICSharpCode.Editor/Properties/AssemblyInfo.cs
  10. 321
      ICSharpCode.Editor/ReadOnlyDocument.cs
  11. 91
      ICSharpCode.Editor/StringTextSource.cs
  12. 64
      ICSharpCode.Editor/TextChangeEventArgs.cs
  13. 173
      ICSharpCode.Editor/TextLocation.cs
  14. 2
      ICSharpCode.NRefactory.Demo/CSDemo.cs
  15. 53
      ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs
  16. 17
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs
  17. 69
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs
  18. 8
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs
  19. 4
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs
  20. 8
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs
  21. 57
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs
  22. 115
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  23. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  24. 12
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs
  25. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  26. 88
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  27. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  28. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  29. 47
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  30. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs
  31. 1
      ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs
  32. 3
      ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs
  33. 1
      ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs
  34. 19
      ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs
  35. 3
      ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs
  36. 7
      ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs
  37. 70
      ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs
  38. 40
      ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs
  39. 30
      ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  40. 6
      ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs
  41. 4
      ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs
  42. 2
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  43. 82
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  44. 2
      ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs
  45. 150
      ICSharpCode.NRefactory.VB/Ast/AstNode.cs
  46. 2
      ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs
  47. 2
      ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs
  48. 10
      ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs
  49. 2
      ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs
  50. 4
      ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs
  51. 6
      ICSharpCode.NRefactory.VB/Parser/Parser.cs
  52. 7
      ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs
  53. 26
      ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  54. 21
      ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs
  55. 531
      ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs
  56. 11
      ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs
  57. 95
      ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs
  58. 78
      ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs
  59. 4
      ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs
  60. 79
      ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs
  61. 13
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs
  62. 4
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs
  63. 13
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs
  64. 11
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs
  65. 4
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs
  66. 31
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs
  67. 10
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs
  68. 21
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs
  69. 13
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs
  70. 4
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs
  71. 13
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs
  72. 2
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs
  73. 4
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs
  74. 13
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs
  75. 11
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs
  76. 8
      ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs
  77. 45
      ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs
  78. 82
      ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs
  79. 36
      ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs
  80. 1141
      ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs
  81. 10
      ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs
  82. 27
      ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs
  83. 11
      ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs
  84. 13
      ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs
  85. 4
      ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs
  86. 4
      ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs
  87. 9
      ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs
  88. 13
      ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs
  89. 5
      ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs
  90. 9
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs
  91. 5
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs
  92. 5
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs
  93. 13
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs
  94. 15
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs
  95. 13
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs
  96. 95
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs
  97. 13
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs
  98. 13
      ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs
  99. 56
      ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs
  100. 35
      ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs
  101. Some files were not shown because too many files have changed in this diff Show More

72
ICSharpCode.Editor/ICSharpCode.Editor.csproj

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{F054A788-B591-4561-A8BA-AE745BBEB817}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.Editor</RootNamespace>
<AssemblyName>ICSharpCode.Editor</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<AppDesignerFolder>Properties</AppDesignerFolder>
<SignAssembly>False</SignAssembly>
<DelaySign>False</DelaySign>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<DocumentationFile>bin\Debug\ICSharpCode.Editor.xml</DocumentationFile>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<RunCodeAnalysis>False</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<StartAction>Project</StartAction>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="IDocument.cs" />
<Compile Include="IDocumentLine.cs" />
<Compile Include="ISegment.cs" />
<Compile Include="ITextEditor.cs" />
<Compile Include="ITextSource.cs" />
<Compile Include="LinkedElement.cs" />
<Compile Include="ReadOnlyDocument.cs" />
<Compile Include="StringTextSource.cs" />
<Compile Include="TextLocation.cs" />
<Compile Include="ITextAnchor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextChangeEventArgs.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

141
ICSharpCode.Editor/IDocument.cs

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
/// <summary>
/// A document representing a source code file for refactoring.
/// Line and column counting starts at 1.
/// Offset counting starts at 0.
/// </summary>
public interface IDocument : ITextSource, IServiceProvider
{
/// <summary>
/// Gets/Sets the text of the whole document..
/// </summary>
new string Text { get; set; } // hides TextBuffer.Text to add the setter
/// <summary>
/// Is raised when the Text property changes.
/// </summary>
event EventHandler TextChanged;
/// <summary>
/// Gets the total number of lines in the document.
/// </summary>
int TotalNumberOfLines { get; }
/// <summary>
/// Gets the document line with the specified number.
/// </summary>
/// <param name="lineNumber">The number of the line to retrieve. The first line has number 1.</param>
IDocumentLine GetLine(int lineNumber);
/// <summary>
/// Gets the document line that contains the specified offset.
/// </summary>
IDocumentLine GetLineByOffset(int offset);
/// <summary>
/// Gets the offset from a text location.
/// </summary>
/// <seealso cref="GetLocation"/>
int GetOffset(int line, int column);
/// <summary>
/// Gets the offset from a text location.
/// </summary>
/// <seealso cref="GetLocation"/>
int GetOffset(TextLocation location);
/// <summary>
/// Gets the location from an offset.
/// </summary>
/// <seealso cref="GetOffset(TextLocation)"/>
TextLocation GetLocation(int offset);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
void Insert(int offset, string text);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Removes text.
/// </summary>
/// <param name="offset">Starting offset of the text to be removed.</param>
/// <param name="length">Length of the text to be removed.</param>
void Remove(int offset, int length);
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, string newText);
/// <summary>
/// Make the document combine the following actions into a single
/// action for undo purposes.
/// </summary>
void StartUndoableAction();
/// <summary>
/// Ends the undoable action started with <see cref="StartUndoableAction"/>.
/// </summary>
void EndUndoableAction();
/// <summary>
/// Creates an undo group. Dispose the returned value to close the undo group.
/// </summary>
/// <returns>An object that closes the undo group when Dispose() is called.</returns>
IDisposable OpenUndoGroup();
/// <summary>
/// Creates a new <see cref="ITextAnchor"/> at the specified offset.
/// </summary>
/// <inheritdoc cref="ITextAnchor" select="remarks|example"/>
ITextAnchor CreateAnchor(int offset);
/// <summary>
/// This event is called directly before a change is applied to the document.
/// </summary>
/// <remarks>
/// It is invalid to modify the document within this event handler.
/// Aborting the change (by throwing an exception) is likely to cause corruption of data structures
/// that listen to the Changing and Changed events.
/// </remarks>
event EventHandler<TextChangeEventArgs> Changing;
/// <summary>
/// This event is called directly after a change is applied to the document.
/// </summary>
/// <remarks>
/// It is invalid to modify the document within this event handler.
/// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures
/// that listen to the Changing and Changed events.
/// </remarks>
event EventHandler<TextChangeEventArgs> Changed;
}
}

30
ICSharpCode.Editor/IDocumentLine.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
/// <summary>
/// A line inside a <see cref="IDocument"/>.
/// </summary>
public interface IDocumentLine : ISegment
{
/// <summary>
/// Gets the length of this line, including the line delimiter.
/// </summary>
int TotalLength { get; }
/// <summary>
/// Gets the length of the line terminator.
/// Returns 1 or 2; or 0 at the end of the document.
/// </summary>
int DelimiterLength { get; }
/// <summary>
/// Gets the number of this line.
/// The first line has the number 1.
/// </summary>
int LineNumber { get; }
}
}

55
ICSharpCode.Editor/ISegment.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
/// <summary>
/// An (Offset,Length)-pair.
/// </summary>
public interface ISegment
{
/// <summary>
/// Gets the start offset of the segment.
/// </summary>
int Offset { get; }
/// <summary>
/// Gets the length of the segment.
/// </summary>
/// <remarks>Must not be negative.</remarks>
int Length { get; }
/// <summary>
/// Gets the end offset of the segment.
/// </summary>
/// <remarks>EndOffset = Offset + Length;</remarks>
int EndOffset { get; }
}
/// <summary>
/// Extension methods for <see cref="ISegment"/>.
/// </summary>
public static class ISegmentExtensions
{
/// <summary>
/// Gets whether the segment contains the offset.
/// </summary>
/// <returns>
/// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false.
/// </returns>
public static bool Contains (this ISegment segment, int offset)
{
return segment.Offset <= offset && offset <= segment.EndOffset;
}
/// <summary>
/// True, if the segment contains the specified segment, false otherwise.
/// </summary>
public static bool Contains (this ISegment thisSegment, ISegment segment)
{
return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset;
}
}
}

102
ICSharpCode.Editor/ITextAnchor.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
/// <summary>
/// The TextAnchor class references an offset (a position between two characters).
/// It automatically updates the offset when text is inserted/removed in front of the anchor.
/// </summary>
/// <remarks>
/// <para>Use the <see cref="ITextAnchor.Offset"/> property to get the offset from a text anchor.
/// Use the <see cref="IDocument.CreateAnchor"/> method to create an anchor from an offset.
/// </para>
/// <para>
/// The document will automatically update all text anchors; and because it uses weak references to do so,
/// the garbage collector can simply collect the anchor object when you don't need it anymore.
/// </para>
/// <para>Moreover, the document is able to efficiently update a large number of anchors without having to look
/// at each anchor object individually. Updating the offsets of all anchors usually only takes time logarithmic
/// to the number of anchors. Retrieving the <see cref="ITextAnchor.Offset"/> property also runs in O(lg N).</para>
/// </remarks>
/// <example>
/// Usage:
/// <code>TextAnchor anchor = document.CreateAnchor(offset);
/// ChangeMyDocument();
/// int newOffset = anchor.Offset;
/// </code>
/// </example>
public interface ITextAnchor
{
/// <summary>
/// Gets the text location of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
TextLocation Location { get; }
/// <summary>
/// Gets the offset of the text anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Offset { get; }
/// <summary>
/// Controls how the anchor moves.
/// </summary>
AnchorMovementType MovementType { get; set; }
/// <summary>
/// Specifies whether the anchor survives deletion of the text containing it.
/// <c>false</c>: The anchor is deleted when the a selection that includes the anchor is deleted.
/// <c>true</c>: The anchor is not deleted.
/// </summary>
bool SurviveDeletion { get; set; }
/// <summary>
/// Gets whether the anchor was deleted.
/// </summary>
bool IsDeleted { get; }
/// <summary>
/// Occurs after the anchor was deleted.
/// </summary>
event EventHandler Deleted;
/// <summary>
/// Gets the line number of the anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Line { get; }
/// <summary>
/// Gets the column number of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Column { get; }
}
/// <summary>
/// Defines how a text anchor moves.
/// </summary>
public enum AnchorMovementType
{
/// <summary>
/// When text is inserted at the anchor position, the type of the insertion
/// determines where the caret moves to. For normal insertions, the anchor will stay
/// behind the inserted text.
/// </summary>
Default,
/// <summary>
/// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay
/// before the inserted text.
/// </summary>
BeforeInsertion,
/// <summary>
/// Behave like an end marker - when text is insered at the anchor position, the anchor will move
/// after the inserted text.
/// </summary>
AfterInsertion
}
}

100
ICSharpCode.Editor/ITextEditor.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ICSharpCode.Editor
{
/// <summary>
/// Interface for text editors.
/// </summary>
public interface ITextEditor : IServiceProvider
{
/// <summary>
/// Gets the document that is being edited.
/// </summary>
IDocument Document { get; }
/// <summary>
/// Gets an object that represents the caret inside this text editor.
/// </summary>
ITextEditorCaret Caret { get; }
/// <summary>
/// Sets the caret to the specified line/column and brings the caret into view.
/// </summary>
void JumpTo(int line, int column);
/// <summary>
/// Gets the start offset of the selection.
/// </summary>
int SelectionStart { get; }
/// <summary>
/// Gets the length of the selection.
/// </summary>
int SelectionLength { get; }
/// <summary>
/// Gets/Sets the selected text.
/// </summary>
string SelectedText { get; set; }
/// <summary>
/// Sets the selection.
/// </summary>
/// <param name="selectionStart">Start offset of the selection</param>
/// <param name="selectionLength">Length of the selection</param>
void Select(int selectionStart, int selectionLength);
/// <summary>
/// Shows the specified linked elements, and allows the user to edit them.
/// </summary>
/// <returns>
/// Returns true when the user has finished editing the elements and pressed Return;
/// or false when editing is aborted for any reason.
/// </returns>
/// <remarks>
/// The user can also edit other parts of the document (or other documents) while in link mode.
/// In case of success (true return value), this method will update the offsets of the linked elements
/// to reflect the changes done by the user.
/// If the text editor does not support link mode, it will immediately return false.
/// </remarks>
// Task<bool> ShowLinkedElements(IEnumerable<LinkedElement> linkedElements);
}
/// <summary>
/// Represents the caret in a text editor.
/// </summary>
public interface ITextEditorCaret
{
/// <summary>
/// Gets/Sets the caret offset;
/// </summary>
int Offset { get; set; }
/// <summary>
/// Gets/Sets the caret line number.
/// Line numbers are counted starting from 1.
/// </summary>
int Line { get; set; }
/// <summary>
/// Gets/Sets the caret column number.
/// Column numbers are counted starting from 1.
/// </summary>
int Column { get; set; }
/// <summary>
/// Gets/sets the caret location.
/// </summary>
TextLocation Location { get; set; }
/// <summary>
/// Is raised whenever the location of the caret has changed.
/// </summary>
event EventHandler LocationChanged;
}
}

147
ICSharpCode.Editor/ITextSource.cs

@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
namespace ICSharpCode.Editor
{
/// <summary>
/// A read-only view on a (potentially mutable) text source.
/// The IDocument interfaces derives from this interface.
/// </summary>
public interface ITextSource
{
/// <summary>
/// Gets a version identifier for this text source.
/// Returns null for unversioned text sources.
/// </summary>
ITextSourceVersion Version { get; }
/// <summary>
/// Creates an immutable snapshot of this text source.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextSource CreateSnapshot();
/// <summary>
/// Creates an immutable snapshot of a part of this text source.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextSource CreateSnapshot(int offset, int length);
/// <summary>
/// Creates a new TextReader to read from this text source.
/// </summary>
TextReader CreateReader();
/// <summary>
/// Creates a new TextReader to read from this text source.
/// </summary>
TextReader CreateReader(int offset, int length);
/// <summary>
/// Gets the total text length.
/// </summary>
/// <returns>The length of the text, in characters.</returns>
/// <remarks>This is the same as Text.Length, but is more efficient because
/// it doesn't require creating a String object.</remarks>
int TextLength { get; }
/// <summary>
/// Gets the whole text as string.
/// </summary>
string Text { get; }
/// <summary>
/// Gets a character at the specified position in the document.
/// </summary>
/// <paramref name="offset">The index of the character to get.</paramref>
/// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception>
/// <returns>The character at the specified position.</returns>
/// <remarks>This is the same as Text[offset], but is more efficient because
/// it doesn't require creating a String object.</remarks>
char GetCharAt(int offset);
/// <summary>
/// Retrieves the text for a portion of the document.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
/// <remarks>This is the same as Text.Substring, but is more efficient because
/// it doesn't require creating a String object for the whole document.</remarks>
string GetText(int offset, int length);
/// <summary>
/// Retrieves the text for a portion of the document.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
string GetText(ISegment segment);
/// <summary>
/// Gets the index of the first occurrence of any character in the specified array.
/// </summary>
/// <param name="anyOf">Characters to search for</param>
/// <param name="startIndex">Start index of the search.</param>
/// <param name="count">Length of the area to search.</param>
/// <returns>The first index where any character was found; or -1 if no occurrence was found.</returns>
int IndexOfAny(char[] anyOf, int startIndex, int count);
/* What about:
void Insert (int offset, string value);
void Remove (int offset, int count);
void Remove (ISegment segment);
void Replace (int offset, int count, string value);
Or more search operations:
IEnumerable<int> SearchForward (string pattern, int startIndex);
IEnumerable<int> SearchForwardIgnoreCase (string pattern, int startIndex);
IEnumerable<int> SearchBackward (string pattern, int startIndex);
IEnumerable<int> SearchBackwardIgnoreCase (string pattern, int startIndex);
*/
}
/// <summary>
/// Represents a version identifier for a text source.
/// </summary>
/// <remarks>
/// Verions can be used to efficiently detect whether a document has changed and needs reparsing;
/// or even to implement incremental parsers.
/// It is a separate class from ITextBuffer to allow the GC to collect the text buffer while
/// the version checkpoint is still in use.
/// </remarks>
public interface ITextSourceVersion
{
/// <summary>
/// Gets whether this checkpoint belongs to the same document as the other checkpoint.
/// </summary>
bool BelongsToSameDocumentAs(ITextSourceVersion other);
/// <summary>
/// Compares the age of this checkpoint to the other checkpoint.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this version.</exception>
/// <returns>-1 if this version is older than <paramref name="other"/>.
/// 0 if <c>this</c> version instance represents the same version as <paramref name="other"/>.
/// 1 if this version is newer than <paramref name="other"/>.</returns>
int CompareAge(ITextSourceVersion other);
/// <summary>
/// Gets the changes from this checkpoint to the other checkpoint.
/// If 'other' is older than this checkpoint, reverse changes are calculated.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
IEnumerable<TextChangeEventArgs> GetChangesTo(ITextSourceVersion other);
/// <summary>
/// Calculates where the offset has moved in the other buffer version.
/// </summary>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement);
}
}

68
ICSharpCode.Editor/LinkedElement.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
// I'm not sure if we need this.
// How about a method in the context - this method could wrap the internal representation.
// public void StartTextLinkMode (int linkLength, IEnumerable<int> offsets)
// and maybe then variations taking more than one link element ?
// /// <summary>
// /// Represents an element in the text editor that is either editable, or bound to another editable element.
// /// Used with <see cref="ITextEditor.ShowLinkedElements"/>
// /// </summary>
// public class LinkedElement
// {
// LinkedElement boundTo;
//
// /// <summary>
// /// Gets/Sets the start offset of this linked element.
// /// </summary>
// public int StartOffset { get; set; }
//
// /// <summary>
// /// Gets/Sets the end offset of this linked element.
// /// </summary>
// public int EndOffset { get; set; }
//
// /// <summary>
// /// Gets the linked element to which this element is bound.
// /// </summary>
// public LinkedElement BoundTo {
// get { return boundTo; }
// }
//
// /// <summary>
// /// Gets whether this element is editable. Returns true if this element is not bound.
// /// </summary>
// public bool IsEditable {
// get { return boundTo == null; }
// }
//
// /// <summary>
// /// Creates a new editable element.
// /// </summary>
// public LinkedElement(int startOffset, int endOffset)
// {
// this.StartOffset = startOffset;
// this.EndOffset = endOffset;
// }
//
// /// <summary>
// /// Creates a new element that is bound to <paramref name="boundTo"/>.
// /// </summary>
// public LinkedElement(int startOffset, int endOffset, LinkedElement boundTo)
// {
// if (boundTo == null)
// throw new ArgumentNullException("boundTo");
// this.StartOffset = startOffset;
// this.EndOffset = endOffset;
// while (boundTo.boundTo != null)
// boundTo = boundTo.boundTo;
// this.boundTo = boundTo;
// }
// }
}

31
ICSharpCode.Editor/Properties/AssemblyInfo.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
#region Using directives
using System;
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ICSharpCode.Editor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ICSharpCode.Editor")]
[assembly: AssemblyCopyright("Copyright 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]

321
ICSharpCode.Editor/ReadOnlyDocument.cs

@ -0,0 +1,321 @@ @@ -0,0 +1,321 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
namespace ICSharpCode.Editor
{
/// <summary>
/// Read-only implementation of <see cref="IDocument"/>.
/// </summary>
public sealed class ReadOnlyDocument : IDocument
{
readonly ITextSource textSource;
int[] lines;
static readonly char[] newline = { '\r', '\n' };
/// <summary>
/// Creates a new ReadOnlyDocument from the given text source.
/// </summary>
public ReadOnlyDocument(ITextSource textSource)
{
if (textSource == null)
throw new ArgumentNullException("textSource");
// ensure that underlying buffer is immutable
this.textSource = textSource.CreateSnapshot();
List<int> lines = new List<int>();
lines.Add(0);
int offset = 0;
int textLength = textSource.TextLength;
while ((offset = textSource.IndexOfAny(newline, offset, textLength - offset)) >= 0) {
offset++;
if (textSource.GetCharAt(offset - 1) == '\r' && offset < textLength && textSource.GetCharAt(offset) == '\n') {
offset++;
}
lines.Add(offset);
}
this.lines = lines.ToArray();
}
/// <summary>
/// Creates a new ReadOnlyDocument from the given string.
/// </summary>
public ReadOnlyDocument(string text)
: this(new StringTextSource(text))
{
}
/// <inheritdoc/>
public IDocumentLine GetLine(int lineNumber)
{
if (lineNumber < 1 || lineNumber > lines.Length)
throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length);
return new ReadOnlyDocumentLine(this, lineNumber);
}
sealed class ReadOnlyDocumentLine : IDocumentLine
{
readonly ReadOnlyDocument doc;
readonly int lineNumber;
readonly int offset, endOffset;
public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber)
{
this.doc = doc;
this.lineNumber = lineNumber;
this.offset = doc.GetStartOffset(lineNumber);
this.endOffset = doc.GetEndOffset(lineNumber);
}
public int Offset {
get { return offset; }
}
public int Length {
get { return endOffset - offset; }
}
public int EndOffset {
get { return endOffset; }
}
public int TotalLength {
get {
return doc.GetTotalEndOffset(lineNumber) - offset;
}
}
public int DelimiterLength {
get {
return doc.GetTotalEndOffset(lineNumber) - endOffset;
}
}
public int LineNumber {
get { return lineNumber; }
}
}
int GetStartOffset(int lineNumber)
{
return lines[lineNumber-1];
}
int GetTotalEndOffset(int lineNumber)
{
return lineNumber < lines.Length ? lines[lineNumber] : textSource.TextLength;
}
int GetEndOffset(int lineNumber)
{
if (lineNumber == lines.Length)
return textSource.TextLength;
int off = lines[lineNumber] - 1;
if (off > 0 && textSource.GetCharAt(off - 1) == '\r' && textSource.GetCharAt(off) == '\n')
off--;
return off;
}
/// <inheritdoc/>
public IDocumentLine GetLineByOffset(int offset)
{
return GetLine(GetLineNumberForOffset(offset));
}
int GetLineNumberForOffset(int offset)
{
int r = Array.BinarySearch(lines, offset);
return r < 0 ? ~r : r + 1;
}
/// <inheritdoc/>
public int GetOffset(int line, int column)
{
if (line < 1 || line > lines.Length)
throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length);
int lineStart = GetStartOffset(line);
if (column <= 0)
return lineStart;
int lineEnd = GetEndOffset(line);
if (column >= lineEnd - lineStart)
return lineEnd;
return lineStart + column - 1;
}
/// <inheritdoc/>
public int GetOffset(TextLocation location)
{
return GetOffset(location.Line, location.Column);
}
/// <inheritdoc/>
public TextLocation GetLocation(int offset)
{
if (offset < 0 || offset > textSource.TextLength)
throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textSource.TextLength);
int line = GetLineNumberForOffset(offset);
return new TextLocation(offset-GetStartOffset(line)+1, line);
}
/// <inheritdoc/>
public string Text {
get { return textSource.Text; }
set {
throw new NotSupportedException();
}
}
/// <inheritdoc/>
public int TotalNumberOfLines {
get { return lines.Length; }
}
ITextSourceVersion ITextSource.Version {
get { return null; }
}
/// <inheritdoc/>
public int TextLength {
get { return textSource.TextLength; }
}
event EventHandler<TextChangeEventArgs> IDocument.Changing { add {} remove {} }
event EventHandler<TextChangeEventArgs> IDocument.Changed { add {} remove {} }
event EventHandler IDocument.TextChanged { add {} remove {} }
void IDocument.Insert(int offset, string text)
{
throw new NotSupportedException();
}
void IDocument.Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
throw new NotSupportedException();
}
void IDocument.Remove(int offset, int length)
{
throw new NotSupportedException();
}
void IDocument.Replace(int offset, int length, string newText)
{
throw new NotSupportedException();
}
void IDocument.StartUndoableAction()
{
}
void IDocument.EndUndoableAction()
{
}
IDisposable IDocument.OpenUndoGroup()
{
return null;
}
/// <inheritdoc/>
public ITextAnchor CreateAnchor(int offset)
{
return new ReadOnlyDocumentTextAnchor(GetLocation(offset), offset);
}
sealed class ReadOnlyDocumentTextAnchor : ITextAnchor
{
readonly TextLocation location;
readonly int offset;
public ReadOnlyDocumentTextAnchor(TextLocation location, int offset)
{
this.location = location;
this.offset = offset;
}
public event EventHandler Deleted { add {} remove {} }
public TextLocation Location {
get { return location; }
}
public int Offset {
get { return offset; }
}
public AnchorMovementType MovementType { get; set; }
public bool SurviveDeletion { get; set; }
public bool IsDeleted {
get { return false; }
}
public int Line {
get { return location.Line; }
}
public int Column {
get { return location.Column; }
}
}
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return textSource; // textBuffer is immutable
}
/// <inheritdoc/>
public ITextSource CreateSnapshot(int offset, int length)
{
return textSource.CreateSnapshot(offset, length);
}
/// <inheritdoc/>
public System.IO.TextReader CreateReader()
{
return textSource.CreateReader();
}
/// <inheritdoc/>
public System.IO.TextReader CreateReader(int offset, int length)
{
return textSource.CreateReader(offset, length);
}
/// <inheritdoc/>
public char GetCharAt(int offset)
{
return textSource.GetCharAt(offset);
}
/// <inheritdoc/>
public string GetText(int offset, int length)
{
return textSource.GetText(offset, length);
}
/// <inheritdoc/>
public string GetText(ISegment segment)
{
return textSource.GetText(segment);
}
/// <inheritdoc/>
public int IndexOfAny(char[] anyOf, int startIndex, int count)
{
return textSource.IndexOfAny(anyOf, startIndex, count);
}
/// <inheritdoc/>
public object GetService(Type serviceType)
{
return null;
}
}
}

91
ICSharpCode.Editor/StringTextSource.cs

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.IO;
namespace ICSharpCode.Editor
{
/// <summary>
/// Implements the ITextSource interface using a string.
/// </summary>
[Serializable]
public class StringTextSource : ITextSource
{
readonly string text;
/// <summary>
/// Creates a new StringTextSource with the given text.
/// </summary>
public StringTextSource(string text)
{
if (text == null)
throw new ArgumentNullException("text");
this.text = text;
}
ITextSourceVersion ITextSource.Version {
get { return null; }
}
/// <inheritdoc/>
public int TextLength {
get { return text.Length; }
}
/// <inheritdoc/>
public string Text {
get { return text; }
}
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return this; // StringTextBuffer is immutable
}
/// <inheritdoc/>
public ITextSource CreateSnapshot(int offset, int length)
{
return new StringTextSource(text.Substring(offset, length));
}
/// <inheritdoc/>
public TextReader CreateReader()
{
return new StringReader(text);
}
/// <inheritdoc/>
public TextReader CreateReader(int offset, int length)
{
return new StringReader(text.Substring(offset, length));
}
/// <inheritdoc/>
public char GetCharAt(int offset)
{
return text[offset];
}
/// <inheritdoc/>
public string GetText(int offset, int length)
{
return text.Substring(offset, length);
}
/// <inheritdoc/>
public string GetText(ISegment segment)
{
if (segment == null)
throw new ArgumentNullException("segment");
return text.Substring(segment.Offset, segment.Length);
}
/// <inheritdoc/>
public int IndexOfAny(char[] anyOf, int startIndex, int count)
{
return text.IndexOfAny(anyOf, startIndex, count);
}
}
}

64
ICSharpCode.Editor/TextChangeEventArgs.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Editor
{
/// <summary>
/// Describes a change of the document text.
/// This class is thread-safe.
/// </summary>
[Serializable]
public class TextChangeEventArgs : EventArgs
{
readonly int offset;
readonly string removedText;
readonly string insertedText;
/// <summary>
/// The offset at which the change occurs.
/// </summary>
public int Offset {
get { return offset; }
}
/// <summary>
/// The text that was inserted.
/// </summary>
public string RemovedText {
get { return removedText; }
}
/// <summary>
/// The number of characters removed.
/// </summary>
public int RemovalLength {
get { return removedText.Length; }
}
/// <summary>
/// The text that was inserted.
/// </summary>
public string InsertedText {
get { return insertedText; }
}
/// <summary>
/// The number of characters inserted.
/// </summary>
public int InsertionLength {
get { return insertedText.Length; }
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, string removedText, string insertedText)
{
this.offset = offset;
this.removedText = removedText ?? string.Empty;
this.insertedText = insertedText ?? string.Empty;
}
}
}

173
ICSharpCode.Editor/TextLocation.cs

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.Globalization;
namespace ICSharpCode.Editor
{
/// <summary>
/// A line/column position.
/// Text editor lines/columns are counted started from one.
/// </summary>
/// <remarks>
/// The document provides the methods <see cref="IDocument.GetLocation"/> and
/// <see cref="IDocument.GetOffset(TextLocation)"/> to convert between offsets and TextLocations.
/// </remarks>
[Serializable]
public struct TextLocation : IComparable<TextLocation>, IEquatable<TextLocation>
{
/// <summary>
/// Represents no text location (0, 0).
/// </summary>
public static readonly TextLocation Empty = new TextLocation(0, 0);
/// <summary>
/// Constant of the minimum line.
/// </summary>
public const int MinLine = 1;
/// <summary>
/// Constant of the minimum column.
/// </summary>
public const int MinColumn = 1;
/// <summary>
/// Creates a TextLocation instance.
/// </summary>
public TextLocation(int line, int column)
{
this.line = line;
this.column = column;
}
int column, line;
/// <summary>
/// Gets the line number.
/// </summary>
public int Line {
get { return line; }
}
/// <summary>
/// Gets the column number.
/// </summary>
public int Column {
get { return column; }
}
/// <summary>
/// Gets whether the TextLocation instance is empty.
/// </summary>
public bool IsEmpty {
get {
return column < MinLine && line < MinColumn;
}
}
/// <summary>
/// Gets a string representation for debugging purposes.
/// </summary>
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line);
}
/// <summary>
/// Gets a hash code.
/// </summary>
public override int GetHashCode()
{
return unchecked (191 * column.GetHashCode() ^ line.GetHashCode());
}
/// <summary>
/// Equality test.
/// </summary>
public override bool Equals(object obj)
{
if (!(obj is TextLocation)) return false;
return (TextLocation)obj == this;
}
/// <summary>
/// Equality test.
/// </summary>
public bool Equals(TextLocation other)
{
return this == other;
}
/// <summary>
/// Equality test.
/// </summary>
public static bool operator ==(TextLocation left, TextLocation right)
{
return left.column == right.column && left.line == right.line;
}
/// <summary>
/// Inequality test.
/// </summary>
public static bool operator !=(TextLocation left, TextLocation right)
{
return left.column != right.column || left.line != right.line;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator <(TextLocation left, TextLocation right)
{
if (left.line < right.line)
return true;
else if (left.line == right.line)
return left.column < right.column;
else
return false;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator >(TextLocation left, TextLocation right)
{
if (left.line > right.line)
return true;
else if (left.line == right.line)
return left.column > right.column;
else
return false;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator <=(TextLocation left, TextLocation right)
{
return !(left > right);
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator >=(TextLocation left, TextLocation right)
{
return !(left < right);
}
/// <summary>
/// Compares two text locations.
/// </summary>
public int CompareTo(TextLocation other)
{
if (this == other)
return 0;
if (this < other)
return -1;
else
return 1;
}
}
}

2
ICSharpCode.NRefactory.Demo/CSDemo.cs

@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.Demo @@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.Demo
SimpleProjectContent project = new SimpleProjectContent();
TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(project, "dummy.cs");
compilationUnit.AcceptVisitor(convertVisitor, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile.TopLevelTypeDefinitions, null, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile);
List<ITypeResolveContext> projects = new List<ITypeResolveContext>();
projects.Add(project);

53
ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs

@ -23,7 +23,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -23,7 +23,8 @@ namespace ICSharpCode.NRefactory.CSharp
expr = expr.Clone();
expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }, null);
StringWriter w = new StringWriter();
expr.AcceptVisitor(new OutputVisitor(w, policy), null);
w.NewLine = " ";
expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null);
return w.ToString();
}
@ -32,7 +33,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -32,7 +33,8 @@ namespace ICSharpCode.NRefactory.CSharp
expr = expr.Clone();
expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = false }, null);
StringWriter w = new StringWriter();
expr.AcceptVisitor(new OutputVisitor(w, policy), null);
w.NewLine = " ";
expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null);
return w.ToString();
}
@ -85,6 +87,33 @@ namespace ICSharpCode.NRefactory.CSharp @@ -85,6 +87,33 @@ namespace ICSharpCode.NRefactory.CSharp
Assert.AreEqual("(MyType)(!a)", InsertReadable(expr));
}
[Test]
public void TrickyCast4()
{
Expression expr = new PrimitiveExpression(int.MinValue).CastTo(new SimpleType("MyType"));
Assert.AreEqual("(MyType)(-2147483648)", InsertRequired(expr));
Assert.AreEqual("(MyType)(-2147483648)", InsertReadable(expr));
}
[Test]
public void TrickyCast5()
{
Expression expr = new PrimitiveExpression(-1.0).CastTo(new SimpleType("MyType"));
Assert.AreEqual("(MyType)(-1.0)", InsertRequired(expr));
Assert.AreEqual("(MyType)(-1.0)", InsertReadable(expr));
}
[Test]
public void TrickyCast6()
{
Expression expr = new PrimitiveExpression(int.MinValue).CastTo(new PrimitiveType("double"));
Assert.AreEqual("(double)-2147483648", InsertRequired(expr));
Assert.AreEqual("(double)-2147483648", InsertReadable(expr));
}
[Test]
public void CastAndInvoke()
{
@ -170,8 +199,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -170,8 +199,8 @@ namespace ICSharpCode.NRefactory.CSharp
}
}.Invoke("ToArray");
Assert.AreEqual("(from a in b" + Environment.NewLine + "select a.c ()).ToArray ()", InsertRequired(expr));
Assert.AreEqual("(from a in b" + Environment.NewLine + "select a.c ()).ToArray ()", InsertReadable(expr));
Assert.AreEqual("( from a in b select a.c ()).ToArray ()", InsertRequired(expr));
Assert.AreEqual("( from a in b select a.c ()).ToArray ()", InsertReadable(expr));
}
[Test]
@ -194,12 +223,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -194,12 +223,10 @@ namespace ICSharpCode.NRefactory.CSharp
query.Clone()
);
Assert.AreEqual("(from a in b" + Environment.NewLine +
"select a) + from a in b" + Environment.NewLine +
"select a", InsertRequired(expr));
Assert.AreEqual("(from a in b" + Environment.NewLine +
"select a) + (from a in b" + Environment.NewLine +
"select a)", InsertReadable(expr));
Assert.AreEqual("( from a in b select a) + " +
" from a in b select a", InsertRequired(expr));
Assert.AreEqual("( from a in b select a) + " +
"( from a in b select a)", InsertReadable(expr));
}
[Test]
@ -217,10 +244,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -217,10 +244,8 @@ namespace ICSharpCode.NRefactory.CSharp
}
}.IsType(new PrimitiveType("int"));
Assert.AreEqual("(from a in b" + Environment.NewLine +
"select a) is int", InsertRequired(expr));
Assert.AreEqual("(from a in b" + Environment.NewLine +
"select a) is int", InsertReadable(expr));
Assert.AreEqual("( from a in b select a) is int", InsertRequired(expr));
Assert.AreEqual("( from a in b select a) is int", InsertReadable(expr));
}
[Test]

17
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs

@ -118,7 +118,22 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -118,7 +118,22 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
"typeof(MyType<,>)",
new TypeOfExpression {
Type = type
});
});
}
[Test]
public void NestedArraysTest()
{
ParseUtilCSharp.AssertExpression(
"typeof(int[,][])",
new TypeOfExpression {
Type = new ComposedType {
BaseType = new PrimitiveType("int"),
ArraySpecifiers = {
new ArraySpecifier(2),
new ArraySpecifier(1)
}
}});
}
}
}

69
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs

@ -4,7 +4,9 @@ @@ -4,7 +4,9 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope
@ -12,7 +14,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope @@ -12,7 +14,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope
[TestFixture]
public class AttributeSectionTests
{
[Test, Ignore("Parser crash")]
[Test]
public void GlobalAttributeCSharp()
{
string program = @"[global::Microsoft.VisualBasic.CompilerServices.DesignerGenerated()]
@ -27,7 +29,7 @@ public class Form1 { @@ -27,7 +29,7 @@ public class Form1 {
Assert.AreEqual("someprefix::DesignerGenerated", decl.Attributes.Last().Attributes.Single().Type.ToString());
}
[Test, Ignore("assembly/module attributes are broken")]
[Test]
public void AssemblyAttributeCSharp()
{
string program = @"[assembly: System.Attribute()]";
@ -80,20 +82,59 @@ public class Form1 { @@ -80,20 +82,59 @@ public class Form1 {
[Test, Ignore("Parser doesn't support attributes on type parameters")]
public void AttributesOnTypeParameter()
{
string program = @"class Test<[A,B]C> {}";
TypeDeclaration type = ParseUtilCSharp.ParseGlobal<TypeDeclaration>(program);
Assert.IsTrue(
new TypeParameterDeclaration {
Attributes = {
new AttributeSection {
ParseUtilCSharp.AssertGlobal(
"class Test<[A,B]C> {}",
new TypeDeclaration {
ClassType = ClassType.Class,
Name = "Test",
TypeParameters = {
new TypeParameterDeclaration {
Attributes = {
new Attribute { Type = new SimpleType("A") },
new Attribute { Type = new SimpleType("B") }
}
new AttributeSection {
Attributes = {
new Attribute { Type = new SimpleType("A") },
new Attribute { Type = new SimpleType("B") }
}
}
},
Name = "C"
}
}});
}
[Test]
public void AttributeOnMethodParameter()
{
ParseUtilCSharp.AssertTypeMember(
"void M([In] int p);",
new MethodDeclaration {
ReturnType = new PrimitiveType("void"),
Name = "M",
Parameters = {
new ParameterDeclaration {
Attributes = { new AttributeSection(new Attribute { Type = new SimpleType("In") }) },
Type = new PrimitiveType("int"),
Name = "p"
}
},
Name = "C"
}.IsMatch(type.TypeParameters.Single()));
}});
}
[Test]
public void AttributeOnSetterValue()
{
ParseUtilCSharp.AssertTypeMember(
"int P { get; [param: In] set; }",
new PropertyDeclaration {
ReturnType = new PrimitiveType("int"),
Name = "P",
Getter = new Accessor(),
Setter = new Accessor {
Attributes = {
new AttributeSection {
AttributeTarget = "param",
Attributes = { new Attribute { Type = new SimpleType("In") } },
} },
}});
}
// TODO: Tests for other contexts where attributes can appear

8
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs

@ -280,5 +280,13 @@ public abstract class MyClass : MyBase, Interface1, My.Test.Interface2 @@ -280,5 +280,13 @@ public abstract class MyClass : MyBase, Interface1, My.Test.Interface2
Assert.AreEqual("Val1", member.Name);
Assert.AreEqual(10, ((PrimitiveExpression)member.Initializer).Value);
}
[Test]
public void EnumWithBaseType()
{
TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum : short { }");
Assert.AreEqual("MyEnum", td.Name);
Assert.AreEqual("short", ((PrimitiveType)td.BaseTypes.Single()).Keyword);
}
}
}

4
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs

@ -10,7 +10,7 @@ using NUnit.Framework; @@ -10,7 +10,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Parser
{
[TestFixture, Ignore("TypeSystemConvertVisitor is not complete yet")]
[TestFixture]
public class TypeSystemConvertVisitorTests : TypeSystemTests
{
ITypeResolveContext ctx = CecilLoaderTests.Mscorlib;
@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
TypeSystemConvertVisitor visitor = new TypeSystemConvertVisitor(testCasePC, fileName);
cu.AcceptVisitor(visitor, null);
ParsedFile parsedFile = visitor.ParsedFile;
((SimpleProjectContent)testCasePC).UpdateProjectContent(null, parsedFile.TopLevelTypeDefinitions, null, null);
((SimpleProjectContent)testCasePC).UpdateProjectContent(null, parsedFile);
}
}
}

8
ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs

@ -7,7 +7,7 @@ using NUnit.Framework; @@ -7,7 +7,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture, Ignore("DOM for attributes is incomplete")]
[TestFixture]
public class AttributeTests : ResolverTestBase
{
[Test]
@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
string program = "using System; [$LoaderOptimization(3)$] class Test { }";
var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("System.LoaderOptimization.#ctor", mrr.Member.FullName);
Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName);
Assert.AreEqual("System.Byte", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName);
}
@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }";
var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("System.LoaderOptimization.#ctor", mrr.Member.FullName);
Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName);
Assert.AreEqual("System.LoaderOptimization", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName);
}
@ -78,7 +78,7 @@ enum E { A, B } @@ -78,7 +78,7 @@ enum E { A, B }
Assert.AreEqual("MyNamespace.E.A", result.Member.FullName);
}
[Test]
[Test, Ignore("Not implemented in type system.")]
public void SD_1384()
{
string program = @"using System;

57
ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs

@ -388,5 +388,62 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -388,5 +388,62 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
AssertType(typeof(dynamic), resolver.ResolveBinaryOperator(
BinaryOperatorType.NullCoalescing, MakeResult(typeof(string)), MakeResult(typeof(dynamic))));
}
[Test, Ignore("user-defined operators not yet implemented")]
public void LiftedUserDefined()
{
AssertType(typeof(TimeSpan), resolver.ResolveBinaryOperator(
BinaryOperatorType.Subtract, MakeResult(typeof(DateTime)), MakeResult(typeof(DateTime))));
AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator(
BinaryOperatorType.Subtract, MakeResult(typeof(DateTime?)), MakeResult(typeof(DateTime))));
AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator(
BinaryOperatorType.Subtract, MakeResult(typeof(DateTime)), MakeResult(typeof(DateTime?))));
AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator(
BinaryOperatorType.Subtract, MakeResult(typeof(DateTime?)), MakeResult(typeof(DateTime?))));
}
[Test, Ignore("user-defined operators not yet implemented")]
public void UserDefinedNeedsLiftingDueToImplicitConversion()
{
string program = @"struct S {}
struct A {
public static implicit operator S?(A a) { return null; }
public static S operator +(A a, S s) { return s; }
}
class Test {
void M(A a) {
var s = $a + a$;
}
}
";
MemberResolveResult trr = Resolve<MemberResolveResult>(program);
Assert.IsFalse(trr.IsError);
Assert.AreEqual("A.op_Addition", trr.Member.FullName);
// even though we're calling the lifted operator, trr.Member should be the original operator method
Assert.AreEqual("S", trr.Member.ReturnType.Resolve(context).ReflectionName);
Assert.AreEqual("System.Nullable`1[[S]]", trr.Type.ReflectionName);
}
[Test, Ignore("user-defined operators not yet implemented")]
public void ThereIsNoLiftedOperatorsForClasses()
{
string program = @"struct S {}
class A {
public static implicit operator S?(A a) { return null; }
public static S operator +(A a, S s) { return s; }
}
class Test {
void M(A a) {
var s = $a + a$;
}
}
";
MemberResolveResult trr = Resolve<MemberResolveResult>(program);
Assert.IsTrue(trr.IsError); // cannot convert from A to S
Assert.AreEqual("A.op_Addition", trr.Member.FullName);
Assert.AreEqual("S", trr.Type.ReflectionName);
}
}
}

115
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -16,13 +17,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -16,13 +17,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[TestFixture]
public unsafe class ConversionsTest
{
IProjectContent mscorlib = CecilLoaderTests.Mscorlib;
ITypeResolveContext ctx = CecilLoaderTests.Mscorlib;
Conversions conversions = new Conversions(CecilLoaderTests.Mscorlib);
bool ImplicitConversion(Type from, Type to)
{
IType from2 = from.ToTypeReference().Resolve(mscorlib);
IType to2 = to.ToTypeReference().Resolve(mscorlib);
IType from2 = from.ToTypeReference().Resolve(ctx);
IType to2 = to.ToTypeReference().Resolve(ctx);
return conversions.ImplicitConversion(from2, to2);
}
@ -194,18 +195,102 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -194,18 +195,102 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(dynamic)));
}
[Test, Ignore]
public void TypeParameterConversions()
[Test]
public void UnconstrainedTypeParameter()
{
DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2");
DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM");
Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t));
Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
Assert.IsTrue(conversions.ImplicitConversion(t, t));
Assert.IsFalse(conversions.ImplicitConversion(t2, t));
Assert.IsFalse(conversions.ImplicitConversion(t, t2));
Assert.IsFalse(conversions.ImplicitConversion(t, tm));
Assert.IsFalse(conversions.ImplicitConversion(tm, t));
}
[Test]
public void TypeParameterWithReferenceTypeConstraint()
{
DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
t.HasReferenceTypeConstraint = true;
Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t));
Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
}
[Test]
public void TypeParameterWithValueTypeConstraint()
{
DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
t.HasValueTypeConstraint = true;
Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t));
Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
}
[Test]
public void TypeParameterWithClassConstraint()
{
DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer)));
Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t));
Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer))));
Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer))));
Assert.IsFalse(conversions.ImplicitConversion(t, typeof(IComparer<int>).ToTypeReference().Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, typeof(IComparer<string>).ToTypeReference().Resolve(ctx)));
}
[Test]
public void TypeParameterWithInterfaceConstraint()
{
DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList)));
Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t));
Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList))));
Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable))));
}
[Test]
public void UserDefinedImplicitConversion()
{
Assert.IsTrue(ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset)));
Assert.IsFalse(ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime)));
}
[Test]
public void UserDefinedImplicitNullableConversion()
{
// TODO: write tests for conversions of type parameters
throw new NotImplementedException();
// User-defined conversion followed by nullable conversion
Assert.IsTrue(ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset?)));
// Lifted user-defined conversion
Assert.IsTrue(ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset?)));
// User-defined conversion doesn't drop the nullability
Assert.IsFalse(ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset)));
}
bool IntegerLiteralConversion(object value, Type to)
{
IType fromType = value.GetType().ToTypeReference().Resolve(mscorlib);
IType fromType = value.GetType().ToTypeReference().Resolve(ctx);
ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
IType to2 = to.ToTypeReference().Resolve(mscorlib);
IType to2 = to.ToTypeReference().Resolve(ctx);
return conversions.ImplicitConversion(crr, to2);
}
@ -280,18 +365,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -280,18 +365,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
int BetterConversion(Type s, Type t1, Type t2)
{
IType sType = s.ToTypeReference().Resolve(mscorlib);
IType t1Type = t1.ToTypeReference().Resolve(mscorlib);
IType t2Type = t2.ToTypeReference().Resolve(mscorlib);
IType sType = s.ToTypeReference().Resolve(ctx);
IType t1Type = t1.ToTypeReference().Resolve(ctx);
IType t2Type = t2.ToTypeReference().Resolve(ctx);
return conversions.BetterConversion(sType, t1Type, t2Type);
}
int BetterConversion(object value, Type t1, Type t2)
{
IType fromType = value.GetType().ToTypeReference().Resolve(mscorlib);
IType fromType = value.GetType().ToTypeReference().Resolve(ctx);
ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
IType t1Type = t1.ToTypeReference().Resolve(mscorlib);
IType t2Type = t2.ToTypeReference().Resolve(mscorlib);
IType t1Type = t1.ToTypeReference().Resolve(ctx);
IType t2Type = t2.ToTypeReference().Resolve(ctx);
return conversions.BetterConversion(crr, t1Type, t2Type);
}

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs

@ -57,7 +57,7 @@ namespace XN { @@ -57,7 +57,7 @@ namespace XN {
Assert.AreEqual("C.F", mrr.Member.FullName);
}
[Test, Ignore("Test fails due to parser returning incorrect position")]
[Test, Ignore("Anonymous methods not yet implemented")]
public void ExtensionMethodsTest2()
{
string program = @"using System; using System.Collections.Generic;

12
ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.AreSame(SharedTypes.UnknownType, result.Type);
}
[Test, Ignore("Inheritance not supported in parser")]
[Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")]
public void OverriddenMethodCall()
{
string program = @"class A {
@ -70,7 +70,7 @@ class B : A { @@ -70,7 +70,7 @@ class B : A {
Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
}
[Test, Ignore("Inheritance not supported in parser")]
[Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")]
public void OverriddenMethodCall2()
{
string program = @"class A {
@ -122,7 +122,7 @@ class A { @@ -122,7 +122,7 @@ class A {
Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName);
}
[Test, Ignore("parser is broken for events")]
[Test]
public void EventCallTest()
{
string program = @"using System;
@ -209,7 +209,7 @@ class Program { @@ -209,7 +209,7 @@ class Program {
Assert.IsTrue(((IMethod)mrr.Member).Parameters[0].IsRef);
}
[Test, Ignore("Inheritance not supported in parser")]
[Test, Ignore("Grouping by declaring type not yet implemented")]
public void AddedOverload()
{
string program = @"class BaseClass {
@ -225,7 +225,7 @@ class DerivedClass : BaseClass { @@ -225,7 +225,7 @@ class DerivedClass : BaseClass {
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
}
[Test, Ignore("Inheritance not supported in parser")]
[Test]
public void AddedNonApplicableOverload()
{
string program = @"class BaseClass {
@ -244,7 +244,7 @@ class DerivedClass : BaseClass { @@ -244,7 +244,7 @@ class DerivedClass : BaseClass {
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
}
[Test, Ignore("Inheritance not supported in parser")]
[Test, Ignore("Grouping by declaring type not yet implemented")]
public void OverrideShadowed()
{
string program = @"using System;

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

@ -6,7 +6,7 @@ using NUnit.Framework; @@ -6,7 +6,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture, Ignore("Expression Lambdas not supported by parser")]
[TestFixture, Ignore("Lambdas not supported by resolver")]
public class LambdaTests : ResolverTestBase
{
[Test]

88
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -134,7 +134,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -134,7 +134,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public void FindTypeParameters()
{
resolver.UsingScope = MakeUsingScope("System.Collections.Generic");
resolver.CurrentTypeDefinition = context.GetClass(typeof(List<>));
resolver.CurrentTypeDefinition = context.GetTypeDefinition(typeof(List<>));
resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.Single(m => m.Name == "ConvertAll");
TypeResolveResult trr;
@ -191,7 +191,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -191,7 +191,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.AreSame(SharedTypes.UnknownType, result.Type);
}
[Test, Ignore("not yet implemented (depends on distuishing types and expressions in the DOM)")]
[Test]
public void PropertyNameAmbiguousWithTypeName()
{
string program = @"class A {
@ -230,7 +230,7 @@ class Color { public static readonly Color Empty = null; } @@ -230,7 +230,7 @@ class Color { public static readonly Color Empty = null; }
Assert.AreEqual("value", result.Variable.Name);
}
[Test, Ignore("type references not supported")]
[Test]
public void ValueInsideEventTest()
{
string program = @"using System; class A {
@ -263,7 +263,7 @@ class Color { public static readonly Color Empty = null; } @@ -263,7 +263,7 @@ class Color { public static readonly Color Empty = null; }
Assert.AreEqual("value", result.Variable.Name);
}
[Test, Ignore("Anonymous method parameters not supported by parser")]
[Test, Ignore("Anonymous methods not supported in resolver")]
public void AnonymousMethodParameters()
{
string program = @"using System;
@ -350,7 +350,7 @@ namespace Root.Child { @@ -350,7 +350,7 @@ namespace Root.Child {
Assert.AreEqual("Root.Alpha", result.Type.FullName);
}
[Test, Ignore("type references not implemented")]
[Test]
public void ImportAliasTest()
{
string program = @"using COL = System.Collections;
@ -366,7 +366,7 @@ class TestClass { @@ -366,7 +366,7 @@ class TestClass {
Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved");
}
[Test, Ignore("Parser position bug")]
[Test]
public void ImportAliasNamespaceResolveTest()
{
NamespaceResolveResult ns;
@ -377,7 +377,7 @@ class TestClass { @@ -377,7 +377,7 @@ class TestClass {
Assert.AreEqual("System.Collections.Generic", ns.NamespaceName, "COL.Generic");
}
[Test, Ignore("Cannot resolve type references")]
[Test]
public void ImportAliasClassResolveTest()
{
string program = @"using COL = System.Collections.ArrayList;
@ -394,7 +394,36 @@ class TestClass { @@ -394,7 +394,36 @@ class TestClass {
Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a");
}
[Test, Ignore("Parser position bug")]
[Test]
public void ImportSubnamespaceWithAliasTest()
{
string program = @"namespace PC
{
// Define an alias for the nested namespace.
using Project = PC.MyCompany.Project;
class A
{
Project.MyClass M()
{
// Use the alias
$Project.MyClass$ mc = new Project.MyClass();
return mc;
}
}
namespace MyCompany
{
namespace Project
{
public class MyClass { }
}
}
}
";
var mrr = Resolve(program);
Assert.AreEqual("PC.MyCompany.Project.MyClass", mrr.Type.FullName);
}
[Test]
public void ResolveNamespaceSD_863()
{
string program = @"using System;
@ -414,7 +443,7 @@ namespace A.B { @@ -414,7 +443,7 @@ namespace A.B {
Assert.AreEqual("A.B.C.D", trr.Type.FullName);
}
[Test, Ignore("Broken due to parser returning incorrect positions")]
[Test]
public void ResolveTypeSD_863()
{
string program = @"using System;
@ -432,6 +461,31 @@ namespace A.B { @@ -432,6 +461,31 @@ namespace A.B {
Assert.AreEqual("A.B.C", trr.Type.FullName);
}
[Test]
public void InnerTypeResolve ()
{
string program = @"public class C<T> { public class Inner { } }
class TestClass {
void Test() {
$C<string>.Inner$ a;
}
}
";
TypeResolveResult trr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("C.Inner", trr.Type.FullName);
program = @"public class C<T> { public class D<S,U> { public class Inner { } }}
class TestClass {
void Test() {
$C<string>.D<int,TestClass>.Inner$ a;
}
}
";
trr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("C.D.Inner", trr.Type.FullName);
}
[Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")]
public void ShortMaxValueTest()
{
@ -446,7 +500,7 @@ class TestClass { @@ -446,7 +500,7 @@ class TestClass {
Assert.AreEqual(short.MaxValue, rr.ConstantValue);
}
[Test, Ignore("Parser produces incorrect positions for :: operator")]
[Test]
public void ClassWithSameNameAsNamespace()
{
string program = @"using System; namespace XX {
@ -471,7 +525,7 @@ class TestClass { @@ -471,7 +525,7 @@ class TestClass {
Assert.AreEqual("XX.XX.Test", mrr.Member.FullName);
}
[Test, Ignore("Parser position bug")]
[Test]
public void ClassNameLookup1()
{
string program = @"namespace MainNamespace {
@ -490,7 +544,7 @@ namespace Test.Subnamespace { @@ -490,7 +544,7 @@ namespace Test.Subnamespace {
Assert.AreEqual("Test.Subnamespace.Test.TheClass", trr.Type.FullName);
}
[Test, Ignore("Parser position bug")]
[Test]
public void ClassNameLookup2()
{
string program = @"using Test.Subnamespace;
@ -566,7 +620,7 @@ namespace A { @@ -566,7 +620,7 @@ namespace A {
Assert.AreEqual("MainNamespace.Test", nrr.NamespaceName);
}
[Test, Ignore("Fails because parser does not support base type references")]
[Test]
public void InvocableRule()
{
string program = @"using System;
@ -593,7 +647,7 @@ namespace A { @@ -593,7 +647,7 @@ namespace A {
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
}
[Test, Ignore("Fails because parser does not support base type references")]
[Test]
public void InvocableRule2()
{
string program = @"using System;
@ -621,7 +675,7 @@ namespace A { @@ -621,7 +675,7 @@ namespace A {
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
}
[Test, Ignore("Fails because parser does not support base type references")]
[Test]
public void AccessibleRule()
{
string program = @"using System;
@ -676,7 +730,7 @@ namespace A { @@ -676,7 +730,7 @@ namespace A {
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
}
[Test, Ignore("Parser doesn't support inheritance")]
[Test, Ignore("Resolver Bug")]
public void SD_1487()
{
string program = @"using System;
@ -713,7 +767,7 @@ class Test { @@ -713,7 +767,7 @@ class Test {
Assert.AreEqual("System.Int32", rr.Member.ReturnType.Resolve(context).FullName);
}
[Test, Ignore("Parser doesn't support inheritance")]
[Test, Ignore("Resolver bug")]
public void MethodHidesEvent()
{
// see SD-1542

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs

@ -100,7 +100,7 @@ class A { @@ -100,7 +100,7 @@ class A {
Assert.AreEqual(0, m.Parameters.Count);
}
[Test, Ignore("parser doesn't produce any nodes for base constructor calls")]
[Test, Ignore("Not implemented")]
public void ChainedConstructorCall()
{
string program = @"using System;

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -151,7 +151,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -151,7 +151,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ParsedFile parsedFile = new ParsedFile("test.cs", rootUsingScope);
TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.UsingScope, null);
cu.AcceptVisitor(convertVisitor, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile.TopLevelTypeDefinitions, null, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile);
FindNodeVisitor fnv = new FindNodeVisitor(dollars[0], dollars[1]);
cu.AcceptVisitor(fnv, null);

47
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -6,8 +6,8 @@ using System.Collections; @@ -6,8 +6,8 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -15,14 +15,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -15,14 +15,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[TestFixture]
public class TypeInferenceTests
{
readonly ITypeResolveContext ctx = CecilLoaderTests.Mscorlib;
TypeInference ti;
[SetUp]
public void Setup()
{
ti = new TypeInference(CecilLoaderTests.Mscorlib);
ti = new TypeInference(ctx);
}
#region Type Inference
IType[] Resolve(params Type[] types)
{
IType[] r = new IType[types.Length];
@ -34,6 +36,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -34,6 +36,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return r;
}
[Test]
public void ArrayToEnumerable()
{
ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T");
IType stringType = KnownTypeReference.String.Resolve(ctx);
ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>));
bool success;
Assert.AreEqual(
new [] { stringType },
ti.InferTypeArguments(new [] { tp },
new [] { new ResolveResult(new ArrayType(stringType)) },
new [] { new ParameterizedType(enumerableType, new [] { tp }) },
out success));
Assert.IsTrue(success);
}
[Test]
public void EnumerableToArrayInContravariantType()
{
ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T");
IType stringType = KnownTypeReference.String.Resolve(ctx);
ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>));
ITypeDefinition comparerType = ctx.GetTypeDefinition(typeof(IComparer<>));
var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType} ) });
var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(tp) });
bool success;
Assert.AreEqual(
new [] { stringType },
ti.InferTypeArguments(new [] { tp },
new [] { new ResolveResult(comparerOfIEnumerableOfString) },
new [] { comparerOfTpArray },
out success));
Assert.IsTrue(success);
}
#endregion
#region FindTypeInBounds
IType[] FindAllTypesInBounds(IList<IType> lowerBounds, IList<IType> upperBounds = null)
{
ti.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults;
@ -154,5 +196,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -154,5 +196,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Resolve(typeof(List<string>), typeof(List<Version>), typeof(Collection<string>), typeof(Collection<Version>), typeof(ReadOnlyCollection<string>), typeof(ReadOnlyCollection<Version>)),
FindAllTypesInBounds(Resolve(), Resolve(typeof(IEnumerable<ICloneable>), typeof(IEnumerable<IComparable>), typeof(IList))));
}
#endregion
}
}

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -9,7 +9,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[TestFixture]
public class UnsafeCodeTests : ResolverTestBase
{
[Test, Ignore("fixed statement not implemented in parser")]
[Test, Ignore("Parser returns incorrect positions")]
public void FixedStatement()
{
string program = @"using System;

1
ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs

@ -31,6 +31,7 @@ using ICSharpCode.NRefactory.CSharp; @@ -31,6 +31,7 @@ using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.FormattingTests
{
[Ignore ("TODO")]
[TestFixture()]
public class TestBlankLineFormatting : TestBase
{

3
ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs

@ -34,6 +34,7 @@ namespace ICSharpCode.NRefactory.FormattingTests @@ -34,6 +34,7 @@ namespace ICSharpCode.NRefactory.FormattingTests
[TestFixture()]
public class TestBraceStyle : TestBase
{
[Ignore ("TODO")]
[Test()]
public void TestNamespaceBraceStyle ()
{
@ -221,6 +222,7 @@ namespace B { @@ -221,6 +222,7 @@ namespace B {
}");
}
[Ignore ("TODO")]
[Test()]
public void TestAllowPropertyGetBlockInline ()
{
@ -262,6 +264,7 @@ namespace B { @@ -262,6 +264,7 @@ namespace B {
}");
}
[Ignore ("TODO")]
[Test()]
public void TestAllowPropertySetBlockInline ()
{

1
ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs

@ -31,6 +31,7 @@ using ICSharpCode.NRefactory.CSharp; @@ -31,6 +31,7 @@ using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.FormattingTests
{
[Ignore()]
[TestFixture()]
public class TestFormattingBugs : TestBase
{

19
ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs

@ -1065,6 +1065,25 @@ return (Test)null; @@ -1065,6 +1065,25 @@ return (Test)null;
i2 = result.Text.IndexOf (";") + ";".Length;
Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetTextAt (i1, i2 - i1));
}
[Test()]
public void TestLocalVariableWithGenerics ()
{
CSharpFormattingOptions policy = new CSharpFormattingOptions ();
policy.SpaceBeforeLocalVariableDeclarationComma = true;
policy.SpaceAfterLocalVariableDeclarationComma = true;
var result = GetResult (policy, @"class Test {
void TestMe ()
{
List<Test> a;
}
}");
int i1 = result.Text.IndexOf ("List");
int i2 = result.Text.IndexOf (";") + ";".Length;
Assert.AreEqual (@"List<Test> a;", result.GetTextAt (i1, i2 - i1));
}
#region Constructors

3
ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs

@ -55,6 +55,7 @@ this.TestMethod (); @@ -55,6 +55,7 @@ this.TestMethod ();
}");
}
[Ignore ("TODO")]
[Test()]
public void TestIndentBlocks ()
{
@ -498,6 +499,7 @@ using (var o = new MyObj()) { @@ -498,6 +499,7 @@ using (var o = new MyObj()) {
}");
}
[Ignore ("TODO")]
[Test()]
public void TestUsingAlignment ()
{
@ -944,6 +946,7 @@ do { @@ -944,6 +946,7 @@ do {
}");
}
[Ignore ("TODO")]
[Test()]
public void TestIfAlignment ()
{

7
ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs

@ -249,6 +249,7 @@ A @@ -249,6 +249,7 @@ A
}");
}
[Ignore ("TODO")]
[Test()]
public void TestIndentMethodBodyOperatorCase ()
{
@ -283,6 +284,7 @@ A @@ -283,6 +284,7 @@ A
}");
}
[Ignore ("TODO")]
[Test()]
public void TestIndentPropertyBody ()
{
@ -354,6 +356,7 @@ set; @@ -354,6 +356,7 @@ set;
}");
}
[Ignore ("TODO")]
[Test()]
public void TestIndentPropertyBodyIndexerCase ()
{
@ -398,7 +401,7 @@ set { @@ -398,7 +401,7 @@ set {
}");
}
[Ignore ("TODO")]
[Test()]
public void TestPropertyAlignment ()
{
@ -432,6 +435,7 @@ set { @@ -432,6 +435,7 @@ set {
}
[Ignore ("TODO")]
[Test()]
public void TestIndentNamespaceBody ()
{
@ -511,6 +515,7 @@ set; @@ -511,6 +515,7 @@ set;
}
[Ignore ("TODO")]
[Test()]
public void TestIndentEventBody ()
{

70
ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp;
using System.IO;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.FormattingTests
{
@ -41,7 +42,10 @@ namespace ICSharpCode.NRefactory.FormattingTests @@ -41,7 +42,10 @@ namespace ICSharpCode.NRefactory.FormattingTests
return string.Format ("[Delimiter: Offset={0}, Length={1}]", Offset, Length);
}
}
public void Replace (int offset, int count, string value)
{
this.text = this.text.Substring (0, offset) + value + this.text.Substring (offset + count);
}
static IEnumerable<Delimiter> FindDelimiter (string text)
{
for (int i = 0; i < text.Length; i++) {
@ -104,16 +108,6 @@ namespace ICSharpCode.NRefactory.FormattingTests @@ -104,16 +108,6 @@ namespace ICSharpCode.NRefactory.FormattingTests
return new Segment (startOffset, endOffset - startOffset, delimiterLength);
}
public void ApplyChanges (List<Change> changes)
{
changes.Sort ((x, y) => x.Offset.CompareTo (y.Offset));
changes.Reverse ();
foreach (var change in changes) {
text = text.Substring (0, change.Offset) + change.InsertedText + text.Substring (change.Offset + change.RemovedChars);
}
delimiters = new List<Delimiter> (FindDelimiter (text));
}
#region ITextEditorAdapter implementation
public int LocationToOffset (int line, int col)
{
@ -221,14 +215,50 @@ namespace ICSharpCode.NRefactory.FormattingTests @@ -221,14 +215,50 @@ namespace ICSharpCode.NRefactory.FormattingTests
public abstract class TestBase
{
static IActionFactory factory = new TestFactory ();
class TestTextReplaceAction : TextReplaceAction
{
public TestTextReplaceAction (int offset, int removedChars, string insertedText) : base (offset, removedChars, insertedText)
{
}
public override void Perform (Script script)
{
}
}
class TestFactory : AbstractActionFactory
{
public override TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText)
{
return new TestTextReplaceAction (offset, removedChars, insertedText);
}
}
static void ApplyChanges (TextEditorTestAdapter adapter, List<TextReplaceAction> changes)
{
changes.Sort ((x, y) => y.Offset.CompareTo (x.Offset));
foreach (var change in changes) {
// Console.WriteLine ("---- apply:" + change);
// Console.WriteLine (adapter.Text);
if (change.Offset > adapter.Length)
continue;
adapter.Replace (change.Offset, change.RemovedChars, change.InsertedText);
}
// Console.WriteLine ("---result:");
// Console.WriteLine (adapter.Text);
}
protected static ITextEditorAdapter GetResult (CSharpFormattingOptions policy, string input)
{
var adapter = new TextEditorTestAdapter (input);
var visitior = new AstFormattingVisitor (policy, adapter);
var visitior = new AstFormattingVisitor (policy, adapter, factory);
var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text));
compilationUnit.AcceptVisitor (visitior, null);
adapter.ApplyChanges (visitior.Changes);
ApplyChanges (adapter, visitior.Changes);
return adapter;
}
@ -236,22 +266,28 @@ namespace ICSharpCode.NRefactory.FormattingTests @@ -236,22 +266,28 @@ namespace ICSharpCode.NRefactory.FormattingTests
protected static ITextEditorAdapter Test (CSharpFormattingOptions policy, string input, string expectedOutput)
{
var adapter = new TextEditorTestAdapter (input);
var visitior = new AstFormattingVisitor (policy, adapter);
var visitior = new AstFormattingVisitor (policy, adapter, factory);
var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text));
compilationUnit.AcceptVisitor (visitior, null);
adapter.ApplyChanges (visitior.Changes);
ApplyChanges (adapter, visitior.Changes);
if (expectedOutput != adapter.Text) {
Console.WriteLine (adapter.Text);
}
Assert.AreEqual (expectedOutput, adapter.Text);
return adapter;
}
protected static void Continue (CSharpFormattingOptions policy, ITextEditorAdapter adapter, string expectedOutput)
{
var visitior = new AstFormattingVisitor (policy, adapter);
var visitior = new AstFormattingVisitor (policy, adapter, factory);
var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text));
compilationUnit.AcceptVisitor (visitior, null);
((TextEditorTestAdapter)adapter).ApplyChanges (visitior.Changes);
ApplyChanges (((TextEditorTestAdapter)adapter), visitior.Changes);
if (expectedOutput != adapter.Text) {
Console.WriteLine (adapter.Text);
}
Assert.AreEqual (expectedOutput, adapter.Text);
}

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

@ -27,8 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -27,8 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void InheritanceTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(SystemException));
ITypeDefinition c2 = Mscorlib.GetClass(typeof(Exception));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(SystemException));
ITypeDefinition c2 = Mscorlib.GetTypeDefinition(typeof(Exception));
Assert.IsNotNull(c, "c is null");
Assert.IsNotNull(c2, "c2 is null");
//Assert.AreEqual(3, c.BaseTypes.Count); // Inherited interfaces are not reported by Cecil
@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void GenericPropertyTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(Comparer<>));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Comparer<>));
IProperty def = c.Properties.Single(p => p.Name == "Default");
ParameterizedType pt = (ParameterizedType)def.ReturnType.Resolve(ctx);
Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName);
@ -56,7 +56,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -56,7 +56,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void PointerTypeTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(IntPtr));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(IntPtr));
IMethod toPointer = c.Methods.Single(p => p.Name == "ToPointer");
Assert.AreEqual("System.Void*", toPointer.ReturnType.Resolve(ctx).ReflectionName);
Assert.IsTrue (toPointer.ReturnType.Resolve(ctx) is PointerType);
@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void DateTimeDefaultConstructor()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(DateTime));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(DateTime));
Assert.IsFalse(c.Methods.Any(m => m.IsConstructor && m.Parameters.Count == 0)); // struct ctor isn't declared
// but it is implicit:
Assert.IsTrue(c.GetConstructors(ctx).Any(m => m.Parameters.Count == 0));
@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void NoEncodingInfoDefaultConstructor()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(EncodingInfo));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(EncodingInfo));
// EncodingInfo only has an internal constructor
Assert.IsFalse(c.Methods.Any(m => m.IsConstructor));
// and no implicit ctor should be added:
@ -85,7 +85,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -85,7 +85,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void StaticModifierTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(Environment));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment));
Assert.IsNotNull(c, "System.Environment not found");
Assert.IsTrue(c.IsAbstract, "class should be abstract");
Assert.IsTrue(c.IsSealed, "class should be sealed");
@ -95,16 +95,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -95,16 +95,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void InnerClassReferenceTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(Environment));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment));
Assert.IsNotNull(c, "System.Environment not found");
ITypeReference rt = c.Methods.First(m => m.Name == "GetFolderPath").Parameters[0].Type;
Assert.AreSame(c.InnerClasses.Single(ic => ic.Name == "SpecialFolder"), rt.Resolve(ctx));
Assert.AreSame(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"), rt.Resolve(ctx));
}
[Test]
public void InnerClassesTest()
public void NestedTypesTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(Environment.SpecialFolder));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment.SpecialFolder));
Assert.IsNotNull(c, "c is null");
Assert.AreEqual("System.Environment.SpecialFolder", c.FullName);
Assert.AreEqual("System.Environment+SpecialFolder", c.ReflectionName);
@ -113,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -113,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void VoidTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(void));
ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(void));
Assert.IsNotNull(c, "System.Void not found");
Assert.AreEqual(0, c.GetMethods(ctx).Count());
Assert.AreEqual(0, c.GetProperties(ctx).Count());
@ -131,11 +131,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -131,11 +131,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void NestedClassInGenericClassTest()
{
ITypeDefinition dictionary = Mscorlib.GetClass(typeof(Dictionary<,>));
ITypeDefinition dictionary = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>));
Assert.IsNotNull(dictionary);
ITypeDefinition valueCollection = Mscorlib.GetClass(typeof(Dictionary<,>.ValueCollection));
ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection));
Assert.IsNotNull(valueCollection);
var dictionaryRT = new ParameterizedType(dictionary, new[] { Mscorlib.GetClass(typeof(string)), Mscorlib.GetClass(typeof(int)) });
var dictionaryRT = new ParameterizedType(dictionary, new[] { Mscorlib.GetTypeDefinition(typeof(string)), Mscorlib.GetTypeDefinition(typeof(int)) });
IProperty valueProperty = dictionaryRT.GetProperties(ctx).Single(p => p.Name == "Values");
IType parameterizedValueCollection = valueProperty.ReturnType.Resolve(ctx);
Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]", parameterizedValueCollection.ReflectionName);
@ -145,7 +145,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -145,7 +145,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void ValueCollectionCountModifiers()
{
ITypeDefinition valueCollection = Mscorlib.GetClass(typeof(Dictionary<,>.ValueCollection));
ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection));
Assert.AreEqual(Accessibility.Public, valueCollection.Accessibility);
Assert.IsTrue(valueCollection.IsSealed);
Assert.IsFalse(valueCollection.IsAbstract);
@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void MathAcosModifiers()
{
ITypeDefinition math = Mscorlib.GetClass(typeof(Math));
ITypeDefinition math = Mscorlib.GetTypeDefinition(typeof(Math));
Assert.AreEqual(Accessibility.Public, math.Accessibility);
Assert.IsTrue(math.IsSealed);
Assert.IsTrue(math.IsAbstract);
@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void EncodingModifiers()
{
ITypeDefinition encoding = Mscorlib.GetClass(typeof(Encoding));
ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(Encoding));
Assert.AreEqual(Accessibility.Public, encoding.Accessibility);
Assert.IsFalse(encoding.IsSealed);
Assert.IsTrue(encoding.IsAbstract);
@ -213,7 +213,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -213,7 +213,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void UnicodeEncodingModifiers()
{
ITypeDefinition encoding = Mscorlib.GetClass(typeof(UnicodeEncoding));
ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UnicodeEncoding));
Assert.AreEqual(Accessibility.Public, encoding.Accessibility);
Assert.IsFalse(encoding.IsSealed);
Assert.IsFalse(encoding.IsAbstract);
@ -230,7 +230,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -230,7 +230,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void UTF32EncodingModifiers()
{
ITypeDefinition encoding = Mscorlib.GetClass(typeof(UTF32Encoding));
ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UTF32Encoding));
Assert.AreEqual(Accessibility.Public, encoding.Accessibility);
Assert.IsTrue(encoding.IsSealed);
Assert.IsFalse(encoding.IsAbstract);

30
ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs

@ -100,8 +100,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -100,8 +100,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
c,
c.BaseTypes[0].Resolve(context),
c.BaseTypes[1].Resolve(context),
mscorlib.GetClass(typeof(IEnumerable)),
mscorlib.GetClass(typeof(object))
mscorlib.GetTypeDefinition(typeof(IEnumerable)),
mscorlib.GetTypeDefinition(typeof(object))
};
Assert.AreEqual(expected,
c.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray());
@ -114,15 +114,35 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -114,15 +114,35 @@ namespace ICSharpCode.NRefactory.TypeSystem
// don't use a Cecil-loaded struct for this test; we're testing the implicit addition of System.ValueType
DefaultTypeDefinition s = new DefaultTypeDefinition(mscorlib, string.Empty, "S");
s.ClassType = ClassType.Struct;
s.BaseTypes.Add(new ParameterizedType(mscorlib.GetClass(typeof(IEquatable<>)), new[] { s }));
s.BaseTypes.Add(new ParameterizedType(mscorlib.GetTypeDefinition(typeof(IEquatable<>)), new[] { s }));
IType[] expected = {
s,
s.BaseTypes[0].Resolve(context),
mscorlib.GetClass(typeof(object)),
mscorlib.GetClass(typeof(ValueType))
mscorlib.GetTypeDefinition(typeof(object)),
mscorlib.GetTypeDefinition(typeof(ValueType))
};
Assert.AreEqual(expected,
s.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray());
}
[Test]
public void BaseTypesOfListOfString()
{
Assert.AreEqual(
GetTypes(typeof(List<string>), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IEnumerable<string>), typeof(ICollection<string>), typeof(IList<string>)),
GetAllBaseTypes(typeof(List<string>)));
}
[Test]
public void BaseTypeDefinitionsOfListOfString()
{
Assert.AreEqual(
GetTypes(typeof(List<>), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)),
typeof(List<string>).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray());
}
}
}

6
ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -16,7 +16,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
void TestGetClass(Type type)
{
ITypeDefinition t = CecilLoaderTests.Mscorlib.GetClass(type);
ITypeDefinition t = CecilLoaderTests.Mscorlib.GetTypeDefinition(type);
Assert.IsNotNull(t, type.FullName);
Assert.AreEqual(type.FullName, t.ReflectionName);
}
@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("System.Converter`2[[?],[?]]",
parameterType.ToTypeReference().Resolve(context).ReflectionName);
// now try with parent entity:
IMethod convertAll = context.GetClass(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll");
IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll");
Assert.AreEqual("System.Converter`2[[`0],[``0]]",
parameterType.ToTypeReference(entity: convertAll).Resolve(context).ReflectionName);
}
@ -163,7 +163,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -163,7 +163,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void ParseOpenGenericReflectionName()
{
IMethod convertAll = context.GetClass(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll");
IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll");
Assert.AreEqual("System.Converter`2[[?],[?]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]").Resolve(context).ReflectionName);
Assert.AreEqual("System.Converter`2[[`0],[``0]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]", convertAll).Resolve(context).ReflectionName);
}

4
ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// Copyright (c) 2010 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)
using System;
@ -130,7 +130,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -130,7 +130,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void InternProject(IProjectContent pc)
{
foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.InnerClasses)) {
foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.NestedTypes)) {
Intern(c.Namespace);
Intern(c.Name);
foreach (IMember m in c.Members) {

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

@ -10,6 +10,8 @@ using System.Runtime.InteropServices; @@ -10,6 +10,8 @@ using System.Runtime.InteropServices;
namespace ICSharpCode.NRefactory.TypeSystem.TestCase
{
public delegate S GenericDelegate<in T, out S>(T input) where T : S where S : class;
public class SimplePublicClass
{
public void Method() {}

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

@ -28,13 +28,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -28,13 +28,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
ITypeDefinition GetClass(Type type)
{
return testCasePC.GetClass(type);
return testCasePC.GetTypeDefinition(type);
}
[Test]
public void SimplePublicClassTest()
{
ITypeDefinition c = testCasePC.GetClass(typeof(SimplePublicClass));
ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass));
Assert.AreEqual(typeof(SimplePublicClass).Name, c.Name);
Assert.AreEqual(typeof(SimplePublicClass).FullName, c.FullName);
Assert.AreEqual(typeof(SimplePublicClass).Namespace, c.Namespace);
@ -50,8 +50,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -50,8 +50,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void SimplePublicClassMethodTest()
{
ITypeDefinition c = testCasePC.GetClass(typeof(SimplePublicClass));
Assert.AreEqual(2, c.Methods.Count);
ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass));
IMethod method = c.Methods.Single(m => m.Name == "Method");
Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Method", method.FullName);
@ -68,7 +67,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -68,7 +67,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void DynamicType()
{
ITypeDefinition testClass = testCasePC.GetClass(typeof(DynamicTest));
ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest));
Assert.AreSame(SharedTypes.Dynamic, testClass.Properties.Single().ReturnType.Resolve(ctx));
Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count);
}
@ -76,7 +75,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -76,7 +75,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void DynamicTypeInGenerics()
{
ITypeDefinition testClass = testCasePC.GetClass(typeof(DynamicTest));
ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest));
IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1");
Assert.AreEqual("System.Collections.Generic.List`1[[dynamic]]", m1.ReturnType.Resolve(ctx).ReflectionName);
@ -104,7 +103,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -104,7 +103,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void DynamicParameterHasNoAttributes()
{
ITypeDefinition testClass = testCasePC.GetClass(typeof(DynamicTest));
ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest));
IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1");
Assert.AreEqual(0, m1.Parameters[0].Attributes.Count);
}
@ -134,7 +133,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -134,7 +133,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void TestClassTypeParameters()
{
var testClass = testCasePC.GetClass(typeof(GenericClass<,>));
var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>));
Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[0].OwnerType);
Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[1].OwnerType);
Assert.AreSame(testClass.TypeParameters[1], testClass.TypeParameters[0].Constraints[0].Resolve(ctx));
@ -143,7 +142,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -143,7 +142,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void TestMethod()
{
var testClass = testCasePC.GetClass(typeof(GenericClass<,>));
var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>));
IMethod m = testClass.Methods.Single(me => me.Name == "TestMethod");
Assert.AreEqual("K", m.TypeParameters[0].Name);
@ -158,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -158,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void GetIndex()
{
var testClass = testCasePC.GetClass(typeof(GenericClass<,>));
var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>));
IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex");
Assert.AreEqual("T", m.TypeParameters[0].Name);
@ -174,7 +173,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -174,7 +173,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void PropertyWithProtectedSetter()
{
var testClass = testCasePC.GetClass(typeof(PropertyTest));
var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest));
IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithProtectedSetter");
Assert.IsTrue(p.CanGet);
Assert.IsTrue(p.CanSet);
@ -186,7 +185,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -186,7 +185,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void PropertyWithPrivateSetter()
{
var testClass = testCasePC.GetClass(typeof(PropertyTest));
var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest));
IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithPrivateSetter");
Assert.IsTrue(p.CanGet);
Assert.IsTrue(p.CanSet);
@ -198,7 +197,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -198,7 +197,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void Indexer()
{
var testClass = testCasePC.GetClass(typeof(PropertyTest));
var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest));
IProperty p = testClass.Properties.Single(pr => pr.IsIndexer);
Assert.IsTrue(p.CanGet);
Assert.AreEqual(Accessibility.Public, p.Accessibility);
@ -210,9 +209,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -210,9 +209,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void EnumTest()
{
var e = testCasePC.GetClass(typeof(MyEnum));
var e = testCasePC.GetTypeDefinition(typeof(MyEnum));
Assert.AreEqual(ClassType.Enum, e.ClassType);
Assert.AreEqual(false, e.IsReferenceType);
Assert.AreEqual(false, e.IsReferenceType(ctx));
Assert.AreEqual("System.Int16", e.BaseTypes[0].Resolve(ctx).ReflectionName);
Assert.AreEqual(new[] { "System.Enum" }, e.GetBaseTypes(ctx).Select(t => t.ReflectionName).ToArray());
}
@ -220,7 +219,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -220,7 +219,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void EnumFieldsTest()
{
var e = testCasePC.GetClass(typeof(MyEnum));
var e = testCasePC.GetTypeDefinition(typeof(MyEnum));
Assert.AreEqual(5, e.Fields.Count);
foreach (IField f in e.Fields) {
@ -267,21 +266,21 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -267,21 +266,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void SerializableAttribute()
{
IAttribute attr = ctx.GetClass(typeof(NonCustomAttributes)).Attributes.Single();
IAttribute attr = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single();
Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.Resolve(ctx).FullName);
}
[Test]
public void NonSerializedAttribute()
{
IField field = ctx.GetClass(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField");
IField field = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField");
Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
}
[Test]
public void ExplicitStructLayoutAttribute()
{
IAttribute attr = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Attributes.Single();
IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName);
IConstantValue arg1 = attr.GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.GetValueType(ctx).FullName);
@ -302,13 +301,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -302,13 +301,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void FieldOffsetAttribute()
{
IField field = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
IConstantValue arg = field.Attributes.Single().GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName);
Assert.AreEqual(0, arg.GetValue(ctx));
field = ctx.GetClass(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100");
field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
arg = field.Attributes.Single().GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName);
@ -318,7 +317,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -318,7 +317,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void DllImportAttribute()
{
IMethod method = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute dllImport = method.Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName);
Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].GetValue(ctx));
@ -328,7 +327,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -328,7 +327,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void InOutParametersOnRefMethod()
{
IParameter p = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single();
IParameter p = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single();
Assert.IsTrue(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.AreEqual(2, p.Attributes.Count);
@ -339,7 +338,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -339,7 +338,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void MarshalAsAttributeOnMethod()
{
IMethod method = ctx.GetClass(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute marshalAs = method.ReturnTypeAttributes.Single();
Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().GetValue(ctx));
}
@ -347,7 +346,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -347,7 +346,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void MethodWithOutParameter()
{
IParameter p = ctx.GetClass(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single();
IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single();
Assert.IsFalse(p.IsRef);
Assert.IsTrue(p.IsOut);
Assert.AreEqual(0, p.Attributes.Count);
@ -357,12 +356,43 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -357,12 +356,43 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void MethodWithParamsArray()
{
IParameter p = ctx.GetClass(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single();
IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single();
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsTrue(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count);
Assert.IsTrue(p.Type is ArrayTypeReference);
}
[Test, Ignore("C# Parser does not set the variance")]
public void GenericDelegate_Variance()
{
ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>));
Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance);
Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance);
Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0]);
}
[Test]
public void GenericDelegate_ReferenceTypeConstraints()
{
ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>));
Assert.IsFalse(type.TypeParameters[0].HasReferenceTypeConstraint);
Assert.IsTrue(type.TypeParameters[1].HasReferenceTypeConstraint);
Assert.IsTrue(type.TypeParameters[0].IsReferenceType(ctx) == true);
Assert.IsTrue(type.TypeParameters[1].IsReferenceType(ctx) == true);
}
[Test]
public void GenericDelegate_GetInvokeMethod()
{
IType type = typeof(GenericDelegate<string, object>).ToTypeReference().Resolve(ctx);
IMethod m = type.GetDelegateInvokeMethod();
Assert.AreEqual("Invoke", m.Name);
Assert.AreEqual("System.Object", m.ReturnType.Resolve(ctx).FullName);
Assert.AreEqual("System.String", m.Parameters[0].Type.Resolve(ctx).FullName);
}
}
}

2
ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast @@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast
string program = "Imports My.Name.Space\n";
var clause2 = new MemberImportsClause {
Member = new QualifiedType(new QualifiedType(new SimpleType("My"), new Identifier("Name", AstLocation.Empty)), new Identifier("Space", AstLocation.Empty))
Member = new QualifiedType(new QualifiedType(new SimpleType("My"), new Identifier ("Name", AstLocation.Empty)), new Identifier ("Space", AstLocation.Empty))
};
var node = new ImportsStatement();

150
ICSharpCode.NRefactory.VB/Ast/AstNode.cs

@ -35,7 +35,7 @@ using ICSharpCode.NRefactory.VB.Ast; @@ -35,7 +35,7 @@ using ICSharpCode.NRefactory.VB.Ast;
namespace ICSharpCode.NRefactory.VB
{
public abstract class AstNode : PatternMatching.INode
public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode
{
#region Null
public static readonly AstNode Null = new NullAstNode ();
@ -443,157 +443,13 @@ namespace ICSharpCode.NRefactory.VB @@ -443,157 +443,13 @@ namespace ICSharpCode.NRefactory.VB
return copy;
}
#region Annotation support
// Annotations: points either null (no annotations), to the single annotation,
// or to an AnnotationList.
// Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list)
object annotations;
sealed class AnnotationList : List<object>, ICloneable
{
// There are two uses for this custom list type:
// 1) it's private, and thus (unlike List<object>) cannot be confused with real annotations
// 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation.
public AnnotationList(int initialCapacity) : base(initialCapacity)
{
}
public object Clone()
{
lock (this) {
AnnotationList copy = new AnnotationList(this.Count);
for (int i = 0; i < this.Count; i++) {
object obj = this[i];
ICloneable c = obj as ICloneable;
copy.Add(c != null ? c.Clone() : obj);
}
return copy;
}
}
}
public void AddAnnotation(object annotation)
public override void AddAnnotation (object annotation)
{
if (annotation == null)
throw new ArgumentNullException("annotation");
if (this.IsNull)
throw new InvalidOperationException("Cannot add annotations to the null node");
retry: // Retry until successful
object oldAnnotation = Interlocked.CompareExchange(ref this.annotations, annotation, null);
if (oldAnnotation == null) {
return; // we successfully added a single annotation
}
AnnotationList list = oldAnnotation as AnnotationList;
if (list == null) {
// we need to transform the old annotation into a list
list = new AnnotationList(4);
list.Add(oldAnnotation);
list.Add(annotation);
if (Interlocked.CompareExchange(ref this.annotations, list, oldAnnotation) != oldAnnotation) {
// the transformation failed (some other thread wrote to this.annotations first)
goto retry;
}
} else {
// once there's a list, use simple locking
lock (list) {
list.Add(annotation);
}
}
}
public void RemoveAnnotations<T>() where T : class
{
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll(obj => obj is T);
} else if (oldAnnotations is T) {
if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
base.AddAnnotation (annotation);
}
public void RemoveAnnotations(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll(obj => type.IsInstanceOfType(obj));
} else if (type.IsInstanceOfType(oldAnnotations)) {
if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
}
public T Annotation<T>() where T: class
{
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
T t = obj as T;
if (t != null)
return t;
}
return null;
}
} else {
return annotations as T;
}
}
public object Annotation(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
if (type.IsInstanceOfType(obj))
return obj;
}
}
} else {
if (type.IsInstanceOfType(annotations))
return annotations;
}
return null;
}
/// <summary>
/// Gets all annotations stored on this AstNode.
/// </summary>
public IEnumerable<object> Annotations {
get {
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
return list.ToArray();
}
} else {
if (annotations != null)
return new object[] { annotations };
else
return Enumerable.Empty<object>();
}
}
}
#endregion
public abstract S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data);
#region Pattern Matching

2
ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -21,7 +21,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
public string Name {
get { return GetChildByRole (Roles.Identifier).Name; }
set { SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); }
set { SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty)); }
}
public AstNodeCollection<AstType> Constraints {

2
ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
return builder.ToString ();
}
set {
GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier(ident, AstLocation.Empty)));
GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier (ident, AstLocation.Empty)));
}
}

10
ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs

@ -20,9 +20,11 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -20,9 +20,11 @@ namespace ICSharpCode.NRefactory.VB.Ast
public ClassType ClassType { get; set; }
public Identifier Name {
get { return GetChildByRole(Roles.Identifier); }
set { SetChildByRole(Roles.Identifier, value); }
public string Name {
get { return GetChildByRole(Roles.Identifier).Name; }
set {
SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty));
}
}
public AstNodeCollection<TypeParameterDeclaration> TypeParameters {
@ -44,7 +46,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -44,7 +46,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
MatchAttributesAndModifiers(t, match) &&
Members.DoMatch(t.Members, match) &&
ClassType == t.ClassType &&
Name.DoMatch(t.Name, match) &&
MatchString(Name, t.Name) &&
TypeParameters.DoMatch(t.TypeParameters, match) &&
InheritsType.DoMatch(t.InheritsType, match) &&
ImplementsTypes.DoMatch(t.ImplementsTypes, match);

2
ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty));
}
}

4
ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
public SimpleType(string identifier, AstLocation location)
{
SetChildByRole (Roles.Identifier, new Identifier(identifier, location));
SetChildByRole (Roles.Identifier, new Identifier (identifier, location));
}
public string Identifier {
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.VB.Ast @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.VB.Ast
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty));
}
}

6
ICSharpCode.NRefactory.VB/Parser/Parser.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
@ -402,7 +402,7 @@ partial class VBParser @@ -402,7 +402,7 @@ partial class VBParser
while (la.kind == 26) {
Get();
Identifier();
type = new QualifiedType(type, new Identifier(t.val, t.Location));
type = new QualifiedType(type, new Identifier (t.val, t.Location));
}
}
@ -445,7 +445,7 @@ partial class VBParser @@ -445,7 +445,7 @@ partial class VBParser
var result = new AliasImportsClause(); NodeStart(result);
AstType alias;
Identifier();
result.Name = new Identifier(t.val, t.Location);
result.Name = new Identifier (t.val, t.Location);
Expect(20);
TypeName(out alias);
result.Alias = alias;

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

@ -143,7 +143,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -143,7 +143,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Dictionary<string, ControlFlowNode> labels;
List<ControlFlowNode> gotoStatements;
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken))
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context)
{
return BuildControlFlowGraph(statement, context, CancellationToken.None);
}
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken)
{
return BuildControlFlowGraph(statement, new ResolveVisitor(
new CSharpResolver(context, cancellationToken),

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

@ -79,12 +79,22 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -79,12 +79,22 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Queue<DefiniteAssignmentNode> nodesWithModifiedInput = new Queue<DefiniteAssignmentNode>();
public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken = default(CancellationToken))
public DefiniteAssignmentAnalysis(Statement rootStatement)
: this(rootStatement, null, CancellationToken.None)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken)
: this(rootStatement, null, cancellationToken)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken))
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context)
: this(rootStatement, context, CancellationToken.None)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken)
: this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken),
null, ConstantModeResolveVisitorNavigator.Skip))
{
@ -167,12 +177,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -167,12 +177,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// This method can be used to restrict the analysis to only a part of the method.
/// Only the control flow paths that are fully contained within the selected part will be analyzed.
/// </summary>
/// <remarks>Both 'start' and 'end' are inclusive.</remarks>
public void SetAnalyzedRange(Statement start, Statement end)
/// <remarks>By default, both 'start' and 'end' are inclusive.</remarks>
public void SetAnalyzedRange(Statement start, Statement end, bool startInclusive = true, bool endInclusive = true)
{
Debug.Assert(beginNodeDict.ContainsKey(start) && endNodeDict.ContainsKey(end));
int startIndex = beginNodeDict[start].Index;
int endIndex = endNodeDict[end].Index;
var dictForStart = startInclusive ? beginNodeDict : endNodeDict;
var dictForEnd = endInclusive ? endNodeDict : beginNodeDict;
Debug.Assert(dictForStart.ContainsKey(start) && dictForEnd.ContainsKey(end));
int startIndex = dictForStart[start].Index;
int endIndex = dictForEnd[end].Index;
if (startIndex > endIndex)
throw new ArgumentException("The start statement must be lexically preceding the end statement");
this.analyzedRangeStart = startIndex;

21
ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// 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)
using System;
@ -14,7 +14,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -14,7 +14,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <summary>
/// Resolve context represents the minimal mscorlib required for evaluating constants.
/// </summary>
sealed class MinimalResolveContext : IProjectContent, ISynchronizedTypeResolveContext
sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext
{
static readonly Lazy<MinimalResolveContext> instance = new Lazy<MinimalResolveContext>(() => new MinimalResolveContext());
@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
};
}
public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{
foreach (ITypeDefinition type in types) {
if (nameComparer.Equals(type.Name, name) && nameComparer.Equals(type.Namespace, nameSpace) && type.TypeParameterCount == typeParameterCount)
@ -67,12 +67,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -67,12 +67,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return null;
}
public IEnumerable<ITypeDefinition> GetClasses()
public IEnumerable<ITypeDefinition> GetTypes()
{
return types;
}
public IEnumerable<ITypeDefinition> GetClasses(string nameSpace, StringComparer nameComparer)
public IEnumerable<ITypeDefinition> GetTypes(string nameSpace, StringComparer nameComparer)
{
return types.Where(t => nameComparer.Equals(t.Namespace, nameSpace));
}
@ -112,5 +112,16 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -112,5 +112,16 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
{
// exit from Synchronize() block
}
IParsedFile IProjectContent.GetFile(string fileName)
{
return null;
}
IEnumerable<IParsedFile> IProjectContent.Files {
get {
return EmptyList<IParsedFile>.Instance;
}
}
}
}

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

@ -23,7 +23,6 @@ @@ -23,7 +23,6 @@
// 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;
using System.Collections.Generic;
@ -33,7 +32,7 @@ using System.Threading; @@ -33,7 +32,7 @@ using System.Threading;
namespace ICSharpCode.NRefactory.CSharp
{
public abstract class AstNode : PatternMatching.INode
public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode
{
#region Null
public static readonly AstNode Null = new NullAstNode ();
@ -57,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -57,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp
return default (S);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
return other == null || other.IsNull;
}
@ -65,16 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -65,16 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp
#endregion
#region PatternPlaceholder
public static implicit operator AstNode(PatternMatching.Pattern pattern)
public static implicit operator AstNode (PatternMatching.Pattern pattern)
{
return pattern != null ? new PatternPlaceholder(pattern) : null;
return pattern != null ? new PatternPlaceholder (pattern) : null;
}
sealed class PatternPlaceholder : AstNode, PatternMatching.INode
{
readonly PatternMatching.Pattern child;
public PatternPlaceholder(PatternMatching.Pattern child)
public PatternPlaceholder (PatternMatching.Pattern child)
{
this.child = child;
}
@ -83,19 +82,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -83,19 +82,19 @@ namespace ICSharpCode.NRefactory.CSharp
get { return NodeType.Pattern; }
}
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.VisitPatternPlaceholder(this, child, data);
return visitor.VisitPatternPlaceholder (this, child, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
return child.DoMatch(other, match);
return child.DoMatch (other, match);
}
bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo)
bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo)
{
return child.DoMatchCollection(role, pos, match, backtrackingInfo);
return child.DoMatchCollection (role, pos, match, backtrackingInfo);
}
}
#endregion
@ -163,7 +162,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -163,7 +162,7 @@ namespace ICSharpCode.NRefactory.CSharp
get {
AstNode next;
for (AstNode cur = firstChild; cur != null; cur = next) {
Debug.Assert(cur.parent == this);
Debug.Assert (cur.parent == this);
// Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list.
next = cur.nextSibling;
@ -188,7 +187,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -188,7 +187,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public IEnumerable<AstNode> Descendants {
get {
return Utils.TreeTraversal.PreOrder(this.Children, n => n.Children);
return Utils.TreeTraversal.PreOrder (this.Children, n => n.Children);
}
}
@ -197,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -197,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public IEnumerable<AstNode> DescendantsAndSelf {
get {
return Utils.TreeTraversal.PreOrder(this, n => n.Children);
return Utils.TreeTraversal.PreOrder (this, n => n.Children);
}
}
@ -205,10 +204,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -205,10 +204,10 @@ namespace ICSharpCode.NRefactory.CSharp
/// Gets the first child with the specified role.
/// Returns the role's null object if the child is not found.
/// </summary>
public T GetChildByRole<T>(Role<T> role) where T : AstNode
public T GetChildByRole<T> (Role<T> role) where T : AstNode
{
if (role == null)
throw new ArgumentNullException("role");
throw new ArgumentNullException ("role");
for (var cur = firstChild; cur != null; cur = cur.nextSibling) {
if (cur.role == role)
return (T)cur;
@ -216,37 +215,37 @@ namespace ICSharpCode.NRefactory.CSharp @@ -216,37 +215,37 @@ namespace ICSharpCode.NRefactory.CSharp
return role.NullObject;
}
public AstNodeCollection<T> GetChildrenByRole<T>(Role<T> role) where T : AstNode
public AstNodeCollection<T> GetChildrenByRole<T> (Role<T> role) where T : AstNode
{
return new AstNodeCollection<T>(this, role);
return new AstNodeCollection<T> (this, role);
}
protected void SetChildByRole<T>(Role<T> role, T newChild) where T : AstNode
protected void SetChildByRole<T> (Role<T> role, T newChild) where T : AstNode
{
AstNode oldChild = GetChildByRole(role);
AstNode oldChild = GetChildByRole (role);
if (oldChild.IsNull)
AddChild(newChild, role);
AddChild (newChild, role);
else
oldChild.ReplaceWith(newChild);
oldChild.ReplaceWith (newChild);
}
public void AddChild<T>(T child, Role<T> role) where T : AstNode
public void AddChild<T> (T child, Role<T> role) where T : AstNode
{
if (role == null)
throw new ArgumentNullException("role");
throw new ArgumentNullException ("role");
if (child == null || child.IsNull)
return;
if (this.IsNull)
throw new InvalidOperationException("Cannot add children to null nodes");
throw new InvalidOperationException ("Cannot add children to null nodes");
if (child.parent != null)
throw new ArgumentException ("Node is already used in another tree.", "child");
AddChildUnsafe(child, role);
AddChildUnsafe (child, role);
}
/// <summary>
/// Adds a child without performing any safety checks.
/// </summary>
void AddChildUnsafe(AstNode child, Role role)
void AddChildUnsafe (AstNode child, Role role)
{
child.parent = this;
child.role = role;
@ -259,12 +258,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -259,12 +258,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public void InsertChildBefore<T>(AstNode nextSibling, T child, Role<T> role) where T : AstNode
public void InsertChildBefore<T> (AstNode nextSibling, T child, Role<T> role) where T : AstNode
{
if (role == null)
throw new ArgumentNullException("role");
throw new ArgumentNullException ("role");
if (nextSibling == null || nextSibling.IsNull) {
AddChild(child, role);
AddChild (child, role);
return;
}
@ -276,11 +275,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -276,11 +275,10 @@ namespace ICSharpCode.NRefactory.CSharp
throw new ArgumentException ("NextSibling is not a child of this node.", "nextSibling");
// No need to test for "Cannot add children to null nodes",
// as there isn't any valid nextSibling in null nodes.
InsertChildBeforeUnsafe(nextSibling, child, role);
InsertChildBeforeUnsafe (nextSibling, child, role);
}
void InsertChildBeforeUnsafe(AstNode nextSibling, AstNode child, Role role)
void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role)
{
child.parent = this;
child.role = role;
@ -288,38 +286,38 @@ namespace ICSharpCode.NRefactory.CSharp @@ -288,38 +286,38 @@ namespace ICSharpCode.NRefactory.CSharp
child.prevSibling = nextSibling.prevSibling;
if (nextSibling.prevSibling != null) {
Debug.Assert(nextSibling.prevSibling.nextSibling == nextSibling);
Debug.Assert (nextSibling.prevSibling.nextSibling == nextSibling);
nextSibling.prevSibling.nextSibling = child;
} else {
Debug.Assert(firstChild == nextSibling);
Debug.Assert (firstChild == nextSibling);
firstChild = child;
}
nextSibling.prevSibling = child;
}
public void InsertChildAfter<T>(AstNode prevSibling, T child, Role<T> role) where T : AstNode
public void InsertChildAfter<T> (AstNode prevSibling, T child, Role<T> role) where T : AstNode
{
InsertChildBefore((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role);
InsertChildBefore ((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role);
}
/// <summary>
/// Removes this node from its parent.
/// </summary>
public void Remove()
public void Remove ()
{
if (parent != null) {
if (prevSibling != null) {
Debug.Assert(prevSibling.nextSibling == this);
Debug.Assert (prevSibling.nextSibling == this);
prevSibling.nextSibling = nextSibling;
} else {
Debug.Assert(parent.firstChild == this);
Debug.Assert (parent.firstChild == this);
parent.firstChild = nextSibling;
}
if (nextSibling != null) {
Debug.Assert(nextSibling.prevSibling == this);
Debug.Assert (nextSibling.prevSibling == this);
nextSibling.prevSibling = prevSibling;
} else {
Debug.Assert(parent.lastChild == this);
Debug.Assert (parent.lastChild == this);
parent.lastChild = prevSibling;
}
parent = null;
@ -332,28 +330,28 @@ namespace ICSharpCode.NRefactory.CSharp @@ -332,28 +330,28 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Replaces this node with the new node.
/// </summary>
public void ReplaceWith(AstNode newNode)
public void ReplaceWith (AstNode newNode)
{
if (newNode == null || newNode.IsNull) {
Remove();
Remove ();
return;
}
if (newNode == this)
return; // nothing to do...
if (parent == null) {
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
}
// Because this method doesn't statically check the new node's type with the role,
// we perform a runtime test:
if (!role.IsValid(newNode)) {
throw new ArgumentException (string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), "newNode");
if (!role.IsValid (newNode)) {
throw new ArgumentException (string.Format ("The new node '{0}' is not valid in the role {1}", newNode.GetType ().Name, role.ToString ()), "newNode");
}
if (newNode.parent != null) {
// newNode is used within this tree?
if (newNode.Ancestors.Contains(this)) {
if (newNode.Ancestors.Contains (this)) {
// e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);"
// enable automatic removal
newNode.Remove();
newNode.Remove ();
} else {
throw new ArgumentException ("Node is already used in another tree.", "newNode");
}
@ -365,17 +363,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -365,17 +363,17 @@ namespace ICSharpCode.NRefactory.CSharp
newNode.nextSibling = nextSibling;
if (parent != null) {
if (prevSibling != null) {
Debug.Assert(prevSibling.nextSibling == this);
Debug.Assert (prevSibling.nextSibling == this);
prevSibling.nextSibling = newNode;
} else {
Debug.Assert(parent.firstChild == this);
Debug.Assert (parent.firstChild == this);
parent.firstChild = newNode;
}
if (nextSibling != null) {
Debug.Assert(nextSibling.prevSibling == this);
Debug.Assert (nextSibling.prevSibling == this);
nextSibling.prevSibling = newNode;
} else {
Debug.Assert(parent.lastChild == this);
Debug.Assert (parent.lastChild == this);
parent.lastChild = newNode;
}
parent = null;
@ -385,31 +383,31 @@ namespace ICSharpCode.NRefactory.CSharp @@ -385,31 +383,31 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public AstNode ReplaceWith(Func<AstNode, AstNode> replaceFunction)
public AstNode ReplaceWith (Func<AstNode, AstNode> replaceFunction)
{
if (replaceFunction == null)
throw new ArgumentNullException("replaceFunction");
throw new ArgumentNullException ("replaceFunction");
if (parent == null) {
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
}
AstNode oldParent = parent;
AstNode oldSuccessor = nextSibling;
Role oldRole = role;
Remove();
AstNode replacement = replaceFunction(this);
Remove ();
AstNode replacement = replaceFunction (this);
if (oldSuccessor != null && oldSuccessor.parent != oldParent)
throw new InvalidOperationException("replace function changed nextSibling of node being replaced?");
throw new InvalidOperationException ("replace function changed nextSibling of node being replaced?");
if (!(replacement == null || replacement.IsNull)) {
if (replacement.parent != null)
throw new InvalidOperationException("replace function must return the root of a tree");
if (!oldRole.IsValid(replacement)) {
throw new InvalidOperationException (string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString()));
throw new InvalidOperationException ("replace function must return the root of a tree");
if (!oldRole.IsValid (replacement)) {
throw new InvalidOperationException (string.Format ("The new node '{0}' is not valid in the role {1}", replacement.GetType ().Name, oldRole.ToString ()));
}
if (oldSuccessor != null)
oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldRole);
oldParent.InsertChildBeforeUnsafe (oldSuccessor, replacement, oldRole);
else
oldParent.AddChildUnsafe(replacement, oldRole);
oldParent.AddChildUnsafe (replacement, oldRole);
}
return replacement;
}
@ -417,10 +415,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -417,10 +415,10 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Clones the whole subtree starting at this AST node.
/// </summary>
/// <remarks>Annotations are copied over to the new nodes; and any annotations implementating ICloneable will be cloned.</remarks>
public AstNode Clone()
/// <remarks>Annotations are copied over to the new nodes; and any annotations implementing ICloneable will be cloned.</remarks>
public AstNode Clone ()
{
AstNode copy = (AstNode)MemberwiseClone();
AstNode copy = (AstNode)MemberwiseClone ();
// First, reset the shallow pointer copies
copy.parent = null;
copy.role = Roles.Root;
@ -431,186 +429,35 @@ namespace ICSharpCode.NRefactory.CSharp @@ -431,186 +429,35 @@ namespace ICSharpCode.NRefactory.CSharp
// Then perform a deep copy:
for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) {
copy.AddChildUnsafe(cur.Clone(), cur.role);
copy.AddChildUnsafe (cur.Clone (), cur.role);
}
// Finally, clone the annotation, if necessary
ICloneable annotations = copy.annotations as ICloneable; // read from copy (for thread-safety)
if (annotations != null)
copy.annotations = annotations.Clone();
ICloneable copiedAnnotations = copy.annotations as ICloneable; // read from copy (for thread-safety)
if (copiedAnnotations != null)
copy.annotations = copiedAnnotations.Clone();
return copy;
}
#region Annotation support
// Annotations: points either null (no annotations), to the single annotation,
// or to an AnnotationList.
// Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list)
object annotations;
sealed class AnnotationList : List<object>, ICloneable
{
// There are two uses for this custom list type:
// 1) it's private, and thus (unlike List<object>) cannot be confused with real annotations
// 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation.
public AnnotationList(int initialCapacity) : base(initialCapacity)
{
}
public object Clone()
{
lock (this) {
AnnotationList copy = new AnnotationList(this.Count);
for (int i = 0; i < this.Count; i++) {
object obj = this[i];
ICloneable c = obj as ICloneable;
copy.Add(c != null ? c.Clone() : obj);
}
return copy;
}
}
}
public void AddAnnotation(object annotation)
{
if (annotation == null)
throw new ArgumentNullException("annotation");
if (this.IsNull)
throw new InvalidOperationException("Cannot add annotations to the null node");
retry: // Retry until successful
object oldAnnotation = Interlocked.CompareExchange(ref this.annotations, annotation, null);
if (oldAnnotation == null) {
return; // we successfully added a single annotation
}
AnnotationList list = oldAnnotation as AnnotationList;
if (list == null) {
// we need to transform the old annotation into a list
list = new AnnotationList(4);
list.Add(oldAnnotation);
list.Add(annotation);
if (Interlocked.CompareExchange(ref this.annotations, list, oldAnnotation) != oldAnnotation) {
// the transformation failed (some other thread wrote to this.annotations first)
goto retry;
}
} else {
// once there's a list, use simple locking
lock (list) {
list.Add(annotation);
}
}
}
public void RemoveAnnotations<T>() where T : class
{
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll(obj => obj is T);
} else if (oldAnnotations is T) {
if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
}
public void RemoveAnnotations(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll(obj => type.IsInstanceOfType(obj));
} else if (type.IsInstanceOfType(oldAnnotations)) {
if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
}
public T Annotation<T>() where T: class
{
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
T t = obj as T;
if (t != null)
return t;
}
return null;
}
} else {
return annotations as T;
}
}
public object Annotation(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
if (type.IsInstanceOfType(obj))
return obj;
}
}
} else {
if (type.IsInstanceOfType(annotations))
return annotations;
}
return null;
}
/// <summary>
/// Gets all annotations stored on this AstNode.
/// </summary>
public IEnumerable<object> Annotations {
get {
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
return list.ToArray();
}
} else {
if (annotations != null)
return new object[] { annotations };
else
return Enumerable.Empty<object>();
}
}
}
#endregion
public abstract S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data);
#region Pattern Matching
protected static bool MatchString(string name1, string name2)
protected static bool MatchString (string name1, string name2)
{
return string.IsNullOrEmpty(name1) || name1 == name2;
return string.IsNullOrEmpty (name1) || name1 == name2;
}
protected internal abstract bool DoMatch(AstNode other, PatternMatching.Match match);
protected internal abstract bool DoMatch (AstNode other, PatternMatching.Match match);
bool PatternMatching.INode.DoMatch(PatternMatching.INode other, PatternMatching.Match match)
bool PatternMatching.INode.DoMatch (PatternMatching.INode other, PatternMatching.Match match)
{
AstNode o = other as AstNode;
// try matching if other is null, or if other is an AstNode
return (other == null || o != null) && DoMatch(o, match);
return (other == null || o != null) && DoMatch (o, match);
}
bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo)
bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo)
{
AstNode o = pos as AstNode;
return (pos == null || o != null) && DoMatch (o, match);
@ -623,6 +470,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -623,6 +470,7 @@ namespace ICSharpCode.NRefactory.CSharp
PatternMatching.INode PatternMatching.INode.FirstChild {
get { return firstChild; }
}
#endregion
public AstNode GetNextNode ()
@ -655,8 +503,168 @@ namespace ICSharpCode.NRefactory.CSharp @@ -655,8 +503,168 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
public AstNode GetNodeAt (int line, int column)
{
return GetNodeAt (new AstLocation (line, column));
}
public AstNode GetNodeAt (AstLocation location, Predicate<AstNode> pred = null)
{
AstNode result = null;
AstNode node = this;
while (node.FirstChild != null) {
var child = node.FirstChild;
while (child != null) {
if (child.StartLocation <= location && location < child.EndLocation) {
if (pred == null || pred (child))
result = child;
node = child;
break;
}
child = child.NextSibling;
}
// found no better child node - therefore the parent is the right one.
if (child == null)
break;
}
return result;
}
public T GetNodeAt<T> (int line, int column) where T : AstNode
{
return GetNodeAt<T> (new AstLocation (line, column));
}
/// <summary>
/// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching
/// the current method declaration.
/// </summary>
public T GetNodeAt<T> (AstLocation location) where T : AstNode
{
T result = null;
AstNode node = this;
while (node.FirstChild != null) {
var child = node.FirstChild;
while (child != null) {
if (child.StartLocation <= location && location < child.EndLocation) {
if (child is T)
result = (T)child;
node = child;
break;
}
child = child.NextSibling;
}
// found no better child node - therefore the parent is the right one.
if (child == null)
break;
}
return result;
}
public AstNode GetResolveableNodeAt (int line, int column)
{
return GetResolveableNodeAt (new AstLocation (line, column));
}
/// <summary>
/// Gets a node that can be resolved at location.
/// </summary>
public AstNode GetResolveableNodeAt (AstLocation location)
{
return GetNodeAt (location, delegate (AstNode n) {
if (n is TypeDeclaration) {
var decl = (TypeDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is DelegateDeclaration) {
var decl = (DelegateDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is MemberDeclaration) {
var decl = (MemberDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is ConstructorDeclaration) {
var decl = (ConstructorDeclaration)n;
return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation;
}
if (n is DestructorDeclaration) {
var decl = (DestructorDeclaration)n;
return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation;
}
if (n is VariableInitializer) {
var decl = (VariableInitializer)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is ParameterDeclaration) {
var decl = (ParameterDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is MemberReferenceExpression) {
var decl = (MemberReferenceExpression)n;
return decl.MemberNameToken.StartLocation <= location && location <= decl.MemberNameToken.EndLocation;
}
return n is IdentifierExpression || n is AstType;
});
}
public IEnumerable<AstNode> GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn)
{
return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn));
}
public IEnumerable<AstNode> GetNodesBetween (AstLocation start, AstLocation end)
{
AstNode node = this;
while (node != null) {
AstNode next;
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;
yield return node;
} else {
if (node.EndLocation <= start) {
next = node.NextSibling;
} else {
next = node.FirstChild;
}
}
if (next != null && next.StartLocation > end)
yield break;
node = next;
}
}
public bool Contains (int line, int column)
{
return Contains (new AstLocation (line, column));
}
public bool Contains (AstLocation location)
{
return this.StartLocation <= location && location < this.EndLocation;
}
public override void AddAnnotation (object annotation)
{
if (this.IsNull)
throw new InvalidOperationException ("Cannot add annotations to the null node");
base.AddAnnotation (annotation);
}
// the Root role must be available when creating the null nodes, so we can't put it in the Roles class
static readonly Role<AstNode> RootRole = new Role<AstNode>("Root");
static readonly Role<AstNode> RootRole = new Role<AstNode> ("Root");
public static class Roles
{
@ -666,41 +674,38 @@ namespace ICSharpCode.NRefactory.CSharp @@ -666,41 +674,38 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<AstNode> Root = RootRole;
// some pre defined constants for common roles
public static readonly Role<Identifier> Identifier = new Role<Identifier>("Identifier", CSharp.Identifier.Null);
public static readonly Role<BlockStatement> Body = new Role<BlockStatement>("Body", CSharp.BlockStatement.Null);
public static readonly Role<ParameterDeclaration> Parameter = new Role<ParameterDeclaration>("Parameter");
public static readonly Role<Expression> Argument = new Role<Expression>("Argument", CSharp.Expression.Null);
public static readonly Role<AstType> Type = new Role<AstType>("Type", CSharp.AstType.Null);
public static readonly Role<Expression> Expression = new Role<Expression>("Expression", CSharp.Expression.Null);
public static readonly Role<Expression> TargetExpression = new Role<Expression>("Target", CSharp.Expression.Null);
public readonly static Role<Expression> Condition = new Role<Expression>("Condition", CSharp.Expression.Null);
public static readonly Role<TypeParameterDeclaration> TypeParameter = new Role<TypeParameterDeclaration>("TypeParameter");
public static readonly Role<AstType> TypeArgument = new Role<AstType>("TypeArgument", CSharp.AstType.Null);
public readonly static Role<Constraint> Constraint = new Role<Constraint>("Constraint");
public static readonly Role<VariableInitializer> Variable = new Role<VariableInitializer>("Variable");
public static readonly Role<Statement> EmbeddedStatement = new Role<Statement>("EmbeddedStatement", CSharp.Statement.Null);
public static readonly Role<CSharpTokenNode> Keyword = new Role<CSharpTokenNode>("Keyword", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> InKeyword = new Role<CSharpTokenNode>("InKeyword", CSharpTokenNode.Null);
public static readonly Role<Identifier> Identifier = new Role<Identifier> ("Identifier", CSharp.Identifier.Null);
public static readonly Role<BlockStatement> Body = new Role<BlockStatement> ("Body", CSharp.BlockStatement.Null);
public static readonly Role<ParameterDeclaration> Parameter = new Role<ParameterDeclaration> ("Parameter");
public static readonly Role<Expression> Argument = new Role<Expression> ("Argument", CSharp.Expression.Null);
public static readonly Role<AstType> Type = new Role<AstType> ("Type", CSharp.AstType.Null);
public static readonly Role<Expression> Expression = new Role<Expression> ("Expression", CSharp.Expression.Null);
public static readonly Role<Expression> TargetExpression = new Role<Expression> ("Target", CSharp.Expression.Null);
public readonly static Role<Expression> Condition = new Role<Expression> ("Condition", CSharp.Expression.Null);
public static readonly Role<TypeParameterDeclaration> TypeParameter = new Role<TypeParameterDeclaration> ("TypeParameter");
public static readonly Role<AstType> TypeArgument = new Role<AstType> ("TypeArgument", CSharp.AstType.Null);
public readonly static Role<Constraint> Constraint = new Role<Constraint> ("Constraint");
public static readonly Role<VariableInitializer> Variable = new Role<VariableInitializer> ("Variable");
public static readonly Role<Statement> EmbeddedStatement = new Role<Statement> ("EmbeddedStatement", CSharp.Statement.Null);
public static readonly Role<CSharpTokenNode> Keyword = new Role<CSharpTokenNode> ("Keyword", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> InKeyword = new Role<CSharpTokenNode> ("InKeyword", CSharpTokenNode.Null);
// some pre defined constants for most used punctuation
public static readonly Role<CSharpTokenNode> LPar = new Role<CSharpTokenNode>("LPar", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RPar = new Role<CSharpTokenNode>("RPar", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LBracket = new Role<CSharpTokenNode>("LBracket", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RBracket = new Role<CSharpTokenNode>("RBracket", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LBrace = new Role<CSharpTokenNode>("LBrace", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RBrace = new Role<CSharpTokenNode>("RBrace", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LChevron = new Role<CSharpTokenNode>("LChevron", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RChevron = new Role<CSharpTokenNode>("RChevron", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Comma = new Role<CSharpTokenNode>("Comma", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Dot = new Role<CSharpTokenNode>("Dot", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Semicolon = new Role<CSharpTokenNode>("Semicolon", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Assign = new Role<CSharpTokenNode>("Assign", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Colon = new Role<CSharpTokenNode>("Colon", CSharpTokenNode.Null);
public static readonly Role<Comment> Comment = new Role<Comment>("Comment");
public static readonly Role<CSharpTokenNode> LPar = new Role<CSharpTokenNode> ("LPar", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RPar = new Role<CSharpTokenNode> ("RPar", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LBracket = new Role<CSharpTokenNode> ("LBracket", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RBracket = new Role<CSharpTokenNode> ("RBracket", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LBrace = new Role<CSharpTokenNode> ("LBrace", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RBrace = new Role<CSharpTokenNode> ("RBrace", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> LChevron = new Role<CSharpTokenNode> ("LChevron", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> RChevron = new Role<CSharpTokenNode> ("RChevron", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Comma = new Role<CSharpTokenNode> ("Comma", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Dot = new Role<CSharpTokenNode> ("Dot", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Semicolon = new Role<CSharpTokenNode> ("Semicolon", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Assign = new Role<CSharpTokenNode> ("Assign", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Colon = new Role<CSharpTokenNode> ("Colon", CSharpTokenNode.Null);
public static readonly Role<Comment> Comment = new Role<Comment> ("Comment");
public static readonly Role<ErrorNode> Error = new Role<ErrorNode> ("Error");
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// TokenNode.cs
//
// Author:
@ -27,7 +27,7 @@ using System; @@ -27,7 +27,7 @@ using System;
namespace ICSharpCode.NRefactory.CSharp
{
public class CSharpTokenNode : AstNode
public class CSharpTokenNode : AstNode, IRelocatable
{
public static new readonly CSharpTokenNode Null = new NullCSharpTokenNode ();
class NullCSharpTokenNode : CSharpTokenNode
@ -80,6 +80,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,6 +80,13 @@ namespace ICSharpCode.NRefactory.CSharp
this.tokenLength = tokenLength;
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.startLocation = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitCSharpTokenNode (this, data);

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

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
//
// CSharpUtil.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.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.CSharp;
namespace ICSharpCode.NRefactory.CSharp
{
public static class CSharpUtil
{
public static Expression InvertCondition (Expression condition)
{
return InvertConditionInternal (condition.Clone ());
}
static Expression InvertConditionInternal (Expression condition)
{
if (condition is ParenthesizedExpression) {
((ParenthesizedExpression)condition).Expression = InvertCondition (((ParenthesizedExpression)condition).Expression);
return condition;
}
if (condition is UnaryOperatorExpression) {
var uOp = (UnaryOperatorExpression)condition;
if (uOp.Operator == UnaryOperatorType.Not)
return uOp.Expression;
return new UnaryOperatorExpression (UnaryOperatorType.Not, uOp);
}
if (condition is BinaryOperatorExpression) {
var bOp = (BinaryOperatorExpression)condition;
switch (bOp.Operator) {
case BinaryOperatorType.GreaterThan:
bOp.Operator = BinaryOperatorType.LessThanOrEqual;
return bOp;
case BinaryOperatorType.GreaterThanOrEqual:
bOp.Operator = BinaryOperatorType.LessThan;
return bOp;
case BinaryOperatorType.Equality:
bOp.Operator = BinaryOperatorType.InEquality;
return bOp;
case BinaryOperatorType.InEquality:
bOp.Operator = BinaryOperatorType.Equality;
return bOp;
case BinaryOperatorType.LessThan:
bOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
return bOp;
case BinaryOperatorType.LessThanOrEqual:
bOp.Operator = BinaryOperatorType.GreaterThan;
return bOp;
default:
return new UnaryOperatorExpression (UnaryOperatorType.Not, new ParenthesizedExpression (condition));
}
}
if (condition is ConditionalExpression) {
var cEx = condition as ConditionalExpression;
cEx.Condition = InvertCondition (cEx.Condition);
return cEx;
}
if (condition is PrimitiveExpression) {
var pex = condition as PrimitiveExpression;
if (pex.Value is bool) {
pex.Value = !((bool)pex.Value);
return pex;
}
}
return new UnaryOperatorExpression (UnaryOperatorType.Not, condition);
}
}
}

78
ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
@ -38,67 +39,48 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,67 +39,48 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public CompilationUnit ()
{
List<Error> errors = new List<Error> ();
public List<Error> Errors {
get { return errors; }
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
CompilationUnit o = other as CompilationUnit;
return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match);
/// <summary>
/// Gets the expression that was on top of the parse stack.
/// This is the only way to get an expression that isn't part of a statment.
/// (eg. when an error follows an expression).
///
/// This is used for code completion to 'get the expression before a token - like ., <, ('.
/// </summary>
public AstNode TopExpression {
get;
internal set;
}
public AstNode GetNodeAt (int line, int column)
public CompilationUnit ()
{
return GetNodeAt (new AstLocation (line, column));
}
public AstNode GetNodeAt (AstLocation location)
public IEnumerable<TypeDeclaration> GetTypes (bool includeInnerTypes = false)
{
AstNode node = this;
while (node.FirstChild != null) {
var child = node.FirstChild;
while (child != null) {
if (child.StartLocation <= location && location < child.EndLocation) {
node = child;
break;
}
child = child.NextSibling;
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;
foreach (var child in curNode.Children) {
if (!(child is Statement || child is Expression) &&
(child.Role != TypeDeclaration.MemberRole || (child is TypeDeclaration && includeInnerTypes)))
nodeStack.Push (child);
}
// found no better child node - therefore the parent is the right one.
if (child == null)
break;
}
return node;
}
public IEnumerable<AstNode> GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn)
{
return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn));
}
public IEnumerable<AstNode> GetNodesBetween (AstLocation start, AstLocation end)
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
AstNode node = this;
while (node != null) {
AstNode next;
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;
yield return node;
} else {
if (node.EndLocation < start) {
next = node.NextSibling;
} else {
next = node.FirstChild;
}
}
if (next != null && next.StartLocation > end)
yield break;
node = next;
}
CompilationUnit o = other as CompilationUnit;
return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)

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

@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp
public int PointerRank {
get {
return GetChildrenByRole(PointerRole).Count();
return GetChildrenByRole(PointerRole).Count;
}
set {
if (value < 0)
@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
public int Dimensions {
get { return 1 + GetChildrenByRole(Roles.Comma).Count(); }
get { return 1 + GetChildrenByRole(Roles.Comma).Count; }
set {
int d = this.Dimensions;
while (d > value) {

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

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
//
// ErrorNode.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Xamarin (http://www.xamarin.com);
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// Represents a parsing error in the ast. At the moment it only represents missing closing bracket.
/// This closing bracket is replaced by a node at the highest possible position.
/// (To make GetAstNodeAt (line, col) working).
/// </summary>
public class ErrorNode : AstNode
{
static AstLocation maxLoc = new AstLocation (int.MaxValue, int.MaxValue);
public override NodeType NodeType {
get {
return NodeType.Unknown;
}
}
public override AstLocation StartLocation {
get {
return maxLoc;
}
}
public override AstLocation EndLocation {
get {
return maxLoc;
}
}
public ErrorNode ()
{
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
// nothing
return default (S);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
var o = other as ErrorNode;
return o != null;
}
public override string ToString ()
{
return "[ErrorNode]";
}
}
}

13
ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Type&lt;[EMPTY]&gt;
/// </summary>
public class EmptyExpression : Expression
public class EmptyExpression : Expression, IRelocatable
{
AstLocation location;
@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp
return location;
}
}
public override AstLocation EndLocation {
get {
return location;
@ -54,7 +54,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -54,7 +54,14 @@ namespace ICSharpCode.NRefactory.CSharp
{
this.location = location;
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.location = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitEmptyExpression (this, data);

4
ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp
public IdentifierExpression(string identifier, AstLocation location)
{
SetChildByRole(Roles.Identifier, new Identifier(identifier, location));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (identifier, location));
}
// public Identifier IdentifierToken {
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// MemberReferenceExpression.cs
//
// Author:
@ -43,7 +43,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,7 +43,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier MemberNameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -15,7 +15,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -15,7 +15,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier IdentifierToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole(Roles.Identifier, value);
}
}

4
ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// PointerReferenceExpression.cs
//
// Author:
@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Represents a literal value.
/// </summary>
public class PrimitiveExpression : Expression
public class PrimitiveExpression : Expression, IRelocatable
{
public static readonly object AnyValue = new object();
@ -40,16 +40,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,16 +40,22 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
int length;
string literalValue;
public override AstLocation EndLocation {
get {
return new AstLocation (StartLocation.Line, StartLocation.Column + length);
return new AstLocation (StartLocation.Line, StartLocation.Column + literalValue.Length);
}
}
public object Value {
get;
private set;
set;
}
public string LiteralValue {
get {
return literalValue;
}
}
public PrimitiveExpression (object value)
@ -57,12 +63,25 @@ namespace ICSharpCode.NRefactory.CSharp @@ -57,12 +63,25 @@ namespace ICSharpCode.NRefactory.CSharp
this.Value = value;
}
public PrimitiveExpression (object value, AstLocation startLocation, int length)
public PrimitiveExpression (object value, string literalValue)
{
this.Value = value;
this.literalValue = literalValue ?? "";
}
public PrimitiveExpression (object value, AstLocation startLocation, string literalValue)
{
this.Value = value;
this.startLocation = startLocation;
this.length = length;
this.literalValue = literalValue ?? "";
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.startLocation = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{

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

@ -89,7 +89,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -89,7 +89,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}
@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}
@ -153,7 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -153,7 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole(Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}
@ -237,7 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -237,7 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole(JoinIdentifierRole).Name;
}
set {
SetChildByRole(JoinIdentifierRole, new Identifier(value, AstLocation.Empty));
SetChildByRole(JoinIdentifierRole, Identifier.Create (value, AstLocation.Empty));
}
}
@ -277,7 +277,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -277,7 +277,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (IntoIdentifierRole).Name;
}
set {
SetChildByRole(IntoIdentifierRole, new Identifier(value, AstLocation.Empty));
SetChildByRole(IntoIdentifierRole, Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -47,16 +47,31 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,16 +47,31 @@ namespace ICSharpCode.NRefactory.CSharp
public AstNodeCollection<Expression> Arguments {
get { return base.GetChildrenByRole (Roles.Argument); }
}
// HasArgumentList == false: [Empty]
public bool HasArgumentList {
get;
set;
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitAttribute (this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
Attribute o = other as Attribute;
return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match);
return o != null && this.Type.DoMatch (o.Type, match) && this.Arguments.DoMatch (o.Arguments, match);
}
public override string ToString ()
{
if (IsNull)
return "Null";
var w = new System.IO.StringWriter ();
AcceptVisitor (new OutputVisitor (w, new CSharpFormattingOptions ()), null);
return w.ToString ();
}
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// Comment.cs
//
// Author:
@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp
Documentation
}
public class Comment : AstNode
public class Comment : AstNode, IRelocatable
{
public override NodeType NodeType {
get {
@ -81,6 +81,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -81,6 +81,15 @@ namespace ICSharpCode.NRefactory.CSharp
this.startLocation = startLocation;
this.endLocation = endLocation;
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
int lineDelta = startLocation.Line - this.startLocation.Line;
endLocation = new AstLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column);
this.startLocation = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// Constraint.cs
//
// Author:
@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// DelegateDeclaration.cs
//
// Author:
@ -50,7 +50,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -50,7 +50,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// NamespaceDeclaration.cs
//
// Author:
@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp
return builder.ToString ();
}
set {
GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier(ident, AstLocation.Empty)));
GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident, AstLocation.Empty)));
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// TypeDeclaration.cs
//
// Author:
@ -55,7 +55,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -55,7 +55,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -35,7 +35,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -35,7 +35,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

8
ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// UsingAliasDeclaration.cs
//
// Author:
@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (AliasRole).Name;
}
set {
SetChildByRole(AliasRole, new Identifier(value, AstLocation.Empty));
SetChildByRole(AliasRole, Identifier.Create (value, AstLocation.Empty));
}
}
@ -72,13 +72,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -72,13 +72,13 @@ namespace ICSharpCode.NRefactory.CSharp
public UsingAliasDeclaration (string alias, string nameSpace)
{
AddChild (new Identifier (alias, AstLocation.Empty), AliasRole);
AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole);
AddChild (new SimpleType (nameSpace), ImportRole);
}
public UsingAliasDeclaration (string alias, AstType import)
{
AddChild (new Identifier (alias, AstLocation.Empty), AliasRole);
AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole);
AddChild (import, ImportRole);
}

45
ICSharpCode.NRefactory/CSharp/Formatter/Change.cs → ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
//
// Change.cs
// IRelocationable.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
@ -25,48 +25,11 @@ @@ -25,48 +25,11 @@
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory
namespace ICSharpCode.NRefactory.CSharp
{
public class Change
public interface IRelocatable
{
public int Offset {
get;
set;
}
int removedChars;
public int RemovedChars {
get {
return removedChars;
}
set {
if (value < 0)
throw new ArgumentOutOfRangeException ("RemovedChars", "needs to be >= 0");
removedChars = value;
}
}
public string InsertedText {
get;
set;
}
public Change (int offset, int removedChars, string insertedText)
{
if (removedChars < 0)
throw new ArgumentOutOfRangeException ("removedChars", "removedChars needs to be >= 0");
if (offset < 0)
throw new ArgumentOutOfRangeException ("offset", "offset needs to be >= 0");
this.removedChars = removedChars;
this.Offset = offset;
this.InsertedText = insertedText;
}
public override string ToString ()
{
return string.Format ("[Change: Offset={0}, RemovedChars={1}, InsertedText={2}]", Offset, RemovedChars, InsertedText);
}
void SetStartLocation (AstLocation startLocation);
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// Identifier.cs
//
// Author:
@ -28,9 +28,9 @@ using System; @@ -28,9 +28,9 @@ using System;
namespace ICSharpCode.NRefactory.CSharp
{
public class Identifier : AstNode
public class Identifier : AstNode, IRelocatable
{
public static readonly new Identifier Null = new NullIdentifier ();
public static readonly Identifier Null = new NullIdentifier ();
class NullIdentifier : Identifier
{
public override bool IsNull {
@ -66,40 +66,69 @@ namespace ICSharpCode.NRefactory.CSharp @@ -66,40 +66,69 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
/// <summary>
/// True if this is a verbatim identifier (starting with '@')
/// </summary>
public bool IsVerbatim {
get;
set;
}
AstLocation startLocation;
public override AstLocation StartLocation {
get {
return startLocation;
}
}
public virtual bool IsVerbatim {
get {
return false;
}
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.startLocation = startLocation;
}
#endregion
public override AstLocation EndLocation {
get {
return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + (IsVerbatim ? 1 : 0));
return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length);
}
}
private Identifier ()
Identifier ()
{
this.name = string.Empty;
}
public Identifier (string name, AstLocation location)
protected Identifier (string name, AstLocation location)
{
if (name == null)
throw new ArgumentNullException("name");
IsVerbatim = name.StartsWith ("@");
this.Name = IsVerbatim ? name.Substring (1) : name;
this.Name = name;
this.startLocation = location;
}
public static Identifier Create (string name)
{
return Create (name, AstLocation.Empty);
}
public static Identifier Create (string name, AstLocation location)
{
if (name == null)
throw new ArgumentNullException("name");
if (name.Length > 0 && name[0] == '@')
return new VerbatimIdentifier(name.Substring (1), location);
return new Identifier (name, location);
}
public static Identifier Create (string name, AstLocation location, bool isVerbatim)
{
if (name == null)
throw new ArgumentNullException("name");
if (isVerbatim)
return new VerbatimIdentifier(name, location);
return new Identifier (name, location);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
@ -111,5 +140,24 @@ namespace ICSharpCode.NRefactory.CSharp @@ -111,5 +140,24 @@ namespace ICSharpCode.NRefactory.CSharp
Identifier o = other as Identifier;
return o != null && !o.IsNull && MatchString(this.Name, o.Name);
}
class VerbatimIdentifier : Identifier
{
public override AstLocation EndLocation {
get {
return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..."
}
}
public override bool IsVerbatim {
get {
return true;
}
}
public VerbatimIdentifier(string name, AstLocation location) : base (name, location)
{
}
}
}
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// FullTypeName.cs
//
// Author:
@ -47,7 +47,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,7 +47,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier MemberNameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}
@ -55,6 +64,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -55,6 +64,29 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildrenByRole (Roles.TypeArgument); }
}
public MemberType ()
{
}
public MemberType (AstType target, string memberName)
{
this.Target = target;
this.MemberName = memberName;
}
public MemberType (AstType target, string memberName, IEnumerable<AstType> typeArguments)
{
this.Target = target;
this.MemberName = memberName;
foreach (var arg in typeArguments) {
AddChild (arg, Roles.TypeArgument);
}
}
public MemberType (AstType target, string memberName, params AstType[] typeArguments) : this (target, memberName, (IEnumerable<AstType>)typeArguments)
{
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitMemberType (this, data);

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

File diff suppressed because it is too large Load Diff

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

@ -29,7 +29,7 @@ using System.Linq; @@ -29,7 +29,7 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
public class PrimitiveType : AstType
public class PrimitiveType : AstType, IRelocatable
{
public string Keyword { get; set; }
public AstLocation Location { get; set; }
@ -60,6 +60,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -60,6 +60,14 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.Location = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitPrimitiveType (this, data);

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// FullTypeName.cs
//
// Author:
@ -44,7 +44,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,7 +44,19 @@ namespace ICSharpCode.NRefactory.CSharp
public SimpleType(string identifier, AstLocation location)
{
SetChildByRole (Roles.Identifier, new Identifier(identifier, location));
SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (identifier, location));
}
public SimpleType (string identifier, IEnumerable<AstType> typeArguments)
{
this.Identifier = identifier;
foreach (var arg in typeArguments) {
AddChild (arg, Roles.TypeArgument);
}
}
public SimpleType (string identifier, params AstType[] typeArguments) : this (identifier, (IEnumerable<AstType>)typeArguments)
{
}
public string Identifier {
@ -52,7 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier IdentifierToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

11
ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// EmptyStatement.cs
//
// Author:
@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// ;
/// </summary>
public class EmptyStatement : Statement
public class EmptyStatement : Statement, IRelocatable
{
public AstLocation Location {
get;
@ -48,6 +48,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,6 +48,13 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (AstLocation startLocation)
{
this.Location = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitEmptyStatement (this, data);

13
ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// ForeachStatement.cs
//
// Author:
@ -49,7 +49,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,7 +49,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier VariableNameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole(Roles.Identifier, value);
}
}

4
ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// GotoStatement.cs
//
// Author:
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (string.IsNullOrEmpty(value))
SetChildByRole(Roles.Identifier, null);
else
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// LabelStatement.cs
//
// Author:
@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}

9
ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs

@ -156,6 +156,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -156,6 +156,15 @@ namespace ICSharpCode.NRefactory.CSharp
set { SetChildByRole (Roles.Expression, value); }
}
public CaseLabel ()
{
}
public CaseLabel (Expression expression)
{
this.Expression = expression;
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitCaseLabel (this, data);

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// TryCatchStatement.cs
//
// Author:
@ -140,7 +140,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -140,7 +140,16 @@ namespace ICSharpCode.NRefactory.CSharp
if (string.IsNullOrEmpty(value))
SetChildByRole (Roles.Identifier, null);
else
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier VariableNameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole(Roles.Identifier, value);
}
}

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

@ -61,6 +61,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -61,6 +61,11 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildByRole (Roles.Semicolon); }
}
public VariableInitializer GetVariable (string name)
{
return Variables.FirstOrDefault (vi => vi.Name == name);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitVariableDeclarationStatement (this, data);

9
ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs

@ -58,9 +58,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,9 +58,14 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
protected bool MatchAttributesAndModifiers(AttributedNode o, PatternMatching.Match match)
protected bool MatchAttributesAndModifiers (AttributedNode o, PatternMatching.Match match)
{
return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match);
return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch (o.Attributes, match);
}
public bool HasModifier (Modifiers mod)
{
return (Modifiers & mod) == mod;
}
}
}

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

@ -40,6 +40,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -40,6 +40,11 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public string Name { get; set; }
public Identifier IdentifierToken {
get { return GetChildByRole (Roles.Identifier); }
set { SetChildByRole (Roles.Identifier, value); }
}
public CSharpTokenNode LParToken {
get { return GetChildByRole (Roles.LPar); }
}

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

@ -41,6 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,6 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public string Name { get; set; }
public Identifier IdentifierToken {
get { return GetChildByRole (Roles.Identifier); }
set { SetChildByRole (Roles.Identifier, value); }
}
public CSharpTokenNode LParToken {
get { return GetChildByRole (Roles.LPar); }
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// EnumMemberDeclaration.cs
//
// Author:
@ -36,7 +36,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -36,7 +36,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

15
ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// FixedFieldDeclaration.cs
//
// Author:
@ -54,10 +54,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -54,10 +54,19 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}
public CSharpTokenNode LBracketToken {
get { return GetChildByRole (Roles.LBracket); }
}

13
ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// AbstractMember.cs
//
// Author:
@ -48,7 +48,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,7 +48,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -23,52 +23,55 @@ @@ -23,52 +23,55 @@
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
public enum OperatorType {
public enum OperatorType
{
// Values must correspond to Mono.CSharp.Operator.OpType
// due to the casts used in OperatorDeclaration.
// Unary operators
LogicalNot,
OnesComplement,
Increment,
Decrement,
True,
False,
LogicalNot = Mono.CSharp.Operator.OpType.LogicalNot,
OnesComplement = Mono.CSharp.Operator.OpType.OnesComplement,
Increment = Mono.CSharp.Operator.OpType.Increment,
Decrement = Mono.CSharp.Operator.OpType.Decrement,
True = Mono.CSharp.Operator.OpType.True,
False = Mono.CSharp.Operator.OpType.False,
// Unary and Binary operators
Addition,
Subtraction,
Addition = Mono.CSharp.Operator.OpType.Addition,
Subtraction = Mono.CSharp.Operator.OpType.Subtraction,
UnaryPlus,
UnaryNegation,
UnaryPlus = Mono.CSharp.Operator.OpType.UnaryPlus,
UnaryNegation = Mono.CSharp.Operator.OpType.UnaryNegation,
// Binary operators
Multiply,
Division,
Modulus,
BitwiseAnd,
BitwiseOr,
ExclusiveOr,
LeftShift,
RightShift,
Equality,
Inequality,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
Multiply = Mono.CSharp.Operator.OpType.Multiply,
Division = Mono.CSharp.Operator.OpType.Division,
Modulus = Mono.CSharp.Operator.OpType.Modulus,
BitwiseAnd = Mono.CSharp.Operator.OpType.BitwiseAnd,
BitwiseOr = Mono.CSharp.Operator.OpType.BitwiseOr,
ExclusiveOr = Mono.CSharp.Operator.OpType.ExclusiveOr,
LeftShift = Mono.CSharp.Operator.OpType.LeftShift,
RightShift = Mono.CSharp.Operator.OpType.RightShift,
Equality = Mono.CSharp.Operator.OpType.Equality,
Inequality = Mono.CSharp.Operator.OpType.Inequality,
GreaterThan = Mono.CSharp.Operator.OpType.GreaterThan,
LessThan = Mono.CSharp.Operator.OpType.LessThan,
GreaterThanOrEqual = Mono.CSharp.Operator.OpType.GreaterThanOrEqual,
LessThanOrEqual = Mono.CSharp.Operator.OpType.LessThanOrEqual,
// Implicit and Explicit
Implicit,
Explicit
Implicit = Mono.CSharp.Operator.OpType.Implicit,
Explicit = Mono.CSharp.Operator.OpType.Explicit
}
public class OperatorDeclaration : AttributedNode
{
public static readonly Role<CSharpTokenNode> OperatorTypeRole = new Role<CSharpTokenNode>("OperatorType", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> OperatorTypeRole = new Role<CSharpTokenNode> ("OperatorType", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> OperatorKeywordRole = Roles.Keyword;
public OperatorType OperatorType {
@ -78,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -78,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp
public AstType ReturnType {
get { return GetChildByRole (Roles.Type); }
set { SetChildByRole(Roles.Type, value); }
set { SetChildByRole (Roles.Type, value); }
}
public CSharpTokenNode LParToken {
@ -98,14 +101,28 @@ namespace ICSharpCode.NRefactory.CSharp @@ -98,14 +101,28 @@ namespace ICSharpCode.NRefactory.CSharp
set { SetChildByRole (Roles.Body, value); }
}
public static string GetName(OperatorType type)
/// <summary>
/// Gets the operator type from the method name, or null, if the method does not represent one of the known operator types.
/// </summary>
public static OperatorType? GetOperatorType(string methodName)
{
return (OperatorType?)Mono.CSharp.Operator.GetType(methodName);
}
/// <summary>
/// Gets the method name for the operator type. ("op_Addition", "op_Implicit", etc.)
/// </summary>
public static string GetName (OperatorType type)
{
return Mono.CSharp.Operator.GetMetadataName((Mono.CSharp.Operator.OpType)type);
return Mono.CSharp.Operator.GetMetadataName ((Mono.CSharp.Operator.OpType)type);
}
public static string GetToken(OperatorType type)
/// <summary>
/// Gets the token for the operator type ("+", "implicit", etc.)
/// </summary>
public static string GetToken (OperatorType type)
{
return Mono.CSharp.Operator.GetName((Mono.CSharp.Operator.OpType)type);
return Mono.CSharp.Operator.GetName ((Mono.CSharp.Operator.OpType)type);
}
public override NodeType NodeType {
@ -118,15 +135,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -118,15 +135,15 @@ namespace ICSharpCode.NRefactory.CSharp
}
public string Name {
get { return GetName(this.OperatorType); }
get { return GetName (this.OperatorType); }
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
OperatorDeclaration o = other as OperatorDeclaration;
return o != null && this.MatchAttributesAndModifiers(o, match) && this.OperatorType == o.OperatorType
&& this.ReturnType.DoMatch(o.ReturnType, match)
&& this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
return o != null && this.MatchAttributesAndModifiers (o, match) && this.OperatorType == o.OperatorType
&& this.ReturnType.DoMatch (o.ReturnType, match)
&& this.Parameters.DoMatch (o.Parameters, match) && this.Body.DoMatch (o.Body, match);
}
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// ParameterDeclarationExpression.cs
//
// Author:
@ -68,7 +68,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -68,7 +68,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// VariableInitializer.cs
//
// Author:
@ -85,7 +85,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -85,7 +85,16 @@ namespace ICSharpCode.NRefactory.CSharp
return GetChildByRole (Roles.Identifier).Name;
}
set {
SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty));
SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty));
}
}
public Identifier NameToken {
get {
return GetChildByRole (Roles.Identifier);
}
set {
SetChildByRole (Roles.Identifier, value);
}
}

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

@ -28,6 +28,7 @@ using System.Text; @@ -28,6 +28,7 @@ using System.Text;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp
{
@ -35,7 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -35,7 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
CSharpFormattingOptions policy;
ITextEditorAdapter data;
List<Change> changes = new List<Change> ();
IActionFactory factory;
List<TextReplaceAction> changes = new List<TextReplaceAction> ();
Indent curIndent = new Indent ();
public int IndentLevel {
@ -52,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -52,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public List<Change> Changes {
public List<TextReplaceAction> Changes {
get { return this.changes; }
}
@ -66,15 +68,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -66,15 +68,18 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data)
public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data, IActionFactory factory)
{
if (factory == null)
throw new ArgumentNullException ("factory");
this.policy = policy;
this.data = data;
this.curIndent.TabsToSpaces = this.data.TabsToSpaces;
this.curIndent.TabSize = this.data.TabSize;
this.factory = factory;
CorrectBlankLines = true;
}
public override object VisitCompilationUnit (CompilationUnit unit, object data)
{
base.VisitCompilationUnit (unit, data);
@ -90,11 +95,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -90,11 +95,20 @@ namespace ICSharpCode.NRefactory.CSharp
do {
line++;
} while (line < data.LineCount && data.GetEditableLength (line) == data.GetIndentation (line).Length);
var start = data.GetLineEndOffset (loc.Line);
var start = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column);
int foundBlankLines = line - loc.Line - 1;
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < blankLines; i++)
for (int i = 0; i < blankLines - foundBlankLines; i++)
sb.Append (data.EolMarker);
int removedChars = line < data.LineCount ? data.GetLineOffset (line) - start : 0;
int ws = start;
while (ws < data.Length && IsSpacing (data.GetCharAt (ws)))
ws++;
int removedChars = ws - start;
if (foundBlankLines > blankLines)
removedChars += data.GetLineEndOffset (loc.Line + foundBlankLines - blankLines) - data.GetLineEndOffset (loc.Line);
AddChange (start, removedChars, sb.ToString ());
}
@ -107,7 +121,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -107,7 +121,6 @@ namespace ICSharpCode.NRefactory.CSharp
do {
line--;
} while (line > 0 && data.GetEditableLength (line) == data.GetIndentation (line).Length);
int end = data.GetLineOffset (loc.Line);
int start = line >= 1 ? data.GetLineEndOffset (line) : 0;
StringBuilder sb = new StringBuilder ();
@ -118,20 +131,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -118,20 +131,20 @@ namespace ICSharpCode.NRefactory.CSharp
public override object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data)
{
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration))
EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings);
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
return null;
}
public override object VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, object data)
{
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration))
EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings);
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
return null;
}
@ -528,12 +541,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -528,12 +541,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
return base.VisitFieldDeclaration (fieldDeclaration, data);
}
public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data)
{
FixIndentationForceNewLine (fixedFieldDeclaration.StartLocation);
FormatCommas (fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma);
if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration ) {
if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) {
EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenFields);
} else if (IsMember (fixedFieldDeclaration.NextSibling)) {
EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenMembers);
@ -952,10 +965,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -952,10 +965,10 @@ namespace ICSharpCode.NRefactory.CSharp
return;
}
}
// Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars , insertedText == null ? "<null>" : insertedText.Replace("\n", "\\n").Replace("\t", "\\t").Replace(" ", "."));
// Console.WriteLine (Environment.StackTrace);
//Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\t", "\\t").Replace (" ", "."));
//Console.WriteLine (Environment.StackTrace);
changes.Add (new Change (offset, removedChars, insertedText));
changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText));
}
public bool IsLineIsEmptyUpToEol (AstLocation startLocation)
@ -1556,13 +1569,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1556,13 +1569,13 @@ namespace ICSharpCode.NRefactory.CSharp
void FixIndentation (AstLocation location, int relOffset)
{
if (location.Line < 0 || location.Line >= data.LineCount) {
if (location.Line < 1 || location.Line > data.LineCount) {
Console.WriteLine ("Invalid location " + location);
Console.WriteLine (Environment.StackTrace);
return;
}
string lineIndent = data.GetIndentation (location.Line);
string lineIndent = data.GetIndentation (location.Line);
string indentString = this.curIndent.IndentString;
if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) {
AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString);
@ -1573,9 +1586,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1573,9 +1586,9 @@ namespace ICSharpCode.NRefactory.CSharp
{
string lineIndent = data.GetIndentation (location.Line);
string indentString = this.curIndent.IndentString;
if (indentString != lineIndent && location.Column - 1 == lineIndent.Length) {
if (location.Column - 1 == lineIndent.Length) {
AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString);
} else {
} else {
int offset = data.LocationToOffset (location.Line, location.Column);
int start = SearchWhitespaceLineStart (offset);
if (start > 0) {
@ -1593,4 +1606,3 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1593,4 +1606,3 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
}

35
ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs

@ -23,30 +23,61 @@ @@ -23,30 +23,61 @@
// 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
{
public interface ITextEditorAdapter
{
bool TabsToSpaces { get; }
int TabSize { get; }
string EolMarker { get; }
string Text { get; }
string Text { get; }
int Length { get; }
int LocationToOffset (int line, int col);
char GetCharAt (int offset);
string GetTextAt (int offset, int length);
int LineCount { get; }
int GetEditableLength (int lineNumber);
string GetIndentation (int lineNumber);
int GetLineOffset (int lineNumber);
int GetLineLength (int lineNumber);
int GetLineEndOffset (int lineNumber);
void Replace (int offset, int count, string text);
}
/*
public static class ITextEditorAdapterHelperMethods
{
public static void AcceptChanges (this ITextEditorAdapter adapter, List<Change> changes)
{
for (int i = 0; i < changes.Count; i++) {
changes [i].PerformChange (adapter);
var replaceChange = changes [i];
for (int j = i + 1; j < changes.Count; j++) {
var change = changes [j];
if (replaceChange.Offset >= 0 && change.Offset >= 0) {
if (replaceChange.Offset < change.Offset) {
change.Offset -= replaceChange.RemovedChars;
if (!string.IsNullOrEmpty (replaceChange.InsertedText))
change.Offset += replaceChange.InsertedText.Length;
} else if (replaceChange.Offset < change.Offset + change.RemovedChars) {
change.RemovedChars -= replaceChange.RemovedChars;
change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0);
}
}
}
}
}
}*/
}

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

Loading…
Cancel
Save