Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created April 12, 2018 20:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save praeclarum/79470aa146f3fccadff0ac4cc7c89fa2 to your computer and use it in GitHub Desktop.
Save praeclarum/79470aa146f3fccadff0ac4cc7c89fa2 to your computer and use it in GitHub Desktop.
Formats C# code using roslyn syntax and semantics
let getRefInfo (x : SyntaxNode) (ident : SyntaxToken) (isO : bool) =
let si = semantics.GetSymbolInfo (x)
if si.Symbol <> null then
Some (ident, si.Symbol, true, isO)
else None
let getDefInfo (x : SyntaxNode) (ident : SyntaxToken) (isO : bool) =
let s = semantics.GetDeclaredSymbol (x)
if s <> null then
Some (ident, s, false, isO)
else None
let f : uint16[] = Array.zeroCreate text.Length
let rec paintNode (x : SyntaxNode) =
cancellationToken.ThrowIfCancellationRequested ()
// printfn "PAINT NODE %O" (x.GetType())
for c in x.ChildNodesAndTokens() do
if c.IsToken then paintToken (c.AsToken())
else paintNode (c.AsNode())
let tkos =
let refInfo =
match x with
| :? CSharp.Syntax.IdentifierNameSyntax as y ->
//printfn "IDENT `%O` (%O) (%O)" x.Identifier s k
getRefInfo x y.Identifier false
| :? CSharp.Syntax.GenericNameSyntax as y ->
//printfn "IDENT `%O` (%O) (%O)" x.Identifier s k
getRefInfo x y.Identifier false
| :? CSharp.Syntax.PredefinedTypeSyntax as y ->
getRefInfo x y.Keyword false
| :? CSharp.Syntax.BinaryExpressionSyntax as y ->
getRefInfo x y.OperatorToken false
| :? CSharp.Syntax.PostfixUnaryExpressionSyntax as y ->
getRefInfo x y.OperatorToken false
| :? CSharp.Syntax.PrefixUnaryExpressionSyntax as y ->
getRefInfo x y.OperatorToken false
| _ ->
//Debug.WriteLine (sprintf "SYM `%O` (%O)" x (x.GetType()))
None
if Option.isSome refInfo then refInfo
else
match x with
| :? CSharp.Syntax.ClassDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.StructDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.EnumDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.EnumMemberDeclarationSyntax as y ->
getDefInfo x y.Identifier true
| :? CSharp.Syntax.MethodDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.ConstructorDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.PropertyDeclarationSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.AccessorDeclarationSyntax as y ->
getDefInfo x y.Keyword false
| :? CSharp.Syntax.ParameterSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.VariableDeclaratorSyntax as y ->
getDefInfo x y.Identifier false
| :? CSharp.Syntax.TypeParameterSyntax as y ->
getDefInfo x y.Identifier false
| _ ->
//Debug.WriteLine (sprintf "DSYM `%O` (%O)" x (x.GetType()))
None
match tkos with
| None -> ()
| Some (t, k, r, ef) ->
let code = if t.Text = "var" then FormatCode.Keyword
else getFormatCodeForSymbol k r ef
paint t code
and paint (x : SyntaxToken) (code : FormatCode) =
let span = x.Span
// printfn "PAINT TOKEN %O %A %d %d" x kind i len
for i = span.Start to (span.End-1) do
f.[i] <- uint16 code
and paintToken (x : SyntaxToken) =
let kind : CSharp.SyntaxKind = LanguagePrimitives.EnumOfValue (uint16 x.RawKind)
// https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
let code =
match x.RawKind with
| 8508 ->
FormatCode.Identifier
| 8509 -> FormatCode.Number
| 8510 -> FormatCode.String // Char
| 8482 | 8483 | 8484 | 8517 -> FormatCode.String // Interpolated String
| 8511 -> FormatCode.String
| 8513 -> FormatCode.String // XML Text
| x when 8300 <= x && x <= 8485 -> FormatCode.Keyword
| _ ->
//let kind : CSharp.SyntaxKind = LanguagePrimitives.EnumOfValue (uint16 x.RawKind)
//printfn "BAD %A" kind
FormatCode.Punctuation
paint x code
for t in x.GetAllTrivia () do
let code =
match t.Kind() with
| SyntaxKind.MultiLineDocumentationCommentTrivia
| SyntaxKind.DocumentationCommentExteriorTrivia
| SyntaxKind.SingleLineDocumentationCommentTrivia ->
FormatCode.DocumentationComment
| SyntaxKind.MultiLineCommentTrivia
| SyntaxKind.SingleLineCommentTrivia ->
FormatCode.Comment
| SyntaxKind.RegionDirectiveTrivia
| SyntaxKind.EndRegionDirectiveTrivia
| SyntaxKind.PragmaWarningDirectiveTrivia
| SyntaxKind.PragmaChecksumDirectiveTrivia
| SyntaxKind.ErrorDirectiveTrivia
| SyntaxKind.IfDirectiveTrivia
| SyntaxKind.DefineDirectiveTrivia
| SyntaxKind.ElifDirectiveTrivia
| SyntaxKind.ElseDirectiveTrivia
| SyntaxKind.EndIfDirectiveTrivia ->
FormatCode.Preprocessor
| SyntaxKind.DisabledTextTrivia ->
FormatCode.DisabledCode
| kind ->
//printfn "BAD TRIVIA %A" kind
FormatCode.Text
if code <> FormatCode.Text then
let span = t.FullSpan
for i = span.Start to (span.End-1) do
f.[i] <- uint16 code
paintNode (syntax.GetRoot())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment