Last active
January 17, 2022 01:03
-
-
Save bondsbw/6d76260ab00b4cc34b2b2f2091b782ae to your computer and use it in GitHub Desktop.
C# without semicolons or braces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | |
#light | |
namespace Microsoft.CodeAnalysis.CSharp | |
using System | |
using System.Collections.Generic | |
using System.Collections.Immutable | |
using System.Diagnostics | |
using System.Text | |
using System.Threading | |
using System.Threading.Tasks | |
using Microsoft.CodeAnalysis.CSharp.Syntax | |
using Microsoft.CodeAnalysis.Text | |
using Roslyn.Utilities | |
using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax | |
public abstract partial class CSharpSyntaxTree : SyntaxTree | |
internal static readonly SyntaxTree Dummy = new DummySyntaxTree() | |
public new abstract CSharpParseOptions Options { get } | |
protected T CloneNodeAsRoot<T>(T node) where T : CSharpSyntaxNode => | |
CSharpSyntaxNode.CloneNodeAsRoot(node, this) | |
public new abstract CSharpSyntaxNode GetRoot(CancellationToken cancellationToken = default(CancellationToken)) | |
public abstract bool TryGetRoot(out CSharpSyntaxNode root) | |
public new virtual Task<CSharpSyntaxNode> GetRootAsync(CancellationToken cancellationToken = default(CancellationToken)) | |
CSharpSyntaxNode node | |
return Task.FromResult(this.TryGetRoot(out node) ? node : this.GetRoot(cancellationToken)) | |
public CompilationUnitSyntax GetCompilationUnitRoot(CancellationToken cancellationToken = default(CancellationToken)) => | |
(CompilationUnitSyntax)this.GetRoot(cancellationToken) | |
public override bool IsEquivalentTo(SyntaxTree tree, bool topLevel = false) => | |
SyntaxFactory.AreEquivalent(this, tree, topLevel) | |
internal bool HasReferenceDirectives | |
get | |
Debug.Assert(HasCompilationUnitRoot) | |
return Options.Kind == SourceCodeKind.Script && GetCompilationUnitRoot().GetReferenceDirectives().Count > 0 | |
internal bool HasReferenceOrLoadDirectives | |
get | |
Debug.Assert(HasCompilationUnitRoot) | |
if (Options.Kind == SourceCodeKind.Script) | |
var compilationUnitRoot = GetCompilationUnitRoot() | |
return compilationUnitRoot.GetReferenceDirectives().Count > 0 || compilationUnitRoot.GetLoadDirectives().Count > 0 | |
return false | |
private bool _hasDirectives | |
private InternalSyntax.DirectiveStack _directives | |
internal void SetDirectiveStack(InternalSyntax.DirectiveStack directives) | |
_directives = directives | |
_hasDirectives = true | |
private InternalSyntax.DirectiveStack GetDirectives() | |
if (!_hasDirectives) | |
var stack = this.GetRoot().CsGreen.ApplyDirectives(default(InternalSyntax.DirectiveStack)) | |
SetDirectiveStack(stack) | |
return _directives | |
internal bool IsAnyPreprocessorSymbolDefined(ImmutableArray<string> conditionalSymbols) | |
Debug.Assert(conditionalSymbols != null) | |
foreach (string conditionalSymbol in conditionalSymbols) | |
if (IsPreprocessorSymbolDefined(conditionalSymbol)) | |
return true | |
return false | |
internal bool IsPreprocessorSymbolDefined(string symbolName) => | |
IsPreprocessorSymbolDefined(GetDirectives(), symbolName) | |
private bool IsPreprocessorSymbolDefined(InternalSyntax.DirectiveStack directives, string symbolName) | |
switch (directives.IsDefined(symbolName)) | |
case InternalSyntax.DefineState.Defined: | |
return true | |
case InternalSyntax.DefineState.Undefined: | |
return false | |
default: | |
return this.Options.PreprocessorSymbols.Contains(symbolName) | |
private ImmutableArray<int> _preprocessorStateChangePositions | |
private ImmutableArray<InternalSyntax.DirectiveStack> _preprocessorStates | |
internal bool IsPreprocessorSymbolDefined(string symbolName, int position) | |
if (_preprocessorStateChangePositions.IsDefault) | |
BuildPreprocessorStateChangeMap() | |
int searchResult = _preprocessorStateChangePositions.BinarySearch(position) | |
InternalSyntax.DirectiveStack directives | |
if (searchResult < 0) | |
searchResult = (~searchResult) - 1 | |
if (searchResult >= 0) | |
directives = _preprocessorStates[searchResult] | |
else | |
directives = InternalSyntax.DirectiveStack.Empty | |
else | |
directives = _preprocessorStates[searchResult] | |
return IsPreprocessorSymbolDefined(directives, symbolName) | |
private void BuildPreprocessorStateChangeMap() | |
InternalSyntax.DirectiveStack currentState = InternalSyntax.DirectiveStack.Empty | |
var positions = ArrayBuilder<int>.GetInstance() | |
var states = ArrayBuilder<InternalSyntax.DirectiveStack>.GetInstance() | |
foreach (DirectiveTriviaSyntax directive in this.GetRoot().GetDirectives(d => | |
switch (d.Kind()) | |
case SyntaxKind.IfDirectiveTrivia: | |
case SyntaxKind.ElifDirectiveTrivia: | |
case SyntaxKind.ElseDirectiveTrivia: | |
case SyntaxKind.EndIfDirectiveTrivia: | |
case SyntaxKind.DefineDirectiveTrivia: | |
case SyntaxKind.UndefDirectiveTrivia: | |
return true | |
default: | |
return false | |
)) | |
currentState = directive.ApplyDirectives(currentState) | |
switch (directive.Kind()) | |
case SyntaxKind.IfDirectiveTrivia: | |
break | |
case SyntaxKind.ElifDirectiveTrivia: | |
states.Add(currentState) | |
positions.Add(((ElifDirectiveTriviaSyntax)directive).ElifKeyword.SpanStart) | |
break | |
case SyntaxKind.ElseDirectiveTrivia: | |
states.Add(currentState) | |
positions.Add(((ElseDirectiveTriviaSyntax)directive).ElseKeyword.SpanStart) | |
break | |
case SyntaxKind.EndIfDirectiveTrivia: | |
states.Add(currentState) | |
positions.Add(((EndIfDirectiveTriviaSyntax)directive).EndIfKeyword.SpanStart) | |
break | |
case SyntaxKind.DefineDirectiveTrivia: | |
states.Add(currentState) | |
positions.Add(((DefineDirectiveTriviaSyntax)directive).Name.SpanStart) | |
break | |
case SyntaxKind.UndefDirectiveTrivia: | |
states.Add(currentState) | |
positions.Add(((UndefDirectiveTriviaSyntax)directive).Name.SpanStart) | |
break | |
default: | |
throw ExceptionUtilities.UnexpectedValue(directive.Kind()) | |
#if DEBUG | |
int currentPos = -1 | |
foreach (int pos in positions) | |
Debug.Assert(currentPos < pos) | |
currentPos = pos | |
#endif | |
ImmutableInterlocked.InterlockedInitialize(ref _preprocessorStates, states.ToImmutableAndFree()) | |
ImmutableInterlocked.InterlockedInitialize(ref _preprocessorStateChangePositions, positions.ToImmutableAndFree()) | |
public static SyntaxTree Create(CSharpSyntaxNode root, CSharpParseOptions options = null, string path = "", Encoding encoding = null) | |
if (root == null) | |
throw new ArgumentNullException(nameof(root)) | |
var directives = root.Kind() == SyntaxKind.CompilationUnit ? | |
((CompilationUnitSyntax)root).GetConditionalDirectivesStack() : | |
InternalSyntax.DirectiveStack.Empty | |
return new ParsedSyntaxTree( | |
textOpt: null, | |
encodingOpt: encoding, | |
checksumAlgorithm: SourceHashAlgorithm.Sha1, | |
path: path, | |
options: options ?? CSharpParseOptions.Default, | |
root: root, | |
directives: directives) | |
internal static SyntaxTree CreateForDebugger(CSharpSyntaxNode root, SourceText text) | |
Debug.Assert(root != null) | |
return new DebuggerSyntaxTree(root, text) | |
internal static SyntaxTree CreateWithoutClone(CSharpSyntaxNode root) | |
Debug.Assert(root != null) | |
return new ParsedSyntaxTree( | |
textOpt: null, | |
encodingOpt: null, | |
checksumAlgorithm: SourceHashAlgorithm.Sha1, | |
path: "", | |
options: CSharpParseOptions.Default, | |
root: root, | |
directives: InternalSyntax.DirectiveStack.Empty, | |
cloneRoot: false) | |
public static SyntaxTree ParseText( | |
string text, | |
CSharpParseOptions options = null, | |
string path = "", | |
Encoding encoding = null, | |
CancellationToken cancellationToken = default(CancellationToken)) | |
return ParseText(SourceText.From(text, encoding), options, path, cancellationToken) | |
public static SyntaxTree ParseText( | |
SourceText text, | |
CSharpParseOptions options = null, | |
string path = "", | |
CancellationToken cancellationToken = default(CancellationToken)) | |
if (text == null) | |
throw new ArgumentNullException(nameof(text)) | |
options = options ?? CSharpParseOptions.Default | |
using (var lexer = new InternalSyntax.Lexer(text, options)) | |
using (var parser = new InternalSyntax.LanguageParser(lexer, oldTree: null, changes: null, cancellationToken: cancellationToken)) | |
var compilationUnit = (CompilationUnitSyntax)parser.ParseCompilationUnit().CreateRed() | |
var tree = new ParsedSyntaxTree(text, text.Encoding, text.ChecksumAlgorithm, path, options, compilationUnit, parser.Directives) | |
tree.VerifySource() | |
return tree | |
public override SyntaxTree WithChangedText(SourceText newText) | |
SourceText oldText | |
if (this.TryGetText(out oldText)) | |
var changes = newText.GetChangeRanges(oldText) | |
if (changes.Count == 0 && newText == oldText) | |
return this | |
return this.WithChanges(newText, changes) | |
return this.WithChanges(newText, new[] { new TextChangeRange(new TextSpan(0, this.Length), newText.Length) }) | |
private SyntaxTree WithChanges(SourceText newText, IReadOnlyList<TextChangeRange> changes) | |
if (changes == null) | |
throw new ArgumentNullException(nameof(changes)) | |
var oldTree = this | |
if (changes.Count == 1 && changes[0].Span == new TextSpan(0, this.Length) && changes[0].NewLength == newText.Length) | |
changes = null | |
oldTree = null | |
using (var lexer = new InternalSyntax.Lexer(newText, this.Options)) | |
using (var parser = new InternalSyntax.LanguageParser(lexer, oldTree?.GetRoot(), changes)) | |
var compilationUnit = (CompilationUnitSyntax)parser.ParseCompilationUnit().CreateRed() | |
var tree = new ParsedSyntaxTree(newText, newText.Encoding, newText.ChecksumAlgorithm, this.FilePath, this.Options, compilationUnit, parser.Directives) | |
tree.VerifySource(changes) | |
return tree | |
public override IList<TextSpan> GetChangedSpans(SyntaxTree oldTree) | |
if (oldTree == null) | |
throw new ArgumentNullException(nameof(oldTree)) | |
return SyntaxDiffer.GetPossiblyDifferentTextSpans(oldTree, this) | |
public override IList<TextChange> GetChanges(SyntaxTree oldTree) | |
if (oldTree == null) | |
throw new ArgumentNullException(nameof(oldTree)) | |
return SyntaxDiffer.GetTextChanges(oldTree, this) | |
public override FileLinePositionSpan GetLineSpan(TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) | |
return new FileLinePositionSpan(this.FilePath, GetLinePosition(span.Start), GetLinePosition(span.End)) | |
public override FileLinePositionSpan GetMappedLineSpan(TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) | |
if (_lazyLineDirectiveMap == null) | |
Interlocked.CompareExchange(ref _lazyLineDirectiveMap, new CSharpLineDirectiveMap(this), null) | |
return _lazyLineDirectiveMap.TranslateSpan(this.GetText(cancellationToken), this.FilePath, span) | |
public override LineVisibility GetLineVisibility(int position, CancellationToken cancellationToken = default(CancellationToken)) | |
if (_lazyLineDirectiveMap == null) | |
Interlocked.CompareExchange(ref _lazyLineDirectiveMap, new CSharpLineDirectiveMap(this), null) | |
return _lazyLineDirectiveMap.GetLineVisibility(this.GetText(cancellationToken), position) | |
internal override FileLinePositionSpan GetMappedLineSpanAndVisibility(TextSpan span, out bool isHiddenPosition) | |
if (_lazyLineDirectiveMap == null) | |
Interlocked.CompareExchange(ref _lazyLineDirectiveMap, new CSharpLineDirectiveMap(this), null) | |
return _lazyLineDirectiveMap.TranslateSpanAndVisibility(this.GetText(), this.FilePath, span, out isHiddenPosition) | |
public override bool HasHiddenRegions() | |
if (_lazyLineDirectiveMap == null) | |
Interlocked.CompareExchange(ref _lazyLineDirectiveMap, new CSharpLineDirectiveMap(this), null) | |
return _lazyLineDirectiveMap.HasAnyHiddenRegions() | |
internal ReportDiagnostic GetPragmaDirectiveWarningState(string id, int position) | |
if (_lazyPragmaWarningStateMap == null) | |
Interlocked.CompareExchange(ref _lazyPragmaWarningStateMap, new CSharpPragmaWarningStateMap(this), null) | |
return _lazyPragmaWarningStateMap.GetWarningState(id, position) | |
private CSharpLineDirectiveMap _lazyLineDirectiveMap | |
private CSharpPragmaWarningStateMap _lazyPragmaWarningStateMap | |
private LinePosition GetLinePosition(int position) => | |
this.GetText().Lines.GetLinePosition(position) | |
public override Location GetLocation(TextSpan span) => | |
new SourceLocation(this, span) | |
public override IEnumerable<Diagnostic> GetDiagnostics(SyntaxNode node) | |
if (node == null) | |
throw new ArgumentNullException(nameof(node)) | |
return GetDiagnostics(node.Green, node.Position) | |
private IEnumerable<Diagnostic> GetDiagnostics(GreenNode greenNode, int position) | |
if (greenNode == null) | |
throw new InvalidOperationException() | |
if (greenNode.ContainsDiagnostics) | |
return EnumerateDiagnostics(greenNode, position) | |
return SpecializedCollections.EmptyEnumerable<Diagnostic>() | |
private IEnumerable<Diagnostic> EnumerateDiagnostics(GreenNode node, int position) | |
var enumerator = new SyntaxTreeDiagnosticEnumerator(this, node, position) | |
while (enumerator.MoveNext()) | |
yield return enumerator.Current | |
public override IEnumerable<Diagnostic> GetDiagnostics(SyntaxToken token) => | |
GetDiagnostics(token.Node, token.Position) | |
public override IEnumerable<Diagnostic> GetDiagnostics(SyntaxTrivia trivia) => | |
GetDiagnostics(trivia.UnderlyingNode, trivia.Position) | |
public override IEnumerable<Diagnostic> GetDiagnostics(SyntaxNodeOrToken nodeOrToken) => | |
GetDiagnostics(nodeOrToken.UnderlyingNode, nodeOrToken.Position) | |
public override IEnumerable<Diagnostic> GetDiagnostics(CancellationToken cancellationToken = default(CancellationToken)) => | |
this.GetDiagnostics(this.GetRoot(cancellationToken)) | |
protected override SyntaxNode GetRootCore(CancellationToken cancellationToken) => | |
this.GetRoot(cancellationToken) | |
protected override async Task<SyntaxNode> GetRootAsyncCore(CancellationToken cancellationToken) => | |
await this.GetRootAsync(cancellationToken).ConfigureAwait(false) | |
protected override bool TryGetRootCore(out SyntaxNode root) | |
CSharpSyntaxNode node | |
if (this.TryGetRoot(out node)) | |
root = node | |
return true | |
else | |
root = null | |
return false | |
protected override ParseOptions OptionsCore => | |
this.Options |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
wow