├── .editorconfig
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── Microsoft.Language.Xml.sln
├── NuGet.config
├── README.md
├── appveyor.yml
├── benchmark
└── Microsoft.Language.Xml.Benchmarks
│ ├── Microsoft.Language.Xml.Benchmarks.csproj
│ ├── ParserBenchmarks.cs
│ ├── Program.cs
│ └── XmlSnippets.cs
├── key.snk
├── language_xml_logo.png
├── src
├── Microsoft.Language.Xml.Editor
│ ├── Classification
│ │ ├── ClassificationTypeDefinitions.cs
│ │ ├── Classifier.cs
│ │ └── ClassifierProvider.cs
│ ├── Comments
│ │ └── CommentingService.cs
│ ├── ContentType.cs
│ ├── Microsoft.Language.Xml.Editor.csproj
│ ├── Outlining
│ │ ├── OutliningTagger.cs
│ │ └── OutliningTaggerProvider.cs
│ ├── Parsing
│ │ └── ParserService.cs
│ ├── SmartIndent
│ │ ├── SmartIndent.cs
│ │ └── SmartIndentProvider.cs
│ ├── Tagging
│ │ └── AbstractSyntaxTreeTagger.cs
│ └── TextSnapshotBuffer.cs
└── Microsoft.Language.Xml
│ ├── AssemblyInfo.cs
│ ├── Blender.cs
│ ├── Buffer.cs
│ ├── Classification
│ ├── ClassificationTypeNames.cs
│ ├── ClassifierVisitor.cs
│ └── XmlClassificationTypes.cs
│ ├── Comments
│ └── CommentUtilities.cs
│ ├── DiagnosticInfo.cs
│ ├── ErrorFactory.cs
│ ├── Extensions.cs
│ ├── InternalSyntax
│ ├── GreenNode.cs
│ ├── GreenNodeExtensions.cs
│ ├── NodeFlags.cs
│ ├── SeparatedSyntaxList.cs
│ ├── SeparatedSyntaxListBuilder.cs
│ ├── SyntaxFactory.cs
│ ├── SyntaxList.cs
│ ├── SyntaxListBuilder.cs
│ ├── SyntaxListBuilder`1.cs
│ ├── SyntaxList`1.cs
│ ├── SyntaxRewriter.cs
│ ├── SyntaxVisitor.cs
│ └── TriviaInfo.cs
│ ├── Microsoft.Language.Xml.csproj
│ ├── Parser.cs
│ ├── PooledStringBuilder.cs
│ ├── Scanner.cs
│ ├── ScannerState.cs
│ ├── StringBuffer.cs
│ ├── Structure
│ ├── INamedXmlNode.cs
│ └── IXmlElement.cs
│ ├── Syntax
│ ├── BadTokenSyntax.cs
│ ├── ChildSyntaxList.cs
│ ├── ERRID.cs
│ ├── IXmlElementSyntax.cs
│ ├── KeywordSyntax.cs
│ ├── PunctuationSyntax.cs
│ ├── SeparatedSyntaxListBuilder`1.cs
│ ├── SeparatedSyntaxList`1.cs
│ ├── SkippedTokensTriviaSyntax.cs
│ ├── SkippedTriviaBuilder.cs
│ ├── SyntaxAnnotation.cs
│ ├── SyntaxDiffer.cs
│ ├── SyntaxFactory.cs
│ ├── SyntaxKind.cs
│ ├── SyntaxList.cs
│ ├── SyntaxListBuilder.cs
│ ├── SyntaxListBuilderExtensions.cs
│ ├── SyntaxListBuilder`1.cs
│ ├── SyntaxListPool.cs
│ ├── SyntaxList`1.cs
│ ├── SyntaxNode.Enumerators.cs
│ ├── SyntaxNode.cs
│ ├── SyntaxNodeExtensions.cs
│ ├── SyntaxNodeRemover.cs
│ ├── SyntaxReplacer.cs
│ ├── SyntaxRewriter.cs
│ ├── SyntaxSubKind.cs
│ ├── SyntaxToken.cs
│ ├── SyntaxTrivia.cs
│ ├── SyntaxTriviaList.cs
│ ├── SyntaxTriviaListBuilder.cs
│ ├── SyntaxVisitor.cs
│ ├── XmlAttributeSyntax.cs
│ ├── XmlCDataSectionSyntax.cs
│ ├── XmlCommentSyntax.cs
│ ├── XmlContentExtensions.cs
│ ├── XmlContext.cs
│ ├── XmlDeclarationOptionSyntax.cs
│ ├── XmlDeclarationSyntax.cs
│ ├── XmlDocumentSyntax.cs
│ ├── XmlElementEndTagSyntax.cs
│ ├── XmlElementStartTagSyntax.cs
│ ├── XmlElementSyntax.cs
│ ├── XmlEmptyElementSyntax.cs
│ ├── XmlEntityTokenSyntax.cs
│ ├── XmlNameSyntax.cs
│ ├── XmlNameTokenSyntax.cs
│ ├── XmlNodeSyntax.cs
│ ├── XmlPrefixSyntax.cs
│ ├── XmlProcessingInstructionSyntax.cs
│ ├── XmlStringSyntax.cs
│ ├── XmlTextSyntax.cs
│ └── XmlTextTokenSyntax.cs
│ ├── TextChange.cs
│ ├── TextChangeRange.cs
│ ├── TextSpan.cs
│ ├── Utilities
│ ├── ArrayBuilder.cs
│ ├── ArrayElement.cs
│ ├── FirstTokenReplacer.cs
│ ├── HashFunctions.cs
│ ├── LastTokenReplacer.cs
│ ├── Normalization.cs
│ ├── ObjectPool.cs
│ ├── SpecializedCollections.cs
│ ├── StringTable.cs
│ ├── SyntaxLocator.cs
│ ├── SyntaxNodeCache.cs
│ └── TextKeyedCache.cs
│ ├── XmlCharType.cs
│ ├── XmlExtensions.cs
│ ├── XmlResources.Designer.cs
│ └── XmlResources.resx
├── test
├── Microsoft.Language.Xml.Editor.Tests
│ ├── Microsoft.Language.Xml.Editor.Tests.csproj
│ ├── SyntaxReplacerTests.cs
│ └── TestSmartIndent.cs
└── Microsoft.Language.Xml.Tests
│ ├── Microsoft.Language.Xml.Tests.csproj
│ ├── Properties
│ ├── Resources.Designer.cs
│ └── Resources.resx
│ ├── TestAnnotations.cs
│ ├── TestApi.cs
│ ├── TestClassifier.cs
│ ├── TestComments.cs
│ ├── TestDiagnostic.cs
│ ├── TestIncremental.cs
│ ├── TestModification.cs
│ ├── TestParser.cs
│ ├── TestSyntaxLocator.cs
│ ├── TestTrivia.cs
│ └── TestXml.xml
└── version.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome:http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Baseline
7 | [*]
8 | charset = utf-8
9 | indent_style = space
10 | trim_trailing_whitespace = true
11 | max_line_length = 120
12 |
13 | # MSBuild
14 | [*.{csproj,proj,projitems,shproj,fsproj,target,props}]
15 | indent_style = space
16 | indent_size = 2
17 |
18 | # XML config files
19 | [*.{config,nuspec,resx}]
20 | indent_style = space
21 | indent_size = 2
22 |
23 | # JSON files
24 | [*.json]
25 | indent_style = space
26 | indent_size = 2
27 |
28 | # Dotnet code style settings:
29 | [*.{cs,vb}]
30 |
31 | # Sort using and Import directives with System.* appearing first
32 | dotnet_sort_system_directives_first = true
33 |
34 | # CSharp code style settings:
35 | [*.cs]
36 |
37 | # spaces before parens
38 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
39 | csharp_space_between_method_call_name_and_opening_parenthesis = false
40 | csharp_space_after_keywords_in_control_flow_statements = true
41 |
42 | # Newline settings
43 | csharp_new_line_before_open_brace = all
44 | csharp_new_line_before_else = true
45 | csharp_new_line_before_catch = true
46 | csharp_new_line_before_finally = true
47 | csharp_new_line_before_members_in_object_initializers = true
48 | csharp_new_line_before_members_in_anonymous_types = true
49 |
50 | # Switch indentation
51 | csharp_indent_switch_labels = true
52 |
53 | # Prefer "var" everywhere it's apparent
54 | csharp_style_var_for_built_in_types = true:suggestion
55 | csharp_style_var_when_type_is_apparent = true:suggestion
56 | csharp_style_var_elsewhere = false:suggestion
57 |
58 | # Prefer method-like constructs to have a block body
59 | csharp_style_expression_bodied_methods = false:none
60 | csharp_style_expression_bodied_constructors = false:none
61 | csharp_style_expression_bodied_operators = false:none
62 |
63 | # Prefer property-like constructs to have an expression-body
64 | csharp_style_expression_bodied_properties = true:none
65 | csharp_style_expression_bodied_indexers = true:none
66 | csharp_style_expression_bodied_accessors = true:none
67 |
68 | # Suggest more modern language features when available
69 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
70 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
71 | csharp_style_inlined_variable_declaration = true:suggestion
72 | csharp_style_throw_expression = false:suggestion
73 | csharp_style_conditional_delegate_call = true:suggestion
74 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Don't mess with my line endings.
3 | ###############################################################################
4 | * -text
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [KirillOsenkov]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 | *.binlog
10 |
11 | # User-specific files (MonoDevelop/Xamarin Studio)
12 | *.userprefs
13 |
14 | # Build results
15 | [Dd]ebug/
16 | [Dd]ebugPublic/
17 | [Rr]elease/
18 | [Rr]eleases/
19 | x64/
20 | x86/
21 | build/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 |
26 | # Visual Studo 2015 cache/options directory
27 | .vs/
28 |
29 | # MSTest test Results
30 | [Tt]est[Rr]esult*/
31 | [Bb]uild[Ll]og.*
32 |
33 | # NUNIT
34 | *.VisualState.xml
35 | TestResult.xml
36 |
37 | # Build Results of an ATL Project
38 | [Dd]ebugPS/
39 | [Rr]eleasePS/
40 | dlldata.c
41 |
42 | *_i.c
43 | *_p.c
44 | *_i.h
45 | *.ilk
46 | *.meta
47 | *.obj
48 | *.pch
49 | *.pdb
50 | *.pgc
51 | *.pgd
52 | *.rsp
53 | *.sbr
54 | *.tlb
55 | *.tli
56 | *.tlh
57 | *.tmp
58 | *.tmp_proj
59 | *.log
60 | *.vspscc
61 | *.vssscc
62 | .builds
63 | *.pidb
64 | *.svclog
65 | *.scc
66 |
67 | # Chutzpah Test files
68 | _Chutzpah*
69 |
70 | # Visual C++ cache files
71 | ipch/
72 | *.aps
73 | *.ncb
74 | *.opensdf
75 | *.sdf
76 | *.cachefile
77 |
78 | # Visual Studio profiler
79 | *.psess
80 | *.vsp
81 | *.vspx
82 |
83 | # TFS 2012 Local Workspace
84 | $tf/
85 |
86 | # Guidance Automation Toolkit
87 | *.gpState
88 |
89 | # ReSharper is a .NET coding add-in
90 | _ReSharper*/
91 | *.[Rr]e[Ss]harper
92 | *.DotSettings.user
93 |
94 | # JustCode is a .NET coding addin-in
95 | .JustCode
96 |
97 | # TeamCity is a build add-in
98 | _TeamCity*
99 |
100 | # DotCover is a Code Coverage Tool
101 | *.dotCover
102 |
103 | # NCrunch
104 | _NCrunch_*
105 | .*crunch*.local.xml
106 |
107 | # MightyMoose
108 | *.mm.*
109 | AutoTest.Net/
110 |
111 | # Web workbench (sass)
112 | .sass-cache/
113 |
114 | # Installshield output folder
115 | [Ee]xpress/
116 |
117 | # DocProject is a documentation generator add-in
118 | DocProject/buildhelp/
119 | DocProject/Help/*.HxT
120 | DocProject/Help/*.HxC
121 | DocProject/Help/*.hhc
122 | DocProject/Help/*.hhk
123 | DocProject/Help/*.hhp
124 | DocProject/Help/Html2
125 | DocProject/Help/html
126 |
127 | # Click-Once directory
128 | publish/
129 |
130 | # Publish Web Output
131 | *.[Pp]ublish.xml
132 | *.azurePubxml
133 | # TODO: Comment the next line if you want to checkin your web deploy settings
134 | # but database connection strings (with potential passwords) will be unencrypted
135 | *.pubxml
136 | *.publishproj
137 |
138 | # NuGet Packages
139 | *.nupkg
140 | # The packages folder can be ignored because of Package Restore
141 | **/packages/*
142 | # except build/, which is used as an MSBuild target.
143 | !**/packages/build/
144 | # Uncomment if necessary however generally it will be regenerated when needed
145 | #!**/packages/repositories.config
146 |
147 | # Windows Azure Build Output
148 | csx/
149 | *.build.csdef
150 |
151 | # Windows Store app package directory
152 | AppPackages/
153 |
154 | # Others
155 | *.[Cc]ache
156 | ClientBin/
157 | [Ss]tyle[Cc]op.*
158 | ~$*
159 | *~
160 | *.dbmdl
161 | *.dbproj.schemaview
162 | *.pfx
163 | *.publishsettings
164 | node_modules/
165 | bower_components/
166 |
167 | # RIA/Silverlight projects
168 | Generated_Code/
169 |
170 | # Backup & report files from converting an old project file
171 | # to a newer Visual Studio version. Backup files are not needed,
172 | # because we have git ;-)
173 | _UpgradeReport_Files/
174 | Backup*/
175 | UpgradeLog*.XML
176 | UpgradeLog*.htm
177 |
178 | # SQL Server files
179 | *.mdf
180 | *.ldf
181 |
182 | # Business Intelligence projects
183 | *.rdl.data
184 | *.bim.layout
185 | *.bim_*.settings
186 |
187 | # Microsoft Fakes
188 | FakesAssemblies/
189 |
190 | # Node.js Tools for Visual Studio
191 | .ntvs_analysis.dat
192 |
193 | # Visual Studio 6 build log
194 | *.plg
195 |
196 | # Visual Studio 6 workspace options file
197 | *.opt
198 | /NuGet.exe
199 |
--------------------------------------------------------------------------------
/Microsoft.Language.Xml.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.9.34321.82
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution items", "{9D11B9F6-7DFB-41A6-ACA9-E5DE89C02ED4}"
7 | ProjectSection(SolutionItems) = preProject
8 | .editorconfig = .editorconfig
9 | appveyor.yml = appveyor.yml
10 | NuGet.config = NuGet.config
11 | EndProjectSection
12 | EndProject
13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{79B2600B-6786-460B-85D7-1CB16DC9AE06}"
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Language.Xml", "src\Microsoft.Language.Xml\Microsoft.Language.Xml.csproj", "{2989FBE6-194F-46C9-8EF4-022F62519C9A}"
16 | EndProject
17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Language.Xml.Editor", "src\Microsoft.Language.Xml.Editor\Microsoft.Language.Xml.Editor.csproj", "{C432B014-61DD-4F97-9D6F-966C1021F535}"
18 | EndProject
19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{07F190D5-06B2-4F4C-B000-6EBE042AB43A}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Language.Xml.Tests", "test\Microsoft.Language.Xml.Tests\Microsoft.Language.Xml.Tests.csproj", "{20B89FC2-53BD-41AF-BFE9-A029362FE49C}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Language.Xml.Editor.Tests", "test\Microsoft.Language.Xml.Editor.Tests\Microsoft.Language.Xml.Editor.Tests.csproj", "{E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10}"
24 | EndProject
25 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{5D08C6A7-C10A-4CFD-8B6C-A278DC6C2701}"
26 | EndProject
27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Language.Xml.Benchmarks", "benchmark\Microsoft.Language.Xml.Benchmarks\Microsoft.Language.Xml.Benchmarks.csproj", "{7A2B7E87-9B54-437D-A7A1-B6F38BEA0819}"
28 | EndProject
29 | Global
30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
31 | Debug|Any CPU = Debug|Any CPU
32 | Release|Any CPU = Release|Any CPU
33 | EndGlobalSection
34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
35 | {2989FBE6-194F-46C9-8EF4-022F62519C9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {2989FBE6-194F-46C9-8EF4-022F62519C9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {2989FBE6-194F-46C9-8EF4-022F62519C9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {2989FBE6-194F-46C9-8EF4-022F62519C9A}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {C432B014-61DD-4F97-9D6F-966C1021F535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {C432B014-61DD-4F97-9D6F-966C1021F535}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {C432B014-61DD-4F97-9D6F-966C1021F535}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {C432B014-61DD-4F97-9D6F-966C1021F535}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {20B89FC2-53BD-41AF-BFE9-A029362FE49C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {20B89FC2-53BD-41AF-BFE9-A029362FE49C}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {20B89FC2-53BD-41AF-BFE9-A029362FE49C}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {20B89FC2-53BD-41AF-BFE9-A029362FE49C}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {7A2B7E87-9B54-437D-A7A1-B6F38BEA0819}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {7A2B7E87-9B54-437D-A7A1-B6F38BEA0819}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {7A2B7E87-9B54-437D-A7A1-B6F38BEA0819}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {7A2B7E87-9B54-437D-A7A1-B6F38BEA0819}.Release|Any CPU.Build.0 = Release|Any CPU
55 | EndGlobalSection
56 | GlobalSection(SolutionProperties) = preSolution
57 | HideSolutionNode = FALSE
58 | EndGlobalSection
59 | GlobalSection(NestedProjects) = preSolution
60 | {2989FBE6-194F-46C9-8EF4-022F62519C9A} = {79B2600B-6786-460B-85D7-1CB16DC9AE06}
61 | {C432B014-61DD-4F97-9D6F-966C1021F535} = {79B2600B-6786-460B-85D7-1CB16DC9AE06}
62 | {20B89FC2-53BD-41AF-BFE9-A029362FE49C} = {07F190D5-06B2-4F4C-B000-6EBE042AB43A}
63 | {E3CEC50E-40AF-4E53-93AF-D7E2F2C9FF10} = {07F190D5-06B2-4F4C-B000-6EBE042AB43A}
64 | {7A2B7E87-9B54-437D-A7A1-B6F38BEA0819} = {5D08C6A7-C10A-4CFD-8B6C-A278DC6C2701}
65 | EndGlobalSection
66 | EndGlobal
67 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XmlParser
2 |
3 | 
4 |
5 | [](https://ci.appveyor.com/project/KirillOsenkov/xmlparser)
6 | [](https://nuget.org/packages/GuiLabs.Language.Xml)
7 | [](https://nuget.org/packages/GuiLabs.Language.Xml.Editor)
8 |
9 | A Roslyn-inspired full-fidelity XML parser with no dependencies and a simple Visual Studio XML language service.
10 |
11 | * The parser produces a **full-fidelity** syntax tree, meaning every character of the source text is represented in the tree. The tree covers the entire source text.
12 | * The parser has **no dependencies** and can easily be made portable. I would appreciate a high quality pull request making the parser portable.
13 | * The parser is based on the section of the Roslyn VB parser that parses XML literals. The Roslyn code is ported to C# and is made standalone.
14 | * The parser is **error-tolerant**. It will still produce a full tree even from invalid XML with missing tags, extra invalid text, etc. Missing and skipped tokens are still represented in the tree.
15 | * The resulting tree is **immutable** and follows Roslyn's [green/red separation](https://blogs.msdn.microsoft.com/ericlippert/2012/06/08/persistence-facades-and-roslyns-red-green-trees/) for maximum reusability of nodes.
16 | * The parser has basic support for **incrementality**. Given a previous constructed tree and a list of changes it will try to reuse existing nodes and only re-create what is necessary.
17 | * This library is more **low-level** than XLinq (for instance XLinq doesn't seem to represent whitespace around attributes). Also it has no idea about XML namespaces and just tells you what's in the source text (whereas in XLinq there's too much ceremony around XML namespaces).
18 |
19 | This is work in progress and by no means complete. Specifically:
20 | * XML DTD is not supported (Roslyn didn't support it either)
21 | * Code wasn't tuned for performance and allocations, I'm sure a lot can be done to reduce memory consumption by the resulting tree. It should be pretty efficient though.
22 | * We reserve the right to accept only very high quality pull requests. We have very limited time to work on this so I ask everybody to please respect that.
23 |
24 | ## Download from NuGet:
25 | * [GuiLabs.Language.Xml](https://www.nuget.org/packages/GuiLabs.Language.Xml)
26 | * [GuiLabs.Language.Xml.Editor](https://www.nuget.org/packages/GuiLabs.Language.Xml.Editor)
27 |
28 | ## Try it!
29 |
30 | https://xmlsyntaxvisualizer.azurewebsites.net/index.html
31 |
32 | The above app leverages the parser and can help you visualize the resulting syntax tree generated from an XML document.
33 |
34 | Code is available at https://github.com/garuma/XmlSyntaxVisualizer
35 | C# UWP example at https://github.com/michael-hawker/XmlSyntaxVisualizerUWP
36 |
37 | Also see the blog post:
38 | https://blog.neteril.org/blog/2018/03/21/xml-parsing-roslyn/
39 |
40 | Resources about Immutable Syntax Trees:
41 | https://github.com/KirillOsenkov/Bliki/wiki/Roslyn-Immutable-Trees
42 |
43 | ## FAQ:
44 |
45 | ### How to find a node in the tree given a position in the source text?
46 | https://github.com/KirillOsenkov/XmlParser/blob/master/src/Microsoft.Language.Xml/Utilities/SyntaxLocator.cs#L24
47 |
48 | ```
49 | SyntaxLocator.FindNode(SyntaxNode node, int position);
50 | ```
51 |
52 | ### How to replace a node in the tree
53 |
54 | ```csharp
55 | var original = """
56 |
57 |
58 | net8.0
59 |
60 |
61 | """;
62 |
63 | var expected = """
64 |
65 |
66 | net9.0
67 |
68 |
69 | """;
70 |
71 | XmlDocumentSyntax root = Parser.ParseText(original);
72 | XmlElementSyntax syntaxToReplace = root
73 | .Descendants()
74 | .OfType()
75 | .Single(n => n.Name == "TargetFramework");
76 | SyntaxNode textSyntaxToReplace = syntaxToReplace.Content.Single();
77 |
78 | XmlTextSyntax content = SyntaxFactory.XmlText(SyntaxFactory.XmlTextLiteralToken("net9.0", null, null));
79 |
80 | root = root.ReplaceNode(textSyntaxToReplace, content);
81 |
82 | Assert.Equal(expected, root.ToFullString());
83 | ```
84 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.2.{build}
2 | image: Visual Studio 2022
3 | before_build:
4 | - cmd: dotnet restore
5 | build:
6 | project: Microsoft.Language.Xml.sln
7 | parallel: true
8 | verbosity: minimal
9 |
--------------------------------------------------------------------------------
/benchmark/Microsoft.Language.Xml.Benchmarks/Microsoft.Language.Xml.Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | Microsoft.Language.Xml.Benchmarks
5 | net472;net8.0
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/benchmark/Microsoft.Language.Xml.Benchmarks/ParserBenchmarks.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using BenchmarkDotNet.Jobs;
3 |
4 | namespace Microsoft.Language.Xml.Benchmarks;
5 |
6 | [MemoryDiagnoser]
7 | [SimpleJob(RuntimeMoniker.Net472, id: ".NET Framework")]
8 | [SimpleJob(RuntimeMoniker.Net80, id: "Modern .NET")]
9 | public class ParserBenchmarks
10 | {
11 | private Buffer textBuffer;
12 |
13 | [GlobalSetup]
14 | public void Setup()
15 | {
16 | textBuffer = new StringBuffer(XmlSnippets.LongAndroidLayoutXml);
17 | }
18 |
19 | [Benchmark]
20 | public void ParseLongXml() => Parser.Parse(textBuffer);
21 | }
22 |
--------------------------------------------------------------------------------
/benchmark/Microsoft.Language.Xml.Benchmarks/Program.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Running;
2 | using Microsoft.Language.Xml.Benchmarks;
3 |
4 | BenchmarkRunner.Run();
5 |
--------------------------------------------------------------------------------
/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KirillOsenkov/XmlParser/57739b0cc45178eea0461a21386f73eb0695d1e2/key.snk
--------------------------------------------------------------------------------
/language_xml_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KirillOsenkov/XmlParser/57739b0cc45178eea0461a21386f73eb0695d1e2/language_xml_logo.png
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Classification/Classifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Microsoft.VisualStudio.Text;
5 | using Microsoft.VisualStudio.Text.Classification;
6 |
7 | namespace Microsoft.Language.Xml.Editor
8 | {
9 | public class Classifier : AbstractSyntaxTreeTagger, IClassifier
10 | {
11 | private static readonly IList emptySpanList = new ClassificationSpan[0];
12 |
13 | private readonly IClassificationType[] types;
14 |
15 | public event EventHandler ClassificationChanged;
16 |
17 | public Classifier(IClassificationType[] types, ParserService parserService)
18 | : base(parserService)
19 | {
20 | this.types = types;
21 | }
22 |
23 | public IList GetClassificationSpans(SnapshotSpan span)
24 | {
25 | // don't classify documents larger than 5 MB, arbitrary large number
26 | if (span.Snapshot.Length > 5000000)
27 | {
28 | return emptySpanList;
29 | }
30 |
31 | var task = parserService.GetSyntaxTree(span.Snapshot);
32 |
33 | // wait for 100 milliseconds to see if we're lucky and it finishes before that
34 | // this helps significantly reduce flicker since we're not going to clear and re-add all tags on every keystroke
35 | task.Wait(100);
36 |
37 | if (task.Status == TaskStatus.RanToCompletion)
38 | {
39 | var root = task.Result;
40 | var spans = new List();
41 | ClassifierVisitor.Visit(
42 | root,
43 | span.Start,
44 | span.Length,
45 | (start, length, node, xmlClassification) => spans.Add(
46 | new ClassificationSpan(
47 | new SnapshotSpan(
48 | span.Snapshot,
49 | start,
50 | length),
51 | types[(int)xmlClassification])));
52 | return spans;
53 | }
54 |
55 | task.ContinueWith(t =>
56 | {
57 | RaiseClassificationChanged(span.Snapshot);
58 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
59 |
60 | return emptySpanList;
61 | }
62 |
63 | private void RaiseClassificationChanged(ITextSnapshot snapshot)
64 | {
65 | var handler = ClassificationChanged;
66 | if (handler != null)
67 | {
68 | handler(this, new ClassificationChangedEventArgs(new SnapshotSpan(snapshot, 0, snapshot.Length)));
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Classification/ClassifierProvider.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using Microsoft.VisualStudio.Text;
3 | using Microsoft.VisualStudio.Text.Classification;
4 | using Microsoft.VisualStudio.Utilities;
5 |
6 | namespace Microsoft.Language.Xml.Editor
7 | {
8 | [Export(typeof(IClassifierProvider))]
9 | [ContentType("xml")]
10 | public class ClassifierProvider : IClassifierProvider
11 | {
12 | private readonly ParserService parserService;
13 | private IClassificationType[] types;
14 |
15 | [ImportingConstructor]
16 | public ClassifierProvider(IClassificationTypeRegistryService classificationTypeRegistryService, ParserService parserService)
17 | {
18 | types = new IClassificationType[]
19 | {
20 | classificationTypeRegistryService.GetClassificationType("text"),
21 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlAttributeName),
22 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlAttributeQuotes),
23 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlAttributeValue),
24 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlCDataSection),
25 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlComment),
26 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlDelimiter),
27 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlEntityReference),
28 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlName),
29 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlProcessingInstruction),
30 | classificationTypeRegistryService.GetClassificationType(ClassificationTypeNames.XmlText),
31 | };
32 | this.parserService = parserService;
33 | }
34 |
35 | public IClassifier GetClassifier(ITextBuffer textBuffer)
36 | {
37 | return new Classifier(types, parserService);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/ContentType.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using Microsoft.VisualStudio.Utilities;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | public class ContentType
7 | {
8 | public const string Xml = "xml";
9 |
10 | [Export]
11 | [Name(Xml)]
12 | [BaseDefinition("text")]
13 | public static readonly ContentTypeDefinition XmlContentTypeDefinition = null;
14 |
15 | [Export]
16 | [FileExtension(".xml")]
17 | [ContentType(Xml)]
18 | internal static readonly FileExtensionToContentTypeDefinition XmlFileExtension = null;
19 |
20 | [Export]
21 | [FileExtension(".csproj")]
22 | [ContentType(Xml)]
23 | internal static readonly FileExtensionToContentTypeDefinition CsprojFileExtension = null;
24 |
25 | [Export]
26 | [FileExtension(".vbproj")]
27 | [ContentType(Xml)]
28 | internal static readonly FileExtensionToContentTypeDefinition VbprojFileExtension = null;
29 |
30 | [Export]
31 | [FileExtension(".nuspec")]
32 | [ContentType(Xml)]
33 | internal static readonly FileExtensionToContentTypeDefinition NuspecFileExtension = null;
34 |
35 | [Export]
36 | [FileExtension(".props")]
37 | [ContentType(Xml)]
38 | internal static readonly FileExtensionToContentTypeDefinition PropsFileExtension = null;
39 |
40 | [Export]
41 | [FileExtension(".targets")]
42 | [ContentType(Xml)]
43 | internal static readonly FileExtensionToContentTypeDefinition TargetsFileExtension = null;
44 |
45 | [Export]
46 | [FileExtension(".settings")]
47 | [ContentType(Xml)]
48 | internal static readonly FileExtensionToContentTypeDefinition SettingsFileExtension = null;
49 |
50 | [Export]
51 | [FileExtension(".proj")]
52 | [ContentType(Xml)]
53 | internal static readonly FileExtensionToContentTypeDefinition ProjFileExtension = null;
54 |
55 | [Export]
56 | [FileExtension(".config")]
57 | [ContentType(Xml)]
58 | internal static readonly FileExtensionToContentTypeDefinition ConfigFileExtension = null;
59 |
60 | [Export]
61 | [FileExtension(".vsixmanifest")]
62 | [ContentType(Xml)]
63 | internal static readonly FileExtensionToContentTypeDefinition VsixmanifestFileExtension = null;
64 |
65 | [Export]
66 | [FileExtension(".dgml")]
67 | [ContentType(Xml)]
68 | internal static readonly FileExtensionToContentTypeDefinition DgmlFileExtension = null;
69 |
70 | [Export]
71 | [FileExtension(".xaml")]
72 | [ContentType(Xml)]
73 | internal static readonly FileExtensionToContentTypeDefinition XamlFileExtension = null;
74 |
75 | [Export]
76 | [FileExtension(".resx")]
77 | [ContentType(Xml)]
78 | internal static readonly FileExtensionToContentTypeDefinition ResxFileExtension = null;
79 | }
80 | }
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Microsoft.Language.Xml.Editor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Microsoft.Language.Xml.Editor
4 | net472
5 | true
6 | $([MSBuild]::IsOSPlatform('Windows'))
7 | embedded
8 | true
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | True
26 | GuiLabs.Language.Xml.Editor
27 | Microsoft
28 | Microsoft
29 | A simple XML language service for the Visual Studio editor
30 | Currently includes a classifier, outlining and smart indent.
31 | Apache-2.0
32 | https://github.com/KirillOsenkov/XmlParser
33 | https://github.com/KirillOsenkov/XmlParser
34 | Xml Parser LanguageService Classifier VS VisualStudio Editor
35 | language_xml_logo.png
36 | true
37 | snupkg
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | True
48 | ..\..\key.snk
49 | False
50 | WPF;$(DefineConstants)
51 |
52 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Outlining/OutliningTagger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.VisualStudio.Text;
6 | using Microsoft.VisualStudio.Text.Tagging;
7 |
8 | namespace Microsoft.Language.Xml.Editor
9 | {
10 | public class OutliningTagger : AbstractSyntaxTreeTagger, ITagger
11 | {
12 | private static readonly IEnumerable> emptyTagList = Enumerable.Empty>();
13 |
14 | private ITextBuffer buffer;
15 | private OutliningTaggerProvider outliningTaggerProvider;
16 |
17 | public OutliningTagger(OutliningTaggerProvider outliningTaggerProvider, ITextBuffer buffer)
18 | : base(outliningTaggerProvider.ParserService)
19 | {
20 | this.outliningTaggerProvider = outliningTaggerProvider;
21 | this.buffer = buffer;
22 | }
23 |
24 | public event EventHandler TagsChanged;
25 |
26 | public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
27 | {
28 | if (spans.Count == 0)
29 | {
30 | return emptyTagList;
31 | }
32 |
33 | var snapshot = spans[0].Snapshot;
34 |
35 | var task = parserService.GetSyntaxTree(snapshot);
36 |
37 | // wait for 100 milliseconds to see if we're lucky and it finishes before that
38 | // this helps significantly reduce flicker since we're not going to clear and re-add all tags on every keystroke
39 | task.Wait(100);
40 |
41 | if (task.Status == TaskStatus.RanToCompletion)
42 | {
43 | var root = task.Result;
44 | var elementSpans = new List>();
45 | CollectElementSpans(root, elementSpans, 0);
46 | var tagSpans = new List>();
47 | foreach (var span in elementSpans)
48 | {
49 | if (snapshot.GetLineNumberFromPosition(span.Item1.Start) < snapshot.GetLineNumberFromPosition(span.Item1.End))
50 | {
51 | tagSpans.Add(new TagSpan(
52 | new SnapshotSpan(snapshot, span.Item1),
53 | new OutliningRegionTag(span.Item2, span.Item2)));
54 | }
55 | }
56 |
57 | return tagSpans;
58 | }
59 |
60 | task.ContinueWith(t =>
61 | {
62 | RaiseTagsChanged(snapshot);
63 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
64 |
65 | return emptyTagList;
66 | }
67 |
68 | private void CollectElementSpans(SyntaxNode node, List> spans, int start)
69 | {
70 | if (node is IXmlElement)
71 | {
72 | var leading = node.GetLeadingTriviaWidth();
73 | var trailing = node.GetTrailingTriviaWidth();
74 | spans.Add(Tuple.Create(
75 | new Span(start + leading, node.FullWidth - leading - trailing),
76 | "<" + (node as IXmlElement).Name + ">"));
77 | }
78 |
79 | foreach (var child in node.ChildNodes)
80 | {
81 | CollectElementSpans(child, spans, start);
82 | start += child.FullWidth;
83 | }
84 | }
85 |
86 | private void RaiseTagsChanged(ITextSnapshot snapshot)
87 | {
88 | TagsChanged?.Invoke(
89 | this,
90 | new SnapshotSpanEventArgs(
91 | new SnapshotSpan(snapshot, 0, snapshot.Length)));
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Outlining/OutliningTaggerProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Composition;
3 | using Microsoft.VisualStudio.Text;
4 | using Microsoft.VisualStudio.Text.Tagging;
5 | using Microsoft.VisualStudio.Utilities;
6 |
7 | namespace Microsoft.Language.Xml.Editor
8 | {
9 | [Export(typeof(ITaggerProvider))]
10 | [TagType(typeof(IOutliningRegionTag))]
11 | [ContentType(ContentType.Xml)]
12 | public class OutliningTaggerProvider : ITaggerProvider
13 | {
14 | [Import]
15 | public ParserService ParserService { get; set; }
16 |
17 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag
18 | {
19 | Func> factory = () => new OutliningTagger(this, buffer) as ITagger;
20 | return buffer.Properties.GetOrCreateSingletonProperty(factory);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Parsing/ParserService.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using System.Runtime.CompilerServices;
3 | using System.Threading.Tasks;
4 | using Microsoft.VisualStudio.Text;
5 |
6 | namespace Microsoft.Language.Xml.Editor
7 | {
8 | [Export]
9 | public class ParserService
10 | {
11 | public Task GetSyntaxTree(ITextSnapshot textSnapshot)
12 | {
13 | var textBuffer = textSnapshot.TextBuffer;
14 |
15 | lock (textBuffer)
16 | {
17 | ConditionalWeakTable> textSnapshotToSyntaxRootMap;
18 | Task syntaxRootTask;
19 |
20 | if (!textBuffer.Properties.TryGetProperty(typeof(ParserService), out textSnapshotToSyntaxRootMap))
21 | {
22 | textSnapshotToSyntaxRootMap = new ConditionalWeakTable>();
23 | textBuffer.Properties.AddProperty(typeof(ParserService), textSnapshotToSyntaxRootMap);
24 | }
25 | else if (textSnapshotToSyntaxRootMap.TryGetValue(textSnapshot, out syntaxRootTask))
26 | {
27 | return syntaxRootTask;
28 | }
29 |
30 | syntaxRootTask = Task.Run(() => Parse(textSnapshot));
31 | textSnapshotToSyntaxRootMap.Add(textSnapshot, syntaxRootTask);
32 |
33 | return syntaxRootTask;
34 | }
35 | }
36 |
37 | public XmlNodeSyntax TryGetSyntaxTree(ITextSnapshot textSnapshot, int timeoutInMilliseconds = 100)
38 | {
39 | var task = GetSyntaxTree(textSnapshot);
40 | if (!task.Wait(timeoutInMilliseconds))
41 | {
42 | return null;
43 | }
44 |
45 | return task.Result;
46 | }
47 |
48 | private static XmlNodeSyntax Parse(ITextSnapshot snapshot)
49 | {
50 | return Parser.Parse(new TextSnapshotBuffer(snapshot));
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/SmartIndent/SmartIndent.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Text;
2 | using Microsoft.VisualStudio.Text.Editor;
3 |
4 | namespace Microsoft.Language.Xml.Editor
5 | {
6 | public class SmartIndent : ISmartIndent
7 | {
8 | private ITextView textView;
9 | private readonly ParserService parserService;
10 | private int indentSize;
11 |
12 | public SmartIndent(ITextView textView, ParserService parserService)
13 | {
14 | this.textView = textView;
15 | this.parserService = parserService;
16 | }
17 |
18 | public int? GetDesiredIndentation(ITextSnapshotLine line)
19 | {
20 | var snapshot = line.Snapshot;
21 | var treeTask = parserService.GetSyntaxTree(snapshot);
22 |
23 | indentSize = textView.Options.GetOptionValue(DefaultOptions.IndentSizeOptionId);
24 |
25 | treeTask.Wait(100);
26 |
27 | if (!treeTask.IsCompleted)
28 | {
29 | return null;
30 | }
31 |
32 | var root = treeTask.Result;
33 | var lineStartPosition = line.Start.Position;
34 | var indent = FindTotalParentChainIndent(
35 | root,
36 | lineStartPosition,
37 | currentPosition: 0,
38 | indent: 0,
39 | indentSize: indentSize);
40 | return indent;
41 | }
42 |
43 | public static int FindTotalParentChainIndent(SyntaxNode node, int position, int currentPosition, int indent, int indentSize = 2)
44 | {
45 | var leading = node.GetLeadingTriviaWidth();
46 | var trailing = node.GetTrailingTriviaWidth();
47 | var fullWidth = node.FullWidth;
48 |
49 | if (position < currentPosition + leading || position >= currentPosition + fullWidth - trailing)
50 | {
51 | return indent;
52 | }
53 |
54 | bool isClosingTag = node is XmlElementEndTagSyntax;
55 | if (isClosingTag && indent >= indentSize)
56 | {
57 | return indent - indentSize;
58 | }
59 |
60 | bool isElementWithAName = node is IXmlElement &&
61 | !(node is XmlDocumentSyntax) &&
62 | !string.IsNullOrEmpty(((IXmlElement)node).Name);
63 | if (isElementWithAName)
64 | {
65 | indent += indentSize;
66 | }
67 |
68 | foreach (var child in node.ChildNodes)
69 | {
70 | int childWidth = child.FullWidth;
71 | if (position < currentPosition + childWidth)
72 | {
73 | int result = indent;
74 | result = FindTotalParentChainIndent(child, position, currentPosition, indent, indentSize);
75 |
76 | return result;
77 | }
78 | else
79 | {
80 | currentPosition += childWidth;
81 | }
82 | }
83 |
84 | return indent;
85 | }
86 |
87 | private static int GetLeadingWhitespaceLength(SyntaxNode node)
88 | {
89 | if (!(node is IXmlElement))
90 | {
91 | return 0;
92 | }
93 |
94 | var leadingTrivia = node.GetLeadingTrivia();
95 | if (leadingTrivia == null)
96 | {
97 | return 0;
98 | }
99 |
100 | int totalLength = 0;
101 | foreach (var child in leadingTrivia)
102 | {
103 | if (child.Kind == SyntaxKind.WhitespaceTrivia)
104 | {
105 | totalLength += child.FullWidth;
106 | }
107 | }
108 |
109 | return totalLength;
110 | }
111 |
112 | public void Dispose()
113 | {
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/SmartIndent/SmartIndentProvider.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using Microsoft.VisualStudio.Text.Editor;
3 | using Microsoft.VisualStudio.Utilities;
4 |
5 | namespace Microsoft.Language.Xml.Editor
6 | {
7 | [Export(typeof(ISmartIndentProvider))]
8 | [ContentType(ContentType.Xml)]
9 | public class SmartIndentProvider : ISmartIndentProvider
10 | {
11 | [Import]
12 | private ParserService parserService = null;
13 |
14 | public ISmartIndent CreateSmartIndent(ITextView textView)
15 | {
16 | return new SmartIndent(textView, parserService);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/Tagging/AbstractSyntaxTreeTagger.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml.Editor
2 | {
3 | public abstract class AbstractSyntaxTreeTagger
4 | {
5 | protected readonly ParserService parserService;
6 |
7 | public AbstractSyntaxTreeTagger(ParserService parserService)
8 | {
9 | this.parserService = parserService;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml.Editor/TextSnapshotBuffer.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Text;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | public class TextSnapshotBuffer : Buffer
6 | {
7 | private ITextSnapshot textSnapshot;
8 |
9 | public TextSnapshotBuffer(ITextSnapshot textSnapshot)
10 | {
11 | this.textSnapshot = textSnapshot;
12 | }
13 |
14 | public override int Length
15 | {
16 | get { return textSnapshot.Length; }
17 | }
18 |
19 | public override char this[int index]
20 | {
21 | get
22 | {
23 | return textSnapshot[index];
24 | }
25 | }
26 |
27 | public override string GetText(int start, int length)
28 | {
29 | return textSnapshot.GetText(start, length);
30 | }
31 |
32 | public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
33 | {
34 | textSnapshot.CopyTo(sourceIndex, destination, destinationIndex, count);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("Microsoft.Language.Xml.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004d58e878a7c3f80f91e670fc8de4def82bc0ec6c5cfdf55b41976c470f568cf9eafd3262aed24e4e66bfac4edeb108ab8400263ee1bf1fc0a41eb22595cb847f5f74fc797d555d48112f854de4e01616e56ab583ad36a81627d962f96d10f9a12505fa2956346c48fd55de0351d331bb886490c01e0dd6048d102c3c47a1c8d0")]
4 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Buffer.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | ///
4 | /// Abstract text buffer
5 | ///
6 | public abstract class Buffer
7 | {
8 | public abstract int Length { get; }
9 |
10 | public abstract char this[int index] { get; }
11 |
12 | public abstract string GetText(int start, int length);
13 |
14 | public abstract void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Classification/ClassificationTypeNames.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | public class ClassificationTypeNames
4 | {
5 | public const string XmlAttributeName = "xml - attribute name";
6 | public const string XmlAttributeQuotes = "xml - attribute quotes";
7 | public const string XmlAttributeValue = "xml - attribute value";
8 | public const string XmlCDataSection = "xml - cdata section";
9 | public const string XmlComment = "xml - comment";
10 | public const string XmlDelimiter = "xml - delimiter";
11 | public const string XmlEntityReference = "xml - entity reference";
12 | public const string XmlName = "xml - name";
13 | public const string XmlProcessingInstruction = "xml - processing instruction";
14 | public const string XmlText = "xml - text";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Classification/XmlClassificationTypes.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | public enum XmlClassificationTypes : byte
4 | {
5 | None,
6 | XmlAttributeName,
7 | XmlAttributeQuotes,
8 | XmlAttributeValue,
9 | XmlCDataSection,
10 | XmlComment,
11 | XmlDelimiter,
12 | XmlEntityReference,
13 | XmlName,
14 | XmlProcessingInstruction,
15 | XmlText,
16 | Count,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/DiagnosticInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Immutable;
4 | using System.Diagnostics;
5 | using System.Globalization;
6 | using System.Resources;
7 |
8 | namespace Microsoft.Language.Xml
9 | {
10 | ///
11 | /// Describes how severe a diagnostic is.
12 | ///
13 | public enum DiagnosticSeverity
14 | {
15 | ///
16 | /// Something that is an issue, as determined by some authority,
17 | /// but is not surfaced through normal means.
18 | /// There may be different mechanisms that act on these issues.
19 | ///
20 | Hidden = 0,
21 |
22 | ///
23 | /// Information that does not indicate a problem (i.e. not prescriptive).
24 | ///
25 | Info = 1,
26 |
27 | ///
28 | /// Something suspicious but allowed.
29 | ///
30 | Warning = 2,
31 |
32 | ///
33 | /// Something not allowed by the rules of the language or other authority.
34 | ///
35 | Error = 3,
36 | }
37 |
38 | public class DiagnosticInfo
39 | {
40 | object[] parameters;
41 |
42 | public ERRID ErrorID { get; }
43 | public DiagnosticSeverity Severity => DiagnosticSeverity.Error;
44 |
45 | public DiagnosticInfo(ERRID errID)
46 | {
47 | ErrorID = errID;
48 | }
49 |
50 | public DiagnosticInfo(ERRID errID, object[] parameters)
51 | : this(errID)
52 | {
53 | this.parameters = parameters;
54 | }
55 |
56 | public string GetDescription() => GetDescription(XmlResources.ResourceManager);
57 |
58 | public string GetDescription(ResourceManager resourceManager)
59 | {
60 | var name = ErrorID.ToString();
61 | var description = resourceManager.GetString(name);
62 | if (parameters != null)
63 | description = string.Format(description, parameters);
64 | return description;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/ErrorFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | internal static class ErrorFactory
4 | {
5 | public static DiagnosticInfo ErrorInfo(ERRID errID)
6 | {
7 | return new DiagnosticInfo(errID);
8 | }
9 |
10 | public static DiagnosticInfo ErrorInfo(ERRID errID, object[] arguments)
11 | {
12 | return new DiagnosticInfo(errID, arguments);
13 | }
14 |
15 | public static DiagnosticInfo ErrorInfo(ERRID errID, char xmlCh, string v)
16 | {
17 | return new DiagnosticInfo(errID, new object[] { xmlCh, v });
18 | }
19 |
20 | public static DiagnosticInfo ErrorInfo(ERRID errID, string xmlCh, string v)
21 | {
22 | return new DiagnosticInfo(errID, new object[] { xmlCh, v });
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Extensions.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | internal static class Extensions
4 | {
5 | ///
6 | /// Search a sorted integer array for the target value in O(log N) time.
7 | ///
8 | /// The array of integers which must be sorted in ascending order.
9 | /// The target value.
10 | /// An index in the array pointing to the position where should be
11 | /// inserted in order to maintain the sorted order. All values to the right of this position will be
12 | /// strictly greater than . Note that this may return a position off the end
13 | /// of the array if all elements are less than or equal to .
14 | public static int BinarySearchUpperBound(this int[] array, int value)
15 | {
16 | int low = 0;
17 | int high = array.Length - 1;
18 |
19 | while (low <= high)
20 | {
21 | int middle = low + ((high - low) >> 1);
22 | if (array[middle] > value)
23 | {
24 | high = middle - 1;
25 | }
26 | else
27 | {
28 | low = middle + 1;
29 | }
30 | }
31 |
32 | return low;
33 | }
34 |
35 | public static bool OverlapsWithAny(this TextSpan span, TextSpan[] otherSpans)
36 | {
37 | foreach (var other in otherSpans)
38 | {
39 | // TextSpan.OverlapsWith does not handle empty spans so
40 | // empty spans need to be handled explicitly.
41 | if (other.Length == 0)
42 | {
43 | if (span.Contains(other.Start))
44 | return false;
45 | }
46 | else
47 | {
48 | if (span.OverlapsWith(other))
49 | return true;
50 | }
51 | }
52 | return false;
53 | }
54 |
55 | public static bool AnyContainsPosition(this TextSpan[] spans, int position)
56 | {
57 | foreach (var span in spans)
58 | {
59 | if (span.Contains(position) || (span.Length == 0 && span.Start == position))
60 | return true;
61 | // Assume that spans are sorted
62 | if (span.Start > position)
63 | return false;
64 | }
65 | return false;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/NodeFlags.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml.InternalSyntax
4 | {
5 | [Flags]
6 | internal enum NodeFlags : byte
7 | {
8 | None = 0,
9 | ContainsDiagnostics = 1 << 0,
10 | ContainsStructuredTrivia = 1 << 1,
11 | ContainsDirectives = 1 << 2,
12 | ContainsSkippedText = 1 << 3,
13 | ContainsAnnotations = 1 << 4,
14 | IsMissing = 1 << 5,
15 |
16 | InheritMask = ContainsDiagnostics | ContainsStructuredTrivia | ContainsDirectives | ContainsSkippedText | ContainsAnnotations | IsMissing,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/SeparatedSyntaxList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace Microsoft.Language.Xml.InternalSyntax
5 | {
6 | internal readonly struct SeparatedSyntaxList : IEquatable> where TNode : GreenNode
7 | {
8 | private readonly SyntaxList _list;
9 |
10 | internal SeparatedSyntaxList(SyntaxList list)
11 | {
12 | Validate(list);
13 | _list = list;
14 | }
15 |
16 | [Conditional("DEBUG")]
17 | private static void Validate(SyntaxList list)
18 | {
19 | for (int i = 0; i < list.Count; i++)
20 | {
21 | var item = list[i];
22 | if ((i & 1) == 0)
23 | {
24 | Debug.Assert(!item.IsToken, "even elements of a separated list must be nodes");
25 | }
26 | else
27 | {
28 | Debug.Assert(item.IsToken, "odd elements of a separated list must be tokens");
29 | }
30 | }
31 | }
32 |
33 | internal GreenNode Node => _list.Node;
34 |
35 | public int Count
36 | {
37 | get
38 | {
39 | return (_list.Count + 1) >> 1;
40 | }
41 | }
42 |
43 | public int SeparatorCount
44 | {
45 | get
46 | {
47 | return _list.Count >> 1;
48 | }
49 | }
50 |
51 | public TNode this[int index]
52 | {
53 | get
54 | {
55 | return (TNode)_list[index << 1];
56 | }
57 | }
58 |
59 | ///
60 | /// Gets the separator at the given index in this list.
61 | ///
62 | /// The index.
63 | ///
64 | public GreenNode GetSeparator(int index)
65 | {
66 | return _list[(index << 1) + 1];
67 | }
68 |
69 | public SyntaxList GetWithSeparators()
70 | {
71 | return _list;
72 | }
73 |
74 | public static bool operator ==(in SeparatedSyntaxList left, in SeparatedSyntaxList right)
75 | {
76 | return left.Equals(right);
77 | }
78 |
79 | public static bool operator !=(in SeparatedSyntaxList left, in SeparatedSyntaxList right)
80 | {
81 | return !left.Equals(right);
82 | }
83 |
84 | public bool Equals(SeparatedSyntaxList other)
85 | {
86 | return _list == other._list;
87 | }
88 |
89 | public override bool Equals(object obj)
90 | {
91 | return (obj is SeparatedSyntaxList) && Equals((SeparatedSyntaxList)obj);
92 | }
93 |
94 | public override int GetHashCode()
95 | {
96 | return _list.GetHashCode();
97 | }
98 |
99 | public static implicit operator SeparatedSyntaxList(SeparatedSyntaxList list)
100 | {
101 | return new SeparatedSyntaxList(list.GetWithSeparators());
102 | }
103 |
104 | #if DEBUG
105 | [Obsolete("For debugging only", true)]
106 | private TNode[] Nodes
107 | {
108 | get
109 | {
110 | int count = this.Count;
111 | TNode[] array = new TNode[count];
112 | for (int i = 0; i < count; i++)
113 | {
114 | array[i] = this[i];
115 | }
116 | return array;
117 | }
118 | }
119 | #endif
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/SeparatedSyntaxListBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml.InternalSyntax
4 | {
5 | internal readonly struct SeparatedSyntaxListBuilder where TNode : GreenNode
6 | {
7 | private readonly SyntaxListBuilder _builder;
8 |
9 | public SeparatedSyntaxListBuilder(int size)
10 | : this(new SyntaxListBuilder(size))
11 | {
12 | }
13 |
14 | public static SeparatedSyntaxListBuilder Create()
15 | {
16 | return new SeparatedSyntaxListBuilder(8);
17 | }
18 |
19 | internal SeparatedSyntaxListBuilder(SyntaxListBuilder builder)
20 | {
21 | _builder = builder;
22 | }
23 |
24 | public bool IsNull
25 | {
26 | get
27 | {
28 | return _builder == null;
29 | }
30 | }
31 |
32 | public int Count
33 | {
34 | get
35 | {
36 | return _builder.Count;
37 | }
38 | }
39 |
40 | public GreenNode this[int index]
41 | {
42 | get
43 | {
44 | return _builder[index];
45 | }
46 |
47 | set
48 | {
49 | _builder[index] = value;
50 | }
51 | }
52 |
53 | public void Clear()
54 | {
55 | _builder.Clear();
56 | }
57 |
58 | public void RemoveLast()
59 | {
60 | this._builder.RemoveLast();
61 | }
62 |
63 | public SeparatedSyntaxListBuilder Add(TNode node)
64 | {
65 | _builder.Add(node);
66 | return this;
67 | }
68 |
69 | public void AddSeparator(GreenNode separatorToken)
70 | {
71 | _builder.Add(separatorToken);
72 | }
73 |
74 | public void AddRange(TNode[] items, int offset, int length)
75 | {
76 | _builder.AddRange(items, offset, length);
77 | }
78 |
79 | public void AddRange(in SeparatedSyntaxList nodes)
80 | {
81 | _builder.AddRange(nodes.GetWithSeparators());
82 | }
83 |
84 | public void AddRange(in SeparatedSyntaxList nodes, int count)
85 | {
86 | var list = nodes.GetWithSeparators();
87 | this._builder.AddRange(list, this.Count, Math.Min(count * 2, list.Count));
88 | }
89 |
90 | public bool Any(SyntaxKind kind)
91 | {
92 | return _builder.Any(kind);
93 | }
94 |
95 | public SeparatedSyntaxList ToList()
96 | {
97 | return _builder == null
98 | ? default(SeparatedSyntaxList)
99 | : new SeparatedSyntaxList(new SyntaxList(_builder.ToListNode()));
100 | }
101 |
102 | ///
103 | /// WARN WARN WARN: This should be used with extreme caution - the underlying builder does
104 | /// not give any indication that it is from a separated syntax list but the constraints
105 | /// (node, token, node, token, ...) should still be maintained.
106 | ///
107 | ///
108 | /// In order to avoid creating a separate pool of SeparatedSyntaxListBuilders, we expose
109 | /// our underlying SyntaxListBuilder to SyntaxListPool.
110 | ///
111 | internal SyntaxListBuilder UnderlyingBuilder
112 | {
113 | get { return _builder; }
114 | }
115 |
116 | public static implicit operator SeparatedSyntaxList(in SeparatedSyntaxListBuilder builder)
117 | {
118 | return builder.ToList();
119 | }
120 |
121 | public static implicit operator SyntaxListBuilder(in SeparatedSyntaxListBuilder builder)
122 | {
123 | return builder._builder;
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/SyntaxListBuilder`1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml.InternalSyntax
4 | {
5 | internal readonly struct SyntaxListBuilder where TNode : GreenNode
6 | {
7 | private readonly SyntaxListBuilder _builder;
8 |
9 | public SyntaxListBuilder(int size)
10 | : this(new SyntaxListBuilder(size))
11 | {
12 | }
13 |
14 | public static SyntaxListBuilder Create()
15 | {
16 | return new SyntaxListBuilder(8);
17 | }
18 |
19 | internal SyntaxListBuilder(SyntaxListBuilder builder)
20 | {
21 | _builder = builder;
22 | }
23 |
24 | public bool IsNull
25 | {
26 | get
27 | {
28 | return _builder == null;
29 | }
30 | }
31 |
32 | public int Count
33 | {
34 | get
35 | {
36 | return _builder.Count;
37 | }
38 | }
39 |
40 | public TNode this[int index]
41 | {
42 | get
43 | {
44 | return (TNode)_builder[index];
45 | }
46 |
47 | set
48 | {
49 | _builder[index] = value;
50 | }
51 | }
52 |
53 | public void Clear()
54 | {
55 | _builder.Clear();
56 | }
57 |
58 | public SyntaxListBuilder Add(TNode node)
59 | {
60 | _builder.Add(node);
61 | return this;
62 | }
63 |
64 | public void AddRange(TNode[] items, int offset, int length)
65 | {
66 | _builder.AddRange(items, offset, length);
67 | }
68 |
69 | public void AddRange(SyntaxList nodes)
70 | {
71 | _builder.AddRange(nodes);
72 | }
73 |
74 | public void AddRange(SyntaxList nodes, int offset, int length)
75 | {
76 | _builder.AddRange(nodes, offset, length);
77 | }
78 |
79 | public bool Any(SyntaxKind kind)
80 | {
81 | return _builder.Any(kind);
82 | }
83 |
84 | public SyntaxList ToList()
85 | {
86 | return _builder.ToList();
87 | }
88 |
89 | public GreenNode ToListNode()
90 | {
91 | return _builder.ToListNode();
92 | }
93 |
94 | public static implicit operator SyntaxListBuilder(SyntaxListBuilder builder)
95 | {
96 | return builder._builder;
97 | }
98 |
99 | public static implicit operator SyntaxList(SyntaxListBuilder builder)
100 | {
101 | if (builder._builder != null)
102 | {
103 | return builder.ToList();
104 | }
105 |
106 | return default(SyntaxList);
107 | }
108 |
109 | public SyntaxList ToList() where TDerived : GreenNode
110 | {
111 | return new SyntaxList(ToListNode());
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/SyntaxList`1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Microsoft.Language.Xml.InternalSyntax
8 | {
9 | internal readonly struct SyntaxList
10 | where TNode : GreenNode
11 | {
12 | private readonly GreenNode _node;
13 |
14 | public SyntaxList(GreenNode node)
15 | {
16 | this._node = node;
17 | }
18 |
19 | public GreenNode Node
20 | {
21 | get
22 | {
23 | return ((GreenNode)this._node);
24 | }
25 | }
26 |
27 | public int Count
28 | {
29 | get
30 | {
31 | return (this._node == null) ? 0 : this._node.IsList ? this._node.SlotCount : 1;
32 | }
33 | }
34 |
35 | public TNode Last
36 | {
37 | get
38 | {
39 | var node = this._node;
40 | if (node.IsList)
41 | {
42 | return ((TNode)node.GetSlot(node.SlotCount - 1));
43 | }
44 |
45 | return ((TNode)node);
46 | }
47 | }
48 |
49 | /* Not Implemented: Default */
50 | public TNode this[int index]
51 | {
52 | get
53 | {
54 | var node = this._node;
55 | if (node.IsList)
56 | {
57 | return ((TNode)node.GetSlot(index));
58 | }
59 |
60 | Debug.Assert(index == 0);
61 | return ((TNode)node);
62 | }
63 | }
64 |
65 | public GreenNode ItemUntyped(int index)
66 | {
67 | var node = this._node;
68 | if (node.IsList)
69 | {
70 | return node.GetSlot(index);
71 | }
72 |
73 | Debug.Assert(index == 0);
74 | return node;
75 | }
76 |
77 | public bool Any()
78 | {
79 | return this._node != null;
80 | }
81 |
82 | public bool Any(SyntaxKind kind)
83 | {
84 | for (var i = 0; i < this.Count; i++)
85 | {
86 | var element = this.ItemUntyped(i);
87 | if ((element.Kind == kind))
88 | {
89 | return true;
90 | }
91 | }
92 |
93 | return false;
94 | }
95 |
96 | public TNode[] Nodes
97 | {
98 | get
99 | {
100 | var arr = new TNode[this.Count];
101 | for (var i = 0; i < this.Count; i++)
102 | {
103 | arr[i] = this[i];
104 | }
105 |
106 | return arr;
107 | }
108 | }
109 |
110 | public static bool operator ==(SyntaxList left, SyntaxList right)
111 | {
112 | return (left._node == right._node);
113 | }
114 |
115 | public static bool operator !=(SyntaxList left, SyntaxList right)
116 | {
117 | return !(left._node == right._node);
118 | }
119 |
120 | public override bool Equals(object obj)
121 | {
122 | return (obj is SyntaxList && (this._node == ((SyntaxList)obj)._node));
123 | }
124 |
125 | public override int GetHashCode()
126 | {
127 | return this._node != null ? this._node.GetHashCode() : 0;
128 | }
129 |
130 | /*public SeparatedSyntaxList AsSeparatedList() where TOther : GreenNode
131 | {
132 | return new SeparatedSyntaxList(new SyntaxList(this._node));
133 | }*/
134 |
135 | public static implicit operator SyntaxList(TNode node)
136 | {
137 | return new SyntaxList(node);
138 | }
139 |
140 | public static implicit operator SyntaxList(SyntaxList nodes)
141 | {
142 | return new SyntaxList(nodes._node);
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/SyntaxVisitor.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace Microsoft.Language.Xml.InternalSyntax
4 | {
5 | internal abstract partial class SyntaxVisitor
6 | {
7 | public virtual GreenNode Visit(GreenNode node)
8 | {
9 | if (node != null)
10 | {
11 | return node.Accept(this);
12 | }
13 |
14 | return null;
15 | }
16 |
17 | public virtual GreenNode VisitSyntaxNode(GreenNode node)
18 | {
19 | return node;
20 | }
21 |
22 | public virtual GreenNode VisitXmlNode(XmlNodeSyntax.Green node)
23 | {
24 | return VisitSyntaxNode(node);
25 | }
26 |
27 | public virtual GreenNode VisitXmlDocument(XmlDocumentSyntax.Green node)
28 | {
29 | return VisitXmlNode(node);
30 | }
31 |
32 | public virtual GreenNode VisitXmlDeclaration(XmlDeclarationSyntax.Green node)
33 | {
34 | return VisitSyntaxNode(node);
35 | }
36 |
37 | public virtual GreenNode VisitXmlDeclarationOption(XmlDeclarationOptionSyntax.Green node)
38 | {
39 | return VisitSyntaxNode(node);
40 | }
41 |
42 | public virtual GreenNode VisitXmlElement(XmlElementSyntax.Green node)
43 | {
44 | return VisitXmlNode(node);
45 | }
46 |
47 | public virtual GreenNode VisitXmlText(XmlTextSyntax.Green node)
48 | {
49 | return VisitXmlNode(node);
50 | }
51 |
52 | public virtual GreenNode VisitXmlElementStartTag(XmlElementStartTagSyntax.Green node)
53 | {
54 | return VisitXmlNode(node);
55 | }
56 |
57 | public virtual GreenNode VisitXmlElementEndTag(XmlElementEndTagSyntax.Green node)
58 | {
59 | return VisitXmlNode(node);
60 | }
61 |
62 | public virtual GreenNode VisitXmlEmptyElement(XmlEmptyElementSyntax.Green node)
63 | {
64 | return VisitXmlNode(node);
65 | }
66 |
67 | public virtual GreenNode VisitXmlAttribute(XmlAttributeSyntax.Green node)
68 | {
69 | return VisitXmlNode(node);
70 | }
71 |
72 | public virtual GreenNode VisitXmlString(XmlStringSyntax.Green node)
73 | {
74 | return VisitXmlNode(node);
75 | }
76 |
77 | public virtual GreenNode VisitXmlName(XmlNameSyntax.Green node)
78 | {
79 | return VisitXmlNode(node);
80 | }
81 |
82 | public virtual GreenNode VisitXmlPrefix(XmlPrefixSyntax.Green node)
83 | {
84 | return VisitSyntaxNode(node);
85 | }
86 |
87 | public virtual GreenNode VisitXmlComment(XmlCommentSyntax.Green node)
88 | {
89 | return VisitXmlNode(node);
90 | }
91 |
92 | public virtual GreenNode VisitSkippedTokensTrivia(SkippedTokensTriviaSyntax.Green node)
93 | {
94 | return VisitSyntaxNode(node);
95 | }
96 |
97 | public virtual GreenNode VisitXmlProcessingInstruction(XmlProcessingInstructionSyntax.Green node)
98 | {
99 | return VisitXmlNode(node);
100 | }
101 |
102 | public virtual GreenNode VisitXmlCDataSection(XmlCDataSectionSyntax.Green node)
103 | {
104 | return VisitXmlNode(node);
105 | }
106 |
107 | public virtual GreenNode VisitList(SyntaxList list)
108 | {
109 | return list;
110 | }
111 |
112 | public virtual SyntaxToken.Green VisitSyntaxToken(SyntaxToken.Green token)
113 | {
114 | return token;
115 | }
116 |
117 | public virtual SyntaxTrivia.Green VisitSyntaxTrivia(SyntaxTrivia.Green trivia)
118 | {
119 | return trivia;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/InternalSyntax/TriviaInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace Microsoft.Language.Xml.InternalSyntax
5 | {
6 | internal class TriviaInfo
7 | {
8 | private TriviaInfo(GreenNode leadingTrivia, GreenNode trailingTrivia)
9 | {
10 | this._leadingTrivia = leadingTrivia;
11 | this._trailingTrivia = trailingTrivia;
12 | }
13 |
14 | private const int maximumCachedTriviaWidth = 40;
15 | private const int triviaInfoCacheSize = 64;
16 | private static readonly Func triviaKeyHasher = (GreenNode key) => Hash.Combine(key.ToFullString(), ((short)key.Kind));
17 | private static readonly Func triviaKeyEquality = (GreenNode key, TriviaInfo value) => (key == value._leadingTrivia) || ((key.Kind == value._leadingTrivia.Kind) && (key.FullWidth == value._leadingTrivia.FullWidth) && (key.ToFullString() == value._leadingTrivia.ToFullString()));
18 |
19 | private static bool ShouldCacheTriviaInfo(GreenNode leadingTrivia, GreenNode trailingTrivia)
20 | {
21 | Debug.Assert(leadingTrivia != null);
22 | if (trailingTrivia == null)
23 | {
24 | return false;
25 | }
26 | else
27 | {
28 | return leadingTrivia.Kind == SyntaxKind.WhitespaceTrivia &&
29 | trailingTrivia.Kind == SyntaxKind.WhitespaceTrivia &&
30 | trailingTrivia.FullWidth == 1 &&
31 | trailingTrivia.ToFullString() == " " &&
32 | leadingTrivia.FullWidth <= maximumCachedTriviaWidth;
33 | }
34 | }
35 |
36 | public static TriviaInfo Create(GreenNode leadingTrivia, GreenNode trailingTrivia)
37 | {
38 | Debug.Assert(leadingTrivia != null);
39 | return new TriviaInfo(leadingTrivia, trailingTrivia);
40 | }
41 |
42 | public GreenNode _leadingTrivia;
43 | public GreenNode _trailingTrivia;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Microsoft.Language.Xml.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Microsoft.Language.Xml
4 | netstandard2.0
5 | true
6 | latest
7 | embedded
8 | true
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | True
22 | True
23 | XmlResources.resx
24 |
25 |
26 |
27 |
28 | ResXFileCodeGenerator
29 | XmlResources.Designer.cs
30 |
31 |
32 |
33 |
34 |
35 |
36 | True
37 | GuiLabs.Language.Xml
38 | Microsoft
39 | Microsoft
40 | A full-fidelity XML parser
41 | A full-fidelity XML parser. Produces a syntax tree from XML text, preserves all whitespace and provides low-level API to examine the exact structure of the source text.
42 | Apache-2.0
43 | https://github.com/KirillOsenkov/XmlParser
44 | https://github.com/KirillOsenkov/XmlParser
45 | language_xml_logo.png
46 | Xml Parser
47 | true
48 | snupkg
49 |
50 |
51 | True
52 | ..\..\key.snk
53 | False
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/PooledStringBuilder.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Text;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | ///
7 | /// The usage is:
8 | /// var inst = PooledStringBuilder.GetInstance();
9 | /// var sb = inst.builder;
10 | /// ... Do Stuff...
11 | /// ... sb.ToString() ...
12 | /// inst.Free();
13 | ///
14 | internal class PooledStringBuilder
15 | {
16 | public readonly StringBuilder Builder = new StringBuilder();
17 | private readonly ObjectPool pool;
18 |
19 | private PooledStringBuilder(ObjectPool pool)
20 | {
21 | Debug.Assert(pool != null);
22 | this.pool = pool;
23 | }
24 |
25 | public int Length
26 | {
27 | get { return this.Builder.Length; }
28 | }
29 |
30 | public void Free()
31 | {
32 | var builder = this.Builder;
33 |
34 | // do not store builders that are too large.
35 | if (builder.Capacity <= 1024)
36 | {
37 | builder.Clear();
38 | pool.Free(this);
39 | }
40 | else
41 | {
42 | pool.ForgetTrackedObject(this);
43 | }
44 | }
45 |
46 | [System.Obsolete("Consider calling ToStringAndFree instead.")]
47 | public new string ToString()
48 | {
49 | return this.Builder.ToString();
50 | }
51 |
52 | public string ToStringAndFree()
53 | {
54 | string result = this.Builder.ToString();
55 | this.Free();
56 |
57 | return result;
58 | }
59 |
60 | public string ToStringAndFree(int startIndex, int length)
61 | {
62 | string result = this.Builder.ToString(startIndex, length);
63 | this.Free();
64 |
65 | return result;
66 | }
67 |
68 | // global pool
69 | private static readonly ObjectPool PoolInstance = CreatePool();
70 |
71 | // if someone needs to create a private pool;
72 | public static ObjectPool CreatePool()
73 | {
74 | ObjectPool pool = null;
75 | pool = new ObjectPool(() => new PooledStringBuilder(pool), 32);
76 | return pool;
77 | }
78 |
79 | public static PooledStringBuilder GetInstance()
80 | {
81 | var builder = PoolInstance.Allocate();
82 | Debug.Assert(builder.Builder.Length == 0);
83 | return builder;
84 | }
85 |
86 | public static implicit operator StringBuilder(PooledStringBuilder obj)
87 | {
88 | return obj.Builder;
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/ScannerState.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | public enum ScannerState
4 | {
5 | Content, // Scan text between markup
6 | Misc, // Scan tokens in Xml misc state, these are tokens between document declaration and the root element
7 | DocType, // Scan tokens inside of
8 | Element, // Scan tokens inside of < ... >
9 | EndElement, // Scan tokens inside of ...>
10 | SingleQuotedString, // Scan a single quoted string
11 | SmartSingleQuotedString, // Scan a single quoted string DWCH_RSMART_Q
12 | QuotedString, // Scan a quoted string
13 | SmartQuotedString, // Scan a quoted string DWCH_RSMART_DQ
14 | UnQuotedString, // Scan a string that is missing quotes (error recovery)
15 | CData, // Scan text inside of
16 | StartProcessingInstruction, // Scan first text inside f ... ?>, the first text can have leading trivia
17 | ProcessingInstruction, // Scan remaining text inside of ... ?>
18 | Comment, // Scan text inside of
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/StringBuffer.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | ///
4 | /// Abstraction around text snapshot to decouple the parser from the editor
5 | ///
6 | public class StringBuffer : Buffer
7 | {
8 | private string text;
9 |
10 | public StringBuffer(string text)
11 | {
12 | this.text = text;
13 | }
14 |
15 | public override int Length
16 | {
17 | get { return text.Length; }
18 | }
19 |
20 | public override char this[int index]
21 | {
22 | get
23 | {
24 | return text[index];
25 | }
26 | }
27 |
28 | public override string GetText(int start, int length)
29 | {
30 | return text.Substring(start, length);
31 | }
32 |
33 | public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
34 | {
35 | text.CopyTo(sourceIndex, destination, destinationIndex, count);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Structure/INamedXmlNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | public interface INamedXmlNode
6 | {
7 | string Name { get; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Structure/IXmlElement.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | public interface IXmlElement
6 | {
7 | int Start { get; }
8 | int FullWidth { get; }
9 | string Name { get; }
10 | string Value { get; }
11 | IXmlElement Parent { get; }
12 | IEnumerable Elements { get; }
13 | IEnumerable> Attributes { get; }
14 | string this[string attributeName] { get; }
15 | IXmlElementSyntax AsSyntaxElement { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/BadTokenSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class BadTokenSyntax : PunctuationSyntax
8 | {
9 | internal new class Green : PunctuationSyntax.Green
10 | {
11 | public SyntaxSubKind SubKind { get; }
12 |
13 | internal Green(SyntaxSubKind subKind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
14 | : base(SyntaxKind.BadToken, name, leadingTrivia, trailingTrivia)
15 | {
16 | SubKind = subKind;
17 | }
18 |
19 | internal Green(SyntaxSubKind subKind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
20 | : base(SyntaxKind.BadToken, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
21 | {
22 | SubKind = subKind;
23 | }
24 |
25 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new BadTokenSyntax(this, parent, position);
26 |
27 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
28 | {
29 | return new Green(SubKind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
30 | }
31 |
32 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
33 | {
34 | return new Green(SubKind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
35 | }
36 | }
37 |
38 | internal new Green GreenNode => (Green)base.GreenNode;
39 |
40 | public SyntaxSubKind SubKind => GreenNode.SubKind;
41 |
42 | internal BadTokenSyntax(Green green, SyntaxNode parent, int position)
43 | : base(green, parent, position)
44 | {
45 |
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/ERRID.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | public enum ERRID
4 | {
5 | //Void = InternalErrorCode.Void,
6 | //Unknown = InternalErrorCode.Unknown,
7 | ERR_None = 0,
8 |
9 | ERR_Syntax = 30035,
10 | ERR_IllegalChar = 30037,
11 | ERR_ExpectedGreater = 30636,
12 | ERR_ExpectedXmlName = 31146,
13 | ERR_DuplicateXmlAttribute = 31149,
14 | ERR_MismatchedXmlEndTag = 31150,
15 | ERR_MissingXmlEndTag = 31151,
16 | ERR_MissingVersionInXmlDecl = 31153,
17 | ERR_IllegalAttributeInXmlDecl = 31154,
18 | ERR_VersionMustBeFirstInXmlDecl = 31156,
19 | ERR_AttributeOrder = 31157,
20 | ERR_ExpectedSQuote = 31163,
21 | ERR_ExpectedQuote = 31164,
22 | ERR_ExpectedLT = 31165,
23 | ERR_StartAttributeValue = 31166,
24 | ERR_IllegalXmlStartNameChar = 31169,
25 | ERR_IllegalXmlNameChar = 31170,
26 | ERR_IllegalXmlCommentChar = 31171,
27 | ERR_ExpectedXmlWhiteSpace = 31173,
28 | ERR_IllegalProcessingInstructionName = 31174,
29 | ERR_DTDNotSupported = 31175,
30 | ERR_IllegalXmlWhiteSpace = 31177,
31 | ERR_ExpectedSColon = 31178,
32 | ERR_XmlEntityReference = 31180,
33 | ERR_InvalidAttributeValue1 = 31181,
34 | ERR_InvalidAttributeValue2 = 31182,
35 | ERR_XmlEndCDataNotAllowedInContent = 31198,
36 | ERR_XmlEndElementNoMatchingStart = 31207,
37 |
38 | ERR_LastPlusOne
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/IXmlElementSyntax.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | public interface IXmlElementSyntax
6 | {
7 | string Name { get; }
8 | XmlNameSyntax NameNode { get; }
9 | SyntaxList Content { get; }
10 | IXmlElementSyntax Parent { get; }
11 | IEnumerable Elements { get; }
12 | IEnumerable Attributes { get; }
13 | SyntaxList AttributesNode { get; }
14 | XmlAttributeSyntax GetAttribute(string localName, string prefix = null);
15 | string GetAttributeValue(string localName, string prefix = null);
16 | IXmlElement AsElement { get; }
17 | XmlNodeSyntax AsNode { get; }
18 | string ToFullString();
19 |
20 | IXmlElementSyntax WithName(XmlNameSyntax newName);
21 | IXmlElementSyntax WithContent(SyntaxList newContent);
22 | IXmlElementSyntax WithAttributes(IEnumerable newAttributes);
23 | IXmlElementSyntax WithAttributes(SyntaxList newAttributes);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/KeywordSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | using InternalSyntax;
4 |
5 | public class KeywordSyntax : SyntaxToken
6 | {
7 | internal new class Green : SyntaxToken.Green
8 | {
9 | internal Green(string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
10 | : base(SyntaxKind.XmlKeyword, name, leadingTrivia, trailingTrivia)
11 | {
12 | }
13 |
14 | internal Green(string name, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
15 | : base(SyntaxKind.XmlKeyword, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
16 | {
17 | }
18 |
19 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new KeywordSyntax(this, parent, position);
20 |
21 | public override SyntaxToken.Green WithLeadingTrivia(GreenNode trivia)
22 | {
23 | return new Green(Text, trivia, TrailingTrivia);
24 | }
25 |
26 | public override SyntaxToken.Green WithTrailingTrivia(GreenNode trivia)
27 | {
28 | return new Green(Text, LeadingTrivia, trivia);
29 | }
30 |
31 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
32 | {
33 | return new Green(Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
34 | }
35 |
36 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
37 | {
38 | return new Green(Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
39 | }
40 | }
41 |
42 | internal new Green GreenNode => (Green)base.GreenNode;
43 |
44 | public string Keyword => Text;
45 |
46 | internal KeywordSyntax(Green green, SyntaxNode parent, int position)
47 | : base(green, parent, position)
48 | {
49 |
50 | }
51 |
52 | internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
53 | {
54 | return (KeywordSyntax)new Green(Text, trivia?.GreenNode, GetTrailingTrivia().Node?.GreenNode).CreateRed(Parent, Start);
55 | }
56 |
57 | internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
58 | {
59 | return (KeywordSyntax)new Green(Text, GetLeadingTrivia().Node?.GreenNode, trivia?.GreenNode).CreateRed(Parent, Start);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/PunctuationSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | using InternalSyntax;
4 |
5 | public class PunctuationSyntax : SyntaxToken
6 | {
7 | internal new class Green : SyntaxToken.Green
8 | {
9 | internal Green(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
10 | : base(kind, name, leadingTrivia, trailingTrivia)
11 | {
12 | }
13 |
14 | internal Green(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
15 | : base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
16 | {
17 | }
18 |
19 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new PunctuationSyntax(this, parent, position);
20 |
21 | public override SyntaxToken.Green WithLeadingTrivia(GreenNode trivia)
22 | {
23 | return new Green(Kind, Text, trivia, TrailingTrivia);
24 | }
25 |
26 | public override SyntaxToken.Green WithTrailingTrivia(GreenNode trivia)
27 | {
28 | return new Green(Kind, Text, LeadingTrivia, trivia);
29 | }
30 |
31 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
32 | {
33 | return new Green(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
34 | }
35 |
36 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
37 | {
38 | return new Green(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
39 | }
40 | }
41 |
42 | internal new Green GreenNode => (Green)base.GreenNode;
43 |
44 | public string Punctuation => Text;
45 |
46 | internal PunctuationSyntax(Green green, SyntaxNode parent, int position)
47 | : base(green, parent, position)
48 | {
49 |
50 | }
51 |
52 | internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
53 | {
54 | return (PunctuationSyntax)new Green(Kind, Text, trivia?.GreenNode, GetTrailingTrivia().Node?.GreenNode).CreateRed(Parent, Start);
55 | }
56 |
57 | internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
58 | {
59 | return (PunctuationSyntax)new Green(Kind, Text, GetLeadingTrivia().Node?.GreenNode, trivia?.GreenNode).CreateRed(Parent, Start);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SeparatedSyntaxListBuilder`1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Microsoft.Language.Xml
8 | {
9 | internal readonly struct SeparatedSyntaxListBuilder
10 | where TNode : SyntaxNode
11 | {
12 | private readonly SyntaxListBuilder builder;
13 |
14 | public SeparatedSyntaxListBuilder(int size) : this(new SyntaxListBuilder(size))
15 | {
16 | }
17 |
18 | public SeparatedSyntaxListBuilder(SyntaxListBuilder builder)
19 | {
20 | this.builder = builder;
21 | }
22 |
23 | public bool IsNull
24 | {
25 | get
26 | {
27 | return (this.builder == null);
28 | }
29 | }
30 |
31 | public int Count
32 | {
33 | get
34 | {
35 | return this.builder.Count;
36 | }
37 | }
38 |
39 | public void Clear()
40 | {
41 | this.builder.Clear();
42 | }
43 |
44 | public void Add(TNode node)
45 | {
46 | this.builder.Add(node);
47 | }
48 |
49 | public void AddSeparator(SyntaxToken separatorToken)
50 | {
51 | this.builder.Add(separatorToken);
52 | }
53 |
54 | public void AddRange(SeparatedSyntaxList nodes, int count)
55 | {
56 | var list = nodes.GetWithSeparators();
57 | this.builder.AddRange(list, this.Count, Math.Min(count * 2, list.Count));
58 | }
59 |
60 | public void RemoveLast()
61 | {
62 | this.builder.RemoveLast();
63 | }
64 |
65 | public bool Any(SyntaxKind kind)
66 | {
67 | return this.builder.Any(kind);
68 | }
69 |
70 | public SeparatedSyntaxList ToList()
71 | {
72 | return new SeparatedSyntaxList(this.builder.ToList());
73 | }
74 |
75 | public SeparatedSyntaxList ToList() where TDerivedNode : TNode
76 | {
77 | return new SeparatedSyntaxList(this.builder.ToList());
78 | }
79 |
80 | public static implicit operator SyntaxListBuilder(SeparatedSyntaxListBuilder builder)
81 | {
82 | return builder.builder;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SeparatedSyntaxList`1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Microsoft.Language.Xml
8 | {
9 | public readonly struct SeparatedSyntaxList
10 | where TNode : SyntaxNode
11 | {
12 | private readonly SyntaxList _list;
13 |
14 | public SeparatedSyntaxList(SyntaxList list)
15 | {
16 | this._list = list;
17 | }
18 |
19 | public SyntaxNode Node
20 | {
21 | get
22 | {
23 | return this._list.Node;
24 | }
25 | }
26 |
27 | public int Count
28 | {
29 | get
30 | {
31 | return (this._list.Count + 1) >> 1;
32 | }
33 | }
34 |
35 | public TNode this[int index]
36 | {
37 | get
38 | {
39 | return (TNode)_list[index << 1];
40 | }
41 | }
42 |
43 | public int SeparatorCount
44 | {
45 | get
46 | {
47 | return (this._list.Count) >> 1;
48 | }
49 | }
50 |
51 | /*
52 | ''' Gets the separator at the given index in this list.
53 | '''
54 | ''' The index.
55 | */
56 | public SyntaxToken GetSeparator(int index)
57 | {
58 | return ((SyntaxToken)this._list[(index << 1) + 1]);
59 | }
60 |
61 | public bool Any()
62 | {
63 | return (this.Count > 0);
64 | }
65 |
66 | public bool Any(SyntaxKind kind)
67 | {
68 | for (var i = 0; i < this.Count; i++)
69 | {
70 | var element = this[i];
71 | if ((element.Kind == kind))
72 | {
73 | return true;
74 | }
75 | }
76 |
77 | return false;
78 | }
79 |
80 | public SyntaxList GetWithSeparators()
81 | {
82 | return this._list;
83 | }
84 |
85 | public bool Contains(TNode node)
86 | {
87 | return this.IndexOf(node) >= 0;
88 | }
89 |
90 | public int IndexOf(TNode node)
91 | {
92 | for (int i = 0, n = this.Count; i < n; i++)
93 | {
94 | if (object.Equals(this[i], node))
95 | {
96 | return i;
97 | }
98 | }
99 |
100 | return -1;
101 | }
102 |
103 | public int IndexOf(Func predicate)
104 | {
105 | for (int i = 0, n = this.Count; i < n; i++)
106 | {
107 | if (predicate(this[i]))
108 | {
109 | return i;
110 | }
111 | }
112 |
113 | return -1;
114 | }
115 |
116 | internal int IndexOf(SyntaxKind kind)
117 | {
118 | for (int i = 0, n = this.Count; i < n; i++)
119 | {
120 | if (this[i].Kind == kind)
121 | {
122 | return i;
123 | }
124 | }
125 |
126 | return -1;
127 | }
128 |
129 | public int LastIndexOf(TNode node)
130 | {
131 | for (int i = this.Count - 1; i >= 0; i--)
132 | {
133 | if (object.Equals(this[i], node))
134 | {
135 | return i;
136 | }
137 | }
138 |
139 | return -1;
140 | }
141 |
142 | public int LastIndexOf(Func predicate)
143 | {
144 | for (int i = this.Count - 1; i >= 0; i--)
145 | {
146 | if (predicate(this[i]))
147 | {
148 | return i;
149 | }
150 | }
151 |
152 | return -1;
153 | }
154 |
155 | internal bool Any(Func predicate)
156 | {
157 | for (int i = 0; i < this.Count; i++)
158 | {
159 | if (predicate(this[i]))
160 | {
161 | return true;
162 | }
163 | }
164 |
165 | return false;
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SkippedTokensTriviaSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class SkippedTokensTriviaSyntax : SyntaxNode
8 | {
9 | internal class Green : GreenNode
10 | {
11 | readonly GreenNode tokens;
12 |
13 | internal Green(GreenNode tokens)
14 | : base(SyntaxKind.SkippedTokensTrivia)
15 | {
16 | this.SlotCount = 1;
17 | this.tokens = tokens;
18 | AdjustWidth(tokens);
19 | }
20 |
21 | internal Green(GreenNode tokens, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
22 | : base(SyntaxKind.SkippedTokensTrivia, diagnostics, annotations)
23 | {
24 | this.SlotCount = 1;
25 | this.tokens = tokens;
26 | AdjustWidth(tokens);
27 | }
28 |
29 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new SkippedTokensTriviaSyntax(this, parent, position);
30 |
31 | internal override GreenNode GetSlot(int index)
32 | {
33 | switch (index)
34 | {
35 | case 0: return tokens;
36 | }
37 | throw new InvalidOperationException();
38 | }
39 |
40 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
41 | {
42 | return visitor.VisitSkippedTokensTrivia(this);
43 | }
44 |
45 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
46 | {
47 | return new Green(tokens, diagnostics, GetAnnotations());
48 | }
49 |
50 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
51 | {
52 | return new Green(tokens, GetDiagnostics(), annotations);
53 | }
54 | }
55 |
56 | internal new Green GreenNode => (Green)base.GreenNode;
57 |
58 | SyntaxNode textTokens;
59 |
60 | public SyntaxList Tokens => new SyntaxList(GetRed(ref textTokens, 0));
61 |
62 | internal SkippedTokensTriviaSyntax(Green green, SyntaxNode parent, int position)
63 | : base(green, parent, position)
64 | {
65 |
66 | }
67 |
68 | public string Value => Tokens.Node?.ToFullString() ?? string.Empty;
69 |
70 | public override SyntaxNode Accept(SyntaxVisitor visitor)
71 | {
72 | return visitor.VisitSkippedTokensTrivia(this);
73 | }
74 |
75 | internal override SyntaxNode GetCachedSlot(int index)
76 | {
77 | switch (index)
78 | {
79 | case 0: return textTokens;
80 | default: return null;
81 | }
82 | }
83 |
84 | internal override SyntaxNode GetNodeSlot(int slot)
85 | {
86 | switch (slot)
87 | {
88 | case 0: return GetRed(ref textTokens, 0);
89 | default: return null;
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxAnnotation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | ///
7 | /// A SyntaxAnnotation is used to annotate syntax elements with additional information.
8 | ///
9 | /// Since syntax elements are immutable, annotating them requires creating new instances of them
10 | /// with the annotations attached.
11 | ///
12 | [DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
13 | public sealed class SyntaxAnnotation : IEquatable
14 | {
15 | // use a value identity instead of object identity so a deserialized instance matches the original instance.
16 | private readonly long _id;
17 | private static long s_nextId;
18 |
19 | // use a value identity instead of object identity so a deserialized instance matches the original instance.
20 | public string Kind { get; }
21 | public string Data { get; }
22 |
23 | public SyntaxAnnotation()
24 | {
25 | _id = System.Threading.Interlocked.Increment(ref s_nextId);
26 | }
27 |
28 | public SyntaxAnnotation(string kind)
29 | : this()
30 | {
31 | this.Kind = kind;
32 | }
33 |
34 | public SyntaxAnnotation(string kind, string data)
35 | : this(kind)
36 | {
37 | this.Data = data;
38 | }
39 |
40 | private string GetDebuggerDisplay()
41 | {
42 | return string.Format("Annotation: Kind='{0}' Data='{1}'", this.Kind ?? "", this.Data ?? "");
43 | }
44 |
45 | public bool Equals(SyntaxAnnotation other)
46 | {
47 | return (object)other != null && _id == other._id;
48 | }
49 |
50 | public static bool operator ==(SyntaxAnnotation left, SyntaxAnnotation right)
51 | {
52 | if ((object)left == (object)right)
53 | {
54 | return true;
55 | }
56 |
57 | if ((object)left == null || (object)right == null)
58 | {
59 | return false;
60 | }
61 |
62 | return left.Equals(right);
63 | }
64 |
65 | public static bool operator !=(SyntaxAnnotation left, SyntaxAnnotation right)
66 | {
67 | if ((object)left == (object)right)
68 | {
69 | return false;
70 | }
71 |
72 | if ((object)left == null || (object)right == null)
73 | {
74 | return true;
75 | }
76 |
77 | return !left.Equals(right);
78 | }
79 |
80 | public override bool Equals(object obj)
81 | {
82 | return this.Equals(obj as SyntaxAnnotation);
83 | }
84 |
85 | public override int GetHashCode()
86 | {
87 | return _id.GetHashCode();
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxKind.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | public enum SyntaxKind : byte
4 | {
5 | LessThanQuestionToken,
6 | XmlNameToken,
7 | XmlKeyword,
8 | LessThanToken,
9 | LessThanGreaterThanToken,
10 | LessThanSlashToken,
11 | BeginCDataToken,
12 | LessThanExclamationMinusMinusToken,
13 | LessThanPercentEqualsToken,
14 | XmlTextLiteralToken,
15 | BadToken,
16 | XmlEntityLiteralToken,
17 | DocumentationCommentLineBreakToken,
18 | SlashToken,
19 | XmlElementStartTag,
20 | GreaterThanToken,
21 | EndOfXmlToken,
22 | EndOfFileToken,
23 | EqualsToken,
24 | SingleQuoteToken,
25 | DoubleQuoteToken,
26 | QuestionGreaterThanToken,
27 | OpenParenToken,
28 | CloseParenToken,
29 | ColonToken,
30 | IdentifierToken,
31 | SlashGreaterThanToken,
32 | WhitespaceTrivia,
33 | EndOfLineTrivia,
34 | XmlString,
35 | XmlName,
36 | XmlProcessingInstruction,
37 | XmlElementEndTag,
38 | XmlDeclaration,
39 | XmlDeclarationOption,
40 | XmlPrefix,
41 | XmlElement,
42 | XmlText,
43 | List,
44 | XmlEmptyElement,
45 | XmlAttribute,
46 | EndCDataToken,
47 | XmlCDataSection,
48 | MinusMinusGreaterThanToken,
49 | XmlComment,
50 | XmlDocument,
51 | None,
52 | SkippedTokensTrivia
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 |
5 | namespace Microsoft.Language.Xml
6 | {
7 | public abstract class SyntaxList : SyntaxNode
8 | {
9 | internal SyntaxList(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
10 | : base(green, parent, position)
11 | {
12 | }
13 |
14 | public override SyntaxNode Accept(SyntaxVisitor visitor)
15 | {
16 | return visitor.Visit(this);
17 | }
18 |
19 | protected internal override SyntaxNode ReplaceCore(IEnumerable nodes = null, Func computeReplacementNode = null, IEnumerable tokens = null, Func computeReplacementToken = null, IEnumerable trivia = null, Func computeReplacementTrivia = null)
20 | {
21 | throw new InvalidOperationException();
22 | }
23 |
24 | internal class WithTwoChildren : SyntaxList
25 | {
26 | private SyntaxNode _child0;
27 | private SyntaxNode _child1;
28 |
29 | internal WithTwoChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
30 | : base(green, parent, position)
31 | {
32 | }
33 |
34 | internal override SyntaxNode GetNodeSlot(int index)
35 | {
36 | switch (index)
37 | {
38 | case 0:
39 | return this.GetRedElement(ref _child0, 0);
40 | case 1:
41 | return this.GetRedElement(ref _child1, 1);
42 | default:
43 | return null;
44 | }
45 | }
46 |
47 | internal override SyntaxNode GetCachedSlot(int index)
48 | {
49 | switch (index)
50 | {
51 | case 0:
52 | return _child0;
53 | case 1:
54 | return _child1;
55 | default:
56 | return null;
57 | }
58 | }
59 | }
60 |
61 | internal class WithThreeChildren : SyntaxList
62 | {
63 | private SyntaxNode _child0;
64 | private SyntaxNode _child1;
65 | private SyntaxNode _child2;
66 |
67 | internal WithThreeChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
68 | : base(green, parent, position)
69 | {
70 | }
71 |
72 | internal override SyntaxNode GetNodeSlot(int index)
73 | {
74 | switch (index)
75 | {
76 | case 0:
77 | return this.GetRedElement(ref _child0, 0);
78 | case 1:
79 | return this.GetRedElement(ref _child1, 1);
80 | case 2:
81 | return this.GetRedElement(ref _child2, 2);
82 | default:
83 | return null;
84 | }
85 | }
86 |
87 | internal override SyntaxNode GetCachedSlot(int index)
88 | {
89 | switch (index)
90 | {
91 | case 0:
92 | return _child0;
93 | case 1:
94 | return _child1;
95 | case 2:
96 | return _child2;
97 | default:
98 | return null;
99 | }
100 | }
101 | }
102 |
103 | internal class WithManyChildren : SyntaxList
104 | {
105 | private readonly ArrayElement[] _children;
106 |
107 | internal WithManyChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
108 | : base(green, parent, position)
109 | {
110 | _children = new ArrayElement[green.SlotCount];
111 | }
112 |
113 | internal override SyntaxNode GetNodeSlot(int index)
114 | {
115 | return this.GetRedElement(ref _children[index].Value, index);
116 | }
117 |
118 | internal override SyntaxNode GetCachedSlot(int index)
119 | {
120 | return _children[index];
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxListBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | internal static class SyntaxListBuilderExtensions
6 | {
7 | public static SyntaxList ToList(this SyntaxListBuilder builder)
8 | {
9 | if (builder == null || builder.Count == 0)
10 | {
11 | return default(SyntaxList);
12 | }
13 |
14 | return new SyntaxList(builder.ToListNode().CreateRed());
15 | }
16 |
17 | public static SyntaxList ToList(this SyntaxListBuilder builder)
18 | where TNode : SyntaxNode
19 | {
20 | if (builder == null || builder.Count == 0)
21 | {
22 | return new SyntaxList();
23 | }
24 |
25 | return new SyntaxList(builder.ToListNode().CreateRed());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxListBuilder`1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Microsoft.Language.Xml
9 | {
10 | internal readonly struct SyntaxListBuilder
11 | where TNode : SyntaxNode
12 | {
13 | private readonly SyntaxListBuilder _builder;
14 |
15 | public SyntaxListBuilder(int size)
16 | : this(new SyntaxListBuilder(size))
17 | {
18 | }
19 |
20 | public static SyntaxListBuilder Create()
21 | {
22 | return new SyntaxListBuilder(8);
23 | }
24 |
25 | internal SyntaxListBuilder(SyntaxListBuilder builder)
26 | {
27 | _builder = builder;
28 | }
29 |
30 | public bool IsNull
31 | {
32 | get
33 | {
34 | return _builder == null;
35 | }
36 | }
37 |
38 | public int Count
39 | {
40 | get
41 | {
42 | return _builder.Count;
43 | }
44 | }
45 |
46 | public void Clear()
47 | {
48 | _builder.Clear();
49 | }
50 |
51 | public SyntaxListBuilder Add(TNode node)
52 | {
53 | _builder.Add(node);
54 | return this;
55 | }
56 |
57 | public void AddRange(TNode[] items, int offset, int length)
58 | {
59 | _builder.AddRange(items, offset, length);
60 | }
61 |
62 | public void AddRange(SyntaxList nodes)
63 | {
64 | _builder.AddRange(nodes);
65 | }
66 |
67 | public void AddRange(SyntaxList nodes, int offset, int length)
68 | {
69 | _builder.AddRange(nodes, offset, length);
70 | }
71 |
72 | public bool Any(SyntaxKind kind)
73 | {
74 | return _builder.Any(kind);
75 | }
76 |
77 | public SyntaxList ToList()
78 | {
79 | return _builder.ToList();
80 | }
81 |
82 | public static implicit operator SyntaxListBuilder(SyntaxListBuilder builder)
83 | {
84 | return builder._builder;
85 | }
86 |
87 | public static implicit operator SyntaxList(SyntaxListBuilder builder)
88 | {
89 | if (builder._builder != null)
90 | {
91 | return builder.ToList();
92 | }
93 |
94 | return default(SyntaxList);
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxListPool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | using InternalSyntax;
7 |
8 | internal class SyntaxListPool
9 | {
10 | private Stack _freeList = new Stack();
11 | public InternalSyntax.SyntaxListBuilder Allocate()
12 | {
13 | if (_freeList.Count > 0)
14 | {
15 | return _freeList.Pop();
16 | }
17 |
18 | return InternalSyntax.SyntaxListBuilder.Create();
19 | }
20 |
21 | public InternalSyntax.SyntaxListBuilder Allocate() where TNode : GreenNode
22 | {
23 | return new InternalSyntax.SyntaxListBuilder(this.Allocate());
24 | }
25 |
26 | /*public SeparatedSyntaxListBuilder AllocateSeparated() where TNode : GreenNode
27 | {
28 | return new SeparatedSyntaxListBuilder(this.Allocate());
29 | }*/
30 |
31 | public void Free(InternalSyntax.SyntaxListBuilder item)
32 | {
33 | if (item != null)
34 | {
35 | item.Clear();
36 | _freeList.Push(item);
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxSubKind.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Microsoft.Language.Xml
7 | {
8 | public enum SyntaxSubKind
9 | {
10 | None,
11 | BeginDocTypeToken,
12 | LessThanExclamationToken,
13 | OpenBracketToken,
14 | CloseBracketToken,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxTrivia.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 |
5 | namespace Microsoft.Language.Xml
6 | {
7 | using InternalSyntax;
8 |
9 | public class SyntaxTrivia : SyntaxNode
10 | {
11 | internal class Green : GreenNode
12 | {
13 | public string Text { get; }
14 |
15 | internal Green(SyntaxKind kind, string text)
16 | : base(kind, text.Length)
17 | {
18 | Text = text;
19 | }
20 |
21 | internal Green(SyntaxKind kind, string text, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
22 | : base(kind, text.Length, diagnostics, annotations)
23 | {
24 | Text = text;
25 | }
26 |
27 | public override int Width => Text.Length;
28 |
29 | internal override void WriteToOrFlatten(TextWriter writer, Stack stack)
30 | {
31 | writer.Write(Text);
32 | }
33 |
34 | public sealed override string ToFullString() => Text;
35 |
36 | public sealed override int GetLeadingTriviaWidth() => 0;
37 | public sealed override int GetTrailingTriviaWidth() => 0;
38 |
39 | protected override sealed int GetSlotCount() => 0;
40 |
41 | internal override sealed GreenNode GetSlot(int index)
42 | {
43 | throw new InvalidOperationException();
44 | }
45 |
46 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new SyntaxTrivia(this, parent, position);
47 |
48 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
49 | {
50 | return visitor.VisitSyntaxTrivia(this);
51 | }
52 |
53 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
54 | {
55 | return new Green(Kind, Text, diagnostics, GetAnnotations());
56 | }
57 |
58 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
59 | {
60 | return new Green(Kind, Text, GetDiagnostics(), annotations);
61 | }
62 | }
63 |
64 | internal new Green GreenNode => (Green)base.GreenNode;
65 |
66 | public string Text => GreenNode.Text;
67 |
68 | internal SyntaxTrivia(Green green, SyntaxNode parent, int position)
69 | : base(green, parent, position)
70 | {
71 | }
72 |
73 | internal override sealed SyntaxNode GetCachedSlot(int index)
74 | {
75 | throw new InvalidOperationException();
76 | }
77 |
78 | internal override sealed SyntaxNode GetNodeSlot(int slot)
79 | {
80 | throw new InvalidOperationException();
81 | }
82 |
83 | public override SyntaxNode Accept(SyntaxVisitor visitor)
84 | {
85 | return visitor.VisitSyntaxTrivia(this);
86 | }
87 |
88 | protected override int GetTextWidth()
89 | {
90 | return Text.Length;
91 | }
92 |
93 | public sealed override SyntaxTriviaList GetTrailingTrivia()
94 | {
95 | return default(SyntaxTriviaList);
96 | }
97 |
98 | public sealed override SyntaxTriviaList GetLeadingTrivia()
99 | {
100 | return default(SyntaxTriviaList);
101 | }
102 |
103 | public override string ToString() => Text;
104 | public sealed override string ToFullString() => Text;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxTriviaListBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace Microsoft.Language.Xml
6 | {
7 | using InternalSyntax;
8 |
9 | internal class SyntaxTriviaListBuilder
10 | {
11 | private SyntaxTrivia[] _nodes;
12 | private int _count;
13 |
14 | public SyntaxTriviaListBuilder(int size)
15 | {
16 | _nodes = new SyntaxTrivia[size];
17 | }
18 |
19 | public static SyntaxTriviaListBuilder Create()
20 | {
21 | return new SyntaxTriviaListBuilder(4);
22 | }
23 |
24 | public static SyntaxTriviaList Create(IEnumerable trivia)
25 | {
26 | if (trivia == null)
27 | {
28 | return new SyntaxTriviaList();
29 | }
30 |
31 | var builder = SyntaxTriviaListBuilder.Create();
32 | builder.AddRange(trivia);
33 | return builder.ToList();
34 | }
35 |
36 | public int Count
37 | {
38 | get { return _count; }
39 | }
40 |
41 | public void Clear()
42 | {
43 | _count = 0;
44 | }
45 |
46 | public SyntaxTrivia this[int index]
47 | {
48 | get
49 | {
50 | if (index < 0 || index > _count)
51 | {
52 | throw new IndexOutOfRangeException();
53 | }
54 |
55 | return _nodes[index];
56 | }
57 | }
58 |
59 | public void AddRange(IEnumerable items)
60 | {
61 | if (items != null)
62 | {
63 | foreach (var item in items)
64 | {
65 | this.Add(item);
66 | }
67 | }
68 | }
69 |
70 | public SyntaxTriviaListBuilder Add(SyntaxTrivia item)
71 | {
72 | if (_nodes == null || _count >= _nodes.Length)
73 | {
74 | this.Grow(_count == 0 ? 8 : _nodes.Length * 2);
75 | }
76 |
77 | _nodes[_count++] = item;
78 | return this;
79 | }
80 |
81 | public void Add(SyntaxTrivia[] items)
82 | {
83 | this.Add(items, 0, items.Length);
84 | }
85 |
86 | public void Add(SyntaxTrivia[] items, int offset, int length)
87 | {
88 | if (_nodes == null || _count + length > _nodes.Length)
89 | {
90 | this.Grow(_count + length);
91 | }
92 |
93 | Array.Copy(items, offset, _nodes, _count, length);
94 | _count += length;
95 | }
96 |
97 | public void Add(in SyntaxTriviaList list)
98 | {
99 | this.Add(list, 0, list.Count);
100 | }
101 |
102 | public void Add(in SyntaxTriviaList list, int offset, int length)
103 | {
104 | if (_nodes == null || _count + length > _nodes.Length)
105 | {
106 | this.Grow(_count + length);
107 | }
108 |
109 | list.CopyTo(offset, _nodes, _count, length);
110 | _count += length;
111 | }
112 |
113 | private void Grow(int size)
114 | {
115 | var tmp = new SyntaxTrivia[size];
116 | Array.Copy(_nodes, tmp, _nodes.Length);
117 | _nodes = tmp;
118 | }
119 |
120 | public static implicit operator SyntaxTriviaList(SyntaxTriviaListBuilder builder)
121 | {
122 | return builder.ToList();
123 | }
124 |
125 | public SyntaxTriviaList ToList()
126 | {
127 | if (_count > 0)
128 | {
129 | var tmp = new ArrayElement[_count];
130 | for (int i = 0; i < _count; i++)
131 | {
132 | tmp[i].Value = _nodes[i].GreenNode;
133 | }
134 | return new SyntaxTriviaList(InternalSyntax.SyntaxList.List(tmp).CreateRed (), position: 0, index: 0);
135 | }
136 | else
137 | {
138 | return default(SyntaxTriviaList);
139 | }
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/SyntaxVisitor.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | public abstract class SyntaxVisitor
6 | {
7 | public virtual SyntaxNode Visit(SyntaxNode node)
8 | {
9 | if (node != null)
10 | {
11 | return node.Accept(this);
12 | }
13 |
14 | return null;
15 | }
16 |
17 | public virtual SyntaxNode VisitSyntaxNode(SyntaxNode node)
18 | {
19 | return node;
20 | }
21 |
22 | public virtual SyntaxNode VisitXmlNode(XmlNodeSyntax node)
23 | {
24 | return VisitSyntaxNode(node);
25 | }
26 |
27 | public virtual SyntaxNode VisitXmlDocument(XmlDocumentSyntax node)
28 | {
29 | return VisitXmlNode(node);
30 | }
31 |
32 | public virtual SyntaxNode VisitXmlDeclaration(XmlDeclarationSyntax node)
33 | {
34 | return VisitSyntaxNode(node);
35 | }
36 |
37 | public virtual SyntaxNode VisitXmlDeclarationOption(XmlDeclarationOptionSyntax node)
38 | {
39 | return VisitSyntaxNode(node);
40 | }
41 |
42 | public virtual SyntaxNode VisitXmlElement(XmlElementSyntax node)
43 | {
44 | return VisitXmlNode(node);
45 | }
46 |
47 | public virtual SyntaxNode VisitXmlText(XmlTextSyntax node)
48 | {
49 | return VisitXmlNode(node);
50 | }
51 |
52 | public virtual SyntaxNode VisitXmlElementStartTag(XmlElementStartTagSyntax node)
53 | {
54 | return VisitXmlNode(node);
55 | }
56 |
57 | public virtual SyntaxNode VisitXmlElementEndTag(XmlElementEndTagSyntax node)
58 | {
59 | return VisitXmlNode(node);
60 | }
61 |
62 | public virtual SyntaxNode VisitXmlEmptyElement(XmlEmptyElementSyntax node)
63 | {
64 | return VisitXmlNode(node);
65 | }
66 |
67 | public virtual SyntaxNode VisitXmlAttribute(XmlAttributeSyntax node)
68 | {
69 | return VisitXmlNode(node);
70 | }
71 |
72 | public virtual SyntaxNode VisitXmlString(XmlStringSyntax node)
73 | {
74 | return VisitXmlNode(node);
75 | }
76 |
77 | public virtual SyntaxNode VisitXmlName(XmlNameSyntax node)
78 | {
79 | return VisitXmlNode(node);
80 | }
81 |
82 | public virtual SyntaxNode VisitXmlPrefix(XmlPrefixSyntax node)
83 | {
84 | return VisitSyntaxNode(node);
85 | }
86 |
87 | public virtual SyntaxNode VisitXmlComment(XmlCommentSyntax node)
88 | {
89 | return VisitXmlNode(node);
90 | }
91 |
92 | public virtual SyntaxNode VisitSkippedTokensTrivia(SkippedTokensTriviaSyntax node)
93 | {
94 | return VisitSyntaxNode(node);
95 | }
96 |
97 | public virtual SyntaxNode VisitXmlProcessingInstruction(XmlProcessingInstructionSyntax node)
98 | {
99 | return VisitXmlNode(node);
100 | }
101 |
102 | public virtual SyntaxNode VisitXmlCDataSection(XmlCDataSectionSyntax node)
103 | {
104 | return VisitXmlNode(node);
105 | }
106 |
107 | public virtual SyntaxList VisitList (SyntaxList list) where TNode : SyntaxNode
108 | {
109 | return list;
110 | }
111 |
112 | public virtual SyntaxToken VisitSyntaxToken(SyntaxToken token)
113 | {
114 | return token;
115 | }
116 |
117 | public virtual SyntaxTrivia VisitSyntaxTrivia(SyntaxTrivia trivia)
118 | {
119 | return trivia;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlCDataSectionSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlCDataSectionSyntax : XmlNodeSyntax
8 | {
9 | internal new class Green : XmlNodeSyntax.Green
10 | {
11 | readonly PunctuationSyntax.Green beginCData;
12 | readonly GreenNode value;
13 | readonly PunctuationSyntax.Green endCData;
14 |
15 | internal PunctuationSyntax.Green BeginCData => beginCData;
16 | internal InternalSyntax.SyntaxList TextTokens => value;
17 | internal PunctuationSyntax.Green EndCData => endCData;
18 |
19 | internal Green(PunctuationSyntax.Green beginCData, GreenNode value, PunctuationSyntax.Green endCData)
20 | : base(SyntaxKind.XmlCDataSection)
21 | {
22 | this.SlotCount = 3;
23 | this.beginCData = beginCData;
24 | AdjustWidth(beginCData);
25 | this.value = value;
26 | AdjustWidth(value);
27 | this.endCData = endCData;
28 | AdjustWidth(endCData);
29 | }
30 |
31 | internal Green(PunctuationSyntax.Green beginCData, GreenNode value, PunctuationSyntax.Green endCData, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
32 | : base(SyntaxKind.XmlCDataSection, diagnostics, annotations)
33 | {
34 | this.SlotCount = 3;
35 | this.beginCData = beginCData;
36 | AdjustWidth(beginCData);
37 | this.value = value;
38 | AdjustWidth(value);
39 | this.endCData = endCData;
40 | AdjustWidth(endCData);
41 | }
42 |
43 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlCDataSectionSyntax(this, parent, position);
44 |
45 | internal override GreenNode GetSlot(int index)
46 | {
47 | switch (index)
48 | {
49 | case 0: return beginCData;
50 | case 1: return value;
51 | case 2: return endCData;
52 | }
53 | throw new InvalidOperationException();
54 | }
55 |
56 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
57 | {
58 | return visitor.VisitXmlCDataSection(this);
59 | }
60 |
61 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
62 | {
63 | return new Green(beginCData, value, endCData, diagnostics, GetAnnotations());
64 | }
65 |
66 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
67 | {
68 | return new Green(beginCData, value, endCData, GetDiagnostics(), annotations);
69 | }
70 | }
71 |
72 | PunctuationSyntax beginCData;
73 | SyntaxNode textTokens;
74 | PunctuationSyntax endCData;
75 |
76 | public PunctuationSyntax BeginCData => GetRed(ref beginCData, 0);
77 | public SyntaxList TextTokens => new SyntaxList(GetRed(ref textTokens, 1));
78 | public PunctuationSyntax EndCData => GetRed(ref endCData, 2);
79 |
80 | internal XmlCDataSectionSyntax(Green green, SyntaxNode parent, int position)
81 | : base(green, parent, position)
82 | {
83 |
84 | }
85 |
86 | public string Value => TextTokens.Node?.ToFullString() ?? string.Empty;
87 |
88 | public override SyntaxNode Accept(SyntaxVisitor visitor)
89 | {
90 | return visitor.VisitXmlCDataSection(this);
91 | }
92 |
93 | internal override SyntaxNode GetCachedSlot(int index)
94 | {
95 | switch (index)
96 | {
97 | case 0: return beginCData;
98 | case 1: return textTokens;
99 | case 2: return endCData;
100 | default: return null;
101 | }
102 | }
103 |
104 | internal override SyntaxNode GetNodeSlot(int slot)
105 | {
106 | switch (slot)
107 | {
108 | case 0: return BeginCData;
109 | case 1: return GetRed(ref textTokens, 1);
110 | case 2: return EndCData;
111 | default: return null;
112 | }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlCommentSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlCommentSyntax : XmlNodeSyntax
8 | {
9 | internal new class Green : XmlNodeSyntax.Green
10 | {
11 | readonly PunctuationSyntax.Green beginComment;
12 | readonly GreenNode content;
13 | readonly PunctuationSyntax.Green endComment;
14 |
15 | internal PunctuationSyntax.Green BeginComment => beginComment;
16 | internal GreenNode Content => content;
17 | internal PunctuationSyntax.Green EndComment => endComment;
18 |
19 | internal Green(PunctuationSyntax.Green beginComment, GreenNode content, PunctuationSyntax.Green endComment)
20 | : base(SyntaxKind.XmlComment)
21 | {
22 | this.SlotCount = 3;
23 | this.beginComment = beginComment;
24 | AdjustWidth(beginComment);
25 | this.content = content;
26 | AdjustWidth(content);
27 | this.endComment = endComment;
28 | AdjustWidth(endComment);
29 | }
30 |
31 | internal Green(PunctuationSyntax.Green beginComment, GreenNode content, PunctuationSyntax.Green endComment, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
32 | : base(SyntaxKind.XmlComment, diagnostics, annotations)
33 | {
34 | this.SlotCount = 3;
35 | this.beginComment = beginComment;
36 | AdjustWidth(beginComment);
37 | this.content = content;
38 | AdjustWidth(content);
39 | this.endComment = endComment;
40 | AdjustWidth(endComment);
41 | }
42 |
43 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlCommentSyntax(this, parent, position);
44 |
45 | internal override GreenNode GetSlot(int index)
46 | {
47 | switch (index)
48 | {
49 | case 0: return beginComment;
50 | case 1: return content;
51 | case 2: return endComment;
52 | }
53 | throw new InvalidOperationException();
54 | }
55 |
56 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
57 | {
58 | return visitor.VisitXmlNode(this);
59 | }
60 |
61 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
62 | {
63 | return new Green(beginComment, content, endComment, diagnostics, GetAnnotations());
64 | }
65 |
66 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
67 | {
68 | return new Green(beginComment, content, endComment, GetDiagnostics(), annotations);
69 | }
70 | }
71 |
72 | PunctuationSyntax beginComment;
73 | SyntaxNode content;
74 | PunctuationSyntax endComment;
75 |
76 | public PunctuationSyntax BeginComment => GetRed(ref beginComment, 0);
77 | public SyntaxList Content => new SyntaxList(GetRed(ref content, 1));
78 | public PunctuationSyntax EndComment => GetRed(ref endComment, 2);
79 |
80 | internal XmlCommentSyntax(Green green, SyntaxNode parent, int position)
81 | : base(green, parent, position)
82 | {
83 |
84 | }
85 |
86 | public string Value => Content.Node?.ToFullString() ?? string.Empty;
87 |
88 | public override SyntaxNode Accept(SyntaxVisitor visitor)
89 | {
90 | return visitor.VisitXmlComment(this);
91 | }
92 |
93 | internal override SyntaxNode GetCachedSlot(int index)
94 | {
95 | switch (index)
96 | {
97 | case 0: return beginComment;
98 | case 1: return content;
99 | case 2: return endComment;
100 | default: return null;
101 | }
102 | }
103 |
104 | internal override SyntaxNode GetNodeSlot(int slot)
105 | {
106 | switch (slot)
107 | {
108 | case 0: return BeginComment;
109 | case 1: return GetRed(ref content, 1);
110 | case 2: return EndComment;
111 | default: return null;
112 | }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlContentExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Microsoft.Language.Xml
9 | {
10 | public static class XmlContextExtensions
11 | {
12 | internal static void Push(this List @this, XmlContext context)
13 | {
14 | @this.Add(context);
15 | }
16 |
17 | internal static XmlContext Pop(this List @this)
18 | {
19 | var last = @this.Count - 1;
20 | var context = @this[last];
21 | @this.RemoveAt(last);
22 | return context;
23 | }
24 |
25 | internal static XmlContext Peek(this List @this, int i = 0)
26 | {
27 | var last = @this.Count - 1;
28 | return @this[last - i];
29 | }
30 |
31 | internal static int MatchEndElement(this List @this, XmlNameSyntax.Green name)
32 | {
33 | Debug.Assert(name == null || name.Kind == SyntaxKind.XmlName);
34 | var last = @this.Count - 1;
35 | if (name == null)
36 | {
37 | return last;
38 | }
39 |
40 | var i = last;
41 | while (i >= 0)
42 | {
43 | var context = @this[i];
44 | var nameExpr = context.StartElement.NameNode;
45 | if (nameExpr.Kind == SyntaxKind.XmlName)
46 | {
47 | var startName = ((XmlNameSyntax.Green)nameExpr);
48 | if (startName.LocalName.Text == name.LocalName.Text)
49 | {
50 | var startPrefix = startName.Prefix;
51 | var endPrefix = name.Prefix;
52 | if (startPrefix == endPrefix)
53 | {
54 | break;
55 | }
56 |
57 | if (startPrefix != null && endPrefix != null)
58 | {
59 | if (startPrefix.Name.Text == endPrefix.Name.Text)
60 | {
61 | break;
62 | }
63 | }
64 | }
65 | }
66 |
67 | i -= 1;
68 | }
69 |
70 | return i;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Microsoft.Language.Xml
8 | {
9 | using InternalSyntax;
10 | using static InternalSyntax.SyntaxFactory;
11 |
12 | internal readonly struct XmlContext
13 | {
14 | private readonly XmlElementStartTagSyntax.Green _start;
15 | private readonly InternalSyntax.SyntaxListBuilder _content;
16 | private readonly SyntaxListPool _pool;
17 |
18 | public XmlContext(SyntaxListPool pool, XmlElementStartTagSyntax.Green start)
19 | {
20 | _pool = pool;
21 | _start = start;
22 | _content = _pool.Allocate();
23 | }
24 |
25 | public void Add(XmlNodeSyntax.Green xml)
26 | {
27 | _content.Add(xml);
28 | }
29 |
30 | public XmlElementStartTagSyntax.Green StartElement
31 | {
32 | get
33 | {
34 | return _start;
35 | }
36 | }
37 |
38 | public XmlNodeSyntax.Green CreateElement(XmlElementEndTagSyntax.Green endElement)
39 | {
40 | Debug.Assert(endElement != null);
41 | var contentList = _content.ToList();
42 | _pool.Free(_content);
43 | return XmlElement(_start, contentList.Node, endElement);
44 | }
45 |
46 | internal XmlNodeSyntax.Green CreateElement(XmlElementEndTagSyntax.Green missingEndElement, object v)
47 | {
48 | return CreateElement(missingEndElement);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlDeclarationOptionSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlDeclarationOptionSyntax : XmlNodeSyntax, INamedXmlNode
8 | {
9 | internal new class Green : XmlNodeSyntax.Green
10 | {
11 | readonly XmlNameTokenSyntax.Green name;
12 | readonly PunctuationSyntax.Green equals;
13 | readonly XmlStringSyntax.Green value;
14 |
15 | internal XmlNameTokenSyntax.Green Name => name;
16 | internal new PunctuationSyntax.Green Equals => equals;
17 | internal XmlStringSyntax.Green Value => value;
18 |
19 | internal Green(XmlNameTokenSyntax.Green name, PunctuationSyntax.Green equals, XmlStringSyntax.Green value)
20 | : base(SyntaxKind.XmlDeclarationOption)
21 | {
22 | this.SlotCount = 3;
23 | this.name = name;
24 | AdjustWidth(name);
25 | this.equals = equals;
26 | AdjustWidth(equals);
27 | this.value = value;
28 | AdjustWidth(value);
29 | }
30 |
31 | internal Green(XmlNameTokenSyntax.Green name, PunctuationSyntax.Green equals, XmlStringSyntax.Green value, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
32 | : base(SyntaxKind.XmlDeclarationOption, diagnostics, annotations)
33 | {
34 | this.SlotCount = 3;
35 | this.name = name;
36 | AdjustWidth(name);
37 | this.equals = equals;
38 | AdjustWidth(equals);
39 | this.value = value;
40 | AdjustWidth(value);
41 | }
42 |
43 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlDeclarationOptionSyntax(this, parent, position);
44 |
45 | internal override GreenNode GetSlot(int index)
46 | {
47 | switch (index)
48 | {
49 | case 0: return name;
50 | case 1: return equals;
51 | case 2: return value;
52 | }
53 | throw new InvalidOperationException();
54 | }
55 |
56 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
57 | {
58 | return visitor.VisitXmlDeclarationOption(this);
59 | }
60 |
61 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
62 | {
63 | return new Green(name, equals, value, diagnostics, GetAnnotations());
64 | }
65 |
66 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
67 | {
68 | return new Green(name, equals, value, GetDiagnostics(), annotations);
69 | }
70 | }
71 |
72 | internal new Green GreenNode => (Green)GreenNode;
73 |
74 | XmlNameTokenSyntax nameNode;
75 | PunctuationSyntax equals;
76 | XmlStringSyntax value;
77 |
78 | public XmlNameTokenSyntax NameNode => GetRed(ref nameNode, 0);
79 | public new PunctuationSyntax Equals => GetRed(ref equals, 1);
80 | public XmlStringSyntax Value => GetRed(ref value, 2);
81 |
82 | public string Name => NameNode?.Name;
83 |
84 | internal XmlDeclarationOptionSyntax(Green green, SyntaxNode parent, int position)
85 | : base(green, parent, position)
86 | {
87 |
88 | }
89 |
90 | public override SyntaxNode Accept(SyntaxVisitor visitor)
91 | {
92 | return visitor.VisitXmlDeclarationOption(this);
93 | }
94 |
95 | internal override SyntaxNode GetCachedSlot(int index)
96 | {
97 | switch (index)
98 | {
99 | case 0: return nameNode;
100 | case 1: return equals;
101 | case 2: return value;
102 | default: return null;
103 | }
104 | }
105 |
106 | internal override SyntaxNode GetNodeSlot(int slot)
107 | {
108 | switch (slot)
109 | {
110 | case 0: return NameNode;
111 | case 1: return Equals;
112 | case 2: return Value;
113 | default: return null;
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlEntityTokenSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | using InternalSyntax;
4 |
5 | public class XmlEntityTokenSyntax : XmlTextTokenSyntax
6 | {
7 | internal new class Green : XmlTextTokenSyntax.Green
8 | {
9 | public string Value { get; }
10 |
11 | internal Green(string text, string value, GreenNode leadingTrivia, GreenNode trailingTrivia)
12 | : base(SyntaxKind.XmlEntityLiteralToken, text, leadingTrivia, trailingTrivia)
13 | {
14 | Value = value;
15 | }
16 |
17 | internal Green(string text, string value, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
18 | : base(SyntaxKind.XmlEntityLiteralToken, text, leadingTrivia, trailingTrivia, diagnostics, annotations)
19 | {
20 | Value = value;
21 | }
22 |
23 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlEntityTokenSyntax(this, parent, position);
24 | }
25 |
26 | internal new Green GreenNode => (Green)base.GreenNode;
27 |
28 | public string Entity => Text;
29 | public string EntityValue => GreenNode.Value;
30 |
31 | internal XmlEntityTokenSyntax(Green green, SyntaxNode parent, int position)
32 | : base(green, parent, position)
33 | {
34 |
35 | }
36 |
37 | internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
38 | {
39 | return (XmlEntityTokenSyntax)new Green(Entity, EntityValue, trivia?.GreenNode, GetTrailingTrivia().Node?.GreenNode).CreateRed(Parent, Start);
40 | }
41 |
42 | internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
43 | {
44 | return (XmlEntityTokenSyntax)new Green(Entity, EntityValue, GetLeadingTrivia().Node?.GreenNode, trivia?.GreenNode).CreateRed(Parent, Start);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlNameTokenSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlNameTokenSyntax : SyntaxToken
8 | {
9 | internal new class Green : SyntaxToken.Green
10 | {
11 | internal Green(string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
12 | : base(SyntaxKind.XmlNameToken, name, leadingTrivia, trailingTrivia)
13 | {
14 | }
15 |
16 | internal Green(string name, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
17 | : base(SyntaxKind.XmlNameToken, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
18 | {
19 | }
20 |
21 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlNameTokenSyntax(this, parent, position);
22 |
23 | public override SyntaxToken.Green WithLeadingTrivia(GreenNode trivia)
24 | {
25 | return new Green(Text, trivia, TrailingTrivia);
26 | }
27 |
28 | public override SyntaxToken.Green WithTrailingTrivia(GreenNode trivia)
29 | {
30 | return new Green(Text, LeadingTrivia, trivia);
31 | }
32 |
33 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
34 | {
35 | return new Green(Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
36 | }
37 |
38 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
39 | {
40 | return new Green(Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
41 | }
42 | }
43 |
44 | internal new Green GreenNode => (Green)base.GreenNode;
45 |
46 | public string Name => Text;
47 |
48 | internal XmlNameTokenSyntax(Green green, SyntaxNode parent, int position)
49 | : base(green, parent, position)
50 | {
51 |
52 | }
53 |
54 | internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
55 | {
56 | return (XmlNameTokenSyntax)new Green(Text, trivia?.GreenNode, GetTrailingTrivia().Node?.GreenNode).CreateRed(Parent, Start);
57 | }
58 |
59 | internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
60 | {
61 | return (XmlNameTokenSyntax)new Green(Text, GetLeadingTrivia().Node?.GreenNode, trivia?.GreenNode).CreateRed(Parent, Start);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlNodeSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | public abstract class XmlNodeSyntax : SyntaxNode
7 | {
8 | internal abstract class Green : InternalSyntax.GreenNode
9 | {
10 | protected Green(SyntaxKind kind)
11 | : base(kind)
12 | {
13 | }
14 |
15 | protected Green(SyntaxKind kind, int fullWidth)
16 | : base(kind, fullWidth)
17 | {
18 | }
19 |
20 | protected Green(SyntaxKind kind, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
21 | : base(kind, diagnostics, annotations)
22 | {
23 | }
24 |
25 | internal override InternalSyntax.GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
26 | {
27 | return visitor.VisitXmlNode(this);
28 | }
29 | }
30 |
31 | internal new Green GreenNode => (Green)base.GreenNode;
32 |
33 | internal XmlNodeSyntax(Green green, SyntaxNode parent, int position) : base(green, parent, position)
34 | {
35 | }
36 |
37 | public override SyntaxNode Accept(SyntaxVisitor visitor)
38 | {
39 | return visitor.VisitXmlNode(this);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlPrefixSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlPrefixSyntax : SyntaxNode
8 | {
9 | internal class Green : GreenNode
10 | {
11 | readonly XmlNameTokenSyntax.Green name;
12 | readonly PunctuationSyntax.Green colonToken;
13 |
14 | internal XmlNameTokenSyntax.Green Name => name;
15 |
16 | internal Green(XmlNameTokenSyntax.Green name, PunctuationSyntax.Green colonToken)
17 | : base(SyntaxKind.XmlPrefix)
18 | {
19 | this.SlotCount = 2;
20 | this.name = name;
21 | AdjustWidth(name);
22 | this.colonToken = colonToken;
23 | AdjustWidth(colonToken);
24 | }
25 |
26 | internal Green(XmlNameTokenSyntax.Green name, PunctuationSyntax.Green colonToken, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
27 | : base(SyntaxKind.XmlPrefix, diagnostics, annotations)
28 | {
29 | this.SlotCount = 2;
30 | this.name = name;
31 | AdjustWidth(name);
32 | this.colonToken = colonToken;
33 | AdjustWidth(colonToken);
34 | }
35 |
36 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlPrefixSyntax(this, parent, position);
37 |
38 | internal override GreenNode GetSlot(int index)
39 | {
40 | switch (index)
41 | {
42 | case 0: return name;
43 | case 1: return colonToken;
44 | }
45 |
46 | throw new InvalidOperationException();
47 | }
48 |
49 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
50 | {
51 | return visitor.VisitXmlPrefix(this);
52 | }
53 |
54 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
55 | {
56 | return new Green(name, colonToken, diagnostics, GetAnnotations());
57 | }
58 |
59 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
60 | {
61 | return new Green(name, colonToken, GetDiagnostics(), annotations);
62 | }
63 | }
64 |
65 | internal new Green GreenNode => (Green)base.GreenNode;
66 |
67 | XmlNameTokenSyntax name;
68 | PunctuationSyntax colonToken;
69 |
70 | public XmlNameTokenSyntax Name => GetRed(ref name, 0);
71 | public PunctuationSyntax ColonToken => GetRed(ref colonToken, 1);
72 |
73 | internal XmlPrefixSyntax(Green green, SyntaxNode parent, int position)
74 | : base(green, parent, position)
75 | {
76 | }
77 |
78 | public override SyntaxNode Accept(SyntaxVisitor visitor)
79 | {
80 | return visitor.VisitXmlPrefix(this);
81 | }
82 |
83 | internal override SyntaxNode GetCachedSlot(int index)
84 | {
85 | switch (index)
86 | {
87 | case 0: return name;
88 | case 1: return colonToken;
89 | default: return null;
90 | }
91 | }
92 |
93 | internal override SyntaxNode GetNodeSlot(int slot)
94 | {
95 | switch (slot)
96 | {
97 | case 0: return Name;
98 | case 1: return ColonToken;
99 | default: return null;
100 | }
101 | }
102 |
103 | public XmlPrefixSyntax Update(XmlNameTokenSyntax name, PunctuationSyntax colonToken)
104 | {
105 | if (name != this.Name || colonToken != this.ColonToken)
106 | {
107 | var newNode = SyntaxFactory.XmlPrefix(name, colonToken);
108 | var annotations = this.GetAnnotations();
109 | if (annotations != null && annotations.Length > 0)
110 | return newNode.WithAnnotations(annotations);
111 | return newNode;
112 | }
113 |
114 | return this;
115 | }
116 |
117 | public XmlPrefixSyntax WithName(XmlNameTokenSyntax name)
118 | {
119 | return Update(name, ColonToken);
120 | }
121 |
122 | public XmlPrefixSyntax WithColonToken(PunctuationSyntax colonToken)
123 | {
124 | return Update(Name, colonToken);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlTextSyntax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | public class XmlTextSyntax : XmlNodeSyntax
8 | {
9 | internal new class Green : XmlNodeSyntax.Green
10 | {
11 | readonly GreenNode value;
12 |
13 | internal InternalSyntax.SyntaxList TextTokens => new InternalSyntax.SyntaxList(value);
14 |
15 | internal Green(GreenNode value)
16 | : base(SyntaxKind.XmlText)
17 | {
18 | this.SlotCount = 1;
19 | this.value = value;
20 | AdjustWidth(value);
21 | }
22 |
23 | internal Green(GreenNode value, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
24 | : base(SyntaxKind.XmlText, diagnostics, annotations)
25 | {
26 | this.SlotCount = 1;
27 | this.value = value;
28 | AdjustWidth(value);
29 | }
30 |
31 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlTextSyntax(this, parent, position);
32 |
33 | internal override GreenNode GetSlot(int index)
34 | {
35 | switch (index)
36 | {
37 | case 0: return value;
38 | }
39 | throw new InvalidOperationException();
40 | }
41 |
42 | internal override GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
43 | {
44 | return visitor.VisitXmlText(this);
45 | }
46 |
47 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
48 | {
49 | return new Green(value, diagnostics, GetAnnotations());
50 | }
51 |
52 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
53 | {
54 | return new Green(value, GetDiagnostics(), annotations);
55 | }
56 | }
57 |
58 | SyntaxNode textTokens;
59 |
60 | public SyntaxList TextTokens => new SyntaxList(GetRed(ref textTokens, 0));
61 |
62 | internal XmlTextSyntax(Green green, SyntaxNode parent, int position)
63 | : base(green, parent, position)
64 | {
65 |
66 | }
67 |
68 | public string Value => TextTokens.Node?.ToFullString() ?? string.Empty;
69 |
70 | public override SyntaxNode Accept(SyntaxVisitor visitor)
71 | {
72 | return visitor.VisitXmlText(this);
73 | }
74 |
75 | internal override SyntaxNode GetCachedSlot(int index)
76 | {
77 | switch (index)
78 | {
79 | case 0: return textTokens;
80 | default: return null;
81 | }
82 | }
83 |
84 | internal override SyntaxNode GetNodeSlot(int slot)
85 | {
86 | switch (slot)
87 | {
88 | case 0: return GetRed(ref textTokens, 0);
89 | default: return null;
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Syntax/XmlTextTokenSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Language.Xml
2 | {
3 | using InternalSyntax;
4 |
5 | public class XmlTextTokenSyntax : SyntaxToken
6 | {
7 | internal new class Green : SyntaxToken.Green
8 | {
9 | internal Green(string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
10 | : base(SyntaxKind.XmlTextLiteralToken, text, leadingTrivia, trailingTrivia)
11 | {
12 | }
13 |
14 | protected Green(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
15 | : base(kind, name, leadingTrivia, trailingTrivia)
16 | {
17 | }
18 |
19 | protected Green(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
20 | : base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
21 | {
22 | }
23 |
24 | internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new XmlTextTokenSyntax(this, parent, position);
25 |
26 | public override SyntaxToken.Green WithLeadingTrivia(GreenNode trivia)
27 | {
28 | return new Green(Kind, Text, trivia, TrailingTrivia);
29 | }
30 |
31 | public override SyntaxToken.Green WithTrailingTrivia(GreenNode trivia)
32 | {
33 | return new Green(Kind, Text, LeadingTrivia, trivia);
34 | }
35 |
36 | internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
37 | {
38 | return new Green(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
39 | }
40 |
41 | internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
42 | {
43 | return new Green(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
44 | }
45 | }
46 |
47 | public string Value => Text;
48 |
49 | internal XmlTextTokenSyntax(Green green, SyntaxNode parent, int position)
50 | : base(green, parent, position)
51 | {
52 |
53 | }
54 |
55 | internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
56 | {
57 | return (XmlTextTokenSyntax)new Green(Text, trivia?.GreenNode, GetTrailingTrivia().Node?.GreenNode).CreateRed(Parent, Start);
58 | }
59 |
60 | internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
61 | {
62 | return (XmlTextTokenSyntax)new Green(Text, GetLeadingTrivia().Node?.GreenNode, trivia?.GreenNode).CreateRed(Parent, Start);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/TextChange.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | public readonly struct TextChange : IEquatable
7 | {
8 | ///
9 | /// The original span of the changed text.
10 | ///
11 | public TextSpan Span { get; }
12 |
13 | ///
14 | /// The new text.
15 | ///
16 | public string NewText { get; }
17 |
18 | ///
19 | /// Initializes a new instance of
20 | ///
21 | /// The original span of the changed text.
22 | /// The new text.
23 | public TextChange(TextSpan span, string newText)
24 | : this()
25 | {
26 | if (newText == null)
27 | {
28 | throw new ArgumentNullException(nameof(newText));
29 | }
30 |
31 | this.Span = span;
32 | this.NewText = newText;
33 | }
34 |
35 | ///
36 | /// Provides a string representation for .
37 | ///
38 | public override string ToString()
39 | {
40 | return string.Format("{0}: {{ {1}, \"{2}\" }}", this.GetType().Name, Span, NewText);
41 | }
42 |
43 | public override bool Equals(object obj)
44 | {
45 | return obj is TextChange && this.Equals((TextChange)obj);
46 | }
47 |
48 | public bool Equals(TextChange other)
49 | {
50 | return
51 | EqualityComparer.Default.Equals(this.Span, other.Span) &&
52 | EqualityComparer.Default.Equals(this.NewText, other.NewText);
53 | }
54 |
55 | public override int GetHashCode()
56 | {
57 | return Hash.Combine(this.Span.GetHashCode(), this.NewText.GetHashCode());
58 | }
59 |
60 | public static bool operator ==(TextChange left, TextChange right)
61 | {
62 | return left.Equals(right);
63 | }
64 |
65 | public static bool operator !=(TextChange left, TextChange right)
66 | {
67 | return !(left == right);
68 | }
69 |
70 | ///
71 | /// Converts a to a .
72 | ///
73 | ///
74 | public static implicit operator TextChangeRange(TextChange change)
75 | {
76 | return new TextChangeRange(change.Span, change.NewText.Length);
77 | }
78 |
79 | ///
80 | /// An empty set of changes.
81 | ///
82 | public static IReadOnlyList NoChanges => SpecializedCollections.EmptyReadOnlyList();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/TextChangeRange.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | ///
7 | /// Represents the change to a span of text.
8 | ///
9 | public readonly struct TextChangeRange : IEquatable
10 | {
11 | ///
12 | /// The span of text before the edit which is being changed
13 | ///
14 | public TextSpan Span { get; }
15 |
16 | ///
17 | /// Width of the span after the edit. A 0 here would represent a delete
18 | ///
19 | public int NewLength { get; }
20 |
21 | public TextSpan NewSpan => new TextSpan(Span.Start, NewLength);
22 |
23 | ///
24 | /// Initializes a new instance of .
25 | ///
26 | ///
27 | ///
28 | public TextChangeRange(TextSpan span, int newLength)
29 | : this()
30 | {
31 | if (newLength < 0)
32 | {
33 | throw new ArgumentOutOfRangeException(nameof(newLength));
34 | }
35 |
36 | this.Span = span;
37 | this.NewLength = newLength;
38 | }
39 |
40 | ///
41 | /// Compares current instance of to another.
42 | ///
43 | public bool Equals(TextChangeRange other)
44 | {
45 | return
46 | other.Span == this.Span &&
47 | other.NewLength == this.NewLength;
48 | }
49 |
50 | ///
51 | /// Compares current instance of to another.
52 | ///
53 | public override bool Equals(object obj)
54 | {
55 | return obj is TextChangeRange && Equals((TextChangeRange)obj);
56 | }
57 |
58 | ///
59 | /// Provides hash code for current instance of .
60 | ///
61 | ///
62 | public override int GetHashCode()
63 | {
64 | return Hash.Combine(this.NewLength, this.Span.GetHashCode());
65 | }
66 |
67 | ///
68 | /// Determines if two instances of are same.
69 | ///
70 | public static bool operator ==(TextChangeRange left, TextChangeRange right)
71 | {
72 | return left.Equals(right);
73 | }
74 |
75 | ///
76 | /// Determines if two instances of are different.
77 | ///
78 | public static bool operator !=(TextChangeRange left, TextChangeRange right)
79 | {
80 | return !(left == right);
81 | }
82 |
83 | ///
84 | /// An empty set of changes.
85 | ///
86 | public static IReadOnlyList NoChanges { get; } = new List().AsReadOnly();
87 |
88 | ///
89 | /// Collapse a set of s into a single encompassing range. If
90 | /// the set of ranges provided is empty, an empty range is returned.
91 | ///
92 | public static TextChangeRange Collapse(IEnumerable changes)
93 | {
94 | var diff = 0;
95 | var start = int.MaxValue;
96 | var end = 0;
97 |
98 | foreach (var change in changes)
99 | {
100 | diff += change.NewLength - change.Span.Length;
101 |
102 | if (change.Span.Start < start)
103 | {
104 | start = change.Span.Start;
105 | }
106 |
107 | if (change.Span.End > end)
108 | {
109 | end = change.Span.End;
110 | }
111 | }
112 |
113 | if (start > end)
114 | {
115 | // there were no changes.
116 | return default(TextChangeRange);
117 | }
118 |
119 | var combined = TextSpan.FromBounds(start, end);
120 | var newLen = combined.Length + diff;
121 |
122 | return new TextChangeRange(combined, newLen);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Utilities/ArrayElement.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Microsoft.Language.Xml
8 | {
9 | public struct ArrayElement
10 | {
11 | public T Value;
12 |
13 | public static implicit operator T(ArrayElement element)
14 | {
15 | return element.Value;
16 | }
17 |
18 | //NOTE: there is no opposite conversion operator T -> ArrayElement
19 | //
20 | // that is because it is preferred to update array elements in-place
21 | // "elements[i].Value = v" results in much better code than "elements[i] = (ArrayElement)v"
22 | //
23 | // The reason is that x86 ABI requires that structs must be returned in
24 | // a return buffer even if they can fit in a register like this one.
25 | // Also since struct contains a reference, the write to the buffer is done with a checked GC barrier
26 | // as JIT does not know if the write goes to a stack or a heap location.
27 | // Assigning to Value directly easily avoids all this redundancy.
28 |
29 | public static ArrayElement[] MakeElementArray(T[] items)
30 | {
31 | if (items == null)
32 | {
33 | return null;
34 | }
35 |
36 | var array = new ArrayElement[items.Length];
37 | for (int i = 0; i < items.Length; i++)
38 | {
39 | array[i].Value = items[i];
40 | }
41 |
42 | return array;
43 | }
44 |
45 | public static T[] MakeArray(ArrayElement[] items)
46 | {
47 | if (items == null)
48 | {
49 | return null;
50 | }
51 |
52 | var array = new T[items.Length];
53 | for (int i = 0; i < items.Length; i++)
54 | {
55 | array[i] = items[i].Value;
56 | }
57 |
58 | return array;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Utilities/FirstTokenReplacer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | internal class FirstTokenReplacer : InternalSyntax.SyntaxRewriter
8 | {
9 | private readonly Func _newItem;
10 | private bool _isFirst = true;
11 |
12 | private FirstTokenReplacer(Func newItem)
13 | {
14 | _newItem = newItem;
15 | }
16 |
17 | internal static TTree Replace(TTree root, Func newItem) where TTree : GreenNode
18 | {
19 | return ((TTree)new FirstTokenReplacer(newItem).Visit(root));
20 | }
21 |
22 | public override SyntaxToken.Green VisitSyntaxToken(SyntaxToken.Green token)
23 | {
24 | if (token == null)
25 | {
26 | return null;
27 | }
28 |
29 | if (_isFirst)
30 | {
31 | _isFirst = false;
32 | return _newItem(token);
33 | }
34 |
35 | return token;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Utilities/LastTokenReplacer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Language.Xml
4 | {
5 | using InternalSyntax;
6 |
7 | internal class LastTokenReplacer : InternalSyntax.SyntaxRewriter
8 | {
9 | private readonly Func _newItem;
10 | private int _skipCnt;
11 | private LastTokenReplacer(Func newItem)
12 | {
13 | _newItem = newItem;
14 | }
15 |
16 | internal static TTree Replace(TTree root, Func newItem) where TTree : GreenNode
17 | {
18 | return (TTree)new LastTokenReplacer(newItem).Visit(root);
19 | }
20 |
21 | public override GreenNode Visit(GreenNode node)
22 | {
23 | if (node == null)
24 | {
25 | return null;
26 | }
27 |
28 | // node is not interesting until skip count is 0
29 | if (_skipCnt != 0)
30 | {
31 | _skipCnt -= 1;
32 | return node;
33 | } // not interested in trivia
34 |
35 | if (!node.IsToken)
36 | {
37 | var allChildrenCnt = 0;
38 | for (int i = 0; i < node.SlotCount; i++)
39 | {
40 | var child = node.GetSlot(i);
41 | if (child == null)
42 | {
43 | continue;
44 | }
45 |
46 | if (child.IsList)
47 | {
48 | allChildrenCnt += child.SlotCount;
49 | }
50 | else
51 | {
52 | allChildrenCnt += 1;
53 | }
54 | }
55 |
56 | // no children
57 | if (allChildrenCnt == 0)
58 | {
59 | return node;
60 | }
61 |
62 | var prevIdx = _skipCnt;
63 | _skipCnt = allChildrenCnt - 1;
64 | GreenNode result;
65 | if (node.IsList)
66 | {
67 | result = VisitList(new InternalSyntax.SyntaxList(node)).Node;
68 | }
69 | else
70 | {
71 | result = base.Visit(node);
72 | }
73 |
74 | _skipCnt = prevIdx;
75 | return result;
76 | }
77 | else
78 | {
79 | return base.Visit(node);
80 | }
81 | }
82 |
83 | public override SyntaxToken.Green VisitSyntaxToken(SyntaxToken.Green token)
84 | {
85 | return _newItem(token);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/Utilities/Normalization.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace Microsoft.Language.Xml.Utilities
4 | {
5 | public static class Normalization
6 | {
7 | ///
8 | /// Get normalized value
9 | ///
10 | /// to normalize.
11 | ///
12 | /// Normalization specs:
13 | /// 2.2.12 [XML] Section 3.3.3
14 | /// 2.11 [XML} End-of-Line Handling
15 | ///
16 | public static string GetNormalizedAttributeValue(this string value) =>
17 | GetNormalizedAttributeValue(new StringBuilder(value));
18 |
19 | internal static string GetNormalizedAttributeValue(StringBuilder inputBuffer)
20 | {
21 | var outputBuffer = PooledStringBuilder.GetInstance();
22 | NormalizeAttributeValueTo(inputBuffer, outputBuffer);
23 | return outputBuffer.ToStringAndFree();
24 | }
25 |
26 | internal static string GetNormalizedAttributeValue(this SyntaxNode node)
27 | {
28 | var inputBuffer = PooledStringBuilder.GetInstance();
29 | var writer = new System.IO.StringWriter(inputBuffer.Builder, System.Globalization.CultureInfo.InvariantCulture);
30 | node.WriteTo(writer);
31 | var outputBuffer = PooledStringBuilder.GetInstance();
32 | inputBuffer.Builder.NormalizeAttributeValueTo(outputBuffer);
33 | inputBuffer.Free();
34 | return outputBuffer.ToStringAndFree();
35 | }
36 |
37 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
38 | private static void NormalizeAttributeValueTo(this StringBuilder inputBuffer, PooledStringBuilder outputBuffer)
39 | {
40 | var inputBufferLength = inputBuffer.Length;
41 | char lastChar = default;
42 | for (int charIndex = 0; charIndex < inputBufferLength; charIndex++)
43 | {
44 | var c = inputBuffer[charIndex];
45 | switch (c)
46 | {
47 | // If there is a sequence of CR and LF or CR 0x85 or CR 0x2028 replace them with a space (0x32)
48 | case '\r' when (charIndex + 1 < inputBufferLength && (inputBuffer[charIndex + 1] is '\n' or '\x85' or '\x2028')):
49 | outputBuffer.Builder.Append(' ');
50 | charIndex++; // Skip next onece
51 | break;
52 | // If current char is single CR or 0x85 or 0x2028 replace with a space(0x32)
53 | case '\r':
54 | case '\x85':
55 | case '\x2000':
56 | outputBuffer.Builder.Append(' ');
57 | break;
58 | // if current char is LF and previus not is LF or CR
59 | case '\n' when lastChar != '\n' && lastChar != '\r':
60 | outputBuffer.Builder.Append(' ');
61 | break;
62 | case '\t':
63 | outputBuffer.Builder.Append(' ');
64 | break;
65 | default:
66 | outputBuffer.Builder.Append(c);
67 | break;
68 | }
69 | lastChar = c;
70 | }
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/src/Microsoft.Language.Xml/XmlExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Microsoft.Language.Xml
5 | {
6 | public static class XmlExtensions
7 | {
8 | ///
9 | /// Returns the text content of a element node
10 | ///
11 | ///
12 | /// In addition to the straightforward case
13 | /// of an element containing simple text tokens, this
14 | /// method also check for embedded CDATA sections
15 | ///
16 | public static string GetContentValue(this IXmlElementSyntax element)
17 | {
18 | if (element.Content.Count == 1 && element.Content.First() is XmlCDataSectionSyntax cdata)
19 | return cdata.TextTokens.ToFullString();
20 | return element.AsElement.Value;
21 | }
22 |
23 | ///
24 | /// Return a new instance with
25 | /// the supplied string prefix.
26 | ///
27 | public static IXmlElementSyntax WithPrefixName(this IXmlElementSyntax element, string prefixName)
28 | {
29 | var existingName = element.NameNode;
30 | var existingPrefix = existingName.PrefixNode;
31 | var newName = SyntaxFactory.XmlNameToken(prefixName, null, null);
32 |
33 | return element.WithName(existingName.WithPrefix(existingPrefix.WithName(newName)));
34 | }
35 |
36 | ///
37 | /// Return a new instance with
38 | /// the supplied string attribute value
39 | ///
40 | public static XmlAttributeSyntax WithValue(this XmlAttributeSyntax attribute, string attributeValue)
41 | {
42 | var textTokens = SyntaxFactory.SingletonList(SyntaxFactory.XmlTextLiteralToken(attributeValue, null, null));
43 | return attribute.WithValue(attribute.ValueNode.WithTextTokens(textTokens));
44 | }
45 |
46 | public static XmlAttributeSyntax WithPrefixName(this XmlAttributeSyntax attribute, string prefixName)
47 | {
48 | var existingName = attribute.NameNode;
49 | var existingPrefix = existingName.PrefixNode;
50 | var newName = SyntaxFactory.XmlNameToken(prefixName, null, null);
51 |
52 | return attribute.WithName(existingName.WithPrefix(existingPrefix.WithName(newName)));
53 | }
54 |
55 | public static XmlAttributeSyntax WithLocalName(this XmlAttributeSyntax attribute, string localName)
56 | {
57 | var existingName = attribute.NameNode;
58 | var existingLocalName = existingName.LocalNameNode;
59 | var newName = SyntaxFactory.XmlNameToken(localName, null, null);
60 |
61 | return attribute.WithName(existingName.WithLocalName(newName));
62 | }
63 |
64 | public static IXmlElementSyntax AddChild(this IXmlElementSyntax parent, IXmlElementSyntax child)
65 | {
66 | return parent.WithContent(parent.Content.Add(child.AsNode));
67 | }
68 |
69 | public static IXmlElementSyntax InsertChild(this IXmlElementSyntax parent, IXmlElementSyntax child, int index)
70 | {
71 | if (index == -1)
72 | return AddChild(parent, child);
73 | return parent.WithContent(parent.Content.Insert(index, child.AsNode));
74 | }
75 |
76 | public static IXmlElementSyntax RemoveChild(this IXmlElementSyntax parent, IXmlElementSyntax child)
77 | {
78 | return parent.WithContent(parent.Content.Remove(child.AsNode));
79 | }
80 |
81 | internal static bool IsXmlNodeName(this XmlNameSyntax name)
82 | {
83 | var p = name.Parent;
84 | switch (p.Kind)
85 | {
86 | case SyntaxKind.XmlElement:
87 | case SyntaxKind.XmlEmptyElement:
88 | case SyntaxKind.XmlElementStartTag:
89 | case SyntaxKind.XmlElementEndTag:
90 | return true;
91 | default: return false;
92 | }
93 | }
94 |
95 | public static IXmlElementSyntax AddAttributes(this IXmlElementSyntax self, params XmlAttributeSyntax[] attributes)
96 | {
97 | return self.WithAttributes(self.AttributesNode.AddRange(attributes));
98 | }
99 |
100 | public static IXmlElementSyntax AddAttributes(this IXmlElementSyntax self, IEnumerable attributes)
101 | {
102 | return self.WithAttributes(self.AttributesNode.AddRange(attributes));
103 | }
104 |
105 | public static IXmlElementSyntax AddAttribute(this IXmlElementSyntax self, XmlAttributeSyntax attribute)
106 | {
107 | return self.WithAttributes(self.AttributesNode.Add(attribute));
108 | }
109 |
110 | public static IXmlElementSyntax RemoveAttribute(this IXmlElementSyntax self, XmlAttributeSyntax attribute)
111 | {
112 | return self.WithAttributes(self.AttributesNode.Remove(attribute));
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Editor.Tests/Microsoft.Language.Xml.Editor.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Microsoft.Language.Xml.Editor.Tests
4 | net472
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Editor.Tests/SyntaxReplacerTests.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Xunit;
3 |
4 | namespace Microsoft.Language.Xml.Test
5 | {
6 | public class SyntaxReplacerTests
7 | {
8 | [Fact]
9 | public void TestReplaceNode()
10 | {
11 | var original = @"
12 |
13 |
14 | net8.0
15 |
16 |
17 | ";
18 |
19 | var expected = @"
20 |
21 |
22 | net9.0
23 |
24 |
25 | ";
26 |
27 | XmlDocumentSyntax root = Parser.ParseText(original);
28 | XmlElementSyntax syntaxToReplace = root
29 | .Descendants()
30 | .OfType()
31 | .Single(n => n.Name == "TargetFramework");
32 | SyntaxNode textSyntaxToReplace = syntaxToReplace.Content.Single();
33 |
34 | XmlTextSyntax content = SyntaxFactory.XmlText(SyntaxFactory.XmlTextLiteralToken("net9.0", null, null));
35 |
36 | root = root.ReplaceNode(textSyntaxToReplace, content);
37 |
38 | Assert.Equal(expected, root.ToFullString());
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Editor.Tests/TestSmartIndent.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Language.Xml.Editor;
2 | using Xunit;
3 |
4 | namespace Microsoft.Language.Xml.Test
5 | {
6 | public class TestSmartIndent
7 | {
8 | [Fact]
9 | public void TestIndent1()
10 | {
11 | T(@"
12 | |
13 | ");
14 | T(@"
15 | |
16 |
17 | ");
18 | T(@"
19 |
20 | |
21 |
22 | ");
23 | T(@"
24 |
25 |
26 | |
27 |
28 |
29 | ");
30 | T(@"
31 | |
32 |
33 |
34 | ");
35 | T(@"
36 |
37 | |
38 | ");
39 | }
40 |
41 | [Fact]
42 | public void TestIndent2()
43 | {
44 | T(@"
45 |
46 | |
47 | ");
48 | }
49 |
50 | [Fact]
51 | public void TestIndent3()
52 | {
53 | T(@"
54 | |");
55 | T(@"
56 |
57 | |
58 | ");
59 | T(@"
60 |
61 |
62 | |");
63 | }
64 |
65 | private void T(string xmlWithCaret)
66 | {
67 | int caret = xmlWithCaret.IndexOf('|');
68 | int expectedIndent = 0;
69 | while (caret - expectedIndent > 1 && xmlWithCaret[caret - expectedIndent - 1] == ' ')
70 | {
71 | expectedIndent++;
72 | }
73 |
74 | var xml = xmlWithCaret.Remove(caret, 1);
75 | var root = Parser.ParseText(xml);
76 | var actualIndent = SmartIndent.FindTotalParentChainIndent(root, caret, 0, 0);
77 | Assert.Equal(expectedIndent, actualIndent);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Tests/Microsoft.Language.Xml.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Microsoft.Language.Xml.Tests
4 | net472
5 | $([MSBuild]::IsOSPlatform('Windows'))
6 |
7 |
8 | True
9 | ..\..\key.snk
10 | False
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::GetDirectoryName('$(XunitConsolePath)'))
31 |
32 |
33 |
34 | Always
35 | False
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Tests/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Microsoft.Language.Xml.Tests.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Language.Xml.Tests.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>
65 | ///<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
66 | /// <metadata>
67 | /// <id>Microsoft.Language.Xml.Editor</id>
68 | /// <summary>A simple XML language service for the Visual Studio editor</summary>
69 | /// <description>
70 | /// Currently includes a classifier, outlining and smart indent.
71 | /// </description>
72 | /// <dependencies>
73 | /// <!-- dependency --><!-- adjacent comment -->
74 | /// <dependency id="Microsoft.Language.Xml" version="$currentVersion$" / [rest of string was truncated]";.
75 | ///
76 | internal static string TestXml {
77 | get {
78 | return ResourceManager.GetString("TestXml", resourceCulture);
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Tests/TestAnnotations.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 |
4 | namespace Microsoft.Language.Xml.Tests
5 | {
6 | public class TestAnnotations
7 | {
8 | private static readonly SyntaxAnnotation annotation = new SyntaxAnnotation("test");
9 |
10 | [Fact]
11 | public void AddingContentToElementPreservesAnnotations()
12 | {
13 | var root = GetRootElementSyntax("");
14 | var child = Parser.ParseText("").RootSyntax;
15 |
16 | AssertAnnotation(root.AddChild(child));
17 | }
18 |
19 | [Fact]
20 | public void AddingChildToEmptyElementPreservesAnnotations()
21 | {
22 | var root = GetRootEmptyElementSyntax("");
23 | var child = Parser.ParseText("").RootSyntax;
24 |
25 | AssertAnnotation(root.AddChild(child));
26 | }
27 |
28 | [Fact]
29 | public void AddingElementTriviaPreservesAnnotations()
30 | {
31 | var root = GetRootElementSyntax("");
32 | var trivia = SyntaxFactory.WhitespaceTrivia(" ");
33 |
34 | AssertAnnotation(root.WithLeadingTrivia(trivia));
35 | }
36 |
37 | [Fact]
38 | public void AddingEmptyElementTriviaPreservesAnnotations()
39 | {
40 | var root = GetRootEmptyElementSyntax("");
41 | var trivia = SyntaxFactory.WhitespaceTrivia(" ");
42 |
43 | AssertAnnotation(root.WithLeadingTrivia(trivia));
44 | }
45 |
46 | private static void AssertAnnotation(T element) where T : SyntaxNode
47 | {
48 | Assert.True(element.ContainsAnnotations);
49 | element.HasAnnotation(annotation);
50 | }
51 |
52 | private static void AssertAnnotation(IXmlElementSyntax element)
53 | {
54 | AssertAnnotation((SyntaxNode)element);
55 | }
56 |
57 | private static XmlElementSyntax GetRootElementSyntax(string xml)
58 | {
59 | return Assert.IsType(Parser.ParseText(xml).RootSyntax)
60 | .WithAdditionalAnnotations(annotation);
61 | }
62 |
63 | private static XmlEmptyElementSyntax GetRootEmptyElementSyntax(string xml)
64 | {
65 | return Assert.IsType(Parser.ParseText(xml).RootSyntax)
66 | .WithAdditionalAnnotations(annotation);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Tests/TestApi.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Xunit;
3 |
4 | namespace Microsoft.Language.Xml.Tests
5 | {
6 | public class TestApi
7 | {
8 | [Fact]
9 | public void TestAttributeValue()
10 | {
11 | var root = Parser.ParseText("")?.RootSyntax;
12 | var attributeValue = root.Attributes.First().Value;
13 | Assert.Equal("", attributeValue);
14 | }
15 |
16 | ///
17 | /// 2.2.12 [XML] Section 3.3.3, Attribute-Value Normalization
18 | ///
19 | ///
20 | [Fact]
21 | public void TestAttributeValueNormalization()
22 | {
23 | const string AllWhitespace = " \n\t";
24 | var xml = $"";
25 | var root = Parser.ParseText(xml)?.RootSyntax;
26 |
27 | var attributeValue = root.Attributes.First().Value;
28 | Assert.Equal(" X ", attributeValue);
29 | }
30 |
31 | [Fact]
32 | public void TestContent()
33 | {
34 | var root = Parser.ParseText("Content")?.Root;
35 | var value = root.Value;
36 | Assert.Equal("Content", value);
37 | }
38 |
39 | [Fact]
40 | public void TestRootLevel()
41 | {
42 | var root = Parser.ParseText("")?.Root;
43 | Assert.Equal("Root", root.Name);
44 | }
45 |
46 | [Fact]
47 | public void TestRootLevelTrivia()
48 | {
49 | var root = Parser.ParseText("")?.Root;
50 | Assert.Equal("Root", root.Name);
51 | }
52 |
53 | [Fact]
54 | public void TestRootLevelTriviaWithDeclaration()
55 | {
56 | var root = Parser.ParseText("")?.Root;
57 | Assert.Equal("Root", root.Name);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/test/Microsoft.Language.Xml.Tests/TestComments.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Microsoft.Language.Xml.Comments;
4 | using Microsoft.Language.Xml.Tests.Properties;
5 | using Xunit;
6 |
7 | namespace Microsoft.Language.Xml.Tests
8 | {
9 | public class TestComments
10 | {
11 | [Fact]
12 | public void CommentElementContent()
13 | {
14 | TC(Resources.TestXml, TextSpan.FromBounds(199, 209),
15 | TextSpan.FromBounds(199, 209));
16 |
17 | // Test at edges xml element content
18 | TC(Resources.TestXml, TextSpan.FromBounds(276, 350),
19 | TextSpan.FromBounds(276, 350));
20 | }
21 |
22 | [Fact]
23 | public void CommentSingleCharacter()
24 | {
25 | TC(Resources.TestXml, TextSpan.FromBounds(722, 723),
26 | TextSpan.FromBounds(722, 723));
27 | }
28 |
29 | [Fact]
30 | public void CommentExpandsExcludingElementWhitespace()
31 | {
32 | TC(Resources.TestXml, TextSpan.FromBounds(451, 453),
33 | TextSpan.FromBounds(444, 513));
34 | }
35 |
36 | [Fact]
37 | public void CommentMultipleElements()
38 | {
39 | TC(Resources.TestXml, TextSpan.FromBounds(753, 912),
40 | TextSpan.FromBounds(740, 919));
41 |
42 | TC(Resources.TestXml, TextSpan.FromBounds(823, 911),
43 | TextSpan.FromBounds(818, 919));
44 | }
45 |
46 | [Fact]
47 | public void CommentDeclaration()
48 | {
49 | TC(Resources.TestXml, TextSpan.FromBounds(22, 25),
50 | TextSpan.FromBounds(0, 39));
51 | }
52 |
53 | [Fact]
54 | public void CommentedDeclaration()
55 | {
56 | TU(Resources.TestXml.Insert(39, "-->").Insert(0, "
11 |
12 |
13 |
14 |
15 | en-US
16 | false
17 | $currentVersion$
18 | Microsoft
19 | http://www.apache.org/licenses/LICENSE-2.0.html
20 | http://github.com/KirillOsenkov/XmlParser
21 |
22 |
23 |
24 | Xml LanguageService Classifier VS VisualStudio Editor
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "1.2",
4 | "assemblyVersion": "1.0",
5 | "buildNumberOffset": 0,
6 | "publicReleaseRefSpec": [
7 | "^refs/heads/main$", // we release out of master
8 | "^refs/heads/v\\d+(?:.\\d+)?$" // we also release out of vNN branches
9 | ],
10 | "cloudBuild": {
11 | "setVersionVariables": true,
12 | "buildNumber": {
13 | "enabled": true,
14 | "includeCommitId": {
15 | "when": "always",
16 | "where": "buildMetadata"
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------