diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 90220d2..7f91f87 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -40,8 +40,8 @@ jobs: - name: Package Nightly Nuget 📦 run: | SUFFIX=`date "+%y%m%d%H%M%S"` - dotnet build src/CssInCSharp.csproj dotnet pack src/CssInCSharp.csproj /p:PackageVersion=$Version-nightly-${SUFFIX} -c Release -o publish + dotnet pack generators/CssInCSharp.CommandLine/CssInCSharp.CommandLine.csproj /p:PackageVersion=$Version-nightly-${SUFFIX} -c Release -o publish - name: Publish to Nuget ✔ run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 332ca5b..831ad1f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,6 @@ jobs: run: | VERSION=`git describe --tags` echo "Publishing Version: ${VERSION}" - dotnet build src/CssInCSharp.csproj dotnet pack src/CssInCSharp.csproj /p:PackageVersion=$VERSION -c Release -o publish + dotnet pack generators/CssInCSharp.CommandLine/CssInCSharp.CommandLine.csproj /p:PackageVersion=$VERSION -c Release -o publish dotnet nuget push publish/*.nupkg -s https://api.nuget.org/v3/index.json -k $NUGET_API_KEY --skip-duplicate diff --git a/README.md b/README.md index 9830650..f7852b1 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,11 @@ AMD Ryzen 7 5700G with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores | CreateCss | .NET 7.0 | .NET 7.0 | 50.61 μs | 0.999 μs | 2.062 μs | 0.87 | 0.05 | 17.6392 | 1.0376 | 144.42 KB | 0.96 | | CreateCss | .NET 8.0 | .NET 8.0 | 37.73 μs | 0.748 μs | 1.642 μs | 0.65 | 0.03 | 17.6392 | 0.9155 | 144.3 KB | 0.96 | + +## Special Thanks + +[cssinjs](https://github.com/ant-design/cssinjs): Component level cssinjs solution used in ant.design. +[stylis](https://github.com/thysultan/stylis): A Light–weight CSS Preprocessor. +[csstype](https://github.com/frenic/csstype): TypeScript and Flow definitions for CSS. +[tinycolor](https://github.com/scttcper/tinycolor): A small library for color manipulation and conversion. +[TypeScriptAST](https://github.com/ToCSharp/TypeScriptAST): .NET port of TypeScript parser. \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Change/ChangeAST.cs b/generators/CssInCSharp.Ast.TypeScript/Change/ChangeAST.cs new file mode 100644 index 0000000..6243122 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Change/ChangeAST.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.Change +{ + public class ChangeAST + { + private readonly ICollection _nodeChangeItems; + + public ChangeAST(ICollection changeItems = null) + { + _nodeChangeItems = changeItems ?? new List(); + } + + public static string Change(string source, IEnumerable changeItems) + { + var changes = changeItems.OrderBy(v => v.Node.Pos).ThenBy(v2 => v2.ChangeType); + var sb = new StringBuilder(); + var pos = 0; + foreach (var ch in changes) + { + if (ch.Node.Pos == null) throw new NullReferenceException("Node.Pos"); + switch (ch.ChangeType) + { + case NodeChangeType.InsertBefore: + if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos)); + sb.Append(ch.NewValue); + pos = (int) ch.Node.Pos; + break; + case NodeChangeType.Change: + if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos)); + sb.Append(ch.NewValue); + if (ch.Node.End != null) pos = (int) ch.Node.End; + else throw new NullReferenceException("Node.End"); + break; + case NodeChangeType.Delete: + if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos)); + if (ch.Node.End != null) pos = (int) ch.Node.End + 1; + break; + case NodeChangeType.InsertAfter: + if (ch.Node.End > pos) sb.Append(source.Substring(pos, (int) ch.Node.End - pos)); + sb.Append(ch.NewValue); + if (ch.Node.End != null) pos = (int) ch.Node.End; + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + if (pos < source.Length) sb.Append(source.Substring(pos)); + var newSource = sb.ToString(); + + return newSource; + } + + public string GetChangedSource(string baseSource) + { + return Change(baseSource, _nodeChangeItems); + } + + public void ChangeNode(INode node, string newValue) + { + if (_nodeChangeItems.Any(v => v.Node == node && + (v.ChangeType == NodeChangeType.Change || + v.ChangeType == NodeChangeType.Delete))) + throw new Exception("ChangeItems already have this node. Delete first"); + if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos)) + throw new Exception("ChangeItems already have node that contains this node. Delete first"); + + if (newValue != node.GetTextWithComments()) + { + var nodeCh = new NodeChangeItem {ChangeType = NodeChangeType.Change, Node = node, NewValue = newValue}; + _nodeChangeItems.Add(nodeCh); + } + else + { + throw new Exception("Same value"); + } + } + + public void InsertBefore(INode node, string newValue) + { + if (node != null) + { + //if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos)) + // throw new Exception("ChangeItems already have node that contains this node. Delete first"); + + var nodeCh = new NodeChangeItem + { + ChangeType = NodeChangeType.InsertBefore, + Node = node, + NewValue = newValue + }; + _nodeChangeItems.Add(nodeCh); + } + } + + public void InsertAfter(INode node, string newValue) + { + if (node != null) + { + //if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos)) + // throw new Exception("ChangeItems already have node that contains this node. Delete first"); + + var nodeCh = new NodeChangeItem + { + ChangeType = NodeChangeType.InsertAfter, + Node = node, + NewValue = newValue + }; + _nodeChangeItems.Add(nodeCh); + } + } + + public void Delete(INode node) + { + if (node != null) + { + if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos)) + throw new Exception("ChangeItems already have node that contains this node. Delete first"); + + var nodeCh = new NodeChangeItem {ChangeType = NodeChangeType.Delete, Node = node}; + _nodeChangeItems.Add(nodeCh); + } + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeItem.cs b/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeItem.cs new file mode 100644 index 0000000..232f86d --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeItem.cs @@ -0,0 +1,27 @@ +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.Change +{ + public class NodeChangeItem + { + public NodeChangeType ChangeType { get; set; } + + public INode Node { get; set; } + //public int Pos { get; set; } + + //public int End { get; set; } + public string NewValue { get; set; } + + private string NewValueSmall => NewValue == null + ? "" + : NewValue.Length > 20 + ? NewValue.Substring(0, 18) + $"..({NewValue.Length})" + : NewValue; + + public override string ToString() + { + if (ChangeType == NodeChangeType.Delete) return $"{ChangeType} {Node}."; + return $"{ChangeType} {Node}. NewValue = \"{NewValueSmall}\""; + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeType.cs b/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeType.cs new file mode 100644 index 0000000..49ba55b --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeType.cs @@ -0,0 +1,10 @@ +namespace Zu.TypeScript.Change +{ + public enum NodeChangeType + { + InsertBefore, + Change, + Delete, + InsertAfter + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/CssInCSharp.Ast.TypeScript.csproj b/generators/CssInCSharp.Ast.TypeScript/CssInCSharp.Ast.TypeScript.csproj new file mode 100644 index 0000000..125f4c9 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/CssInCSharp.Ast.TypeScript.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + enable + enable + + + diff --git a/generators/CssInCSharp.Ast.TypeScript/NOTICE.txt b/generators/CssInCSharp.Ast.TypeScript/NOTICE.txt new file mode 100644 index 0000000..6abe59d --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/NOTICE.txt @@ -0,0 +1 @@ +CssInCSharp.Ast.TypeScript is based TypeScriptAST project hosted on https://github.com/ToCSharp/TypeScriptAST distributed with Apache 2.0 license. diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Core.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Core.cs new file mode 100644 index 0000000..2b39ff2 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Core.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.TsParser +{ + public static class Core + { + // from core.ts + + public static int BinarySearch(int[] array, int value, Func comparer = null, int? offset = null) + { + if (array == null || array.Length == 0) + { + return -1; + } + var low = offset ?? 0; + var high = array.Length - 1; + comparer = comparer ?? ((v1, v2) => (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0))); + while (low <= high) + { + var middle = low + ((high - low) >> 1); + var midValue = array[middle]; + if (comparer(midValue, value) == 0) + { + return middle; + } + else + if (comparer(midValue, value) > 0) + { + high = middle - 1; + } + else + { + low = middle + 1; + } + } + return ~low; + } + public static bool PositionIsSynthesized(int pos) + { + // This is a fast way of testing the following conditions: + // pos == null || pos == null || isNaN(pos) || pos < 0; + return !(pos >= 0); + } + + public static ScriptKind EnsureScriptKind(string fileName, ScriptKind scriptKind) + { + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `null` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'null' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + var sk = scriptKind != ScriptKind.Unknown ? scriptKind : GetScriptKindFromFileName(fileName); + return sk != ScriptKind.Unknown ? sk : ScriptKind.Ts; + } + public static ScriptKind GetScriptKindFromFileName(string fileName) + { + //var ext = fileName.substr(fileName.LastIndexOf(".")); + var ext = Path.GetExtension(fileName); + switch (ext?.ToLower()) + { + case ".js": + return ScriptKind.Js; + case ".jsx": + return ScriptKind.Jsx; + case ".ts": + return ScriptKind.Ts; + case ".tsx": + return ScriptKind.Tsx; + default: + return ScriptKind.Unknown; + } + } + + public static string NormalizePath(string path) + { + path = NormalizeSlashes(path); + var rootLength = GetRootLength(path); + var root = path.Substring(0, rootLength); + var normalized = GetNormalizedParts(path, rootLength); + if (normalized.Any()) + { + var joinedParts = root + string.Join(DirectorySeparator.ToString(), normalized);//.join(directorySeparator); + return PathEndsWithDirectorySeparator(path) ? joinedParts + DirectorySeparator : joinedParts; + } + else + { + return root; + } + } + public static string NormalizeSlashes(string path) + { + return Regex.Replace(path, "/\\/ g", "/"); + //return path.replace(/\\/ g, "/"); + } + public static int GetRootLength(string path) + { + if (path.charCodeAt(0) == (int)CharacterCodes.Slash) + { + if (path.charCodeAt(1) != (int)CharacterCodes.Slash) + { + return 1; + } + var p1 = path.IndexOf("/", 2, StringComparison.Ordinal); + if (p1 < 0) + { + return 2; + } + var p2 = path.IndexOf("/", p1 + 1, StringComparison.Ordinal); + if (p2 < 0) + { + return p1 + 1; + } + return p2 + 1; + } + if (path.charCodeAt(1) == (int)CharacterCodes.Colon) + { + if (path.charCodeAt(2) == (int)CharacterCodes.Slash) + { + return 3; + } + return 2; + } + if (path.LastIndexOf("file:///", 0, StringComparison.Ordinal) == 0) + { + return "file:///".Length; + } + var idx = path.IndexOf("://", StringComparison.Ordinal); + if (idx != -1) + { + return idx + "://".Length; + } + return 0; + } + public static char DirectorySeparator = '/'; + public static int DirectorySeparatorCharCode = (int)CharacterCodes.Slash; + public static List GetNormalizedParts(string normalizedSlashedPath, int rootLength) + { + var parts = normalizedSlashedPath.Substring(rootLength).Split(DirectorySeparator); + List normalized = new List(); + foreach (var part in parts) + { + if (part != ".") + { + if (part == ".." && normalized.Count > 0 && LastOrUndefined(normalized) != "..") + { + normalized.pop(); + } + else + { + // A part may be an empty string (which is 'falsy') if the path had consecutive slashes, + // e.g. "path//file.ts". Drop these before re-joining the parts. + if (part != null) + { + normalized.Add(part); + } + } + } + } + return normalized; + } + public static T LastOrUndefined(List array) + { + return array != null && array.Any() + ? array.Last() + : default(T); + } + public static bool PathEndsWithDirectorySeparator(string path) + { + return path.charCodeAt(path.Length - 1) == DirectorySeparatorCharCode; + } + public static bool FileExtensionIs(string path, string extension) + { + return path.Length > extension.Length && EndsWith(path, extension); + } + public static bool EndsWith(string str, string suffix) + { + var expectedPos = str.Length - suffix.Length; + return expectedPos >= 0 && str.IndexOf(suffix, expectedPos, StringComparison.Ordinal) == expectedPos; + } + public static Diagnostic CreateFileDiagnostic(SourceFile file, int start, int length, DiagnosticMessage message, params string[] arguments) + { + var end = start + length; + Debug.Assert(start >= 0, "start must be non-negative, is " + start); + Debug.Assert(length >= 0, "length must be non-negative, is " + length); + if (file != null) + { + Debug.Assert(start <= file.Text.Length, $"start must be within the bounds of the file. { start} > { file.Text.Length}"); + Debug.Assert(end <= file.Text.Length, $"end must be the bounds of the file. { end} > { file.Text.Length}"); + } + var text = GetLocaleSpecificMessage(message); + if (arguments.Length > 0) // 4) + { + //text = formatStringFromArgs(text, arguments, 4); + } + return new Diagnostic + { + File = file, + Start = start, + Length = length, + + MessageText = text, + Category = message?.Category ?? DiagnosticCategory.Unknown, + Code = message?.Code ?? 0, + }; + } + public static string GetLocaleSpecificMessage(DiagnosticMessage message) + { + return "localizedDiagnosticMessages";// && localizedDiagnosticMessages[message.key] || message.message; + } + + } +} diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Debug.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Debug.cs new file mode 100644 index 0000000..4a4d777 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Debug.cs @@ -0,0 +1,22 @@ +using System; + +namespace Zu.TypeScript.TsParser +{ + internal class Debug + { + internal static void Assert(object v, object v2 = null) + { + + } + + internal static void Fail(string v = null) + { + throw new NotImplementedException(); + } + + internal static bool ShouldAssert(object obj) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Diagnostics.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Diagnostics.cs new file mode 100644 index 0000000..c873bc9 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Diagnostics.cs @@ -0,0 +1,60 @@ +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.TsParser +{ + internal class Diagnostics + { + public static DiagnosticMessage Merge_conflict_marker_encountered; + public static DiagnosticMessage Digit_expected; + public static DiagnosticMessage Unterminated_string_literal; + public static DiagnosticMessage Unterminated_template_literal; + public static DiagnosticMessage Unexpected_end_of_text; + public static DiagnosticMessage Hexadecimal_digit_expected; + public static DiagnosticMessage An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive; + public static DiagnosticMessage Unterminated_Unicode_escape_sequence; + public static DiagnosticMessage Asterisk_Slash_expected; + public static DiagnosticMessage Binary_digit_expected; + public static DiagnosticMessage Octal_digit_expected; + public static DiagnosticMessage Invalid_character; + public static DiagnosticMessage Unterminated_regular_expression_literal; + public static DiagnosticMessage _0_expected; + public static DiagnosticMessage Identifier_expected; + public static DiagnosticMessage Declaration_or_statement_expected; + public static DiagnosticMessage case_or_default_expected; + public static DiagnosticMessage Statement_expected; + public static DiagnosticMessage Property_or_signature_expected; + public static DiagnosticMessage Unexpected_token_A_constructor_method_accessor_or_property_was_expected; + public static DiagnosticMessage Enum_member_expected; + public static DiagnosticMessage Expression_expected; + public static DiagnosticMessage Variable_declaration_expected; + public static DiagnosticMessage Property_destructuring_pattern_expected; + public static DiagnosticMessage Array_element_destructuring_pattern_expected; + public static DiagnosticMessage Argument_expression_expected; + public static DiagnosticMessage Property_assignment_expected; + public static DiagnosticMessage Expression_or_comma_expected; + public static DiagnosticMessage Parameter_declaration_expected; + public static DiagnosticMessage Type_parameter_declaration_expected; + public static DiagnosticMessage Type_argument_expected; + public static DiagnosticMessage Type_expected; + public static DiagnosticMessage Unexpected_token_expected; + + public static DiagnosticMessage + A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses + ; + + public static DiagnosticMessage + An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses + ; + + public static DiagnosticMessage super_must_be_followed_by_an_argument_list_or_member_access; + public static DiagnosticMessage Expected_corresponding_JSX_closing_tag_for_0; + public static DiagnosticMessage JSX_expressions_must_have_one_parent_element; + public static DiagnosticMessage JSX_element_0_has_no_corresponding_closing_tag; + public static DiagnosticMessage Declaration_expected; + public static DiagnosticMessage or_expected; + public static DiagnosticMessage An_AMD_module_cannot_have_multiple_name_assignments; + public static DiagnosticMessage Type_argument_list_cannot_be_empty; + public static DiagnosticMessage Trailing_comma_not_allowed; + public static DiagnosticMessage _0_tag_already_specified; + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Factory.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Factory.cs new file mode 100644 index 0000000..61ccb8d --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Factory.cs @@ -0,0 +1,16 @@ +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.TsParser +{ + public static class Factory + { + public static INode SkipPartiallyEmittedExpressions(INode node) + { + while (node.Kind == SyntaxKind.PartiallyEmittedExpression) + node = ((PartiallyEmittedExpression) node).Expression; + + + return node; + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/JsDocParser.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/JsDocParser.cs new file mode 100644 index 0000000..e59d9fe --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/JsDocParser.cs @@ -0,0 +1,1486 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Zu.TypeScript.TsTypes; +using static Zu.TypeScript.TsParser.Scanner; + +namespace Zu.TypeScript.TsParser +{ + public class JsDocParser + { + public Parser Parser { get; set; } + public JsDocParser(Parser parser) + { + this.Parser = parser; + } + + private Scanner Scanner => Parser.Scanner; + private string SourceText => Parser.SourceText; + private SyntaxKind CurrentToken { get => Parser.CurrentToken; set => Parser.CurrentToken = value; } + private bool ParseErrorBeforeNextFinishedNode { get => Parser.ParseErrorBeforeNextFinishedNode; set => Parser.ParseErrorBeforeNextFinishedNode = value; } + private List ParseDiagnostics { get => Parser.ParseDiagnostics; set => Parser.ParseDiagnostics = value; } + #region parserMethods + + private void ClearState() => Parser.ClearState(); + private void FixupParentReferences(INode rootNode) => Parser.FixupParentReferences(rootNode); + private void ParseErrorAtCurrentToken(DiagnosticMessage message, object arg0 = null) => Parser.ParseErrorAtCurrentToken(message, arg0); + private void ParseErrorAtPosition(int start, int length, DiagnosticMessage message, object arg0 = null) => Parser.ParseErrorAtPosition(start, length, message, arg0); + private SyntaxKind Token() => Parser.Token(); + private SyntaxKind NextToken() => Parser.NextToken(); + private T TryParse(Func callback) => Parser.TryParse(callback); + private bool ParseExpected(SyntaxKind kind, DiagnosticMessage diagnosticMessage = null, bool shouldAdvance = true) => Parser.ParseExpected(kind, diagnosticMessage, shouldAdvance); + private bool ParseOptional(SyntaxKind t) => Parser.ParseOptional(t); + private INode ParseOptionalToken(SyntaxKind t) where T : Node => Parser.ParseOptionalToken(t); + private T ParseTokenNode() where T : Node => Parser.ParseTokenNode(Token()); + private NodeArray CreateList(T[] elements = null, int? pos = null) => Parser.CreateList(elements, pos); + private T FinishNode(T node, int? end = null) where T : Node => Parser.FinishNode(node, end); + private Identifier ParseIdentifierName() => Parser.ParseIdentifierName(); + private NodeArray ParseDelimitedList(ParsingContext kind, Func parseElement, bool? considerSemicolonAsDelimiter = null) where T : INode => Parser.ParseDelimitedList(kind, parseElement, considerSemicolonAsDelimiter); + private TypeLiteralNode ParseTypeLiteral() => Parser.ParseTypeLiteral(); + private IExpression ParseExpression() => Parser.ParseExpression(); + #endregion + + public bool IsJsDocType() + { + switch (Token()) + { + case SyntaxKind.AsteriskToken: + case SyntaxKind.QuestionToken: + case SyntaxKind.OpenParenToken: + case SyntaxKind.OpenBracketToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.DotDotDotToken: + case SyntaxKind.NewKeyword: + case SyntaxKind.ThisKeyword: + + return true; + } + + + return TokenIsIdentifierOrKeyword(Token()); + } + + + public static (JsDocTypeExpression res, List diagnostics) ParseJsDocTypeExpressionForTests(string content, int? start, int? length) + { + var dp = new JsDocParser(new Parser()); + dp.Parser.InitializeState(content, ScriptTarget.Latest, null, ScriptKind.Js); + + var sourceFile = dp.Parser.CreateSourceFile("file.js", ScriptTarget.Latest, ScriptKind.Js); + + dp.Parser.Scanner.SetText(content, start, length); + + var currentToken = dp.Parser.Scanner.Scan(); + var jsDocTypeExpression = dp.ParseJsDocTypeExpression(); + var diagnostics = dp.Parser.ParseDiagnostics; + + dp.Parser.ClearState(); + + + return (jsDocTypeExpression, diagnostics); + } + + + public JsDocTypeExpression ParseJsDocTypeExpression() + { + var result = new JsDocTypeExpression(); + + + ParseExpected(SyntaxKind.OpenBraceToken); + + result.Type = ParseJsDocTopLevelType(); + + ParseExpected(SyntaxKind.CloseBraceToken); + + + FixupParentReferences(result); + + return FinishNode(result); + } + + + public IJsDocType ParseJsDocTopLevelType() + { + var type = ParseJsDocType(); + if (Token() == SyntaxKind.BarToken) + { + var unionType = new JsDocUnionType {Types = ParseJsDocTypeList(type)}; + + + type = FinishNode(unionType); + } + if (Token() == SyntaxKind.EqualsToken) + { + var optionalType = new JsDocOptionalType(); + + NextToken(); + + optionalType.Type = type; + + type = FinishNode(optionalType); + } + + + return type; + } + + + public IJsDocType ParseJsDocType() + { + var type = ParseBasicTypeExpression(); + while (true) + { + if (Token() == SyntaxKind.OpenBracketToken) + { + var arrayType = new JsDocArrayType {ElementType = type}; + + + + NextToken(); + + ParseExpected(SyntaxKind.CloseBracketToken); + + + type = FinishNode(arrayType); + } + else + if (Token() == SyntaxKind.QuestionToken) + { + var nullableType = new JsDocNullableType {Type = type}; + + + + NextToken(); + + type = FinishNode(nullableType); + } + else + if (Token() == SyntaxKind.ExclamationToken) + { + var nonNullableType = new JsDocNonNullableType {Type = type}; + + + + NextToken(); + + type = FinishNode(nonNullableType); + } + else + { + + break; + } + } + + + return type; + } + + + public IJsDocType ParseBasicTypeExpression() + { + switch (Token()) + { + case SyntaxKind.AsteriskToken: + + return ParseJsDocAllType(); + case SyntaxKind.QuestionToken: + + return ParseJsDocUnknownOrNullableType(); + case SyntaxKind.OpenParenToken: + + return ParseJsDocUnionType(); + case SyntaxKind.OpenBracketToken: + + return ParseJsDocTupleType(); + case SyntaxKind.ExclamationToken: + + return ParseJsDocNonNullableType(); + case SyntaxKind.OpenBraceToken: + + return ParseJsDocRecordType(); + case SyntaxKind.FunctionKeyword: + + return ParseJsDocFunctionType(); + case SyntaxKind.DotDotDotToken: + + return ParseJsDocVariadicType(); + case SyntaxKind.NewKeyword: + + return ParseJsDocConstructorType(); + case SyntaxKind.ThisKeyword: + + return ParseJsDocThisType(); + case SyntaxKind.AnyKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ObjectKeyword: + + return ParseTokenNode(); + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + + return ParseJsDocLiteralType(); + } + + + return ParseJsDocTypeReference(); + } + + + public JsDocThisType ParseJsDocThisType() + { + var result = new JsDocThisType(); + + NextToken(); + + ParseExpected(SyntaxKind.ColonToken); + + result.Type = ParseJsDocType(); + + return FinishNode(result); + } + + + public JsDocConstructorType ParseJsDocConstructorType() + { + var result = new JsDocConstructorType(); + + NextToken(); + + ParseExpected(SyntaxKind.ColonToken); + + result.Type = ParseJsDocType(); + + return FinishNode(result); + } + + + public JsDocVariadicType ParseJsDocVariadicType() + { + var result = new JsDocVariadicType(); + + NextToken(); + + result.Type = ParseJsDocType(); + + return FinishNode(result); + } + + + public JsDocFunctionType ParseJsDocFunctionType() + { + var result = new JsDocFunctionType(); + + NextToken(); + + + ParseExpected(SyntaxKind.OpenParenToken); + + result.Parameters = Parser.ParseDelimitedList(ParsingContext.JSDocFunctionParameters, ParseJsDocParameter); + + CheckForTrailingComma(result.Parameters); + + ParseExpected(SyntaxKind.CloseParenToken); + if (Token() == SyntaxKind.ColonToken) + { + + NextToken(); + + result.Type = ParseJsDocType(); + } + + + return FinishNode(result); + } + + + public ParameterDeclaration ParseJsDocParameter() + { + var parameter = new ParameterDeclaration {Type = ParseJsDocType()}; + + if (ParseOptional(SyntaxKind.EqualsToken)) + { + + parameter.QuestionToken = new QuestionToken { }; + } + + return FinishNode(parameter); + } + + + public JsDocTypeReference ParseJsDocTypeReference() + { + var result = new JsDocTypeReference {Name = Parser.ParseSimplePropertyName() as Identifier}; + + if (Token() == SyntaxKind.LessThanToken) + { + + result.TypeArguments = ParseTypeArguments(); + } + else + { + while (ParseOptional(SyntaxKind.DotToken)) + { + if (Token() == SyntaxKind.LessThanToken) + { + + result.TypeArguments = ParseTypeArguments(); + + break; + } + else + { + + result.Name = ParseQualifiedName(result.Name); + } + } + } + + + + return FinishNode(result); + } + + + public NodeArray ParseTypeArguments() + { + + NextToken(); + var typeArguments = ParseDelimitedList(ParsingContext.JSDocTypeArguments, ParseJsDocType); + + CheckForTrailingComma(typeArguments); + + CheckForEmptyTypeArgumentList(typeArguments); + + ParseExpected(SyntaxKind.GreaterThanToken); + + + return typeArguments; + } + + + public void CheckForEmptyTypeArgumentList(NodeArray typeArguments) + { + if (!ParseDiagnostics.Any() && typeArguments != null && !typeArguments.Any()) + { + var start = (typeArguments.Pos ?? 0) - "<".Length; + var end = SkipTriviaM(SourceText, (int)typeArguments.End) + ">".Length; + + ParseErrorAtPosition(start, end - start, Diagnostics.Type_argument_list_cannot_be_empty); + } + } + + + public QualifiedName ParseQualifiedName(IEntityName left) + { + var result = new QualifiedName + { + Left = left, + Right = ParseIdentifierName() + }; + + + + + return FinishNode(result); + } + + + public JsDocRecordType ParseJsDocRecordType() + { + var result = new JsDocRecordType {Literal = ParseTypeLiteral()}; + + + return FinishNode(result); + } + + + public JsDocNonNullableType ParseJsDocNonNullableType() + { + var result = new JsDocNonNullableType(); + + NextToken(); + + result.Type = ParseJsDocType(); + + return FinishNode(result); + } + + + public JsDocTupleType ParseJsDocTupleType() + { + var result = new JsDocTupleType(); + + NextToken(); + + result.Types = ParseDelimitedList(ParsingContext.JSDocTupleTypes, ParseJsDocType); + + CheckForTrailingComma(result.Types); + + ParseExpected(SyntaxKind.CloseBracketToken); + + + return FinishNode(result); + } + + + public void CheckForTrailingComma(NodeArray list) + { + if (Parser.ParseDiagnostics.Count == 0 && list.HasTrailingComma) + { + var start = list.End - ",".Length; + + Parser.ParseErrorAtPosition((int)start, ",".Length, Diagnostics.Trailing_comma_not_allowed); + } + } + + + public JsDocUnionType ParseJsDocUnionType() + { + var result = new JsDocUnionType(); + + NextToken(); + + result.Types = ParseJsDocTypeList(ParseJsDocType()); + + + ParseExpected(SyntaxKind.CloseParenToken); + + + return FinishNode(result); + } + + + public NodeArray ParseJsDocTypeList(IJsDocType firstType) + { + + var types = Parser.CreateList(); + types.Add(firstType); + types.Pos = firstType.Pos; + while (ParseOptional(SyntaxKind.BarToken)) + { + + types.Add(ParseJsDocType()); + } + + + types.End = Scanner.GetStartPos(); + + return types; + } + + + public JsDocAllType ParseJsDocAllType() + { + var result = new JsDocAllType(); + + NextToken(); + + return FinishNode(result); + } + + + public JsDocLiteralType ParseJsDocLiteralType() + { + var result = new JsDocLiteralType {Literal = Parser.ParseLiteralTypeNode()}; + + + return FinishNode(result); + } + + + public JsDocType ParseJsDocUnknownOrNullableType() + { + var pos = Scanner.GetStartPos(); + + NextToken(); + if (Token() == SyntaxKind.CommaToken || + Token() == SyntaxKind.CloseBraceToken || + Token() == SyntaxKind.CloseParenToken || + Token() == SyntaxKind.GreaterThanToken || + Token() == SyntaxKind.EqualsToken || + Token() == SyntaxKind.BarToken) + { + var result = new JsDocUnknownType(); + + return FinishNode(result); + } + else + { + var result = new JsDocNullableType {Type = ParseJsDocType()}; + + + return FinishNode(result); + } + } + + + public Tuple> ParseIsolatedJsDocComment(string content, int start, int length) + { + if (Parser == null) Parser = new Parser(); + Parser.InitializeState(content, ScriptTarget.Latest, null, ScriptKind.Js); + + Parser.SourceFile = new SourceFile { LanguageVariant = LanguageVariant.Standard, Text = content }; + var jsDoc = ParseJsDocCommentWorker(start, length); + var diagnostics = ParseDiagnostics; + + ClearState(); + + + return jsDoc != null ? Tuple.Create(jsDoc, diagnostics) : null; + } + + + public JsDoc ParseJsDocComment(INode parent, int? start, int? length) + { + var saveToken = CurrentToken; + var saveParseDiagnosticsLength = Parser.ParseDiagnostics.Count; + var saveParseErrorBeforeNextFinishedNode = ParseErrorBeforeNextFinishedNode; + var comment = ParseJsDocCommentWorker(start, length); + if (comment != null) + { + + comment.Parent = parent; + } + + + CurrentToken = saveToken; + + ParseDiagnostics = ParseDiagnostics.Take(saveParseDiagnosticsLength).ToList(); + + ParseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + + + return comment; + } + + + public JsDoc ParseJsDocCommentWorker(int? start = null, int? length = null) + { + var content = Parser.SourceText; + + start = start ?? 0; + var end = length == null ? content.Length : start + length; + + length = end - start; + + + Debug.Assert(start >= 0); + + Debug.Assert(start <= end); + + Debug.Assert(end <= content.Length); + NodeArray tags = new NodeArray(); + List comments = new List(); + JsDoc result = null; + if (!IsJsDocStart(content, (int)start)) + { + + return result; + } + + + Scanner.ScanRange(start + 3, (length ?? 0) - 5, () => + { + var advanceToken = true; + var state = JSDocState.SawAsterisk; + int? margin = null; + var indent = start - Math.Max(content.LastIndexOf('\n', (int)start), 0) + 4; + + + NextJsDocToken(); + while (Token() == SyntaxKind.WhitespaceTrivia) + { + + NextJsDocToken(); + } + if (Token() == SyntaxKind.NewLineTrivia) + { + + state = JSDocState.BeginningOfLine; + + indent = 0; + + NextJsDocToken(); + } + while (Token() != SyntaxKind.EndOfFileToken) + { + switch (Token()) + { + case SyntaxKind.AtToken: + if (state == JSDocState.BeginningOfLine || state == JSDocState.SawAsterisk) + { + + RemoveTrailingNewlines(comments); + + ParseTag((int)indent); + + state = JSDocState.BeginningOfLine; + + advanceToken = false; + + margin = null; + + indent++; + } + else + { + + PushComment(Scanner.GetTokenText()); + } + + break; + case SyntaxKind.NewLineTrivia: + + comments.Add(Scanner.GetTokenText()); + + state = JSDocState.BeginningOfLine; + + indent = 0; + + break; + case SyntaxKind.AsteriskToken: + var asterisk = Scanner.GetTokenText(); + if (state == JSDocState.SawAsterisk || state == JSDocState.SavingComments) + { + + state = JSDocState.SavingComments; + + PushComment(asterisk); + } + else + { + + state = JSDocState.SawAsterisk; + + indent += asterisk.Length; + } + + break; + case SyntaxKind.Identifier: + + PushComment(Scanner.GetTokenText()); + + state = JSDocState.SavingComments; + + break; + case SyntaxKind.WhitespaceTrivia: + var whitespace = Scanner.GetTokenText(); + if (state == JSDocState.SavingComments) + { + + comments.Add(whitespace); + } + else + if (margin != null && (indent ?? 0) + whitespace.Length > margin) + { + + comments.Add(whitespace.slice((int)margin - (indent ?? 0) - 1)); + } + + indent += whitespace.Length; + + break; + case SyntaxKind.EndOfFileToken: + + break; + default: + + state = JSDocState.SavingComments; + + PushComment(Scanner.GetTokenText()); + + break; + } + if (advanceToken) + { + + NextJsDocToken(); + } + else + { + + advanceToken = true; + } + } + + RemoveLeadingNewlines(comments); + + RemoveTrailingNewlines(comments); + + result = CreateJsDocComment(); + return result; + void PushComment(string text) + { + if (margin == null) + { + + margin = indent; + } + + comments.Add(text); + + indent += text.Length; + } + } +); + + return result; + + + + + + + void RemoveLeadingNewlines(List comments3) + { + while (comments3.Any() && (comments3[0] == "\n" || comments3[0] == "\r")) + { + + comments3 = comments3.Skip(1).ToList(); + } + } + + + void RemoveTrailingNewlines(List comments2) + { + while (comments2.Any() && (comments2[comments2.Count() - 1] == "\n" || comments2[comments2.Count() - 1] == "\r")) + { + + comments2.pop(); + } + } + + + bool IsJsDocStart(string content2, int start2) + { + + return content2.charCodeAt(start2) == (int)CharacterCodes.Slash && + content2.charCodeAt(start2 + 1) == (int)CharacterCodes.Asterisk && + content2.charCodeAt(start2 + 2) == (int)CharacterCodes.Asterisk && + content2.charCodeAt(start2 + 3) != (int)CharacterCodes.Asterisk; + } + + + JsDoc CreateJsDocComment() + { + var result2 = new JsDoc + { + Tags = tags, + Comment = comments.Any() ? string.Join("", comments) : null + }; + + + + return FinishNode(result2, end); + } + + + void SkipWhitespace() + { + while (Token() == SyntaxKind.WhitespaceTrivia || Token() == SyntaxKind.NewLineTrivia) + { + + NextJsDocToken(); + } + } + + + void ParseTag(int indent) + { + + Debug.Assert(Token() == SyntaxKind.AtToken); + var atToken = new AtToken {End = Scanner.GetTextPos()}; + + + NextJsDocToken(); + var tagName = ParseJsDocIdentifierName(); + + SkipWhitespace(); + if (tagName == null) + { + + return; + } + IJsDocTag tag = null; + if (tagName != null) + { + switch (tagName.Text) + { + case "augments": + + tag = ParseAugmentsTag(atToken, tagName); + + break; + case "param": + + tag = ParseParamTag(atToken, tagName); + + break; + case "return": + case "returns": + + tag = ParseReturnTag(atToken, tagName); + + break; + case "template": + + tag = ParseTemplateTag(atToken, tagName); + + break; + case "type": + + tag = ParseTypeTag(atToken, tagName); + + break; + case "typedef": + + tag = ParseTypedefTag(atToken, tagName); + + break; + default: + + tag = ParseUnknownTag(atToken, tagName); + + break; + } + } + else + { + + tag = ParseUnknownTag(atToken, tagName); + } + if (tag == null) + { + + return; + } + + AddTag(tag, ParseTagComments(indent + (tag.End ?? 0) - (tag.Pos ?? 0))); + } + + + List ParseTagComments(int indent) + { + List comments2 = new List(); + var state = JSDocState.SawAsterisk; + int? margin = null; + while (Token() != SyntaxKind.AtToken && Token() != SyntaxKind.EndOfFileToken) + { + switch (Token()) + { + case SyntaxKind.NewLineTrivia: + if (state >= JSDocState.SawAsterisk) + { + + state = JSDocState.BeginningOfLine; + + comments2.Add(Scanner.GetTokenText()); + } + + indent = 0; + + break; + case SyntaxKind.AtToken: + + break; + case SyntaxKind.WhitespaceTrivia: + if (state == JSDocState.SavingComments) + { + + PushComment(Scanner.GetTokenText()); + } + else + { + var whitespace = Scanner.GetTokenText(); + if (margin != null && indent + whitespace.Length > margin) + { + + comments2.Add(whitespace.slice((int)margin - indent - 1)); + } + + indent += whitespace.Length; + } + + break; + case SyntaxKind.AsteriskToken: + if (state == JSDocState.BeginningOfLine) + { + + state = JSDocState.SawAsterisk; + + indent += Scanner.GetTokenText().Length; + + break; + } + goto caseLabel5; + default: + + caseLabel5: state = JSDocState.SavingComments; + PushComment(Scanner.GetTokenText()); + + break; + } + if (Token() == SyntaxKind.AtToken) + { + + break; + } + + NextJsDocToken(); + } + + + RemoveLeadingNewlines(comments2); + + RemoveTrailingNewlines(comments2); + + return comments2; + void PushComment(string text) + { + if (margin == null) + { + + margin = indent; + } + + comments2.Add(text); + + indent += text.Length; + } + } + + + + + + JsDocTag ParseUnknownTag(AtToken atToken, Identifier tagName) + { + var result2 = new JsDocTag + { + AtToken = atToken, + TagName = tagName + }; + + + + return FinishNode(result2); + } + + + void AddTag(IJsDocTag tag, List comments2) + { + + tag.Comment = string.Join("", comments2); + if (tags == null) + { + + tags = Parser.CreateList(); + tags.Pos = tag.Pos; + + } + else + { + + tags.Add(tag); + } + + tags.End = tag.End; + } + + + JsDocTypeExpression TryParseTypeExpression() + { + + return TryParse(() => + { + SkipWhitespace(); + if (Token() != SyntaxKind.OpenBraceToken) + { + return null; + } + + return ParseJsDocTypeExpression(); + }); + } + + + JsDocParameterTag ParseParamTag(AtToken atToken, Identifier tagName) + { + var typeExpression = TryParseTypeExpression(); + + SkipWhitespace(); + Identifier name = null; + bool isBracketed = false; + if ((OpenBracketToken)ParseOptionalToken(SyntaxKind.OpenBracketToken) != null) + { + + name = ParseJsDocIdentifierName(); + + SkipWhitespace(); + + isBracketed = true; + if ((EqualsToken)ParseOptionalToken(SyntaxKind.EqualsToken) != null) + { + + ParseExpression(); + } + + + ParseExpected(SyntaxKind.CloseBracketToken); + } + else + if (TokenIsIdentifierOrKeyword(Token())) + { + + name = ParseJsDocIdentifierName(); + } + if (name == null) + { + + ParseErrorAtPosition(Scanner.GetStartPos(), 0, Diagnostics.Identifier_expected); + + return null; + } + Identifier preName = null; + Identifier postName = null; + if (typeExpression != null) + { + + postName = name; + } + else + { + + preName = name; + } + if (typeExpression == null) + { + + typeExpression = TryParseTypeExpression(); + } + var result4 = new JsDocParameterTag + { + AtToken = atToken, + TagName = tagName, + PreParameterName = preName, + TypeExpression = typeExpression, + PostParameterName = postName, + ParameterName = postName ?? preName, + IsBracketed = isBracketed + }; + + + + + + + + + return FinishNode(result4); + } + + + JsDocReturnTag ParseReturnTag(AtToken atToken, Identifier tagName) + { + if (tags.Any(t => t.Kind == SyntaxKind.JsDocReturnTag)) + { + + ParseErrorAtPosition(tagName.Pos ?? 0, Scanner.GetTokenPos() - (tagName.Pos ?? 0), Diagnostics._0_tag_already_specified, tagName.Text); + } + var result5 = new JsDocReturnTag + { + AtToken = atToken, + TagName = tagName, + TypeExpression = TryParseTypeExpression() + }; + + + + + return FinishNode(result5); + } + + + JsDocTypeTag ParseTypeTag(AtToken atToken, Identifier tagName) + { + if (tags.Any(t => t.Kind == SyntaxKind.JsDocTypeTag)) + { + + ParseErrorAtPosition(tagName.Pos ?? 0, Scanner.GetTokenPos() - (tagName.Pos ?? 0), Diagnostics._0_tag_already_specified, tagName.Text); + } + var result6 = new JsDocTypeTag + { + AtToken = atToken, + TagName = tagName, + TypeExpression = TryParseTypeExpression() + }; + + + + + return FinishNode(result6); + } + + + JsDocPropertyTag ParsePropertyTag(AtToken atToken, Identifier tagName) + { + var typeExpression = TryParseTypeExpression(); + + SkipWhitespace(); + var name = ParseJsDocIdentifierName(); + + SkipWhitespace(); + if (name == null) + { + + ParseErrorAtPosition(Scanner.GetStartPos(), 0, Diagnostics.Identifier_expected); + + return null; + } + var result7 = new JsDocPropertyTag + { + AtToken = atToken, + TagName = tagName, + Name = name, + TypeExpression = typeExpression + }; + + + + + + return FinishNode(result7); + } + + + JsDocAugmentsTag ParseAugmentsTag(AtToken atToken, Identifier tagName) + { + var typeExpression = TryParseTypeExpression(); + var result8 = new JsDocAugmentsTag + { + AtToken = atToken, + TagName = tagName, + TypeExpression = typeExpression + }; + + + + + return FinishNode(result8); + } + + + IJsDocTag ParseTypedefTag(AtToken atToken, Identifier tagName) + { + var typeExpression = TryParseTypeExpression(); + + SkipWhitespace(); + var typedefTag = new JsDocTypedefTag + { + AtToken = atToken, + TagName = tagName, + FullName = ParseJsDocTypeNameWithNamespace(0) + }; + + + + if (typedefTag.FullName != null) + { + var rightNode = typedefTag.FullName; + while (true) + { + if ((SyntaxKind)rightNode.Kind == SyntaxKind.Identifier || (rightNode as JsDocNamespaceDeclaration)?.Body == null) + { + + typedefTag.Name = (SyntaxKind)rightNode.Kind == SyntaxKind.Identifier ? rightNode : (rightNode as JsDocTypedefTag)?.Name; + + break; + } + + rightNode = (rightNode as JsDocNamespaceDeclaration)?.Body; + } + } + + typedefTag.TypeExpression = typeExpression; + + SkipWhitespace(); + if (typeExpression != null) + { + if ((SyntaxKind)typeExpression.Type.Kind == SyntaxKind.JsDocTypeReference) + { + var jsDocTypeReference = (JsDocTypeReference)typeExpression.Type; + if ((SyntaxKind)jsDocTypeReference.Name.Kind == SyntaxKind.Identifier) + { + Identifier name = jsDocTypeReference.Name as Identifier; + if (name?.Text == "Object") + { + + typedefTag.JsDocTypeLiteral = ScanChildTags(); + } + } + } + if (typedefTag.JsDocTypeLiteral == null) + { + + typedefTag.JsDocTypeLiteral = (JsDocTypeLiteral)typeExpression.Type; + } + } + else + { + + typedefTag.JsDocTypeLiteral = ScanChildTags(); + } + + + return FinishNode(typedefTag); + } + + + JsDocTypeLiteral ScanChildTags() + { + var jsDocTypeLiteral = new JsDocTypeLiteral(); + var resumePos = Scanner.GetStartPos(); + var canParseTag = true; + var seenAsterisk = false; + var parentTagTerminated = false; + while (Token() != SyntaxKind.EndOfFileToken && !parentTagTerminated) + { + + NextJsDocToken(); + switch (Token()) + { + case SyntaxKind.AtToken: + if (canParseTag) + { + + parentTagTerminated = !TryParseChildTag(jsDocTypeLiteral); + if (!parentTagTerminated) + { + + resumePos = Scanner.GetStartPos(); + } + } + + seenAsterisk = false; + + break; + case SyntaxKind.NewLineTrivia: + + resumePos = Scanner.GetStartPos() - 1; + + canParseTag = true; + + seenAsterisk = false; + + break; + case SyntaxKind.AsteriskToken: + if (seenAsterisk) + { + + canParseTag = false; + } + + seenAsterisk = true; + + break; + case SyntaxKind.Identifier: + + canParseTag = false; + goto caseLabel5; + case SyntaxKind.EndOfFileToken: + caseLabel5: + break; + } + } + + Scanner.SetTextPos(resumePos); + + return FinishNode(jsDocTypeLiteral); + } + + + INode ParseJsDocTypeNameWithNamespace(NodeFlags flags) + { + var pos = Scanner.GetTokenPos(); + var typeNameOrNamespaceName = ParseJsDocIdentifierName(); + if (typeNameOrNamespaceName != null && ParseOptional(SyntaxKind.DotToken)) + { + var jsDocNamespaceNode = new JsDocNamespaceDeclaration(); + + jsDocNamespaceNode.Flags |= flags; + + jsDocNamespaceNode.Name = typeNameOrNamespaceName; + + jsDocNamespaceNode.Body = ParseJsDocTypeNameWithNamespace(NodeFlags.NestedNamespace); + + return jsDocNamespaceNode; + } + if (typeNameOrNamespaceName != null && (flags & NodeFlags.NestedNamespace) != 0) + { + + typeNameOrNamespaceName.IsInJsDocNamespace = true; + } + + return typeNameOrNamespaceName; + } + + + bool TryParseChildTag(JsDocTypeLiteral parentTag) + { + + Debug.Assert(Token() == SyntaxKind.AtToken); + var atToken = new AtToken {End = Scanner.GetTextPos()}; + + + NextJsDocToken(); + var tagName = ParseJsDocIdentifierName(); + + SkipWhitespace(); + if (tagName == null) + { + + return false; + } + switch (tagName.Text) + { + case "type": + if (parentTag.JsDocTypeTag != null) + { + + return false; + } + + parentTag.JsDocTypeTag = ParseTypeTag(atToken, tagName); + + return true; + case "prop": + case "property": + var propertyTag = ParsePropertyTag(atToken, tagName); + if (propertyTag != null) + { + if (parentTag.JsDocPropertyTags == null) + { + + parentTag.JsDocPropertyTags = new NodeArray(); + } + + parentTag.JsDocPropertyTags.Add(propertyTag); + + return true; + } + + return false; + } + + return false; + } + + + JsDocTemplateTag ParseTemplateTag(AtToken atToken, Identifier tagName) + { + if (tags.Any(t => t.Kind == SyntaxKind.JsDocTemplateTag)) + { + + ParseErrorAtPosition(tagName.Pos ?? 0, Scanner.GetTokenPos() - (tagName.Pos ?? 0), Diagnostics._0_tag_already_specified, tagName.Text); + } + var typeParameters = CreateList(); + while (true) + { + var name = ParseJsDocIdentifierName(); + + SkipWhitespace(); + if (name == null) + { + + ParseErrorAtPosition(Scanner.GetStartPos(), 0, Diagnostics.Identifier_expected); + + return null; + } + var typeParameter = new TypeParameterDeclaration {Name = name}; + + + FinishNode(typeParameter); + + + typeParameters.Add(typeParameter); + if (Token() == SyntaxKind.CommaToken) + { + + NextJsDocToken(); + + SkipWhitespace(); + } + else + { + + break; + } + } + var result3 = new JsDocTemplateTag + { + AtToken = atToken, + TagName = tagName, + TypeParameters = typeParameters + }; + + + + + FinishNode(result3); + + typeParameters.End = result3.End; + + return result3; + } + + + SyntaxKind NextJsDocToken() + { + CurrentToken = Scanner.ScanJsDocToken(); + return CurrentToken; + } + + + Identifier ParseJsDocIdentifierName() + { + + return CreateJsDocIdentifier(TokenIsIdentifierOrKeyword(Token())); + } + + + Identifier CreateJsDocIdentifier(bool isIdentifier) + { + if (!isIdentifier) + { + + ParseErrorAtCurrentToken(Diagnostics.Identifier_expected); + + return null; + } + var pos = Scanner.GetTokenPos(); + var end2 = Scanner.GetTextPos(); + var result9 = new Identifier {Text = content.substring(pos, end2)}; + + + FinishNode(result9, end2); + + + NextJsDocToken(); + + return result9; + } + } + } +} diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Parser.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Parser.cs new file mode 100644 index 0000000..da697a4 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Parser.cs @@ -0,0 +1,7384 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Zu.TypeScript.TsTypes; +using static Zu.TypeScript.TsParser.Core; +using static Zu.TypeScript.TsParser.Scanner; +using static Zu.TypeScript.TsParser.Ts; +using static Zu.TypeScript.TsParser.Utilities; + +namespace Zu.TypeScript.TsParser +{ + public class Parser + { + + public Scanner Scanner = new Scanner(ScriptTarget.Latest, /*skipTrivia*/ true, LanguageVariant.Standard, null, null); + public NodeFlags DisallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; + + public NodeFlags ContextFlags; + public bool ParseErrorBeforeNextFinishedNode = false; + public SourceFile SourceFile; + public List ParseDiagnostics; + public /*IncrementalParser.SyntaxCursor*/object SyntaxCursor; + + public SyntaxKind CurrentToken; + public string SourceText; + public int NodeCount; + public List Identifiers; + public int IdentifierCount; + + public int ParsingContext; //ParsingContext + public JsDocParser JsDocParser; + public Parser() + { + JsDocParser = new JsDocParser(this); + } + //public (JSDocTypeExpression res, List diagnostics) parseJSDocTypeExpressionForTests(string content, int? start = null, int? length = null) + //{ + + // return JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); + //} + + + public SourceFile ParseSourceFile(string fileName, string sourceText, ScriptTarget languageVersion, /*IncrementalParser.SyntaxCursor*/object syntaxCursor, bool setParentNodes, ScriptKind scriptKind) + { + + scriptKind = EnsureScriptKind(fileName, scriptKind); + + + InitializeState(sourceText, languageVersion, syntaxCursor, scriptKind); + var result = ParseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); + + + ClearState(); + + + return result; + } + + + public IEntityName ParseIsolatedEntityName(string content, ScriptTarget languageVersion) + { + + InitializeState(content, languageVersion, /*syntaxCursor*/ null, ScriptKind.Js); + + // Prime the scanner. + NextToken(); + var entityName = ParseEntityName(/*allowReservedWords*/ true); + var isInvalid = Token() == SyntaxKind.EndOfFileToken && !ParseDiagnostics.Any(); + + ClearState(); + + return isInvalid ? entityName : null; + } + + + public LanguageVariant GetLanguageVariant(ScriptKind scriptKind) + { + + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind == ScriptKind.Tsx || scriptKind == ScriptKind.Jsx || scriptKind == ScriptKind.Js ? LanguageVariant.Jsx : LanguageVariant.Standard; + } + + + public void InitializeState(string _sourceText, ScriptTarget languageVersion, /*IncrementalParser.SyntaxCursor*/object _syntaxCursor, ScriptKind scriptKind) + { + + //NodeConstructor = objectAllocator.getNodeConstructor(); + + //TokenConstructor = objectAllocator.getTokenConstructor(); + + //IdentifierConstructor = objectAllocator.getIdentifierConstructor(); + + //SourceFileConstructor = objectAllocator.getSourceFileConstructor(); + + + SourceText = _sourceText; + + SyntaxCursor = _syntaxCursor; + + + ParseDiagnostics = new List(); // []; + + ParsingContext = 0; + + Identifiers = new List(); + + IdentifierCount = 0; + + NodeCount = 0; + + + ContextFlags = scriptKind == ScriptKind.Js || scriptKind == ScriptKind.Jsx ? NodeFlags.JavaScriptFile : NodeFlags.None; + + ParseErrorBeforeNextFinishedNode = false; + + + // Initialize and prime the scanner before parsing the source elements. + Scanner.SetText(SourceText); + + Scanner.OnError += ScanError; //.setOnError(scanError); + + Scanner.SetScriptTarget(languageVersion); + + Scanner.SetLanguageVariant(GetLanguageVariant(scriptKind)); + } + + + public void ClearState() + { + + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. + Scanner.SetText(""); + + Scanner.SetOnError(null); + + + // Clear any data. We don't want to accidentally hold onto it for too long. + ParseDiagnostics = null; + + SourceFile = null; + + Identifiers = null; + + SyntaxCursor = null; + + SourceText = null; + } + + + public SourceFile ParseSourceFileWorker(string fileName, ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind) + { + + SourceFile = CreateSourceFile(fileName, languageVersion, scriptKind); + + SourceFile.Flags = ContextFlags; + + + // Prime the scanner. + NextToken(); + + ProcessReferenceComments(SourceFile); + + + SourceFile.Statements = ParseList2(TsTypes.ParsingContext.SourceElements, ParseStatement); + + Debug.Assert(Token() == SyntaxKind.EndOfFileToken); + + SourceFile.EndOfFileToken = (EndOfFileToken)ParseTokenNode(Token()); + + + SetExternalModuleIndicator(SourceFile); + + + SourceFile.NodeCount = NodeCount; + + SourceFile.IdentifierCount = IdentifierCount; + + SourceFile.Identifiers = Identifiers; + + SourceFile.ParseDiagnostics = ParseDiagnostics; + if (setParentNodes) + { + + FixupParentReferences(SourceFile); + } + + + return SourceFile; + } + + + public T AddJsDocComment(T node) where T : INode + { + var comments = GetJsDocCommentRanges(node, SourceFile.Text); + if (comments.Any()) + { + foreach (var comment in comments) + { + var jsDoc = JsDocParser.ParseJsDocComment(node, comment.Pos, comment.End - comment.Pos); + if (jsDoc == null) + { + + continue; + } + if (node.JsDoc == null) + { + + node.JsDoc = new List(); + } + + node.JsDoc.Add(jsDoc); + } + } + + + return node; + } + + + public void FixupParentReferences(INode rootNode) + { + INode parent = rootNode; + + ForEachChild(rootNode, visitNode); + + return; + INode visitNode(INode n) + { + if (n.Parent != parent) + { + + n.Parent = parent; + var saveParent = parent; + + parent = n; + + ForEachChild(n, visitNode); + if (n.JsDoc != null) + { + foreach (var jsDoc in n.JsDoc) + { + + jsDoc.Parent = n; + + parent = jsDoc; + + ForEachChild(jsDoc, visitNode); + } + } + + parent = saveParent; + } + return null; + } + + } + + + + public SourceFile CreateSourceFile(string fileName, ScriptTarget languageVersion, ScriptKind scriptKind) + { + //var sourceFile = (SourceFile)new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length); + var sourceFile = new SourceFile { Pos = 0, End = SourceText.Length }; + + NodeCount++; + + + sourceFile.Text = SourceText; + + sourceFile.BindDiagnostics = new List(); + + sourceFile.LanguageVersion = languageVersion; + + sourceFile.FileName = NormalizePath(fileName); + + sourceFile.LanguageVariant = GetLanguageVariant(scriptKind); + + sourceFile.IsDeclarationFile = FileExtensionIs(sourceFile.FileName, ".d.ts"); + + sourceFile.ScriptKind = scriptKind; + + + return sourceFile; + } + + + public void SetContextFlag(bool val, NodeFlags flag) + { + if (val) + { + + ContextFlags |= flag; + } + else + { + + ContextFlags &= ~flag; + } + } + + + public void SetDisallowInContext(bool val) + { + + SetContextFlag(val, NodeFlags.DisallowInContext); + } + + + public void SetYieldContext(bool val) + { + + SetContextFlag(val, NodeFlags.YieldContext); + } + + + public void SetDecoratorContext(bool val) + { + + SetContextFlag(val, NodeFlags.DecoratorContext); + } + + + public void SetAwaitContext(bool val) + { + + SetContextFlag(val, NodeFlags.AwaitContext); + } + + + public T DoOutsideOfContext(NodeFlags context, Func func) + { + var contextFlagsToClear = context & ContextFlags; + if (contextFlagsToClear != 0) + { + + // clear the requested context flags + SetContextFlag(/*val*/ false, contextFlagsToClear); + var result = func(); + + // restore the context flags we just cleared + SetContextFlag(/*val*/ true, contextFlagsToClear); + + return result; + } + + + // no need to do anything special as we are not in any of the requested contexts + return func(); + } + + + public T DoInsideOfContext(NodeFlags context, Func func) + { + var contextFlagsToSet = context & ~ContextFlags; + if (contextFlagsToSet != 0) + { + + // set the requested context flags + SetContextFlag(/*val*/ true, contextFlagsToSet); + var result = func(); + + // reset the context flags we just set + SetContextFlag(/*val*/ false, contextFlagsToSet); + + return result; + } + + + // no need to do anything special as we are already in all of the requested contexts + return func(); + } + + + public T AllowInAnd(Func func) + { + + return DoOutsideOfContext(NodeFlags.DisallowInContext, func); + } + + + public T DisallowInAnd(Func func) + { + + return DoInsideOfContext(NodeFlags.DisallowInContext, func); + } + + + public T DoInYieldContext(Func func) + { + + return DoInsideOfContext(NodeFlags.YieldContext, func); + } + + + public T DoInDecoratorContext(Func func) + { + + return DoInsideOfContext(NodeFlags.DecoratorContext, func); + } + + + public T DoInAwaitContext(Func func) + { + + return DoInsideOfContext(NodeFlags.AwaitContext, func); + } + + + public T DoOutsideOfAwaitContext(Func func) + { + + return DoOutsideOfContext(NodeFlags.AwaitContext, func); + } + + + public T DoInYieldAndAwaitContext(Func func) + { + + return DoInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func); + } + + + public bool InContext(NodeFlags flags) + { + + return (ContextFlags & flags) != 0; + } + + + public bool InYieldContext() + { + + return InContext(NodeFlags.YieldContext); + } + + + public bool InDisallowInContext() + { + + return InContext(NodeFlags.DisallowInContext); + } + + + public bool InDecoratorContext() + { + + return InContext(NodeFlags.DecoratorContext); + } + + + public bool InAwaitContext() + { + + return InContext(NodeFlags.AwaitContext); + } + + + public void ParseErrorAtCurrentToken(DiagnosticMessage message, object arg0 = null) + { + var start = Scanner.GetTokenPos(); + var length = Scanner.GetTextPos() - start; + + + ParseErrorAtPosition(start, length, message, arg0); + } + + + public void ParseErrorAtPosition(int start, int length, DiagnosticMessage message, object arg0 = null) + { + var lastError = LastOrUndefined(ParseDiagnostics); + if (lastError == null || start != lastError.Start) + { + + ParseDiagnostics.Add(CreateFileDiagnostic(SourceFile, start, length, message)); //, arg0)); + } + + + // Mark that we've encountered an error. We'll set an appropriate bit on the next + // node we finish so that it can't be reused incrementally. + ParseErrorBeforeNextFinishedNode = true; + } + + + public void ScanError(DiagnosticMessage message, int? length = null) + { + var pos = Scanner.GetTextPos(); + + ParseErrorAtPosition(pos, length ?? 0, message); + } + + + public int GetNodePos() + { + + return Scanner.GetStartPos(); + } + + + public int GetNodeEnd() + { + + return Scanner.GetStartPos(); + } + + + public SyntaxKind Token() + { + + return CurrentToken; + } + + + public SyntaxKind NextToken() + { + CurrentToken = Scanner.Scan(); + return CurrentToken; + } + + + public SyntaxKind ReScanGreaterToken() + { + CurrentToken = Scanner.ReScanGreaterToken(); + return CurrentToken; + } + + + public SyntaxKind ReScanSlashToken() + { + CurrentToken = Scanner.ReScanSlashToken(); + return CurrentToken; + } + + + public SyntaxKind ReScanTemplateToken() + { + CurrentToken = Scanner.ReScanTemplateToken(); + return CurrentToken; + } + + + public SyntaxKind ScanJsxIdentifier() + { + CurrentToken = Scanner.ScanJsxIdentifier(); + return CurrentToken; + } + + + public SyntaxKind ScanJsxText() + { + CurrentToken = Scanner.ScanJsxToken(); + return CurrentToken; + } + + + public SyntaxKind ScanJsxAttributeValue() + { + CurrentToken = Scanner.ScanJsxAttributeValue(); + return CurrentToken; + } + + + public T SpeculationHelper(Func callback, bool isLookAhead) + { + var saveToken = CurrentToken; + var saveParseDiagnosticsLength = ParseDiagnostics.Count; + var saveParseErrorBeforeNextFinishedNode = ParseErrorBeforeNextFinishedNode; + var saveContextFlags = ContextFlags; + var result = isLookAhead + ? Scanner.LookAhead(callback) + : Scanner.TryScan(callback); + + + Debug.Assert(saveContextFlags == ContextFlags); + if (result == null || ((result is bool) && Convert.ToBoolean(result) == false) || isLookAhead) + { + + CurrentToken = saveToken; + + //parseDiagnostics.Count = saveParseDiagnosticsLength; + ParseDiagnostics = ParseDiagnostics.Take(saveParseDiagnosticsLength).ToList(); + + ParseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + } + + + return result; + } + + + public T LookAhead(Func callback) + { + + return SpeculationHelper(callback, /*isLookAhead*/ true); + } + + + public T TryParse(Func callback) + { + + return SpeculationHelper(callback, /*isLookAhead*/ false); + } + + + public bool IsIdentifier() + { + if (Token() == SyntaxKind.Identifier) + { + + return true; + } + if (Token() == SyntaxKind.YieldKeyword && InYieldContext()) + { + + return false; + } + if (Token() == SyntaxKind.AwaitKeyword && InAwaitContext()) + { + + return false; + } + + + return Token() > SyntaxKind.LastReservedWord; + } + + + public bool ParseExpected(SyntaxKind kind, DiagnosticMessage diagnosticMessage = null, bool shouldAdvance = true) + { + if (Token() == kind) + { + if (shouldAdvance) + { + + NextToken(); + } + + return true; + } + if (diagnosticMessage != null) + { + + ParseErrorAtCurrentToken(diagnosticMessage); + } + else + { + + ParseErrorAtCurrentToken(Diagnostics._0_expected, TokenToString(kind)); + } + + return false; + } + + + public bool ParseOptional(SyntaxKind t) + { + if (Token() == t) + { + + NextToken(); + + return true; + } + + return false; + } + + + //public Token parseOptionalToken(TKind t) where TKind : SyntaxKind + //{ + //} + + + public Node ParseOptionalToken(SyntaxKind t) where T : Node + { + if (Token() == t) + { + + return ParseTokenNode(Token()); + } + + return null; + } + + + //public Token parseExpectedToken(TKind t, bool reportAtCurrentPosition, DiagnosticMessage diagnosticMessage, object arg0 = null) where TKind : SyntaxKind + //{ + //} + + + public Node ParseExpectedToken(SyntaxKind t, bool reportAtCurrentPosition, DiagnosticMessage diagnosticMessage, object arg0 = null) where T : Node + { + + return ParseOptionalToken(t) ?? + CreateMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0); + } + + + public T ParseTokenNode(SyntaxKind sk) where T : Node + { + var node = (T)Activator.CreateInstance(typeof(T));// new T(); + node.Pos = Scanner.GetStartPos(); + node.Kind = sk; + + NextToken(); + + return FinishNode(node); + } + + + public bool CanParseSemicolon() + { + if (Token() == SyntaxKind.SemicolonToken) + { + + return true; + } + + + // We can parse out an optional semicolon in ASI cases in the following cases. + return Token() == SyntaxKind.CloseBraceToken || Token() == SyntaxKind.EndOfFileToken || Scanner.HasPrecedingLineBreak(); + } + + + public bool ParseSemicolon() + { + if (CanParseSemicolon()) + { + if (Token() == SyntaxKind.SemicolonToken) + { + + // consume the semicolon if it was explicitly provided. + NextToken(); + } + + + return true; + } + else + { + + return ParseExpected(SyntaxKind.SemicolonToken); + } + } + + + public NodeArray CreateList(T[] elements = null, int? pos = null) /*where T : Node*/ + { + var array = elements == null ? new NodeArray() : new NodeArray(elements); // (List)(elements || []); + if (!(pos >= 0)) + { + + pos = GetNodePos(); + } + + array.Pos = pos; + + array.End = pos; + + return array; + } + + + + public T FinishNode(T node, int? end = null) where T : INode + { + node.End = end == null ? Scanner.GetStartPos() : (int)end; + if (ContextFlags != NodeFlags.None) + { + node.Flags |= ContextFlags; + } + if (ParseErrorBeforeNextFinishedNode) + { + ParseErrorBeforeNextFinishedNode = false; + node.Flags |= NodeFlags.ThisNodeHasError; + } + return node; + } + + public Node CreateMissingNode(SyntaxKind kind, bool reportAtCurrentPosition, DiagnosticMessage diagnosticMessage = null, object arg0 = null) where T : Node + { + if (reportAtCurrentPosition) + { + ParseErrorAtPosition(Scanner.GetStartPos(), 0, diagnosticMessage, arg0); + } + else + { + ParseErrorAtCurrentToken(diagnosticMessage, arg0); + } + var result = (T)Activator.CreateInstance(typeof(T)); + result.Kind = SyntaxKind.MissingDeclaration; + result.Pos = Scanner.GetStartPos(); + //var result = new MissingNode { kind = kind, pos = scanner.getStartPos(), text = "" }; // createNode(kind, scanner.getStartPos()); + //(< Identifier > result).text = "; + return FinishNode(result); + } + + public string InternIdentifier(string text) + { + + text = EscapeIdentifier(text); + //var identifier = identifiers.get(text); + if (!Identifiers.Contains(text))// identifier == null) + { + + Identifiers.Add(text); //.set(text, identifier = text); + } + + return text; // identifier; + } + + + public Identifier CreateIdentifier(bool isIdentifier, DiagnosticMessage diagnosticMessage = null) + { + + IdentifierCount++; + if (isIdentifier) + { + var node = new Identifier { Pos = Scanner.GetStartPos() }; + if (Token() != SyntaxKind.Identifier) + { + + node.OriginalKeywordKind = Token(); + } + + node.Text = InternIdentifier(Scanner.GetTokenValue()); + + NextToken(); + + return FinishNode(node); + } + + + return (Identifier)CreateMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, diagnosticMessage ?? Diagnostics.Identifier_expected); + } + + + public Identifier ParseIdentifier(DiagnosticMessage diagnosticMessage = null) + { + + return CreateIdentifier(IsIdentifier(), diagnosticMessage); + } + + + public Identifier ParseIdentifierName() + { + + return CreateIdentifier(TokenIsIdentifierOrKeyword(Token())); + } + + + public bool IsLiteralPropertyName() + { + + return TokenIsIdentifierOrKeyword(Token()) || + Token() == SyntaxKind.StringLiteral || + Token() == SyntaxKind.NumericLiteral; + } + + + public IPropertyName ParsePropertyNameWorker(bool allowComputedPropertyNames) + { + if (Token() == SyntaxKind.StringLiteral || Token() == SyntaxKind.NumericLiteral) + { + + var le = ParseLiteralNode(/*internName*/ true); + if (le is StringLiteral) return (StringLiteral)le; + else if (le is NumericLiteral) return (NumericLiteral)le; + return null; // /*(StringLiteral | NumericLiteral)*/le; + } + if (allowComputedPropertyNames && Token() == SyntaxKind.OpenBracketToken) + { + + return ParseComputedPropertyName(); + } + + return ParseIdentifierName(); + } + + + public IPropertyName ParsePropertyName() + { + + return ParsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + } + + + public /*Identifier | LiteralExpression*/IPropertyName ParseSimplePropertyName() + { + + return ParsePropertyNameWorker(/*allowComputedPropertyNames*/ false); + } + + + public bool IsSimplePropertyName() + { + + return Token() == SyntaxKind.StringLiteral || Token() == SyntaxKind.NumericLiteral || TokenIsIdentifierOrKeyword(Token()); + } + + + public ComputedPropertyName ParseComputedPropertyName() + { + var node = new ComputedPropertyName() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBracketToken); + + + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. + node.Expression = AllowInAnd(ParseExpression); + + + ParseExpected(SyntaxKind.CloseBracketToken); + + return FinishNode(node); + } + + + public bool ParseContextualModifier(SyntaxKind t) + { + + return Token() == t && TryParse(NextTokenCanFollowModifier); + } + + + public bool NextTokenIsOnSameLineAndCanFollowModifier() + { + + NextToken(); + if (Scanner.HasPrecedingLineBreak()) + { + + return false; + } + + return CanFollowModifier(); + } + + + public bool NextTokenCanFollowModifier() + { + if (Token() == SyntaxKind.ConstKeyword) + { + + // 'const' is only a modifier if followed by 'enum'. + return NextToken() == SyntaxKind.EnumKeyword; + } + if (Token() == SyntaxKind.ExportKeyword) + { + + NextToken(); + if (Token() == SyntaxKind.DefaultKeyword) + { + + return LookAhead(NextTokenIsClassOrFunctionOrAsync); + } + + return Token() != SyntaxKind.AsteriskToken && Token() != SyntaxKind.AsKeyword && Token() != SyntaxKind.OpenBraceToken && CanFollowModifier(); + } + if (Token() == SyntaxKind.DefaultKeyword) + { + + return NextTokenIsClassOrFunctionOrAsync(); + } + if (Token() == SyntaxKind.StaticKeyword) + { + + NextToken(); + + return CanFollowModifier(); + } + + + return NextTokenIsOnSameLineAndCanFollowModifier(); + } + + + public bool ParseAnyContextualModifier() + { + + return IsModifierKind(Token()) && TryParse(NextTokenCanFollowModifier); + } + + + public bool CanFollowModifier() + { + + return Token() == SyntaxKind.OpenBracketToken + || Token() == SyntaxKind.OpenBraceToken + || Token() == SyntaxKind.AsteriskToken + || Token() == SyntaxKind.DotDotDotToken + || IsLiteralPropertyName(); + } + + + public bool NextTokenIsClassOrFunctionOrAsync() + { + + NextToken(); + + return Token() == SyntaxKind.ClassKeyword || Token() == SyntaxKind.FunctionKeyword || + (Token() == SyntaxKind.AsyncKeyword && LookAhead(NextTokenIsFunctionKeywordOnSameLine)); + } + + + public bool IsListElement(ParsingContext parsingContext, bool inErrorRecovery) + { + var node = CurrentNode(parsingContext); + if (node != null) + { + + return true; + } + switch (parsingContext) + { + case TsTypes.ParsingContext.SourceElements: + case TsTypes.ParsingContext.BlockStatements: + case TsTypes.ParsingContext.SwitchClauseStatements: + + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(Token() == SyntaxKind.SemicolonToken && inErrorRecovery) && IsStartOfStatement(); + case TsTypes.ParsingContext.SwitchClauses: + + return Token() == SyntaxKind.CaseKeyword || Token() == SyntaxKind.DefaultKeyword; + case TsTypes.ParsingContext.TypeMembers: + + return LookAhead(IsTypeMemberStart); + case TsTypes.ParsingContext.ClassMembers: + + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return LookAhead(IsClassMemberStart) || (Token() == SyntaxKind.SemicolonToken && !inErrorRecovery); + case TsTypes.ParsingContext.EnumMembers: + + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return Token() == SyntaxKind.OpenBracketToken || IsLiteralPropertyName(); + case TsTypes.ParsingContext.ObjectLiteralMembers: + + return Token() == SyntaxKind.OpenBracketToken || Token() == SyntaxKind.AsteriskToken || Token() == SyntaxKind.DotDotDotToken || IsLiteralPropertyName(); + case TsTypes.ParsingContext.RestProperties: + + return IsLiteralPropertyName(); + case TsTypes.ParsingContext.ObjectBindingElements: + + return Token() == SyntaxKind.OpenBracketToken || Token() == SyntaxKind.DotDotDotToken || IsLiteralPropertyName(); + case TsTypes.ParsingContext.HeritageClauseElement: + if (Token() == SyntaxKind.OpenBraceToken) + { + + return LookAhead(IsValidHeritageClauseObjectLiteral); + } + if (!inErrorRecovery) + { + + return IsStartOfLeftHandSideExpression() && !IsHeritageClauseExtendsOrImplementsKeyword(); + } + else + { + + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. + return IsIdentifier() && !IsHeritageClauseExtendsOrImplementsKeyword(); + } + //goto caseLabel12; + case TsTypes.ParsingContext.VariableDeclarations: + //caseLabel12: + return IsIdentifierOrPattern(); + case TsTypes.ParsingContext.ArrayBindingElements: + + return Token() == SyntaxKind.CommaToken || Token() == SyntaxKind.DotDotDotToken || IsIdentifierOrPattern(); + case TsTypes.ParsingContext.TypeParameters: + + return IsIdentifier(); + case TsTypes.ParsingContext.ArgumentExpressions: + case TsTypes.ParsingContext.ArrayLiteralMembers: + + return Token() == SyntaxKind.CommaToken || Token() == SyntaxKind.DotDotDotToken || IsStartOfExpression(); + case TsTypes.ParsingContext.Parameters: + + return IsStartOfParameter(); + case TsTypes.ParsingContext.TypeArguments: + case TsTypes.ParsingContext.TupleElementTypes: + + return Token() == SyntaxKind.CommaToken || IsStartOfType(); + case TsTypes.ParsingContext.HeritageClauses: + + return IsHeritageClause(); + case TsTypes.ParsingContext.ImportOrExportSpecifiers: + + return TokenIsIdentifierOrKeyword(Token()); + case TsTypes.ParsingContext.JsxAttributes: + + return TokenIsIdentifierOrKeyword(Token()) || Token() == SyntaxKind.OpenBraceToken; + case TsTypes.ParsingContext.JsxChildren: + + return true; + case TsTypes.ParsingContext.JSDocFunctionParameters: + case TsTypes.ParsingContext.JSDocTypeArguments: + case TsTypes.ParsingContext.JSDocTupleTypes: + + return JsDocParser.IsJsDocType(); + case TsTypes.ParsingContext.JSDocRecordMembers: + + return IsSimplePropertyName(); + } + + + Debug.Fail("Non-exhaustive case in 'isListElement'."); + return false; + } + + + public bool IsValidHeritageClauseObjectLiteral() + { + + Debug.Assert(Token() == SyntaxKind.OpenBraceToken); + if (NextToken() == SyntaxKind.CloseBraceToken) + { + var next = NextToken(); + + return next == SyntaxKind.CommaToken || next == SyntaxKind.OpenBraceToken || next == SyntaxKind.ExtendsKeyword || next == SyntaxKind.ImplementsKeyword; + } + + + return true; + } + + + public bool NextTokenIsIdentifier() + { + + NextToken(); + + return IsIdentifier(); + } + + + public bool NextTokenIsIdentifierOrKeyword() + { + + NextToken(); + + return TokenIsIdentifierOrKeyword(Token()); + } + + + public bool IsHeritageClauseExtendsOrImplementsKeyword() + { + if (Token() == SyntaxKind.ImplementsKeyword || + Token() == SyntaxKind.ExtendsKeyword) + { + + + return LookAhead(NextTokenIsStartOfExpression); + } + + + return false; + } + + + public bool NextTokenIsStartOfExpression() + { + + NextToken(); + + return IsStartOfExpression(); + } + + + public bool IsListTerminator(ParsingContext kind) + { + if (Token() == SyntaxKind.EndOfFileToken) + { + + // Being at the end of the file ends all lists. + return true; + } + switch (kind) + { + case TsTypes.ParsingContext.BlockStatements: + case TsTypes.ParsingContext.SwitchClauses: + case TsTypes.ParsingContext.TypeMembers: + case TsTypes.ParsingContext.ClassMembers: + case TsTypes.ParsingContext.EnumMembers: + case TsTypes.ParsingContext.ObjectLiteralMembers: + case TsTypes.ParsingContext.ObjectBindingElements: + case TsTypes.ParsingContext.ImportOrExportSpecifiers: + + return Token() == SyntaxKind.CloseBraceToken; + case TsTypes.ParsingContext.SwitchClauseStatements: + + return Token() == SyntaxKind.CloseBraceToken || Token() == SyntaxKind.CaseKeyword || Token() == SyntaxKind.DefaultKeyword; + case TsTypes.ParsingContext.HeritageClauseElement: + + return Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.ExtendsKeyword || Token() == SyntaxKind.ImplementsKeyword; + case TsTypes.ParsingContext.VariableDeclarations: + + return IsVariableDeclaratorListTerminator(); + case TsTypes.ParsingContext.TypeParameters: + + // Tokens other than '>' are here for better error recovery + return Token() == SyntaxKind.GreaterThanToken || Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.ExtendsKeyword || Token() == SyntaxKind.ImplementsKeyword; + case TsTypes.ParsingContext.ArgumentExpressions: + + // Tokens other than ')' are here for better error recovery + return Token() == SyntaxKind.CloseParenToken || Token() == SyntaxKind.SemicolonToken; + case TsTypes.ParsingContext.ArrayLiteralMembers: + case TsTypes.ParsingContext.TupleElementTypes: + case TsTypes.ParsingContext.ArrayBindingElements: + + return Token() == SyntaxKind.CloseBracketToken; + case TsTypes.ParsingContext.Parameters: + case TsTypes.ParsingContext.RestProperties: + + // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery + return Token() == SyntaxKind.CloseParenToken || Token() == SyntaxKind.CloseBracketToken /*|| token == SyntaxKind.OpenBraceToken*/; + case TsTypes.ParsingContext.TypeArguments: + + // All other tokens should cause the type-argument to terminate except comma token + return Token() != SyntaxKind.CommaToken; + case TsTypes.ParsingContext.HeritageClauses: + + return Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.CloseBraceToken; + case TsTypes.ParsingContext.JsxAttributes: + + return Token() == SyntaxKind.GreaterThanToken || Token() == SyntaxKind.SlashToken; + case TsTypes.ParsingContext.JsxChildren: + + return Token() == SyntaxKind.LessThanToken && LookAhead(NextTokenIsSlash); + case TsTypes.ParsingContext.JSDocFunctionParameters: + + return Token() == SyntaxKind.CloseParenToken || Token() == SyntaxKind.ColonToken || Token() == SyntaxKind.CloseBraceToken; + case TsTypes.ParsingContext.JSDocTypeArguments: + + return Token() == SyntaxKind.GreaterThanToken || Token() == SyntaxKind.CloseBraceToken; + case TsTypes.ParsingContext.JSDocTupleTypes: + + return Token() == SyntaxKind.CloseBracketToken || Token() == SyntaxKind.CloseBraceToken; + case TsTypes.ParsingContext.JSDocRecordMembers: + + return Token() == SyntaxKind.CloseBraceToken; + } + + return false; // ? + } + + + public bool IsVariableDeclaratorListTerminator() + { + if (CanParseSemicolon()) + { + + return true; + } + if (IsInOrOfKeyword(Token())) + { + + return true; + } + if (Token() == SyntaxKind.EqualsGreaterThanToken) + { + + return true; + } + + + // Keep trying to parse out variable declarators. + return false; + } + + + public bool IsInSomeParsingContext() + { + //throw new NotImplementedException(); + //for (var kind = 0; kind < Enum.GetNames(typeof(ParsingContext)).Count(); kind++) + foreach (ParsingContext kind in Enum.GetValues(typeof(ParsingContext))) + { + if ((ParsingContext & (1 << (int)kind)) != 0) + { + if (IsListElement(kind, /*inErrorRecovery*/ true) || IsListTerminator(kind)) + { + return true; + } + } + } + + + return false; + } + + + public NodeArray ParseList(ParsingContext kind, Func parseElement) where T : INode + { + var saveParsingContext = ParsingContext; + + ParsingContext |= 1 << (int)kind; + var result = CreateList(); + while (!IsListTerminator(kind)) + { + if (IsListElement(kind, /*inErrorRecovery*/ false)) + { + var element = ParseListElement(kind, parseElement); + + result.Add(element); + + + continue; + } + if (AbortParsingListOrMoveToNextToken(kind)) + { + + break; + } + } + + + result.End = GetNodeEnd(); + + ParsingContext = saveParsingContext; + + return result; + } + + public NodeArray ParseList2(ParsingContext kind, Func parseElement) where T : INode + { + var saveParsingContext = ParsingContext; + + ParsingContext |= 1 << (int)kind; + var result = CreateList(); + while (!IsListTerminator(kind)) + { + if (IsListElement(kind, /*inErrorRecovery*/ false)) + { + var element = ParseListElement2(kind, parseElement); + + result.Add(element); + + + continue; + } + if (AbortParsingListOrMoveToNextToken(kind)) + { + + break; + } + } + + + result.End = GetNodeEnd(); + + ParsingContext = saveParsingContext; + + return result; + } + public T ParseListElement(ParsingContext parsingContext, Func parseElement) where T : INode + { + var node = CurrentNode(parsingContext); + if (node != null) + { + + return (T)ConsumeNode(node); + } + + + return parseElement(); + } + public T ParseListElement2(ParsingContext parsingContext, Func parseElement) where T : INode + { + var node = CurrentNode2(parsingContext); + if (node != null) + { + + return (T)ConsumeNode(node); + } + + + return parseElement(); + } + + + public Node CurrentNode(ParsingContext parsingContext) + { + if (ParseErrorBeforeNextFinishedNode) + { + + return null; + } + return null; + //if (syntaxCursor == null) + //{ + + // // if we don't have a cursor, we could never return a node from the old tree. + // return null; + //} + //var node = syntaxCursor.currentNode(scanner.getStartPos()); + //if (nodeIsMissing(node)) + //{ + + // return null; + //} + //if (node.intersectsChange) + //{ + + // return null; + //} + //if (containsParseError(node) != null) + //{ + + // return null; + //} + //var nodeContextFlags = node.flags & NodeFlags.ContextFlags; + //if (nodeContextFlags != contextFlags) + //{ + + // return null; + //} + //if (!canReuseNode(node, parsingContext)) + //{ + + // return null; + //} + + + //return node; + } + + public INode CurrentNode2(ParsingContext parsingContext) + { + if (ParseErrorBeforeNextFinishedNode) + { + + return null; + } + return null; + } + public INode ConsumeNode(INode node) + { + + // Move the scanner so it is after the node we just consumed. + Scanner.SetTextPos(node.End ?? 0); + + NextToken(); + + return node; + } + //public INode consumeNode(INode node) + //{ + + // // Move the scanner so it is after the node we just consumed. + // scanner.setTextPos(node.end); + + // nextToken(); + + // return node; + //} + + + public bool CanReuseNode(Node node, ParsingContext parsingContext) + { + switch (parsingContext) + { + case TsTypes.ParsingContext.ClassMembers: + + return IsReusableClassMember(node); + case TsTypes.ParsingContext.SwitchClauses: + + return IsReusableSwitchClause(node); + case TsTypes.ParsingContext.SourceElements: + case TsTypes.ParsingContext.BlockStatements: + case TsTypes.ParsingContext.SwitchClauseStatements: + + return IsReusableStatement(node); + case TsTypes.ParsingContext.EnumMembers: + + return IsReusableEnumMember(node); + case TsTypes.ParsingContext.TypeMembers: + + return IsReusableTypeMember(node); + case TsTypes.ParsingContext.VariableDeclarations: + + return IsReusableVariableDeclaration(node); + case TsTypes.ParsingContext.Parameters: + + return IsReusableParameter(node); + case TsTypes.ParsingContext.RestProperties: + + return false; + case TsTypes.ParsingContext.HeritageClauses: + case TsTypes.ParsingContext.TypeParameters: + case TsTypes.ParsingContext.TupleElementTypes: + case TsTypes.ParsingContext.TypeArguments: + case TsTypes.ParsingContext.ArgumentExpressions: + case TsTypes.ParsingContext.ObjectLiteralMembers: + case TsTypes.ParsingContext.HeritageClauseElement: + case TsTypes.ParsingContext.JsxAttributes: + case TsTypes.ParsingContext.JsxChildren: + break; + } + + + return false; + } + + + public bool IsReusableClassMember(Node node) + { + if (node != null) + { + switch ((SyntaxKind)node.Kind) + { + case SyntaxKind.Constructor: + case SyntaxKind.IndexSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.SemicolonClassElement: + + return true; + case SyntaxKind.MethodDeclaration: + var methodDeclaration = (MethodDeclaration)node; + var nameIsConstructor = (SyntaxKind)methodDeclaration.Name.Kind == SyntaxKind.Identifier && + ((Identifier)methodDeclaration.Name).OriginalKeywordKind == SyntaxKind.ConstructorKeyword; + + + return !nameIsConstructor; + } + } + + + return false; + } + + + public bool IsReusableSwitchClause(Node node) + { + if (node != null) + { + switch ((SyntaxKind)node.Kind) + { + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + + return true; + } + } + + + return false; + } + + + public bool IsReusableStatement(Node node) + { + if (node != null) + { + switch ((SyntaxKind)node.Kind) + { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.Block: + case SyntaxKind.IfStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.EmptyStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + + return true; + } + } + + + return false; + } + + + public bool IsReusableEnumMember(Node node) + { + + return (SyntaxKind)node.Kind == SyntaxKind.EnumMember; + } + + + public bool IsReusableTypeMember(Node node) + { + if (node != null) + { + switch ((SyntaxKind)node.Kind) + { + case SyntaxKind.ConstructSignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.PropertySignature: + case SyntaxKind.CallSignature: + + return true; + } + } + + + return false; + } + + + public bool IsReusableVariableDeclaration(Node node) + { + if ((SyntaxKind)node.Kind != SyntaxKind.VariableDeclaration) + { + + return false; + } + var variableDeclarator = (VariableDeclaration)node; + + return variableDeclarator.Initializer == null; + } + + + public bool IsReusableParameter(Node node) + { + if ((SyntaxKind)node.Kind != SyntaxKind.Parameter) + { + + return false; + } + var parameter = (ParameterDeclaration)node; + + return parameter.Initializer == null; + } + + + public bool AbortParsingListOrMoveToNextToken(ParsingContext kind) + { + + ParseErrorAtCurrentToken(ParsingContextErrors(kind)); + if (IsInSomeParsingContext()) + { + + return true; + } + + + NextToken(); + + return false; + } + + + public DiagnosticMessage ParsingContextErrors(ParsingContext context) + { + switch (context) + { + case TsTypes.ParsingContext.SourceElements: + return Diagnostics.Declaration_or_statement_expected; + case TsTypes.ParsingContext.BlockStatements: + return Diagnostics.Declaration_or_statement_expected; + case TsTypes.ParsingContext.SwitchClauses: + return Diagnostics.case_or_default_expected; + case TsTypes.ParsingContext.SwitchClauseStatements: + return Diagnostics.Statement_expected; + case TsTypes.ParsingContext.RestProperties: + case TsTypes.ParsingContext.TypeMembers: + return Diagnostics.Property_or_signature_expected; + case TsTypes.ParsingContext.ClassMembers: + return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected; + case TsTypes.ParsingContext.EnumMembers: + return Diagnostics.Enum_member_expected; + case TsTypes.ParsingContext.HeritageClauseElement: + return Diagnostics.Expression_expected; + case TsTypes.ParsingContext.VariableDeclarations: + return Diagnostics.Variable_declaration_expected; + case TsTypes.ParsingContext.ObjectBindingElements: + return Diagnostics.Property_destructuring_pattern_expected; + case TsTypes.ParsingContext.ArrayBindingElements: + return Diagnostics.Array_element_destructuring_pattern_expected; + case TsTypes.ParsingContext.ArgumentExpressions: + return Diagnostics.Argument_expression_expected; + case TsTypes.ParsingContext.ObjectLiteralMembers: + return Diagnostics.Property_assignment_expected; + case TsTypes.ParsingContext.ArrayLiteralMembers: + return Diagnostics.Expression_or_comma_expected; + case TsTypes.ParsingContext.Parameters: + return Diagnostics.Parameter_declaration_expected; + case TsTypes.ParsingContext.TypeParameters: + return Diagnostics.Type_parameter_declaration_expected; + case TsTypes.ParsingContext.TypeArguments: + return Diagnostics.Type_argument_expected; + case TsTypes.ParsingContext.TupleElementTypes: + return Diagnostics.Type_expected; + case TsTypes.ParsingContext.HeritageClauses: + return Diagnostics.Unexpected_token_expected; + case TsTypes.ParsingContext.ImportOrExportSpecifiers: + return Diagnostics.Identifier_expected; + case TsTypes.ParsingContext.JsxAttributes: + return Diagnostics.Identifier_expected; + case TsTypes.ParsingContext.JsxChildren: + return Diagnostics.Identifier_expected; + case TsTypes.ParsingContext.JSDocFunctionParameters: + return Diagnostics.Parameter_declaration_expected; + case TsTypes.ParsingContext.JSDocTypeArguments: + return Diagnostics.Type_argument_expected; + case TsTypes.ParsingContext.JSDocTupleTypes: + return Diagnostics.Type_expected; + case TsTypes.ParsingContext.JSDocRecordMembers: + return Diagnostics.Property_assignment_expected; + } + return null; + } + + + public NodeArray ParseDelimitedList(ParsingContext kind, Func parseElement, bool? considerSemicolonAsDelimiter = null) where T : INode + { + var saveParsingContext = ParsingContext; + + ParsingContext |= 1 << (int)kind; + var result = CreateList(); + var commaStart = -1; + while (true) + { + if (IsListElement(kind, /*inErrorRecovery*/ false)) + { + + result.Add(ParseListElement(kind, parseElement)); + + commaStart = Scanner.GetTokenPos(); + if (ParseOptional(SyntaxKind.CommaToken)) + { + + continue; + } + + + commaStart = -1; + if (IsListTerminator(kind)) + { + + break; + } + + + // We didn't get a comma, and the list wasn't terminated, explicitly parse + // out a comma so we give a good error message. + ParseExpected(SyntaxKind.CommaToken); + if (considerSemicolonAsDelimiter == true && Token() == SyntaxKind.SemicolonToken && !Scanner.HasPrecedingLineBreak()) + { + + NextToken(); + } + + continue; + } + if (IsListTerminator(kind)) + { + + break; + } + if (AbortParsingListOrMoveToNextToken(kind)) + { + + break; + } + } + if (commaStart >= 0) + { + + // Always preserve a trailing comma by marking it on the NodeArray + result.HasTrailingComma = true; + } + + + result.End = GetNodeEnd(); + + ParsingContext = saveParsingContext; + + return result; + } + + + public NodeArray CreateMissingList() where T : INode + { + + return CreateList(); + } + + + + + public NodeArray ParseBracketedList(ParsingContext kind, Func parseElement, SyntaxKind open, SyntaxKind close) where T : INode + { + if (ParseExpected(open)) + { + var result = ParseDelimitedList(kind, parseElement); + + ParseExpected(close); + + return result; + } + + + return CreateMissingList(); + } + + + public IEntityName ParseEntityName(bool allowReservedWords, DiagnosticMessage diagnosticMessage = null) + { + IEntityName entity = ParseIdentifier(diagnosticMessage); + while (ParseOptional(SyntaxKind.DotToken)) + { + QualifiedName node = new QualifiedName { Pos = entity.Pos }; + //(QualifiedName)createNode(SyntaxKind.QualifiedName, entity.pos); + // !!! + node.Left = entity; + + node.Right = ParseRightSideOfDot(allowReservedWords); + + entity = FinishNode(node); + } + + return entity; + } + + + public Identifier ParseRightSideOfDot(bool allowIdentifierNames) + { + if (Scanner.HasPrecedingLineBreak() && TokenIsIdentifierOrKeyword(Token())) + { + var matchesPattern = LookAhead(NextTokenIsIdentifierOrKeywordOnSameLine); + if (matchesPattern) + { + + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return (Identifier)CreateMissingNode< Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + } + } + + + return allowIdentifierNames ? ParseIdentifierName() : ParseIdentifier(); + } + + + public TemplateExpression ParseTemplateExpression() + { + var template = new TemplateExpression() { Pos = Scanner.GetStartPos() }; + + + template.Head = ParseTemplateHead(); + + Debug.Assert((SyntaxKind)template.Head.Kind == SyntaxKind.TemplateHead, "Template head has wrong token kind"); + var templateSpans = CreateList(); + + + do + { + templateSpans.Add(ParseTemplateSpan()); + } + while (LastOrUndefined(templateSpans).Literal.Kind == SyntaxKind.TemplateMiddle); + + + templateSpans.End = GetNodeEnd(); + + template.TemplateSpans = templateSpans; + + + return FinishNode(template); + } + + + public TemplateSpan ParseTemplateSpan() + { + var span = new TemplateSpan() { Pos = Scanner.GetStartPos() }; + + span.Expression = AllowInAnd(ParseExpression); + //var literal = TemplateMiddle | TemplateTail; + if (Token() == SyntaxKind.CloseBraceToken) + { + + ReScanTemplateToken(); + + span.Literal = ParseTemplateMiddleOrTemplateTail(); + } + else + { + + span.Literal = (TemplateTail)ParseExpectedToken(SyntaxKind.TemplateTail, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, TokenToString(SyntaxKind.CloseBraceToken)); + } + + + //span.literal = literal; + + return FinishNode(span); + } + + + public ILiteralExpression ParseLiteralNode(bool? internName = null) + { + var t = Token(); + if (t == SyntaxKind.StringLiteral) return (ILiteralExpression)ParseLiteralLikeNode(new StringLiteral(), internName == true); + else if (t == SyntaxKind.RegularExpressionLiteral) return (ILiteralExpression)ParseLiteralLikeNode(new RegularExpressionLiteral(), internName == true); + else if (t == SyntaxKind.NoSubstitutionTemplateLiteral) return (ILiteralExpression)ParseLiteralLikeNode(new NoSubstitutionTemplateLiteral(), internName == true); + else if (t == SyntaxKind.NumericLiteral) return (ILiteralExpression)ParseLiteralLikeNode(new NumericLiteral(), internName == true); + else + { + throw new NotSupportedException("parseLiteralNode"); + } + //return parseLiteralLikeNode(token(), internName == true); + } + + + public TemplateHead ParseTemplateHead() + { + var t = Token(); + var fragment = new TemplateHead(); + ParseLiteralLikeNode(fragment, /*internName*/ false); + + Debug.Assert((SyntaxKind)fragment.Kind == SyntaxKind.TemplateHead, "Template head has wrong token kind"); + + return fragment; + } + + + public /*TemplateMiddle | TemplateTail*/ILiteralLikeNode ParseTemplateMiddleOrTemplateTail() + { + var t = Token(); + ILiteralLikeNode fragment = null; + if (t == SyntaxKind.TemplateMiddle) + { + fragment = ParseLiteralLikeNode(new TemplateMiddle(), /*internName*/ false); + } + else if (t == SyntaxKind.TemplateTail) + { + fragment = ParseLiteralLikeNode(new TemplateTail(), /*internName*/ false); + } + //var fragment = parseLiteralLikeNode(token(), /*internName*/ false); + + Debug.Assert((SyntaxKind)fragment.Kind == SyntaxKind.TemplateMiddle || (SyntaxKind)fragment.Kind == SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); + + return /*(TemplateMiddle | TemplateTail)*/fragment; + } + + + public ILiteralLikeNode ParseLiteralLikeNode(/*SyntaxKind kind*/ILiteralLikeNode node, bool internName) + { + node.Pos = Scanner.GetStartPos(); + //var node = new LiteralLikeNode { pos = scanner.getStartPos() }; // LiteralExpression(); + var text = Scanner.GetTokenValue(); + + node.Text = internName ? InternIdentifier(text) : text; + if (Scanner.HasExtendedUnicodeEscape()) + { + + node.HasExtendedUnicodeEscape = true; + } + if (Scanner.IsUnterminated()) + { + + node.IsUnterminated = true; + } + var tokenPos = Scanner.GetTokenPos(); + + NextToken(); + + FinishNode(node); + if ((SyntaxKind)node.Kind == SyntaxKind.NumericLiteral + && SourceText.charCodeAt(tokenPos) == (int)CharacterCodes._0 + && IsOctalDigit(SourceText.charCodeAt(tokenPos + 1))) + { + + + node.IsOctalLiteral = true; + } + + + return node; + } + + + public TypeReferenceNode ParseTypeReference() + { + var typeName = ParseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected); + var node = new TypeReferenceNode() { Pos = typeName.Pos }; + + node.TypeName = typeName; + if (!Scanner.HasPrecedingLineBreak() && Token() == SyntaxKind.LessThanToken) + { + + node.TypeArguments = ParseBracketedList(TsTypes.ParsingContext.TypeArguments, ParseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + } + + return FinishNode(node); + } + + + public TypePredicateNode ParseThisTypePredicate(ThisTypeNode lhs) + { + + NextToken(); + var node = new TypePredicateNode { Pos = lhs.Pos }; + + node.ParameterName = lhs; + + node.Type = ParseType(); + + return FinishNode(node); + } + + + public ThisTypeNode ParseThisTypeNode() + { + var node = new ThisTypeNode { Pos = Scanner.GetStartPos() }; + + NextToken(); + + return FinishNode(node); + } + + + public TypeQueryNode ParseTypeQuery() + { + var node = new TypeQueryNode() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.TypeOfKeyword); + + node.ExprName = ParseEntityName(/*allowReservedWords*/ true); + + return FinishNode(node); + } + + + public TypeParameterDeclaration ParseTypeParameter() + { + var node = new TypeParameterDeclaration() { Pos = Scanner.GetStartPos() }; + + node.Name = ParseIdentifier(); + if (ParseOptional(SyntaxKind.ExtendsKeyword)) + { + if (IsStartOfType() || !IsStartOfExpression()) + { + + node.Constraint = ParseType(); + } + else + { + + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the > as we're consuming the expression for "". + node.Expression = (Expression)ParseUnaryExpressionOrHigher(); + } + } + if (ParseOptional(SyntaxKind.EqualsToken)) + { + + node.Default = ParseType(); + } + + + return FinishNode(node); + } + + + public NodeArray ParseTypeParameters() + { + if (Token() == SyntaxKind.LessThanToken) + { + + return ParseBracketedList(TsTypes.ParsingContext.TypeParameters, ParseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + } + return null; + } + + + public ITypeNode ParseParameterType() + { + if (ParseOptional(SyntaxKind.ColonToken)) + { + + return ParseType(); + } + + + return null; + } + + + public bool IsStartOfParameter() + { + + return Token() == SyntaxKind.DotDotDotToken || IsIdentifierOrPattern() || IsModifierKind(Token()) || Token() == SyntaxKind.AtToken || Token() == SyntaxKind.ThisKeyword; + } + + + public ParameterDeclaration ParseParameter() + { + var node = new ParameterDeclaration() { Pos = Scanner.GetStartPos() }; + if (Token() == SyntaxKind.ThisKeyword) + { + + node.Name = CreateIdentifier(/*isIdentifier*/true, null); + + node.Type = ParseParameterType(); + + return FinishNode(node); + } + + + node.Decorators = ParseDecorators(); + + node.Modifiers = ParseModifiers(); + + node.DotDotDotToken = (DotDotDotToken)ParseOptionalToken(SyntaxKind.DotDotDotToken); + + + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] + node.Name = ParseIdentifierOrPattern(); + if (GetFullWidth(node.Name) == 0 && !HasModifiers(node) && IsModifierKind(Token())) + { + + // in cases like + // 'use strict' + // function foo(static) + // isParameter('static') == true, because of isModifier('static') + // however 'static' is not a legal identifier in a strict mode. + // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = null, initializer = null) + // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) + // to avoid this we'll advance cursor to the next token. + NextToken(); + } + + + node.QuestionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + + node.Type = ParseParameterType(); + + node.Initializer = ParseBindingElementInitializer(/*inParameter*/ true); + + + // Do not check for initializers in an ambient context for parameters. This is not + // a grammar error because the grammar allows arbitrary call signatures in + // an ambient context. + // It is actually not necessary for this to be an error at all. The reason is that + // function/constructor implementations are syntactically disallowed in ambient + // contexts. In addition, parameter initializers are semantically disallowed in + // overload signatures. So parameter initializers are transitively disallowed in + // ambient contexts. + + return AddJsDocComment(FinishNode(node)); + } + + + public IExpression ParseBindingElementInitializer(bool inParameter) + { + + return inParameter ? ParseParameterInitializer() : ParseNonParameterInitializer(); + } + + + public IExpression ParseParameterInitializer() + { + + return ParseInitializer(/*inParameter*/ true); + } + + + public void FillSignature(SyntaxKind returnToken, bool + yieldContext, bool + awaitContext, bool + requireCompleteParameterList, ISignatureDeclaration + signature) + { + var returnTokenRequired = returnToken == SyntaxKind.EqualsGreaterThanToken; + + signature.TypeParameters = ParseTypeParameters(); + + signature.Parameters = ParseParameterList(yieldContext, awaitContext, requireCompleteParameterList); + if (returnTokenRequired) + { + + ParseExpected(returnToken); + + signature.Type = ParseTypeOrTypePredicate(); + } + else + if (ParseOptional(returnToken)) + { + + signature.Type = ParseTypeOrTypePredicate(); + } + } + public void FillSignatureEqualsGreaterThanToken(SyntaxKind returnToken, bool + yieldContext, bool + awaitContext, bool + requireCompleteParameterList, SignatureDeclaration + signature) + { + var returnTokenRequired = returnToken == SyntaxKind.EqualsGreaterThanToken; + + signature.TypeParameters = ParseTypeParameters(); + + signature.Parameters = ParseParameterList(yieldContext, awaitContext, requireCompleteParameterList); + if (returnTokenRequired) + { + + ParseExpected(returnToken); + + signature.Type = ParseTypeOrTypePredicate(); + } + else + if (ParseOptional(returnToken)) + { + + signature.Type = ParseTypeOrTypePredicate(); + } + } + public void FillSignatureColonToken(SyntaxKind + returnToken, bool + yieldContext, bool + awaitContext, bool + requireCompleteParameterList, SignatureDeclaration + signature) + { + var returnTokenRequired = returnToken == SyntaxKind.EqualsGreaterThanToken; + + signature.TypeParameters = ParseTypeParameters(); + + signature.Parameters = ParseParameterList(yieldContext, awaitContext, requireCompleteParameterList); + if (returnTokenRequired) + { + + ParseExpected(returnToken); + + signature.Type = ParseTypeOrTypePredicate(); + } + else + if (ParseOptional(returnToken)) + { + + signature.Type = ParseTypeOrTypePredicate(); + } + } + + public NodeArray ParseParameterList(bool yieldContext, bool awaitContext, bool requireCompleteParameterList) + { + if (ParseExpected(SyntaxKind.OpenParenToken)) + { + var savedYieldContext = InYieldContext(); + var savedAwaitContext = InAwaitContext(); + + + SetYieldContext(yieldContext); + + SetAwaitContext(awaitContext); + var result = ParseDelimitedList(TsTypes.ParsingContext.Parameters, ParseParameter); + + + SetYieldContext(savedYieldContext); + + SetAwaitContext(savedAwaitContext); + if (!ParseExpected(SyntaxKind.CloseParenToken) && requireCompleteParameterList) + { + + // Caller insisted that we had to end with a ) We didn't. So just return + // null here. + return null; + } + + + return result; + } + + + // We didn't even have an open paren. If the caller requires a complete parameter list, + // we definitely can't provide that. However, if they're ok with an incomplete one, + // then just return an empty set of parameters. + return requireCompleteParameterList ? null : CreateMissingList(); + } + + + public void ParseTypeMemberSemicolon() + { + if (ParseOptional(SyntaxKind.CommaToken)) + { + + return; + } + + + // Didn't have a comma. We must have a (possible ASI) semicolon. + ParseSemicolon(); + } + + + public /*CallSignatureDeclaration | ConstructSignatureDeclaration*/ITypeElement ParseSignatureMember(SyntaxKind kind) + { + //var node = new CallSignatureDeclaration | ConstructSignatureDeclaration(); + if (kind == SyntaxKind.ConstructSignature) + { + + var node = new ConstructSignatureDeclaration { Pos = Scanner.GetStartPos() }; + ParseExpected(SyntaxKind.NewKeyword); + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + ParseTypeMemberSemicolon(); + + return AddJsDocComment(FinishNode(node)); + } + else + { + var node = new CallSignatureDeclaration { Pos = Scanner.GetStartPos() }; + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + ParseTypeMemberSemicolon(); + + return AddJsDocComment(FinishNode(node)); + } + + //fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + //parseTypeMemberSemicolon(); + + //return addJSDocComment(finishNode(node)); + } + + + public bool IsIndexSignature() + { + if (Token() != SyntaxKind.OpenBracketToken) + { + + return false; + } + + + return LookAhead(IsUnambiguouslyIndexSignature); + } + + + public bool IsUnambiguouslyIndexSignature() + { + + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // + NextToken(); + if (Token() == SyntaxKind.DotDotDotToken || Token() == SyntaxKind.CloseBracketToken) + { + + return true; + } + if (IsModifierKind(Token())) + { + + NextToken(); + if (IsIdentifier()) + { + + return true; + } + } + else + if (!IsIdentifier()) + { + + return false; + } + else + { + + // Skip the identifier + NextToken(); + } + if (Token() == SyntaxKind.ColonToken || Token() == SyntaxKind.CommaToken) + { + + return true; + } + if (Token() != SyntaxKind.QuestionToken) + { + + return false; + } + + + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. + NextToken(); + + return Token() == SyntaxKind.ColonToken || Token() == SyntaxKind.CommaToken || Token() == SyntaxKind.CloseBracketToken; + } + + + public IndexSignatureDeclaration ParseIndexSignatureDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new IndexSignatureDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + node.Parameters = ParseBracketedList(TsTypes.ParsingContext.Parameters, ParseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + + node.Type = ParseTypeAnnotation(); + + ParseTypeMemberSemicolon(); + + return FinishNode(node); + } + + + public /*PropertySignature | MethodSignature*/ITypeElement ParsePropertyOrMethodSignature(int fullStart, NodeArray modifiers) + { + var name = ParsePropertyName(); + var questionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + if (Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken) + { + var method = new MethodSignature() { Pos = fullStart }; + + method.Modifiers = modifiers; + + method.Name = name; + + method.QuestionToken = questionToken; + + + // Method signatures don't exist in expression contexts. So they have neither + // [Yield] nor [Await] + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, method); + + ParseTypeMemberSemicolon(); + + return AddJsDocComment(FinishNode(method)); + } + else + { + var property = new PropertySignature() { Pos = fullStart }; + + property.Modifiers = modifiers; + + property.Name = name; + + property.QuestionToken = questionToken; + + property.Type = ParseTypeAnnotation(); + if (Token() == SyntaxKind.EqualsToken) + { + + // Although type literal properties cannot not have initializers, we attempt + // to parse an initializer so we can report in the checker that an interface + // property or type literal property cannot have an initializer. + property.Initializer = ParseNonParameterInitializer(); + } + + + ParseTypeMemberSemicolon(); + + return AddJsDocComment(FinishNode(property)); + } + } + + + public bool IsTypeMemberStart() + { + if (Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken) + { + + return true; + } + bool idToken = false; + while (IsModifierKind(Token())) + { + + idToken = true; + + NextToken(); + } + if (Token() == SyntaxKind.OpenBracketToken) + { + + return true; + } + if (IsLiteralPropertyName()) + { + + idToken = true; + + NextToken(); + } + if (idToken) + { + + return Token() == SyntaxKind.OpenParenToken || + Token() == SyntaxKind.LessThanToken || + Token() == SyntaxKind.QuestionToken || + Token() == SyntaxKind.ColonToken || + Token() == SyntaxKind.CommaToken || + CanParseSemicolon(); + } + + return false; + } + + + public ITypeElement ParseTypeMember() + { + if (Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken) + { + + return ParseSignatureMember(SyntaxKind.CallSignature); + } + if (Token() == SyntaxKind.NewKeyword && LookAhead(IsStartOfConstructSignature)) + { + + return ParseSignatureMember(SyntaxKind.ConstructSignature); + } + var fullStart = GetNodePos(); + var modifiers = ParseModifiers(); + if (IsIndexSignature()) + { + + return ParseIndexSignatureDeclaration(fullStart, /*decorators*/ null, modifiers); + } + + return ParsePropertyOrMethodSignature(fullStart, modifiers); + } + + + public bool IsStartOfConstructSignature() + { + + NextToken(); + + return Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken; + } + + + public TypeLiteralNode ParseTypeLiteral() + { + var node = new TypeLiteralNode() { Pos = Scanner.GetStartPos() }; + + node.Members = ParseObjectTypeMembers(); + + return FinishNode(node); + } + + + public NodeArray ParseObjectTypeMembers() + { + NodeArray members = null; + if (ParseExpected(SyntaxKind.OpenBraceToken)) + { + + members = ParseList(TsTypes.ParsingContext.TypeMembers, ParseTypeMember); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + members = CreateMissingList(); + } + + + return members; + } + + + public bool IsStartOfMappedType() + { + + NextToken(); + if (Token() == SyntaxKind.ReadonlyKeyword) + { + + NextToken(); + } + + return Token() == SyntaxKind.OpenBracketToken && NextTokenIsIdentifier() && NextToken() == SyntaxKind.InKeyword; + } + + + public TypeParameterDeclaration ParseMappedTypeParameter() + { + var node = new TypeParameterDeclaration() { Pos = Scanner.GetStartPos() }; + + node.Name = ParseIdentifier(); + + ParseExpected(SyntaxKind.InKeyword); + + node.Constraint = ParseType(); + + return FinishNode(node); + } + + + public MappedTypeNode ParseMappedType() + { + var node = new MappedTypeNode() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBraceToken); + + node.ReadonlyToken = (ReadonlyToken)ParseOptionalToken(SyntaxKind.ReadonlyKeyword); + + ParseExpected(SyntaxKind.OpenBracketToken); + + node.TypeParameter = ParseMappedTypeParameter(); + + ParseExpected(SyntaxKind.CloseBracketToken); + + node.QuestionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + + node.Type = ParseTypeAnnotation(); + + ParseSemicolon(); + + ParseExpected(SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + + + public TupleTypeNode ParseTupleType() + { + var node = new TupleTypeNode() { Pos = Scanner.GetStartPos() }; + + node.ElementTypes = ParseBracketedList(TsTypes.ParsingContext.TupleElementTypes, ParseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + + return FinishNode(node); + } + + + public ParenthesizedTypeNode ParseParenthesizedType() + { + var node = new ParenthesizedTypeNode() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Type = ParseType(); + + ParseExpected(SyntaxKind.CloseParenToken); + + return FinishNode(node); + } + + + public IFunctionOrConstructorTypeNode ParseFunctionOrConstructorType(SyntaxKind kind) + { + + var node = kind == SyntaxKind.FunctionType ? + (IFunctionOrConstructorTypeNode)new FunctionTypeNode { Kind = SyntaxKind.FunctionType } : + kind == SyntaxKind.ConstructorType ? + new ConstructorTypeNode { Kind = SyntaxKind.ConstructorType } : + throw new NotSupportedException("parseFunctionOrConstructorType"); + node.Pos = Scanner.GetStartPos(); + //new FunctionOrConstructorTypeNode { kind = kind, pos = scanner.getStartPos() }; + if (kind == SyntaxKind.ConstructorType) + { + + ParseExpected(SyntaxKind.NewKeyword); + } + + FillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + return FinishNode(node); + } + + + public TypeNode ParseKeywordAndNoDot() + { + var node = ParseTokenNode(Token()); + + return Token() == SyntaxKind.DotToken ? null : node; + } + + + public LiteralTypeNode ParseLiteralTypeNode() + { + var node = new LiteralTypeNode() { Pos = Scanner.GetStartPos() }; + + node.Literal = ParseSimpleUnaryExpression(); + + FinishNode(node); + + return node; + } + + + public bool NextTokenIsNumericLiteral() + { + + return NextToken() == SyntaxKind.NumericLiteral; + } + + + public ITypeNode ParseNonArrayType() + { + switch (Token()) + { + case SyntaxKind.AnyKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ObjectKeyword: + var node = TryParse(ParseKeywordAndNoDot); + + return node ?? ParseTypeReference(); + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + + return ParseLiteralTypeNode(); + case SyntaxKind.MinusToken: + + return LookAhead(NextTokenIsNumericLiteral) ? (ITypeNode)ParseLiteralTypeNode() : ParseTypeReference(); + case SyntaxKind.VoidKeyword: + case SyntaxKind.NullKeyword: + + return ParseTokenNode(Token()); + case SyntaxKind.ThisKeyword: + { + var thisKeyword = ParseThisTypeNode(); + if (Token() == SyntaxKind.IsKeyword && !Scanner.HasPrecedingLineBreak()) + { + return ParseThisTypePredicate(thisKeyword); + } + else + { + return thisKeyword; + } + } + //goto caseLabel17; + case SyntaxKind.TypeOfKeyword: + //caseLabel17: + return ParseTypeQuery(); + case SyntaxKind.OpenBraceToken: + + return LookAhead(IsStartOfMappedType) ? (ITypeNode)ParseMappedType() : ParseTypeLiteral(); + case SyntaxKind.OpenBracketToken: + + return ParseTupleType(); + case SyntaxKind.OpenParenToken: + + return ParseParenthesizedType(); + default: + + return ParseTypeReference(); + } + } + + + public bool IsStartOfType() + { + switch (Token()) + { + case SyntaxKind.AnyKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBracketToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.BarToken: + case SyntaxKind.AmpersandToken: + case SyntaxKind.NewKeyword: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.ObjectKeyword: + + return true; + case SyntaxKind.MinusToken: + + return LookAhead(NextTokenIsNumericLiteral); + case SyntaxKind.OpenParenToken: + + // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, + // or something that starts a type. We don't want to consider things like '(1)' a type. + return LookAhead(IsStartOfParenthesizedOrFunctionType); + default: + + return IsIdentifier(); + } + } + + + public bool IsStartOfParenthesizedOrFunctionType() + { + + NextToken(); + + return Token() == SyntaxKind.CloseParenToken || IsStartOfParameter() || IsStartOfType(); + } + + + public ITypeNode ParseArrayTypeOrHigher() + { + var type = ParseNonArrayType(); + while (!Scanner.HasPrecedingLineBreak() && ParseOptional(SyntaxKind.OpenBracketToken)) + { + if (IsStartOfType()) + { + var node = new IndexedAccessTypeNode() { Pos = type.Pos }; + + node.ObjectType = type; + + node.IndexType = ParseType(); + + ParseExpected(SyntaxKind.CloseBracketToken); + + type = FinishNode(node); + } + else + { + var node = new ArrayTypeNode() { Pos = type.Pos }; + + node.ElementType = type; + + ParseExpected(SyntaxKind.CloseBracketToken); + + type = FinishNode(node); + } + } + + return type; + } + + + public /*MappedTypeNode*/TypeOperatorNode ParseTypeOperator(SyntaxKind/*.KeyOfKeyword*/ @operator) + { + var node = new TypeOperatorNode() { Pos = Scanner.GetStartPos() }; + + ParseExpected(@operator); + + node.Operator = @operator; + + node.Type = ParseTypeOperatorOrHigher(); + + return FinishNode(node); + } + + + public ITypeNode ParseTypeOperatorOrHigher() + { + switch (Token()) + { + case SyntaxKind.KeyOfKeyword: + + return ParseTypeOperator(SyntaxKind.KeyOfKeyword); + } + + return ParseArrayTypeOrHigher(); + } + + + public ITypeNode ParseUnionOrIntersectionType(SyntaxKind/*.UnionType | SyntaxKind.IntersectionType*/ kind, Func parseConstituentType, SyntaxKind/*.BarToken | SyntaxKind.AmpersandToken*/ @operator) + { + + ParseOptional(@operator); + var type = parseConstituentType(); + if (Token() == @operator) + { + var types = CreateList(); //[type], type.pos); + types.Pos = type.Pos; + types.Add(type); + + + while (ParseOptional(@operator)) + { + + types.Add(parseConstituentType()); + } + + types.End = GetNodeEnd(); + var node = kind == SyntaxKind.UnionType ? + (IUnionOrIntersectionTypeNode)new UnionTypeNode { Kind = kind, Pos = type.Pos } : + kind == SyntaxKind.IntersectionType ? new IntersectionTypeNode { Kind = kind, Pos = type.Pos } + : throw new NotSupportedException("parseUnionOrIntersectionType"); + + node.Types = types; + + type = FinishNode(node); + } + + return type; + } + + + public ITypeNode ParseIntersectionTypeOrHigher() + { + + return ParseUnionOrIntersectionType(SyntaxKind.IntersectionType, ParseTypeOperatorOrHigher, SyntaxKind.AmpersandToken); + } + + + public ITypeNode ParseUnionTypeOrHigher() + { + + return ParseUnionOrIntersectionType(SyntaxKind.UnionType, ParseIntersectionTypeOrHigher, SyntaxKind.BarToken); + } + + + public bool IsStartOfFunctionType() + { + if (Token() == SyntaxKind.LessThanToken) + { + + return true; + } + + return Token() == SyntaxKind.OpenParenToken && LookAhead(IsUnambiguouslyStartOfFunctionType); + } + + + public bool SkipParameterStart() + { + if (IsModifierKind(Token())) + { + + // Skip modifiers + ParseModifiers(); + } + if (IsIdentifier() || Token() == SyntaxKind.ThisKeyword) + { + + NextToken(); + + return true; + } + if (Token() == SyntaxKind.OpenBracketToken || Token() == SyntaxKind.OpenBraceToken) + { + var previousErrorCount = ParseDiagnostics.Count; + + ParseIdentifierOrPattern(); + + return previousErrorCount == ParseDiagnostics.Count; + } + + return false; + } + + + public bool IsUnambiguouslyStartOfFunctionType() + { + + NextToken(); + if (Token() == SyntaxKind.CloseParenToken || Token() == SyntaxKind.DotDotDotToken) + { + + // ( ) + // ( ... + return true; + } + if (SkipParameterStart()) + { + if (Token() == SyntaxKind.ColonToken || Token() == SyntaxKind.CommaToken || + Token() == SyntaxKind.QuestionToken || Token() == SyntaxKind.EqualsToken) + { + + // ( xxx : + // ( xxx , + // ( xxx ? + // ( xxx = + return true; + } + if (Token() == SyntaxKind.CloseParenToken) + { + + NextToken(); + if (Token() == SyntaxKind.EqualsGreaterThanToken) + { + + // ( xxx ) => + return true; + } + } + } + + return false; + } + + + public ITypeNode ParseTypeOrTypePredicate() + { + var typePredicateVariable = IsIdentifier() ? TryParse(ParseTypePredicatePrefix) : null; + var type = ParseType(); + if (typePredicateVariable != null) + { + var node = new TypePredicateNode() { Pos = typePredicateVariable.Pos }; + + node.ParameterName = typePredicateVariable; + + node.Type = type; + + return FinishNode(node); + } + else + { + + return type; + } + } + + + public Identifier ParseTypePredicatePrefix() + { + var id = ParseIdentifier(); + if (Token() == SyntaxKind.IsKeyword && !Scanner.HasPrecedingLineBreak()) + { + + NextToken(); + + return id; + } + return null; + } + + + public ITypeNode ParseType() + { + + // The rules about 'yield' only apply to actual code/expression contexts. They don't + // apply to 'type' contexts. So we disable these parameters here before moving on. + return DoOutsideOfContext(NodeFlags.TypeExcludesFlags, ParseTypeWorker); + } + + + public ITypeNode ParseTypeWorker() + { + if (IsStartOfFunctionType()) + { + + return ParseFunctionOrConstructorType(SyntaxKind.FunctionType); + } + if (Token() == SyntaxKind.NewKeyword) + { + + return ParseFunctionOrConstructorType(SyntaxKind.ConstructorType); + } + + return ParseUnionTypeOrHigher(); + } + + + public ITypeNode ParseTypeAnnotation() + { + + return ParseOptional(SyntaxKind.ColonToken) ? ParseType() : null; + } + + + public bool IsStartOfLeftHandSideExpression() + { + switch (Token()) + { + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.OpenParenToken: + case SyntaxKind.OpenBracketToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.NewKeyword: + case SyntaxKind.SlashToken: + case SyntaxKind.SlashEqualsToken: + case SyntaxKind.Identifier: + + return true; + default: + + return IsIdentifier(); + } + } + + + public bool IsStartOfExpression() + { + if (IsStartOfLeftHandSideExpression()) + { + + return true; + } + switch (Token()) + { + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.DeleteKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.PlusPlusToken: + case SyntaxKind.MinusMinusToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.AwaitKeyword: + case SyntaxKind.YieldKeyword: + + // Yield/await always starts an expression. Either it is an identifier (in which case + // it is definitely an expression). Or it's a keyword (either because we're in + // a generator or async function, or in strict mode (or both)) and it started a yield or await expression. + return true; + default: + + // Error tolerance. If we see the start of some binary operator, we consider + // that the start of an expression. That way we'll parse out a missing identifier, + // give a good message about an identifier being missing, and then consume the + // rest of the binary expression. + if (IsBinaryOperator()) + { + return true; + } + + + return IsIdentifier(); + } + } + + + public bool IsStartOfExpressionStatement() + { + + // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. + return Token() != SyntaxKind.OpenBraceToken && + Token() != SyntaxKind.FunctionKeyword && + Token() != SyntaxKind.ClassKeyword && + Token() != SyntaxKind.AtToken && + IsStartOfExpression(); + } + + + public IExpression ParseExpression() + { + var saveDecoratorContext = InDecoratorContext(); + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ false); + } + var expr = ParseAssignmentExpressionOrHigher(); + /*BinaryOperator*/ + Token operatorToken = null; + while ((operatorToken = (/*BinaryOperator*/Token)ParseOptionalToken(SyntaxKind.CommaToken)) != null) + { + + expr = MakeBinaryExpression(expr, operatorToken, ParseAssignmentExpressionOrHigher()); + } + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ true); + } + + return expr; + } + + + public IExpression ParseInitializer(bool inParameter) + { + if (Token() != SyntaxKind.EqualsToken) + { + if (Scanner.HasPrecedingLineBreak() || (inParameter && Token() == SyntaxKind.OpenBraceToken) || !IsStartOfExpression()) + { + + // preceding line break, open brace in a parameter (likely a function body) or current token is not an expression - + // do not try to parse initializer + return null; + } + } + + + // Initializer[In, Yield] : + // = AssignmentExpression[?In, ?Yield] + + ParseExpected(SyntaxKind.EqualsToken); + + return ParseAssignmentExpressionOrHigher(); + } + + + public IExpression ParseAssignmentExpressionOrHigher() + { + if (IsYieldExpression()) + { + + return ParseYieldExpression(); + } + var arrowExpression = TryParseParenthesizedArrowFunctionExpression() ?? TryParseAsyncSimpleArrowFunctionExpression(); + if (arrowExpression != null) + { + + return arrowExpression; + } + var expr = ParseBinaryExpressionOrHigher(/*precedence*/ 0); + if ((SyntaxKind)expr.Kind == SyntaxKind.Identifier && Token() == SyntaxKind.EqualsGreaterThanToken) + { + + return ParseSimpleArrowFunctionExpression((Identifier)expr); + } + if (IsLeftHandSideExpression(expr) && IsAssignmentOperator(ReScanGreaterToken())) + { + + return MakeBinaryExpression(expr, ParseTokenNode(Token()), ParseAssignmentExpressionOrHigher()); + } + + + // It wasn't an assignment or a lambda. This is a conditional expression: + return ParseConditionalExpressionRest(expr); + } + + + public bool IsYieldExpression() + { + if (Token() == SyntaxKind.YieldKeyword) + { + if (InYieldContext()) + { + + return true; + } + + + // We're in a context where 'yield expr' is not allowed. However, if we can + // definitely tell that the user was trying to parse a 'yield expr' and not + // just a normal expr that start with a 'yield' identifier, then parse out + // a 'yield expr'. We can then report an error later that they are only + // allowed in generator expressions. + // + // for example, if we see 'yield(foo)', then we'll have to treat that as an + // invocation expression of something called 'yield'. However, if we have + // 'yield foo' then that is not legal as a normal expression, so we can + // definitely recognize this as a yield expression. + // + // for now we just check if the next token is an identifier. More heuristics + // can be added here later as necessary. We just need to make sure that we + // don't accidentally consume something legal. + return LookAhead(NextTokenIsIdentifierOrKeywordOrNumberOnSameLine); + } + + + return false; + } + + + public bool NextTokenIsIdentifierOnSameLine() + { + + NextToken(); + + return !Scanner.HasPrecedingLineBreak() && IsIdentifier(); + } + + + public YieldExpression ParseYieldExpression() + { + var node = new YieldExpression() { Pos = Scanner.GetStartPos() }; + + + // YieldExpression[In] : + // yield + // yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] + // yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] + NextToken(); + if (!Scanner.HasPrecedingLineBreak() && + (Token() == SyntaxKind.AsteriskToken || IsStartOfExpression())) + { + + node.AsteriskToken = (AsteriskToken)ParseOptionalToken(SyntaxKind.AsteriskToken); + + node.Expression = ParseAssignmentExpressionOrHigher(); + + return FinishNode(node); + } + else + { + + // if the next token is not on the same line as yield. or we don't have an '*' or + // the start of an expression, then this is just a simple "yield" expression. + return FinishNode(node); + } + } + + + public ArrowFunction ParseSimpleArrowFunctionExpression(Identifier identifier, NodeArray asyncModifier = null) + { + + Debug.Assert(Token() == SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); + ArrowFunction node = null; + if (asyncModifier != null) + { + + node = new ArrowFunction { Pos = (int)asyncModifier.Pos }; // (ArrowFunction)createNode(SyntaxKind.ArrowFunction, asyncModifier.pos); + + node.Modifiers = asyncModifier; + } + else + { + + node = new ArrowFunction { Pos = identifier.Pos }; // (ArrowFunction)createNode(SyntaxKind.ArrowFunction, identifier.pos); + } + var parameter = new ParameterDeclaration() { Pos = identifier.Pos }; + + parameter.Name = identifier; + + FinishNode(parameter); + + + node.Parameters = CreateList(); // ([parameter], parameter.pos); + node.Parameters.Pos = parameter.Pos; + node.Parameters.Add(parameter); + + + node.Parameters.End = parameter.End; + + + node.EqualsGreaterThanToken = (EqualsGreaterThanToken)ParseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>"); + + node.Body = ParseArrowFunctionExpressionBody(/*isAsync*/ /*!!*/asyncModifier?.Any() == true); + + + return AddJsDocComment(FinishNode(node)); + } + + + public ArrowFunction TryParseParenthesizedArrowFunctionExpression() + { + var triState = IsParenthesizedArrowFunctionExpression(); + if (triState == Tristate.False) + { + + // It's definitely not a parenthesized arrow function expression. + return null; + } + var arrowFunction = triState == Tristate.True + ? ParseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) + : TryParse(ParsePossibleParenthesizedArrowFunctionExpressionHead); + if (arrowFunction == null) + { + + // Didn't appear to actually be a parenthesized arrow function. Just bail out. + return null; + } + var isAsync = /*!!*/(GetModifierFlags(arrowFunction) & ModifierFlags.Async) != 0; + var lastToken = Token(); + + arrowFunction.EqualsGreaterThanToken = (EqualsGreaterThanToken)ParseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/false, Diagnostics._0_expected, "=>"); + + arrowFunction.Body = (lastToken == SyntaxKind.EqualsGreaterThanToken || lastToken == SyntaxKind.OpenBraceToken) + ? ParseArrowFunctionExpressionBody(isAsync) + : ParseIdentifier(); + + + return AddJsDocComment(FinishNode(arrowFunction)); + } + + + public Tristate IsParenthesizedArrowFunctionExpression() + { + if (Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken || Token() == SyntaxKind.AsyncKeyword) + { + + return LookAhead(IsParenthesizedArrowFunctionExpressionWorker); + } + if (Token() == SyntaxKind.EqualsGreaterThanToken) + { + + // ERROR RECOVERY TWEAK: + // If we see a standalone => try to parse it as an arrow function expression as that's + // likely what the user intended to write. + return Tristate.True; + } + + // Definitely not a parenthesized arrow function. + return Tristate.False; + } + + + public Tristate IsParenthesizedArrowFunctionExpressionWorker() + { + if (Token() == SyntaxKind.AsyncKeyword) + { + + NextToken(); + if (Scanner.HasPrecedingLineBreak()) + { + + return Tristate.False; + } + if (Token() != SyntaxKind.OpenParenToken && Token() != SyntaxKind.LessThanToken) + { + + return Tristate.False; + } + } + var first = Token(); + var second = NextToken(); + if (first == SyntaxKind.OpenParenToken) + { + if (second == SyntaxKind.CloseParenToken) + { + var third = NextToken(); + switch (third) + { + case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ColonToken: + case SyntaxKind.OpenBraceToken: + + return Tristate.True; + default: + + return Tristate.False; + } + } + if (second == SyntaxKind.OpenBracketToken || second == SyntaxKind.OpenBraceToken) + { + + return Tristate.Unknown; + } + if (second == SyntaxKind.DotDotDotToken) + { + + return Tristate.True; + } + if (!IsIdentifier()) + { + + return Tristate.False; + } + if (NextToken() == SyntaxKind.ColonToken) + { + + return Tristate.True; + } + + + // This *could* be a parenthesized arrow function. + // Return Unknown to let the caller know. + return Tristate.Unknown; + } + else + { + + Debug.Assert(first == SyntaxKind.LessThanToken); + if (!IsIdentifier()) + { + + return Tristate.False; + } + if (SourceFile.LanguageVariant == LanguageVariant.Jsx) + { + var isArrowFunctionInJsx = LookAhead(() => + { + var third = NextToken(); + if (third == SyntaxKind.ExtendsKeyword) + { + var fourth = NextToken(); + switch (fourth) + { + case SyntaxKind.EqualsToken: + case SyntaxKind.GreaterThanToken: + return false; + default: + return true; + } + } + else if (third == SyntaxKind.CommaToken) + { + return true; + } + return false; + }); + if (isArrowFunctionInJsx) + { + + return Tristate.True; + } + + + return Tristate.False; + } + + + // This *could* be a parenthesized arrow function. + return Tristate.Unknown; + } + } + + + public ArrowFunction ParsePossibleParenthesizedArrowFunctionExpressionHead() + { + + return ParseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); + } + + + public ArrowFunction TryParseAsyncSimpleArrowFunctionExpression() + { + if (Token() == SyntaxKind.AsyncKeyword) + { + var isUnParenthesizedAsyncArrowFunction = LookAhead(IsUnParenthesizedAsyncArrowFunctionWorker); + if (isUnParenthesizedAsyncArrowFunction == Tristate.True) + { + var asyncModifier = ParseModifiersForArrowFunction(); + var expr = ParseBinaryExpressionOrHigher(/*precedence*/ 0); + + return ParseSimpleArrowFunctionExpression((Identifier)expr, asyncModifier); + } + } + + return null; + } + + + public Tristate IsUnParenthesizedAsyncArrowFunctionWorker() + { + if (Token() == SyntaxKind.AsyncKeyword) + { + + NextToken(); + if (Scanner.HasPrecedingLineBreak() || Token() == SyntaxKind.EqualsGreaterThanToken) + { + + return Tristate.False; + } + var expr = ParseBinaryExpressionOrHigher(/*precedence*/ 0); + if (!Scanner.HasPrecedingLineBreak() && (SyntaxKind)expr.Kind == SyntaxKind.Identifier && Token() == SyntaxKind.EqualsGreaterThanToken) + { + + return Tristate.True; + } + } + + + return Tristate.False; + } + + + public ArrowFunction ParseParenthesizedArrowFunctionExpressionHead(bool allowAmbiguity) + { + var node = new ArrowFunction() { Pos = Scanner.GetStartPos() }; + + node.Modifiers = ParseModifiersForArrowFunction(); + var isAsync = /*!!*/(GetModifierFlags(node) & ModifierFlags.Async) != 0; + + + // Arrow functions are never generators. + // + // If we're speculatively parsing a signature for a parenthesized arrow function, then + // we have to have a complete parameter list. Otherwise we might see something like + // a => (b => c) + // And think that "(b =>" was actually a parenthesized arrow function with a missing + // close paren. + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ !allowAmbiguity, node); + if (node.Parameters == null) + { + + return null; + } + if (!allowAmbiguity && Token() != SyntaxKind.EqualsGreaterThanToken && Token() != SyntaxKind.OpenBraceToken) + { + + // Returning null here will cause our caller to rewind to where we started from. + return null; + } + + + return node; + } + + + public /*Block | Expression*/IBlockOrExpression ParseArrowFunctionExpressionBody(bool isAsync) + { + if (Token() == SyntaxKind.OpenBraceToken) + { + + return ParseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false); + } + if (Token() != SyntaxKind.SemicolonToken && + Token() != SyntaxKind.FunctionKeyword && + Token() != SyntaxKind.ClassKeyword && + IsStartOfStatement() && + !IsStartOfExpressionStatement()) + { + + // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) + // + // Here we try to recover from a potential error situation in the case where the + // user meant to supply a block. For example, if the user wrote: + // + // a => + // let v = 0; + // } + // + // they may be missing an open brace. Check to see if that's the case so we can + // try to recover better. If we don't do this, then the next close curly we see may end + // up preemptively closing the containing construct. + // + // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error. + return ParseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ true); + } + + + return isAsync + ? DoInAwaitContext(ParseAssignmentExpressionOrHigher) + : DoOutsideOfAwaitContext(ParseAssignmentExpressionOrHigher); + } + + + public IExpression ParseConditionalExpressionRest(IExpression leftOperand) + { + var questionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + if (questionToken == null) + { + + return leftOperand; + } + var node = new ConditionalExpression() { Pos = leftOperand.Pos }; + + node.Condition = leftOperand; + + node.QuestionToken = questionToken; + + node.WhenTrue = DoOutsideOfContext(DisallowInAndDecoratorContext, ParseAssignmentExpressionOrHigher); + + node.ColonToken = (ColonToken)ParseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition*/ false, + Diagnostics._0_expected, TokenToString(SyntaxKind.ColonToken)); + + node.WhenFalse = ParseAssignmentExpressionOrHigher(); + + return FinishNode(node); + } + + + public IExpression ParseBinaryExpressionOrHigher(int precedence) + { + var leftOperand = ParseUnaryExpressionOrHigher(); + + if (leftOperand as IExpression == null) throw new NullReferenceException(); + return ParseBinaryExpressionRest(precedence, leftOperand as IExpression); + } + + + public bool IsInOrOfKeyword(SyntaxKind t) + { + + return t == SyntaxKind.InKeyword || t == SyntaxKind.OfKeyword; + } + + + public IExpression ParseBinaryExpressionRest(int precedence, IExpression leftOperand) + { + while (true) + { + + // We either have a binary operator here, or we're finished. We call + // reScanGreaterToken so that we merge token sequences like > and = into >= + + ReScanGreaterToken(); + var newPrecedence = GetBinaryOperatorPrecedence(); + var consumeCurrentOperator = Token() == SyntaxKind.AsteriskAsteriskToken ? + newPrecedence >= precedence : + newPrecedence > precedence; + if (!consumeCurrentOperator) + { + + break; + } + if (Token() == SyntaxKind.InKeyword && InDisallowInContext()) + { + + break; + } + if (Token() == SyntaxKind.AsKeyword) + { + if (Scanner.HasPrecedingLineBreak()) + { + + break; + } + else + { + + NextToken(); + + leftOperand = MakeAsExpression(leftOperand, ParseType()); + } + } + else + { + + leftOperand = MakeBinaryExpression(leftOperand, ParseTokenNode(Token()), ParseBinaryExpressionOrHigher(newPrecedence)); + } + } + + + return leftOperand; + } + + + public bool IsBinaryOperator() + { + if (InDisallowInContext() && Token() == SyntaxKind.InKeyword) + { + + return false; + } + + + return GetBinaryOperatorPrecedence() > 0; + } + + + public int GetBinaryOperatorPrecedence() + { + switch (Token()) + { + case SyntaxKind.BarBarToken: + + return 1; + case SyntaxKind.AmpersandAmpersandToken: + + return 2; + case SyntaxKind.BarToken: + + return 3; + case SyntaxKind.CaretToken: + + return 4; + case SyntaxKind.AmpersandToken: + + return 5; + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + + return 6; + case SyntaxKind.LessThanToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.LessThanEqualsToken: + case SyntaxKind.GreaterThanEqualsToken: + case SyntaxKind.InstanceOfKeyword: + case SyntaxKind.InKeyword: + case SyntaxKind.AsKeyword: + + return 7; + case SyntaxKind.LessThanLessThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + + return 8; + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + + return 9; + case SyntaxKind.AsteriskToken: + case SyntaxKind.SlashToken: + case SyntaxKind.PercentToken: + + return 10; + case SyntaxKind.AsteriskAsteriskToken: + + return 11; + } + + + // -1 is lower than all other precedences. Returning it will cause binary expression + // parsing to stop. + return -1; + } + + + public BinaryExpression MakeBinaryExpression(IExpression left, /*BinaryOperator*/Token operatorToken, IExpression right) + { + var node = new BinaryExpression() { Pos = left.Pos }; + + node.Left = left; + + node.OperatorToken = operatorToken; + + node.Right = right; + + return FinishNode(node); + } + + + public AsExpression MakeAsExpression(IExpression left, ITypeNode right) + { + var node = new AsExpression() { Pos = left.Pos }; + + node.Expression = left; + + node.Type = right; + + return FinishNode(node); + } + + + public PrefixUnaryExpression ParsePrefixUnaryExpression() + { + var node = new PrefixUnaryExpression() { Pos = Scanner.GetStartPos() }; + + node.Operator = /*(PrefixUnaryOperator)*/Token(); + + NextToken(); + + node.Operand = ParseSimpleUnaryExpression(); + + + return FinishNode(node); + } + + + public DeleteExpression ParseDeleteExpression() + { + var node = new DeleteExpression() { Pos = Scanner.GetStartPos() }; + + NextToken(); + + node.Expression = ParseSimpleUnaryExpression(); // as UnaryExpression; + + return FinishNode(node); + } + + + public TypeOfExpression ParseTypeOfExpression() + { + var node = new TypeOfExpression() { Pos = Scanner.GetStartPos() }; + + NextToken(); + + node.Expression = ParseSimpleUnaryExpression(); // as UnaryExpression; + + return FinishNode(node); + } + + + public VoidExpression ParseVoidExpression() + { + var node = new VoidExpression() { Pos = Scanner.GetStartPos() }; + + NextToken(); + + node.Expression = ParseSimpleUnaryExpression(); // as UnaryExpression; + + return FinishNode(node); + } + + + public bool IsAwaitExpression() + { + if (Token() == SyntaxKind.AwaitKeyword) + { + if (InAwaitContext()) + { + + return true; + } + + + // here we are using similar heuristics as 'isYieldExpression' + return LookAhead(NextTokenIsIdentifierOnSameLine); + } + + + return false; + } + + + public AwaitExpression ParseAwaitExpression() + { + var node = new AwaitExpression() { Pos = Scanner.GetStartPos() }; + + NextToken(); + + node.Expression = ParseSimpleUnaryExpression(); // as UnaryExpression; + + return FinishNode(node); + } + + //UnaryExpression | BinaryExpression + public IExpression ParseUnaryExpressionOrHigher() + { + if (IsUpdateExpression()) + { + var incrementExpression = ParseIncrementExpression(); + + return Token() == SyntaxKind.AsteriskAsteriskToken ? + ParseBinaryExpressionRest(GetBinaryOperatorPrecedence(), incrementExpression) : + incrementExpression; + } + var unaryOperator = Token(); + var simpleUnaryExpression = ParseSimpleUnaryExpression(); + if (Token() == SyntaxKind.AsteriskAsteriskToken) + { + var start = Scanner.SkipTriviaM(SourceText, simpleUnaryExpression.Pos ?? 0); + if (simpleUnaryExpression.Kind == SyntaxKind.TypeAssertionExpression) + { + + ParseErrorAtPosition(start, (simpleUnaryExpression.End ?? 0) - start, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); + } + else + { + + ParseErrorAtPosition(start, (simpleUnaryExpression.End ?? 0) - start, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, TokenToString(unaryOperator)); + } + } + + return simpleUnaryExpression; + } + + + public /*Unary*/IExpression ParseSimpleUnaryExpression() + { + switch (Token()) + { + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: + + return ParsePrefixUnaryExpression(); + case SyntaxKind.DeleteKeyword: + + return ParseDeleteExpression(); + case SyntaxKind.TypeOfKeyword: + + return ParseTypeOfExpression(); + case SyntaxKind.VoidKeyword: + + return ParseVoidExpression(); + case SyntaxKind.LessThanToken: + + // This is modified UnaryExpression grammar in TypeScript + // UnaryExpression (modified): + // < type > UnaryExpression + return ParseTypeAssertion(); + case SyntaxKind.AwaitKeyword: + if (IsAwaitExpression()) + { + + return ParseAwaitExpression(); + } + break; + default: + + return ParseIncrementExpression(); + } + return null; + } + + + public bool IsUpdateExpression() + { + switch (Token()) + { + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.DeleteKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.AwaitKeyword: + + return false; + case SyntaxKind.LessThanToken: + if (SourceFile.LanguageVariant != LanguageVariant.Jsx) + { + + return false; + } + break; + default: + + return true; + } + return true; + } + + + public /*Increment*/IExpression ParseIncrementExpression() + { + if (Token() == SyntaxKind.PlusPlusToken || Token() == SyntaxKind.MinusMinusToken) + { + var node = new PrefixUnaryExpression() { Pos = Scanner.GetStartPos() }; + + node.Operator = /*(PrefixUnaryOperator)*/Token(); + + NextToken(); + + node.Operand = ParseLeftHandSideExpressionOrHigher(); + + return FinishNode(node); + } + else + if (SourceFile.LanguageVariant == LanguageVariant.Jsx && Token() == SyntaxKind.LessThanToken && LookAhead(NextTokenIsIdentifierOrKeyword)) + { + + // JSXElement is part of primaryExpression + return ParseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true); + } + var expression = ParseLeftHandSideExpressionOrHigher(); + + + //Debug.assert(isLeftHandSideExpression(expression)); + if ((Token() == SyntaxKind.PlusPlusToken || Token() == SyntaxKind.MinusMinusToken) && !Scanner.HasPrecedingLineBreak()) + { + var node = new PostfixUnaryExpression() { Pos = expression.Pos }; + + node.Operand = expression; + + node.Operator = /*(PostfixUnaryOperator)*/Token(); + + NextToken(); + + return FinishNode(node); + } + + + return expression; + } + + + public /*LeftHandSideExpression*/IExpression ParseLeftHandSideExpressionOrHigher() + { + var expression = Token() == SyntaxKind.SuperKeyword + ? ParseSuperExpression() + : ParseMemberExpressionOrHigher(); + + + // Now, we *may* be complete. However, we might have consumed the start of a + // CallExpression. As such, we need to consume the rest of it here to be complete. + return ParseCallExpressionRest(expression); + } + + + public IMemberExpression ParseMemberExpressionOrHigher() + { + var expression = ParsePrimaryExpression(); + + return ParseMemberExpressionRest(expression); + } + + + public IMemberExpression ParseSuperExpression() + { + var expression = ParseTokenNode(Token()); + if (Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.DotToken || Token() == SyntaxKind.OpenBracketToken) + { + + return expression; + } + var node = new PropertyAccessExpression() { Pos = expression.Pos }; + + node.Expression = expression; + + ParseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + + node.Name = ParseRightSideOfDot(/*allowIdentifierNames*/ true); + + return FinishNode(node); + } + + + public bool TagNamesAreEquivalent(IJsxTagNameExpression lhs, IJsxTagNameExpression rhs) + { + if (lhs.Kind != rhs.Kind) + { + + return false; + } + if (lhs.Kind == SyntaxKind.Identifier) + { + + return (lhs as Identifier).Text == (rhs as Identifier).Text; + } + if (lhs.Kind == SyntaxKind.ThisKeyword) + { + + return true; + } + + + // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only + // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression + // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element + return true; + //todo + //((PropertyAccessExpression)lhs).name.text == ((PropertyAccessExpression)rhs).name.text && + //tagNamesAreEquivalent(((PropertyAccessExpression)lhs).expression as JsxTagNameExpression, ((PropertyAccessExpression)rhs).expression as JsxTagNameExpression); + } + + + public /*JsxElement | JsxSelfClosingElement*/PrimaryExpression ParseJsxElementOrSelfClosingElement(bool inExpressionContext) + { + var opening = ParseJsxOpeningOrSelfClosingElement(inExpressionContext); + //var result = JsxElement | JsxSelfClosingElement; + if ((SyntaxKind)opening.Kind == SyntaxKind.JsxOpeningElement) + { + var node = new JsxElement() { Pos = opening.Pos }; + + node.OpeningElement = opening; + + var tn = (opening as JsxOpeningElement)?.TagName; + if (tn == null) tn = (opening as JsxSelfClosingElement)?.TagName; + + node.JsxChildren = ParseJsxChildren(tn); // IJsxTagNameExpression); + + node.ClosingElement = ParseJsxClosingElement(inExpressionContext); + // todo check node.closingElement.tagName as JsxTagNameExpression + if (!TagNamesAreEquivalent(tn as IJsxTagNameExpression, node.ClosingElement.TagName as IJsxTagNameExpression)) + { + + ParseErrorAtPosition(node.ClosingElement.Pos ?? 0, (node.ClosingElement.End ?? 0) - (node.ClosingElement.Pos ?? 0), Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, GetTextOfNodeFromSourceText(SourceText, tn)); + } + + + var result = FinishNode(node); + + if (inExpressionContext && Token() == SyntaxKind.LessThanToken) + { + var invalidElement = TryParse(() => ParseJsxElementOrSelfClosingElement(/*inExpressionContext*/true)); + if (invalidElement != null) + { + + ParseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); + var badNode = new BinaryExpression() { Pos = result.Pos }; + + badNode.End = invalidElement.End; + + badNode.Left = result; + + badNode.Right = invalidElement; + + badNode.OperatorToken = (/*BinaryOperator*/Token)CreateMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ null); + + badNode.OperatorToken.Pos = badNode.OperatorToken.End = badNode.Right.Pos; + + return (JsxElement)(Node)badNode; + } + } + + + + return result; + } + else + { + + Debug.Assert((SyntaxKind)opening.Kind == SyntaxKind.JsxSelfClosingElement); + + // Nothing else to do for self-closing elements + var result = (JsxSelfClosingElement)opening; + if (inExpressionContext && Token() == SyntaxKind.LessThanToken) + { + var invalidElement = TryParse(() => ParseJsxElementOrSelfClosingElement(/*inExpressionContext*/true)); + if (invalidElement != null) + { + + ParseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); + var badNode = new BinaryExpression() { Pos = result.Pos }; + + badNode.End = invalidElement.End; + + badNode.Left = result; + + badNode.Right = invalidElement; + + badNode.OperatorToken = (/*BinaryOperator*/Token)CreateMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ null); + + badNode.OperatorToken.Pos = badNode.OperatorToken.End = badNode.Right.Pos; + + return (JsxElement)(Node)badNode; + } + } + + return result; + } + + } + + + public JsxText ParseJsxText() + { + var node = new JsxText() { Pos = Scanner.GetStartPos() }; + + CurrentToken = Scanner.ScanJsxToken(); + + return FinishNode(node); + } + + + public /*JsxChild*/Node ParseJsxChild() + { + switch (Token()) + { + case SyntaxKind.JsxText: + + return ParseJsxText(); + case SyntaxKind.OpenBraceToken: + + return ParseJsxExpression(/*inExpressionContext*/ false); + case SyntaxKind.LessThanToken: + + return ParseJsxElementOrSelfClosingElement(/*inExpressionContext*/ false); + } + + Debug.Fail("Unknown JSX child kind " + Token()); + return null; + } + + + public NodeArray ParseJsxChildren(/*LeftHandSide*/IExpression openingTagName) + { + var result = CreateList(); //List(); // + var saveParsingContext = ParsingContext; + + ParsingContext |= 1 << (int)TsTypes.ParsingContext.JsxChildren; + while (true) + { + + CurrentToken = Scanner.ReScanJsxToken(); + if (Token() == SyntaxKind.LessThanSlashToken) + { + + // Closing tag + break; + } + else + if (Token() == SyntaxKind.EndOfFileToken) + { + + // If we hit EOF, issue the error at the tag that lacks the closing element + // rather than at the end of the file (which is useless) + ParseErrorAtPosition(openingTagName.Pos ?? 0, (openingTagName.End ?? 0) - (openingTagName.Pos ?? 0), Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, GetTextOfNodeFromSourceText(SourceText, openingTagName)); + + break; + } + else + if (Token() == SyntaxKind.ConflictMarkerTrivia) + { + + break; + } + + result.Add(ParseJsxChild() as IJsxChild); + } + + + result.End = Scanner.GetTokenPos(); + + + ParsingContext = saveParsingContext; + + + return result; + } + + + public JsxAttributes ParseJsxAttributes() + { + var jsxAttributes = new JsxAttributes() { Pos = Scanner.GetStartPos() }; + + jsxAttributes.Properties = ParseList(TsTypes.ParsingContext.JsxAttributes, ParseJsxAttribute); + + return FinishNode(jsxAttributes); + } + + //JsxOpeningElement | JsxSelfClosingElement + public Expression ParseJsxOpeningOrSelfClosingElement(bool inExpressionContext) + { + var fullStart = Scanner.GetStartPos(); + + + ParseExpected(SyntaxKind.LessThanToken); + var tagName = ParseJsxElementName(); + var attributes = ParseJsxAttributes(); + //JsxOpeningLikeElement node = null; + if (Token() == SyntaxKind.GreaterThanToken) + { + + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors + var node = new JsxOpeningElement { Pos = fullStart }; //(JsxOpeningElement)createNode(SyntaxKind.JsxOpeningElement, fullStart); + node.TagName = tagName; + + node.Attributes = attributes; + + ScanJsxText(); + return FinishNode(node); + } + else + { + + ParseExpected(SyntaxKind.SlashToken); + if (inExpressionContext) + { + + ParseExpected(SyntaxKind.GreaterThanToken); + } + else + { + + ParseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ null, /*shouldAdvance*/ false); + + ScanJsxText(); + } + + var node = new JsxSelfClosingElement { Pos = fullStart }; //(JsxSelfClosingElement)createNode(SyntaxKind.JsxSelfClosingElement, fullStart); + node.TagName = tagName; + + node.Attributes = attributes; + return FinishNode(node); + } + + + //node.tagName = tagName; + + //node.attributes = attributes; + + + //return finishNode(node); + } + + + public IJsxTagNameExpression ParseJsxElementName() + { + + ScanJsxIdentifier(); + IJsxTagNameExpression expression = Token() == SyntaxKind.ThisKeyword ? + ParseTokenNode(Token()) : ParseIdentifierName(); + if (Token() == SyntaxKind.ThisKeyword) + { + IJsxTagNameExpression expression2 = ParseTokenNode(Token()); + while (ParseOptional(SyntaxKind.DotToken)) + { + PropertyAccessExpression propertyAccess = new PropertyAccessExpression { Pos = expression2.Pos }; //(PropertyAccessExpression)createNode(SyntaxKind.PropertyAccessExpression, expression.pos); + + propertyAccess.Expression = expression2; + + propertyAccess.Name = ParseRightSideOfDot(/*allowIdentifierNames*/ true); + + expression2 = FinishNode(propertyAccess); + } + + return expression2; + } + else + { + IJsxTagNameExpression expression2 = ParseIdentifierName(); + while (ParseOptional(SyntaxKind.DotToken)) + { + PropertyAccessExpression propertyAccess = new PropertyAccessExpression { Pos = expression2.Pos }; //(PropertyAccessExpression)createNode(SyntaxKind.PropertyAccessExpression, expression.pos); + + propertyAccess.Expression = expression2; + + propertyAccess.Name = ParseRightSideOfDot(/*allowIdentifierNames*/ true); + + expression2 = FinishNode(propertyAccess); + } + + return expression2; + } + } + + + public JsxExpression ParseJsxExpression(bool inExpressionContext) + { + var node = new JsxExpression() { Pos = Scanner.GetStartPos() }; + + + ParseExpected(SyntaxKind.OpenBraceToken); + if (Token() != SyntaxKind.CloseBraceToken) + { + + node.DotDotDotToken = (DotDotDotToken)ParseOptionalToken(SyntaxKind.DotDotDotToken); + + node.Expression = ParseAssignmentExpressionOrHigher(); + } + if (inExpressionContext) + { + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + ParseExpected(SyntaxKind.CloseBraceToken, /*message*/ null, /*shouldAdvance*/ false); + + ScanJsxText(); + } + + + return FinishNode(node); + } + + //JsxAttribute | JsxSpreadAttribute + public ObjectLiteralElement ParseJsxAttribute() + { + if (Token() == SyntaxKind.OpenBraceToken) + { + + return ParseJsxSpreadAttribute(); + } + + + ScanJsxIdentifier(); + var node = new JsxAttribute() { Pos = Scanner.GetStartPos() }; + + node.Name = ParseIdentifierName(); + if (Token() == SyntaxKind.EqualsToken) + { + switch (ScanJsxAttributeValue()) + { + case SyntaxKind.StringLiteral: + + node.Initializer = (StringLiteral)ParseLiteralNode(); + + break; + default: + + node.Initializer = ParseJsxExpression(/*inExpressionContext*/ true); + + break; + } + } + + return FinishNode(node); + } + + + public JsxSpreadAttribute ParseJsxSpreadAttribute() + { + var node = new JsxSpreadAttribute() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBraceToken); + + ParseExpected(SyntaxKind.DotDotDotToken); + + node.Expression = ParseExpression(); + + ParseExpected(SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + + + public JsxClosingElement ParseJsxClosingElement(bool inExpressionContext) + { + var node = new JsxClosingElement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.LessThanSlashToken); + + node.TagName = ParseJsxElementName(); + if (inExpressionContext) + { + + ParseExpected(SyntaxKind.GreaterThanToken); + } + else + { + + ParseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ null, /*shouldAdvance*/ false); + + ScanJsxText(); + } + + return FinishNode(node); + } + + + public TypeAssertion ParseTypeAssertion() + { + var node = new TypeAssertion() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.LessThanToken); + + node.Type = ParseType(); + + ParseExpected(SyntaxKind.GreaterThanToken); + + node.Expression = ParseSimpleUnaryExpression(); // as UnaryExpression; + + return FinishNode(node); + } + + + public IMemberExpression ParseMemberExpressionRest(/*LeftHandSideExpression*/IMemberExpression expression) + { + while (true) + { + var dotToken = (DotToken)ParseOptionalToken(SyntaxKind.DotToken); + if (dotToken != null) + { + var propertyAccess = new PropertyAccessExpression() { Pos = expression.Pos }; + + propertyAccess.Expression = expression; + + propertyAccess.Name = ParseRightSideOfDot(/*allowIdentifierNames*/ true); + + expression = FinishNode(propertyAccess); + + continue; + } + if (Token() == SyntaxKind.ExclamationToken && !Scanner.HasPrecedingLineBreak()) + { + + NextToken(); + var nonNullExpression = new NonNullExpression() { Pos = expression.Pos }; + + nonNullExpression.Expression = expression; + + expression = FinishNode(nonNullExpression); + + continue; + } + if (!InDecoratorContext() && ParseOptional(SyntaxKind.OpenBracketToken)) + { + var indexedAccess = new ElementAccessExpression() { Pos = expression.Pos }; + + indexedAccess.Expression = expression; + if (Token() != SyntaxKind.CloseBracketToken) + { + + indexedAccess.ArgumentExpression = AllowInAnd(ParseExpression); + if ((SyntaxKind)indexedAccess.ArgumentExpression.Kind == SyntaxKind.StringLiteral || + (SyntaxKind)indexedAccess.ArgumentExpression.Kind == SyntaxKind.NumericLiteral) + { + var literal = (LiteralExpression)indexedAccess.ArgumentExpression;//(LiteralExpression) + + literal.Text = InternIdentifier(literal.Text); + } + } + + + ParseExpected(SyntaxKind.CloseBracketToken); + + expression = FinishNode(indexedAccess); + + continue; + } + if (Token() == SyntaxKind.NoSubstitutionTemplateLiteral || Token() == SyntaxKind.TemplateHead) + { + var tagExpression = new TaggedTemplateExpression() { Pos = expression.Pos }; + + tagExpression.Tag = expression; + + tagExpression.Template = Token() == SyntaxKind.NoSubstitutionTemplateLiteral + ? (Node)/*(NoSubstitutionTemplateLiteral)*/ParseLiteralNode() + : ParseTemplateExpression(); + + expression = FinishNode(tagExpression); + + continue; + } + + + return (IMemberExpression)expression; + } + } + + + public /*LeftHandSideExpression*/IMemberExpression ParseCallExpressionRest(/*LeftHandSideExpression*/IMemberExpression expression) + { + while (true) + { + + expression = ParseMemberExpressionRest(expression); + if (Token() == SyntaxKind.LessThanToken) + { + var typeArguments = TryParse(ParseTypeArgumentsInExpression); + if (typeArguments == null) + { + + return expression; + } + var callExpr = new CallExpression() { Pos = expression.Pos }; + + callExpr.Expression = expression; + + callExpr.TypeArguments = typeArguments; + + callExpr.Arguments = ParseArgumentList(); + + expression = FinishNode(callExpr); + + continue; + } + else + if (Token() == SyntaxKind.OpenParenToken) + { + var callExpr = new CallExpression() { Pos = expression.Pos }; + + callExpr.Expression = expression; + + callExpr.Arguments = ParseArgumentList(); + + expression = FinishNode(callExpr); + + continue; + } + + + return expression; + } + } + + + public NodeArray ParseArgumentList() + { + + ParseExpected(SyntaxKind.OpenParenToken); + var result = ParseDelimitedList(TsTypes.ParsingContext.ArgumentExpressions, ParseArgumentExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + return result; + } + + + public NodeArray ParseTypeArgumentsInExpression() + { + if (!ParseOptional(SyntaxKind.LessThanToken)) + { + + return null; + } + var typeArguments = ParseDelimitedList(TsTypes.ParsingContext.TypeArguments, ParseType); + if (!ParseExpected(SyntaxKind.GreaterThanToken)) + { + + // If it doesn't have the closing > then it's definitely not an type argument list. + return null; + } + + + // If we have a '<', then only parse this as a argument list if the type arguments + // are complete and we have an open paren. if we don't, rewind and return nothing. + return typeArguments != null && CanFollowTypeArgumentsInExpression() + ? typeArguments + : null; + } + + + public bool CanFollowTypeArgumentsInExpression() + { + switch (Token()) + { + case SyntaxKind.OpenParenToken: + case SyntaxKind.DotToken: + case SyntaxKind.CloseParenToken: + case SyntaxKind.CloseBracketToken: + case SyntaxKind.ColonToken: + case SyntaxKind.SemicolonToken: + case SyntaxKind.QuestionToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.AmpersandAmpersandToken: + case SyntaxKind.BarBarToken: + case SyntaxKind.CaretToken: + case SyntaxKind.AmpersandToken: + case SyntaxKind.BarToken: + case SyntaxKind.CloseBraceToken: + case SyntaxKind.EndOfFileToken: + // foo + // these cases can't legally follow a type arg list. However, they're not legal + // expressions either. The user is probably in the middle of a generic type. So + // treat it as such. + return true; + case SyntaxKind.CommaToken: + case SyntaxKind.OpenBraceToken: + default: + + // Anything else treat as an expression. + return false; + } + } + + + public IPrimaryExpression ParsePrimaryExpression() + { + switch (Token()) + { + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + + return ParseLiteralNode(); + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + + return ParseTokenNode(Token()); + case SyntaxKind.OpenParenToken: + + return ParseParenthesizedExpression(); + case SyntaxKind.OpenBracketToken: + + return ParseArrayLiteralExpression(); + case SyntaxKind.OpenBraceToken: + + return ParseObjectLiteralExpression(); + case SyntaxKind.AsyncKeyword: + if (!LookAhead(NextTokenIsFunctionKeywordOnSameLine)) + { + + break; + } + + + return ParseFunctionExpression(); + case SyntaxKind.ClassKeyword: + + return ParseClassExpression(); + case SyntaxKind.FunctionKeyword: + + return ParseFunctionExpression(); + case SyntaxKind.NewKeyword: + + return ParseNewExpression(); + case SyntaxKind.SlashToken: + case SyntaxKind.SlashEqualsToken: + if (ReScanSlashToken() == SyntaxKind.RegularExpressionLiteral) + { + + return ParseLiteralNode(); + } + + break; + case SyntaxKind.TemplateHead: + + return ParseTemplateExpression(); + } + + + return ParseIdentifier(Diagnostics.Expression_expected); + } + + + public ParenthesizedExpression ParseParenthesizedExpression() + { + var node = new ParenthesizedExpression() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + return FinishNode(node); + } + + + public Expression ParseSpreadElement() + { + var node = new SpreadElement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.DotDotDotToken); + + node.Expression = ParseAssignmentExpressionOrHigher(); + + return FinishNode(node); + } + + + public IExpression ParseArgumentOrArrayLiteralElement() + { + + return Token() == SyntaxKind.DotDotDotToken ? ParseSpreadElement() : + Token() == SyntaxKind.CommaToken ? (new OmittedExpression() { Pos = Scanner.GetStartPos() }) /*createNode(SyntaxKind.OmittedExpression)*/ : + ParseAssignmentExpressionOrHigher(); + } + + + public IExpression ParseArgumentExpression() + { + + return DoOutsideOfContext(DisallowInAndDecoratorContext, ParseArgumentOrArrayLiteralElement); + } + + + public ArrayLiteralExpression ParseArrayLiteralExpression() + { + var node = new ArrayLiteralExpression() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBracketToken); + if (Scanner.HasPrecedingLineBreak()) + { + + node.MultiLine = true; + } + + node.Elements = ParseDelimitedList(TsTypes.ParsingContext.ArrayLiteralMembers, ParseArgumentOrArrayLiteralElement); + + ParseExpected(SyntaxKind.CloseBracketToken); + + return FinishNode(node); + } + + + public IAccessorDeclaration TryParseAccessorDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + if (ParseContextualModifier(SyntaxKind.GetKeyword)) + { + + return ParseAccessorDeclaration(SyntaxKind.GetAccessor, fullStart, decorators, modifiers); + } + else + if (ParseContextualModifier(SyntaxKind.SetKeyword)) + { + + return ParseAccessorDeclaration(SyntaxKind.SetAccessor, fullStart, decorators, modifiers); + } + + + return null; + } + + + public IObjectLiteralElementLike ParseObjectLiteralElement() + { + var fullStart = Scanner.GetStartPos(); + var dotDotDotToken = (DotDotDotToken)ParseOptionalToken(SyntaxKind.DotDotDotToken); + if (dotDotDotToken != null) + { + var spreadElement = new SpreadAssignment() { Pos = fullStart }; + + spreadElement.Expression = ParseAssignmentExpressionOrHigher(); + + return AddJsDocComment(FinishNode(spreadElement)); + } + var decorators = ParseDecorators(); + var modifiers = ParseModifiers(); + var accessor = TryParseAccessorDeclaration(fullStart, decorators, modifiers); + if (accessor != null) + { + + return accessor; + } + var asteriskToken = (AsteriskToken)ParseOptionalToken(SyntaxKind.AsteriskToken); + var tokenIsIdentifier = IsIdentifier(); + var propertyName = ParsePropertyName(); // parseIdentifierName(); // + var questionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + if (asteriskToken != null || Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken) + { + + return ParseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken); + } + var isShorthandPropertyAssignment = + tokenIsIdentifier && (Token() == SyntaxKind.CommaToken || Token() == SyntaxKind.CloseBraceToken || Token() == SyntaxKind.EqualsToken); + if (isShorthandPropertyAssignment) + { + var shorthandDeclaration = new ShorthandPropertyAssignment() { Pos = fullStart }; + + shorthandDeclaration.Name = (Identifier)propertyName; + + shorthandDeclaration.QuestionToken = questionToken; + var equalsToken = (EqualsToken)ParseOptionalToken(SyntaxKind.EqualsToken); + if (equalsToken != null) + { + + shorthandDeclaration.EqualsToken = equalsToken; + + shorthandDeclaration.ObjectAssignmentInitializer = AllowInAnd(ParseAssignmentExpressionOrHigher); + } + + return AddJsDocComment(FinishNode(shorthandDeclaration)); + } + else + { + var propertyAssignment = new PropertyAssignment() { Pos = fullStart }; + + propertyAssignment.Modifiers = modifiers; + + propertyAssignment.Name = propertyName; + + propertyAssignment.QuestionToken = questionToken; + + ParseExpected(SyntaxKind.ColonToken); + + propertyAssignment.Initializer = AllowInAnd(ParseAssignmentExpressionOrHigher); + + return AddJsDocComment(FinishNode(propertyAssignment)); + } + } + + + public ObjectLiteralExpression ParseObjectLiteralExpression() + { + var node = new ObjectLiteralExpression() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBraceToken); + if (Scanner.HasPrecedingLineBreak()) + { + + node.MultiLine = true; + } + + + node.Properties = ParseDelimitedList(TsTypes.ParsingContext.ObjectLiteralMembers, ParseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); + + ParseExpected(SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + + + public FunctionExpression ParseFunctionExpression() + { + var saveDecoratorContext = InDecoratorContext(); + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ false); + } + var node = new FunctionExpression() { Pos = Scanner.GetStartPos() }; + + node.Modifiers = ParseModifiers(); + + ParseExpected(SyntaxKind.FunctionKeyword); + + node.AsteriskToken = (AsteriskToken)ParseOptionalToken(SyntaxKind.AsteriskToken); + var isGenerator = /*!!*/node.AsteriskToken != null; + var isAsync = /*!!*/(GetModifierFlags(node) & ModifierFlags.Async) != 0; + + node.Name = + isGenerator && isAsync ? DoInYieldAndAwaitContext(ParseOptionalIdentifier) : + isGenerator ? DoInYieldContext(ParseOptionalIdentifier) : + isAsync ? DoInAwaitContext(ParseOptionalIdentifier) : + ParseOptionalIdentifier(); + + + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node); + + node.Body = ParseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false); + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ true); + } + + + return AddJsDocComment(FinishNode(node)); + } + + + public Identifier ParseOptionalIdentifier() + { + + return IsIdentifier() ? ParseIdentifier() : null; + } + + + public /*NewExpression | MetaProperty*/IPrimaryExpression ParseNewExpression() + { + var fullStart = Scanner.GetStartPos(); + + ParseExpected(SyntaxKind.NewKeyword); + if (ParseOptional(SyntaxKind.DotToken)) + { + var node = new MetaProperty() { Pos = fullStart }; + + node.KeywordToken = SyntaxKind.NewKeyword; + + node.Name = ParseIdentifierName(); + + return FinishNode(node); + } + else + { + var node = new NewExpression() { Pos = fullStart }; + + node.Expression = ParseMemberExpressionOrHigher(); + + node.TypeArguments = TryParse(ParseTypeArgumentsInExpression); + if (node.TypeArguments != null || Token() == SyntaxKind.OpenParenToken) + { + + node.Arguments = ParseArgumentList(); + } + + return FinishNode(node); + } + } + + + public Block ParseBlock(bool ignoreMissingOpenBrace, DiagnosticMessage diagnosticMessage = null) + { + var node = new Block() { Pos = Scanner.GetStartPos() }; + if (ParseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) + { + if (Scanner.HasPrecedingLineBreak()) + { + + node.MultiLine = true; + } + + + node.Statements = ParseList2(TsTypes.ParsingContext.BlockStatements, ParseStatement); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + node.Statements = new NodeArray(); //.Cast().ToList(); createMissingList + } + + return FinishNode(node); + } + + + public Block ParseFunctionBlock(bool allowYield, bool allowAwait, bool ignoreMissingOpenBrace, DiagnosticMessage diagnosticMessage = null) + { + var savedYieldContext = InYieldContext(); + + SetYieldContext(allowYield); + var savedAwaitContext = InAwaitContext(); + + SetAwaitContext(allowAwait); + var saveDecoratorContext = InDecoratorContext(); + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ false); + } + var block = ParseBlock(ignoreMissingOpenBrace, diagnosticMessage); + if (saveDecoratorContext) + { + + SetDecoratorContext(/*val*/ true); + } + + + SetYieldContext(savedYieldContext); + + SetAwaitContext(savedAwaitContext); + + + return block; + } + + + public EmptyStatement ParseEmptyStatement() + { + var node = new EmptyStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.SemicolonToken); + + return FinishNode(node); + } + + + public IfStatement ParseIfStatement() + { + var node = new IfStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.IfKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + node.ThenStatement = ParseStatement(); + + node.ElseStatement = ParseOptional(SyntaxKind.ElseKeyword) ? ParseStatement() : null; + + return FinishNode(node); + } + + + public DoStatement ParseDoStatement() + { + var node = new DoStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.DoKeyword); + + node.Statement = ParseStatement(); + + ParseExpected(SyntaxKind.WhileKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + + // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html + // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in + // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby + // do;while(0)x will have a semicolon inserted before x. + ParseOptional(SyntaxKind.SemicolonToken); + + return FinishNode(node); + } + + + public WhileStatement ParseWhileStatement() + { + var node = new WhileStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.WhileKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + node.Statement = ParseStatement(); + + return FinishNode(node); + } + + + public Statement ParseForOrForInOrForOfStatement() + { + var pos = GetNodePos(); + + ParseExpected(SyntaxKind.ForKeyword); + var awaitToken = (AwaitKeywordToken)ParseOptionalToken(SyntaxKind.AwaitKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + IVariableDeclarationListOrExpression initializer = null; + //Node initializer = null; + if (Token() != SyntaxKind.SemicolonToken) + { + if (Token() == SyntaxKind.VarKeyword || Token() == SyntaxKind.LetKeyword || Token() == SyntaxKind.ConstKeyword) + { + + initializer = (IVariableDeclarationListOrExpression)ParseVariableDeclarationList(/*inForStatementInitializer*/ true); + } + else + { + + initializer = (IVariableDeclarationListOrExpression)DisallowInAnd(ParseExpression); + } + } + IterationStatement forOrForInOrForOfStatement = null; + if (awaitToken != null ? ParseExpected(SyntaxKind.OfKeyword) : ParseOptional(SyntaxKind.OfKeyword)) + { + var forOfStatement = new ForOfStatement() { Pos = pos }; + + forOfStatement.AwaitModifier = awaitToken; + + forOfStatement.Initializer = initializer; + + forOfStatement.Expression = AllowInAnd(ParseAssignmentExpressionOrHigher); + + ParseExpected(SyntaxKind.CloseParenToken); + + forOrForInOrForOfStatement = forOfStatement; + } + else + if (ParseOptional(SyntaxKind.InKeyword)) + { + var forInStatement = new ForInStatement() { Pos = pos }; + + forInStatement.Initializer = initializer; + + forInStatement.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + forOrForInOrForOfStatement = forInStatement; + } + else + { + var forStatement = new ForStatement() { Pos = pos }; + + forStatement.Initializer = initializer; + + ParseExpected(SyntaxKind.SemicolonToken); + if (Token() != SyntaxKind.SemicolonToken && Token() != SyntaxKind.CloseParenToken) + { + + forStatement.Condition = AllowInAnd(ParseExpression); + } + + ParseExpected(SyntaxKind.SemicolonToken); + if (Token() != SyntaxKind.CloseParenToken) + { + + forStatement.Incrementor = AllowInAnd(ParseExpression); + } + + ParseExpected(SyntaxKind.CloseParenToken); + + forOrForInOrForOfStatement = forStatement; + } + + + forOrForInOrForOfStatement.Statement = ParseStatement(); + + + return FinishNode(forOrForInOrForOfStatement); + } + + + public IBreakOrContinueStatement ParseBreakOrContinueStatement(SyntaxKind kind) + { + var node = kind == SyntaxKind.ContinueStatement ? (IBreakOrContinueStatement)new ContinueStatement { Pos = Scanner.GetStartPos() } : kind == SyntaxKind.BreakStatement ? new BreakStatement { Pos = Scanner.GetStartPos() } : throw new NotSupportedException("parseBreakOrContinueStatement"); + + + ParseExpected(kind == SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword); + if (!CanParseSemicolon()) + { + + node.Label = ParseIdentifier(); + } + + + ParseSemicolon(); + + return FinishNode(node); + } + + + public ReturnStatement ParseReturnStatement() + { + var node = new ReturnStatement() { Pos = Scanner.GetStartPos() }; + + + ParseExpected(SyntaxKind.ReturnKeyword); + if (!CanParseSemicolon()) + { + + node.Expression = AllowInAnd(ParseExpression); + } + + + ParseSemicolon(); + + return FinishNode(node); + } + + + public WithStatement ParseWithStatement() + { + var node = new WithStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.WithKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + + node.Statement = ParseStatement(); + + return FinishNode(node); + } + + + public CaseClause ParseCaseClause() + { + var node = new CaseClause() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.CaseKeyword); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.ColonToken); + + node.Statements = ParseList2(TsTypes.ParsingContext.SwitchClauseStatements, ParseStatement); + + return FinishNode(node); + } + + + public DefaultClause ParseDefaultClause() + { + var node = new DefaultClause() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.DefaultKeyword); + + ParseExpected(SyntaxKind.ColonToken); + + node.Statements = ParseList2(TsTypes.ParsingContext.SwitchClauseStatements, ParseStatement); + + return FinishNode(node); + } + + + public ICaseOrDefaultClause ParseCaseOrDefaultClause() + { + + return Token() == SyntaxKind.CaseKeyword ? (ICaseOrDefaultClause)ParseCaseClause() : ParseDefaultClause(); + } + + + public SwitchStatement ParseSwitchStatement() + { + var node = new SwitchStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.SwitchKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = AllowInAnd(ParseExpression); + + ParseExpected(SyntaxKind.CloseParenToken); + var caseBlock = new CaseBlock() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBraceToken); + + caseBlock.Clauses = ParseList(TsTypes.ParsingContext.SwitchClauses, ParseCaseOrDefaultClause); + + ParseExpected(SyntaxKind.CloseBraceToken); + + node.CaseBlock = FinishNode(caseBlock); + + return FinishNode(node); + } + + + public ThrowStatement ParseThrowStatement() + { + var node = new ThrowStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.ThrowKeyword); + + node.Expression = Scanner.HasPrecedingLineBreak() ? null : AllowInAnd(ParseExpression); + + ParseSemicolon(); + + return FinishNode(node); + } + + + public TryStatement ParseTryStatement() + { + var node = new TryStatement() { Pos = Scanner.GetStartPos() }; + + + ParseExpected(SyntaxKind.TryKeyword); + + node.TryBlock = ParseBlock(/*ignoreMissingOpenBrace*/ false); + + node.CatchClause = Token() == SyntaxKind.CatchKeyword ? ParseCatchClause() : null; + if (node.CatchClause == null || Token() == SyntaxKind.FinallyKeyword) + { + + ParseExpected(SyntaxKind.FinallyKeyword); + + node.FinallyBlock = ParseBlock(/*ignoreMissingOpenBrace*/ false); + } + + + return FinishNode(node); + } + + + public CatchClause ParseCatchClause() + { + var result = new CatchClause() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.CatchKeyword); + if (ParseExpected(SyntaxKind.OpenParenToken)) + { + + result.VariableDeclaration = ParseVariableDeclaration(); + } + + + ParseExpected(SyntaxKind.CloseParenToken); + + result.Block = ParseBlock(/*ignoreMissingOpenBrace*/ false); + + return FinishNode(result); + } + + + public DebuggerStatement ParseDebuggerStatement() + { + var node = new DebuggerStatement() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.DebuggerKeyword); + + ParseSemicolon(); + + return FinishNode(node); + } + + + public /*ExpressionStatement | LabeledStatement*/Statement ParseExpressionOrLabeledStatement() + { + var fullStart = Scanner.GetStartPos(); + var expression = AllowInAnd(ParseExpression); + if ((SyntaxKind)expression.Kind == SyntaxKind.Identifier && ParseOptional(SyntaxKind.ColonToken)) + { + var labeledStatement = new LabeledStatement() { Pos = fullStart }; + + labeledStatement.Label = (Identifier)expression; + + labeledStatement.Statement = ParseStatement(); + + return AddJsDocComment(FinishNode(labeledStatement)); + } + else + { + var expressionStatement = new ExpressionStatement() { Pos = fullStart }; + + expressionStatement.Expression = expression; + + ParseSemicolon(); + + return AddJsDocComment(FinishNode(expressionStatement)); + } + } + + + public bool NextTokenIsIdentifierOrKeywordOnSameLine() + { + + NextToken(); + + return TokenIsIdentifierOrKeyword(Token()) && !Scanner.HasPrecedingLineBreak(); + } + + + public bool NextTokenIsFunctionKeywordOnSameLine() + { + + NextToken(); + + return Token() == SyntaxKind.FunctionKeyword && !Scanner.HasPrecedingLineBreak(); + } + + + public bool NextTokenIsIdentifierOrKeywordOrNumberOnSameLine() + { + + NextToken(); + + return (TokenIsIdentifierOrKeyword(Token()) || Token() == SyntaxKind.NumericLiteral) && !Scanner.HasPrecedingLineBreak(); + } + + + public bool IsDeclaration() + { + while (true) + { + switch (Token()) + { + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: + + return true; + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.TypeKeyword: + + return NextTokenIsIdentifierOnSameLine(); + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + + return NextTokenIsIdentifierOrStringLiteralOnSameLine(); + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.ReadonlyKeyword: + + NextToken(); + if (Scanner.HasPrecedingLineBreak()) + { + + return false; + } + + continue; + case SyntaxKind.GlobalKeyword: + + NextToken(); + + return Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.Identifier || Token() == SyntaxKind.ExportKeyword; + case SyntaxKind.ImportKeyword: + + NextToken(); + + return Token() == SyntaxKind.StringLiteral || Token() == SyntaxKind.AsteriskToken || + Token() == SyntaxKind.OpenBraceToken || TokenIsIdentifierOrKeyword(Token()); + case SyntaxKind.ExportKeyword: + + NextToken(); + if (Token() == SyntaxKind.EqualsToken || Token() == SyntaxKind.AsteriskToken || + Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.DefaultKeyword || + Token() == SyntaxKind.AsKeyword) + { + + return true; + } + + continue; + case SyntaxKind.StaticKeyword: + + NextToken(); + + continue; + default: + + return false; + } + } + } + + + public bool IsStartOfDeclaration() + { + + return LookAhead(IsDeclaration); + } + + + public bool IsStartOfStatement() + { + switch (Token()) + { + case SyntaxKind.AtToken: + case SyntaxKind.SemicolonToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.IfKeyword: + case SyntaxKind.DoKeyword: + case SyntaxKind.WhileKeyword: + case SyntaxKind.ForKeyword: + case SyntaxKind.ContinueKeyword: + case SyntaxKind.BreakKeyword: + case SyntaxKind.ReturnKeyword: + case SyntaxKind.WithKeyword: + case SyntaxKind.SwitchKeyword: + case SyntaxKind.ThrowKeyword: + case SyntaxKind.TryKeyword: + case SyntaxKind.DebuggerKeyword: + case SyntaxKind.CatchKeyword: + case SyntaxKind.FinallyKeyword: + + return true; + case SyntaxKind.ConstKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.ImportKeyword: + + return IsStartOfDeclaration(); + case SyntaxKind.AsyncKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.GlobalKeyword: + + // When these don't start a declaration, they're an identifier in an expression statement + return true; + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: + + // When these don't start a declaration, they may be the start of a class member if an identifier + // immediately follows. Otherwise they're an identifier in an expression statement. + return IsStartOfDeclaration() || !LookAhead(NextTokenIsIdentifierOrKeywordOnSameLine); + default: + + return IsStartOfExpression(); + } + } + + + public bool NextTokenIsIdentifierOrStartOfDestructuring() + { + + NextToken(); + + return IsIdentifier() || Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.OpenBracketToken; + } + + + public bool IsLetDeclaration() + { + + // In ES6 'let' always starts a lexical declaration if followed by an identifier or { + // or [. + return LookAhead(NextTokenIsIdentifierOrStartOfDestructuring); + } + + + public IStatement ParseStatement() + { + switch (Token()) + { + case SyntaxKind.SemicolonToken: + + return ParseEmptyStatement(); + case SyntaxKind.OpenBraceToken: + + return ParseBlock(/*ignoreMissingOpenBrace*/ false); + case SyntaxKind.VarKeyword: + + return ParseVariableStatement(Scanner.GetStartPos(), /*decorators*/ null, /*modifiers*/ null); + case SyntaxKind.LetKeyword: + if (IsLetDeclaration()) + { + + return ParseVariableStatement(Scanner.GetStartPos(), /*decorators*/ null, /*modifiers*/ null); + } + + break; + case SyntaxKind.FunctionKeyword: + + return ParseFunctionDeclaration(Scanner.GetStartPos(), /*decorators*/ null, /*modifiers*/ null); + case SyntaxKind.ClassKeyword: + + return ParseClassDeclaration(Scanner.GetStartPos(), /*decorators*/ null, /*modifiers*/ null); + case SyntaxKind.IfKeyword: + + return ParseIfStatement(); + case SyntaxKind.DoKeyword: + + return ParseDoStatement(); + case SyntaxKind.WhileKeyword: + + return ParseWhileStatement(); + case SyntaxKind.ForKeyword: + + return ParseForOrForInOrForOfStatement(); + case SyntaxKind.ContinueKeyword: + + return ParseBreakOrContinueStatement(SyntaxKind.ContinueStatement); + case SyntaxKind.BreakKeyword: + + return ParseBreakOrContinueStatement(SyntaxKind.BreakStatement); + case SyntaxKind.ReturnKeyword: + + return ParseReturnStatement(); + case SyntaxKind.WithKeyword: + + return ParseWithStatement(); + case SyntaxKind.SwitchKeyword: + + return ParseSwitchStatement(); + case SyntaxKind.ThrowKeyword: + + return ParseThrowStatement(); + case SyntaxKind.TryKeyword: + case SyntaxKind.CatchKeyword: + case SyntaxKind.FinallyKeyword: + + return ParseTryStatement(); + case SyntaxKind.DebuggerKeyword: + + return ParseDebuggerStatement(); + case SyntaxKind.AtToken: + + return ParseDeclaration(); + case SyntaxKind.AsyncKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.ImportKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.GlobalKeyword: + if (IsStartOfDeclaration()) + { + + return ParseDeclaration(); + } + + break; + } + + return ParseExpressionOrLabeledStatement(); + } + + + public IStatement ParseDeclaration() + { + var fullStart = GetNodePos(); + var decorators = ParseDecorators(); + var modifiers = ParseModifiers(); + switch (Token()) + { + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + + return ParseVariableStatement(fullStart, decorators, modifiers); + case SyntaxKind.FunctionKeyword: + + return ParseFunctionDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ClassKeyword: + + return ParseClassDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.InterfaceKeyword: + + return ParseInterfaceDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.TypeKeyword: + + return ParseTypeAliasDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.EnumKeyword: + + return ParseEnumDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.GlobalKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + + return ParseModuleDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ImportKeyword: + + return ParseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ExportKeyword: + + NextToken(); + switch (Token()) + { + case SyntaxKind.DefaultKeyword: + case SyntaxKind.EqualsToken: + + return ParseExportAssignment(fullStart, decorators, modifiers); + case SyntaxKind.AsKeyword: + + return ParseNamespaceExportDeclaration(fullStart, decorators, modifiers); + default: + + return ParseExportDeclaration(fullStart, decorators, modifiers); + } + break; + default: + + if (decorators?.Any() == true || modifiers?.Any() == true) + { + // We reached this point because we encountered decorators and/or modifiers and assumed a declaration + // would follow. For recovery and error reporting purposes, return an incomplete declaration. + var node = (Statement)CreateMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + node.Pos = fullStart; + node.Decorators = decorators; + node.Modifiers = modifiers; + return FinishNode(node); + } + break; + } + return null; + } + + + public bool NextTokenIsIdentifierOrStringLiteralOnSameLine() + { + + NextToken(); + + return !Scanner.HasPrecedingLineBreak() && (IsIdentifier() || Token() == SyntaxKind.StringLiteral); + } + + + public Block ParseFunctionBlockOrSemicolon(bool isGenerator, bool isAsync, DiagnosticMessage diagnosticMessage = null) + { + if (Token() != SyntaxKind.OpenBraceToken && CanParseSemicolon()) + { + + ParseSemicolon(); + + return null; + } + + + return ParseFunctionBlock(isGenerator, isAsync, /*ignoreMissingOpenBrace*/ false, diagnosticMessage); + } + + + public IArrayBindingElement ParseArrayBindingElement() + { + if (Token() == SyntaxKind.CommaToken) + { + + return new OmittedExpression { Pos = Scanner.GetStartPos() }; //(OmittedExpression)createNode(SyntaxKind.OmittedExpression); + } + var node = new BindingElement() { Pos = Scanner.GetStartPos() }; + + node.DotDotDotToken = (DotDotDotToken)ParseOptionalToken(SyntaxKind.DotDotDotToken); + + node.Name = ParseIdentifierOrPattern(); + + node.Initializer = ParseBindingElementInitializer(/*inParameter*/ false); + + return FinishNode(node); + } + + + public IArrayBindingElement ParseObjectBindingElement() + { + var node = new BindingElement() { Pos = Scanner.GetStartPos() }; + + node.DotDotDotToken = (DotDotDotToken)ParseOptionalToken(SyntaxKind.DotDotDotToken); + var tokenIsIdentifier = IsIdentifier(); + var propertyName = ParsePropertyName(); + if (tokenIsIdentifier && Token() != SyntaxKind.ColonToken) + { + + node.Name = (Identifier)propertyName; + } + else + { + + ParseExpected(SyntaxKind.ColonToken); + + node.PropertyName = propertyName; + + node.Name = ParseIdentifierOrPattern(); + } + + node.Initializer = ParseBindingElementInitializer(/*inParameter*/ false); + + return FinishNode(node); + } + + + public ObjectBindingPattern ParseObjectBindingPattern() + { + var node = new ObjectBindingPattern() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBraceToken); + + node.Elements = ParseDelimitedList(TsTypes.ParsingContext.ObjectBindingElements, ParseObjectBindingElement); + + ParseExpected(SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + + + public ArrayBindingPattern ParseArrayBindingPattern() + { + var node = new ArrayBindingPattern() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.OpenBracketToken); + + node.Elements = ParseDelimitedList(TsTypes.ParsingContext.ArrayBindingElements, ParseArrayBindingElement); + + ParseExpected(SyntaxKind.CloseBracketToken); + + return FinishNode(node); + } + + + public bool IsIdentifierOrPattern() + { + + return Token() == SyntaxKind.OpenBraceToken || Token() == SyntaxKind.OpenBracketToken || IsIdentifier(); + } + + + public /*Identifier | BindingPattern*/Node ParseIdentifierOrPattern() + { + if (Token() == SyntaxKind.OpenBracketToken) + { + + return ParseArrayBindingPattern(); + } + if (Token() == SyntaxKind.OpenBraceToken) + { + + return ParseObjectBindingPattern(); + } + + return ParseIdentifier(); + } + + + public VariableDeclaration ParseVariableDeclaration() + { + var node = new VariableDeclaration() { Pos = Scanner.GetStartPos() }; + + node.Name = ParseIdentifierOrPattern(); + + node.Type = ParseTypeAnnotation(); + if (!IsInOrOfKeyword(Token())) + { + + node.Initializer = ParseInitializer(/*inParameter*/ false); + } + + return FinishNode(node); + } + + + public IVariableDeclarationList ParseVariableDeclarationList(bool inForStatementInitializer) + { + var node = new VariableDeclarationList() { Pos = Scanner.GetStartPos() }; + switch (Token()) + { + case SyntaxKind.VarKeyword: + + break; + case SyntaxKind.LetKeyword: + + node.Flags |= NodeFlags.Let; + + break; + case SyntaxKind.ConstKeyword: + + node.Flags |= NodeFlags.Const; + + break; + default: + + Debug.Fail(); + break; + } + + + NextToken(); + if (Token() == SyntaxKind.OfKeyword && LookAhead(CanFollowContextualOfKeyword)) + { + + node.Declarations = CreateMissingList(); + } + else + { + var savedDisallowIn = InDisallowInContext(); + + SetDisallowInContext(inForStatementInitializer); + + + node.Declarations = ParseDelimitedList(TsTypes.ParsingContext.VariableDeclarations, ParseVariableDeclaration); + + + SetDisallowInContext(savedDisallowIn); + } + + + return FinishNode(node); + } + + + public bool CanFollowContextualOfKeyword() + { + + return NextTokenIsIdentifier() && NextToken() == SyntaxKind.CloseParenToken; + } + + + public VariableStatement ParseVariableStatement(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new VariableStatement() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + node.DeclarationList = ParseVariableDeclarationList(/*inForStatementInitializer*/ false); + + ParseSemicolon(); + + return AddJsDocComment(FinishNode(node)); + } + + + public FunctionDeclaration ParseFunctionDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new FunctionDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + ParseExpected(SyntaxKind.FunctionKeyword); + + node.AsteriskToken = (AsteriskToken)ParseOptionalToken(SyntaxKind.AsteriskToken); + + node.Name = HasModifier(node, ModifierFlags.Default) ? ParseOptionalIdentifier() : ParseIdentifier(); + var isGenerator = /*!!*/node.AsteriskToken != null; + var isAsync = HasModifier(node, ModifierFlags.Async); + + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node); + + node.Body = ParseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected); + + return AddJsDocComment(FinishNode(node)); + } + + + public ConstructorDeclaration ParseConstructorDeclaration(int pos, NodeArray decorators, NodeArray modifiers) + { + var node = new ConstructorDeclaration() { Pos = pos }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + ParseExpected(SyntaxKind.ConstructorKeyword); + + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + node.Body = ParseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, Diagnostics.or_expected); + + return AddJsDocComment(FinishNode(node)); + } + + + public MethodDeclaration ParseMethodDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers, AsteriskToken asteriskToken, IPropertyName name, QuestionToken questionToken, DiagnosticMessage diagnosticMessage = null) + { + var method = new MethodDeclaration() { Pos = fullStart }; + + method.Decorators = decorators; + + method.Modifiers = modifiers; + + method.AsteriskToken = asteriskToken; + + method.Name = name; + + method.QuestionToken = questionToken; + var isGenerator = /*!!*/asteriskToken != null; + var isAsync = HasModifier(method, ModifierFlags.Async); + + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, method); + + method.Body = ParseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage); + + return AddJsDocComment(FinishNode(method)); + } + + + public ClassElement ParsePropertyDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers, IPropertyName name, QuestionToken questionToken) + { + var property = new PropertyDeclaration() { Pos = fullStart }; + + property.Decorators = decorators; + + property.Modifiers = modifiers; + + property.Name = name; + + property.QuestionToken = questionToken; + + property.Type = ParseTypeAnnotation(); + + + // For instance properties specifically, since they are evaluated inside the constructor, + // we do *not * want to parse yield expressions, so we specifically turn the yield context + // off. The grammar would look something like this: + // + // MemberVariableDeclaration[Yield]: + // AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In]; + // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield]; + // + // The checker may still error in the static case to explicitly disallow the yield expression. + property.Initializer = HasModifier(property, ModifierFlags.Static) + ? AllowInAnd(ParseNonParameterInitializer) + : DoOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, ParseNonParameterInitializer); + + + ParseSemicolon(); + + return AddJsDocComment(FinishNode(property)); + } + + + public IClassElement ParsePropertyOrMethodDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var asteriskToken = (AsteriskToken)ParseOptionalToken(SyntaxKind.AsteriskToken); + var name = ParsePropertyName(); + var questionToken = (QuestionToken)ParseOptionalToken(SyntaxKind.QuestionToken); + if (asteriskToken != null || Token() == SyntaxKind.OpenParenToken || Token() == SyntaxKind.LessThanToken) + { + + return ParseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, Diagnostics.or_expected); + } + else + { + + return ParsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken); + } + } + + + public IExpression ParseNonParameterInitializer() + { + + return ParseInitializer(/*inParameter*/ false); + } + + + public IAccessorDeclaration ParseAccessorDeclaration(SyntaxKind kind, int fullStart, NodeArray decorators, NodeArray modifiers) + { + IAccessorDeclaration node = kind == SyntaxKind.GetAccessor ? (IAccessorDeclaration)new GetAccessorDeclaration() { Kind = kind, Pos = fullStart } : kind == SyntaxKind.SetAccessor ? new SetAccessorDeclaration() { Kind = kind, Pos = fullStart } : throw new NotSupportedException("parseAccessorDeclaration"); + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + node.Name = ParsePropertyName(); + + FillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + + node.Body = ParseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false); + + return AddJsDocComment(FinishNode(node)); + } + + + public bool IsClassMemberModifier(SyntaxKind idToken) + { + switch (idToken) + { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: + + return true; + default: + + return false; + } + } + + + public bool IsClassMemberStart() + { + SyntaxKind idToken = SyntaxKind.Unknown; // null; + if (Token() == SyntaxKind.AtToken) + { + + return true; + } + while (IsModifierKind(Token())) + { + + idToken = Token(); + if (IsClassMemberModifier(idToken)) + { + + return true; + } + + + NextToken(); + } + if (Token() == SyntaxKind.AsteriskToken) + { + + return true; + } + if (IsLiteralPropertyName()) + { + + idToken = Token(); + + NextToken(); + } + if (Token() == SyntaxKind.OpenBracketToken) + { + + return true; + } + if (idToken != SyntaxKind.Unknown) // null) + { + if (!IsKeyword(idToken) || idToken == SyntaxKind.SetKeyword || idToken == SyntaxKind.GetKeyword) + { + + return true; + } + switch (Token()) + { + case SyntaxKind.OpenParenToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.ColonToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.QuestionToken: + // Not valid, but permitted so that it gets caught later on. + return true; + default: + + // Covers + // - Semicolons (declaration termination) + // - Closing braces (end-of-class, must be declaration) + // - End-of-files (not valid, but permitted so that it gets caught later on) + // - Line-breaks (enabling *automatic semicolon insertion*) + return CanParseSemicolon(); + } + } + + + return false; + } + + + public NodeArray ParseDecorators() + { + NodeArray decorators = null; + while (true) + { + var decoratorStart = GetNodePos(); + if (!ParseOptional(SyntaxKind.AtToken)) + { + + break; + } + var decorator = new Decorator() { Pos = decoratorStart }; + + decorator.Expression = DoInDecoratorContext(ParseLeftHandSideExpressionOrHigher); + + FinishNode(decorator); + if (decorators == null) + { + + decorators = CreateList(); + decorators.Pos = decoratorStart; + decorators.Add(decorator); + } + else + { + + decorators.Add(decorator); + } + } + if (decorators != null) + { + + decorators.End = GetNodeEnd(); + } + + return decorators; + } + + + public NodeArray ParseModifiers(bool? permitInvalidConstAsModifier = null) + { + var modifiers = CreateList(); + while (true) + { + var modifierStart = Scanner.GetStartPos(); + var modifierKind = Token(); + if (Token() == SyntaxKind.ConstKeyword && permitInvalidConstAsModifier == true) + { + if (!TryParse(NextTokenIsOnSameLineAndCanFollowModifier)) + { + + break; + } + } + else + { + if (!ParseAnyContextualModifier()) + { + + break; + } + } + var modifier = FinishNode(new Modifier { Kind = modifierKind, Pos = modifierStart }); //(Modifier)createNode(modifierKind, modifierStart) + if (modifiers == null) + { + + modifiers = CreateList(); + modifiers.Pos = modifierStart; + modifiers.Add(modifier); + } + else + { + + modifiers.Add(modifier); + } + } + if (modifiers != null) + { + + modifiers.End = Scanner.GetStartPos(); + } + + return modifiers; + } + + + public NodeArray ParseModifiersForArrowFunction() + { + NodeArray modifiers = null; + if (Token() == SyntaxKind.AsyncKeyword) + { + var modifierStart = Scanner.GetStartPos(); + var modifierKind = Token(); + + NextToken(); + var modifier = FinishNode(new Modifier { Kind = modifierKind, Pos = modifierStart }); + //finishNode((Modifier)createNode(modifierKind, modifierStart)); + + modifiers = CreateList(); + modifiers.Pos = modifierStart; + modifiers.Add(modifier); + + modifiers.End = Scanner.GetStartPos(); + } + + + return modifiers; + } + + + public IClassElement ParseClassElement() + { + if (Token() == SyntaxKind.SemicolonToken) + { + var result = new SemicolonClassElement() { Pos = Scanner.GetStartPos() }; + + NextToken(); + + return FinishNode(result); + } + var fullStart = GetNodePos(); + var decorators = ParseDecorators(); + var modifiers = ParseModifiers(/*permitInvalidConstAsModifier*/ true); + var accessor = TryParseAccessorDeclaration(fullStart, decorators, modifiers); + if (accessor != null) + { + + return accessor; + } + if (Token() == SyntaxKind.ConstructorKeyword) + { + + return ParseConstructorDeclaration(fullStart, decorators, modifiers); + } + if (IsIndexSignature()) + { + + return ParseIndexSignatureDeclaration(fullStart, decorators, modifiers); + } + if (TokenIsIdentifierOrKeyword(Token()) || + Token() == SyntaxKind.StringLiteral || + Token() == SyntaxKind.NumericLiteral || + Token() == SyntaxKind.AsteriskToken || + Token() == SyntaxKind.OpenBracketToken) + { + + + return ParsePropertyOrMethodDeclaration(fullStart, decorators, modifiers); + } + if (decorators?.Any() == true || modifiers?.Any() == true) + { + var name = (Identifier)CreateMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + + return ParsePropertyDeclaration(fullStart, decorators, modifiers, name, /*questionToken*/ null); + } + + + // 'isClassMemberStart' should have hinted not to attempt parsing. + Debug.Fail("Should not have attempted to parse class member declaration."); + return null; + } + + + public ClassExpression ParseClassExpression() + { + var node = new ClassExpression { Pos = Scanner.GetStartPos() }; + node.Pos = Scanner.GetStartPos(); + //node.decorators = decorators; + + //node.modifiers = modifiers; + + ParseExpected(SyntaxKind.ClassKeyword); + + node.Name = ParseNameOfClassDeclarationOrExpression(); + + node.TypeParameters = ParseTypeParameters(); + + node.HeritageClauses = ParseHeritageClauses(); + if (ParseExpected(SyntaxKind.OpenBraceToken)) + { + + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } + node.Members = ParseClassMembers(); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + node.Members = new NodeArray(); // createMissingList(); + } + + + return AddJsDocComment(FinishNode(node)); + //return (ClassExpression)parseClassDeclarationOrExpression( + // /*fullStart*/ scanner.getStartPos(), + // /*decorators*/ null, + // /*modifiers*/ null, + // SyntaxKind.ClassExpression); + } + + + public ClassDeclaration ParseClassDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new ClassDeclaration + { + Pos = fullStart, + Decorators = decorators, + Modifiers = modifiers + }; + + + + ParseExpected(SyntaxKind.ClassKeyword); + + node.Name = ParseNameOfClassDeclarationOrExpression(); + + node.TypeParameters = ParseTypeParameters(); + + node.HeritageClauses = ParseHeritageClauses(); + if (ParseExpected(SyntaxKind.OpenBraceToken)) + { + + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } + node.Members = ParseClassMembers(); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + node.Members = new NodeArray(); // createMissingList(); + } + + + return (ClassDeclaration)AddJsDocComment(FinishNode(node)); + + //return (ClassDeclaration)parseClassDeclarationOrExpression(fullStart, decorators, modifiers, SyntaxKind.ClassDeclaration); + } + + + //public ClassLikeDeclaration parseClassDeclarationOrExpression(int fullStart, ListWithPos decorators, ListWithPos modifiers, SyntaxKind kind) + //{ + // var node = new ClassLikeDeclaration() { pos = fullStart }; + + // node.decorators = decorators; + + // node.modifiers = modifiers; + + // parseExpected(SyntaxKind.ClassKeyword); + + // node.name = parseNameOfClassDeclarationOrExpression(); + + // node.typeParameters = parseTypeParameters(); + + // node.heritageClauses = parseHeritageClauses(); + // if (parseExpected(SyntaxKind.OpenBraceToken)) + // { + + // // ClassTail[Yield,Await] : (Modified) See 14.5 + // // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } + // node.members = parseClassMembers(); + + // parseExpected(SyntaxKind.CloseBraceToken); + // } + // else + // { + + // node.members = new NodeArray(); createMissingList(); + // } + + + // return addJSDocComment(finishNode(node)); + //} + + + public Identifier ParseNameOfClassDeclarationOrExpression() + { + + // implements is a future reserved word so + // 'class implements' might mean either + // - class expression with omitted name, 'implements' starts heritage clause + // - class with name 'implements' + // 'isImplementsClause' helps to disambiguate between these two cases + return IsIdentifier() && !IsImplementsClause() + ? ParseIdentifier() + : null; + } + + + public bool IsImplementsClause() + { + + return Token() == SyntaxKind.ImplementsKeyword && LookAhead(NextTokenIsIdentifierOrKeyword); + } + + + public NodeArray ParseHeritageClauses() + { + if (IsHeritageClause()) + { + + return ParseList(TsTypes.ParsingContext.HeritageClauses, ParseHeritageClause); + } + + + return null; + } + + + public HeritageClause ParseHeritageClause() + { + var tok = Token(); + if (tok == SyntaxKind.ExtendsKeyword || tok == SyntaxKind.ImplementsKeyword) + { + var node = new HeritageClause() { Pos = Scanner.GetStartPos() }; + + node.Token = tok; + + NextToken(); + + node.Types = ParseDelimitedList(TsTypes.ParsingContext.HeritageClauseElement, ParseExpressionWithTypeArguments); + + return FinishNode(node); + } + + + return null; + } + + + public ExpressionWithTypeArguments ParseExpressionWithTypeArguments() + { + var node = new ExpressionWithTypeArguments() { Pos = Scanner.GetStartPos() }; + + node.Expression = ParseLeftHandSideExpressionOrHigher(); + if (Token() == SyntaxKind.LessThanToken) + { + + node.TypeArguments = ParseBracketedList(TsTypes.ParsingContext.TypeArguments, ParseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + } + + + return FinishNode(node); + } + + + public bool IsHeritageClause() + { + + return Token() == SyntaxKind.ExtendsKeyword || Token() == SyntaxKind.ImplementsKeyword; + } + + + public NodeArray ParseClassMembers() + { + + return ParseList2(TsTypes.ParsingContext.ClassMembers, ParseClassElement); + } + + + public InterfaceDeclaration ParseInterfaceDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new InterfaceDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + ParseExpected(SyntaxKind.InterfaceKeyword); + + node.Name = ParseIdentifier(); + + node.TypeParameters = ParseTypeParameters(); + + node.HeritageClauses = ParseHeritageClauses(); + + node.Members = ParseObjectTypeMembers(); + + return AddJsDocComment(FinishNode(node)); + } + + + public TypeAliasDeclaration ParseTypeAliasDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new TypeAliasDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + ParseExpected(SyntaxKind.TypeKeyword); + + node.Name = ParseIdentifier(); + + node.TypeParameters = ParseTypeParameters(); + + ParseExpected(SyntaxKind.EqualsToken); + + node.Type = ParseType(); + + ParseSemicolon(); + + return AddJsDocComment(FinishNode(node)); + } + + + public EnumMember ParseEnumMember() + { + var node = new EnumMember() { Pos = Scanner.GetStartPos() }; + + node.Name = ParsePropertyName(); + + node.Initializer = AllowInAnd(ParseNonParameterInitializer); + + return AddJsDocComment(FinishNode(node)); + } + + + public EnumDeclaration ParseEnumDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new EnumDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + ParseExpected(SyntaxKind.EnumKeyword); + + node.Name = ParseIdentifier(); + if (ParseExpected(SyntaxKind.OpenBraceToken)) + { + + node.Members = ParseDelimitedList(TsTypes.ParsingContext.EnumMembers, ParseEnumMember); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + node.Members = CreateMissingList(); + } + + return AddJsDocComment(FinishNode(node)); + } + + + public ModuleBlock ParseModuleBlock() + { + var node = new ModuleBlock() { Pos = Scanner.GetStartPos() }; + if (ParseExpected(SyntaxKind.OpenBraceToken)) + { + + node.Statements = ParseList2(TsTypes.ParsingContext.BlockStatements, ParseStatement); + + ParseExpected(SyntaxKind.CloseBraceToken); + } + else + { + + node.Statements = new NodeArray(); // createMissingList(); + } + + return FinishNode(node); + } + + + public ModuleDeclaration ParseModuleOrNamespaceDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers, NodeFlags flags) + { + var node = new ModuleDeclaration() { Pos = fullStart }; + var namespaceFlag = flags & NodeFlags.Namespace; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + + node.Flags |= flags; + + node.Name = ParseIdentifier(); + + node.Body = ParseOptional(SyntaxKind.DotToken) + ? (/*NamespaceDeclaration*/Node)ParseModuleOrNamespaceDeclaration(GetNodePos(), /*decorators*/ null, /*modifiers*/ null, NodeFlags.NestedNamespace | namespaceFlag) + : ParseModuleBlock(); + + return AddJsDocComment(FinishNode(node)); + } + + + public ModuleDeclaration ParseAmbientExternalModuleDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new ModuleDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + if (Token() == SyntaxKind.GlobalKeyword) + { + + // parse 'global' as name of global scope augmentation + node.Name = ParseIdentifier(); + + node.Flags |= NodeFlags.GlobalAugmentation; + } + else + { + + node.Name = (StringLiteral)ParseLiteralNode(/*internName*/ true); + } + if (Token() == SyntaxKind.OpenBraceToken) + { + + node.Body = ParseModuleBlock(); + } + else + { + + ParseSemicolon(); + } + + + return FinishNode(node); + } + + + public ModuleDeclaration ParseModuleDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + NodeFlags flags = 0; + if (Token() == SyntaxKind.GlobalKeyword) + { + + // global augmentation + return ParseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers); + } + else + if (ParseOptional(SyntaxKind.NamespaceKeyword)) + { + + flags |= NodeFlags.Namespace; + } + else + { + + ParseExpected(SyntaxKind.ModuleKeyword); + if (Token() == SyntaxKind.StringLiteral) + { + + return ParseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers); + } + } + + return ParseModuleOrNamespaceDeclaration(fullStart, decorators, modifiers, flags); + } + + + public bool IsExternalModuleReference() + { + + return Token() == SyntaxKind.RequireKeyword && + LookAhead(NextTokenIsOpenParen); + } + + + public bool NextTokenIsOpenParen() + { + + return NextToken() == SyntaxKind.OpenParenToken; + } + + + public bool NextTokenIsSlash() + { + + return NextToken() == SyntaxKind.SlashToken; + } + + + public NamespaceExportDeclaration ParseNamespaceExportDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var exportDeclaration = new NamespaceExportDeclaration() { Pos = fullStart }; + + exportDeclaration.Decorators = decorators; + + exportDeclaration.Modifiers = modifiers; + + ParseExpected(SyntaxKind.AsKeyword); + + ParseExpected(SyntaxKind.NamespaceKeyword); + + + exportDeclaration.Name = ParseIdentifier(); + + + ParseSemicolon(); + + + return FinishNode(exportDeclaration); + } + + + public /*ImportEqualsDeclaration | ImportDeclaration*/IStatement ParseImportDeclarationOrImportEqualsDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + + ParseExpected(SyntaxKind.ImportKeyword); + var afterImportPos = Scanner.GetStartPos(); + Identifier identifier = null; + if (IsIdentifier()) + { + + identifier = ParseIdentifier(); + if (Token() != SyntaxKind.CommaToken && Token() != SyntaxKind.FromKeyword) + { + + return ParseImportEqualsDeclaration(fullStart, decorators, modifiers, identifier); + } + } + var importDeclaration = new ImportDeclaration() { Pos = fullStart }; + + importDeclaration.Decorators = decorators; + + importDeclaration.Modifiers = modifiers; + if (identifier != null || // import id + Token() == SyntaxKind.AsteriskToken || // import * + Token() == SyntaxKind.OpenBraceToken) + { + // import { + importDeclaration.ImportClause = ParseImportClause(identifier, afterImportPos); + + ParseExpected(SyntaxKind.FromKeyword); + } + + + importDeclaration.ModuleSpecifier = ParseModuleSpecifier(); + + ParseSemicolon(); + + return FinishNode(importDeclaration); + } + + + public ImportEqualsDeclaration ParseImportEqualsDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers, Identifier identifier) + { + var importEqualsDeclaration = new ImportEqualsDeclaration() { Pos = fullStart }; + + importEqualsDeclaration.Decorators = decorators; + + importEqualsDeclaration.Modifiers = modifiers; + + importEqualsDeclaration.Name = identifier; + + ParseExpected(SyntaxKind.EqualsToken); + + importEqualsDeclaration.ModuleReference = ParseModuleReference(); + + ParseSemicolon(); + + return AddJsDocComment(FinishNode(importEqualsDeclaration)); + } + + + public ImportClause ParseImportClause(Identifier identifier, int fullStart) + { + var importClause = new ImportClause() { Pos = fullStart }; + if (identifier != null) + { + + // ImportedDefaultBinding: + // ImportedBinding + importClause.Name = identifier; + } + if (importClause.Name == null || + ParseOptional(SyntaxKind.CommaToken)) + { + + importClause.NamedBindings = Token() == SyntaxKind.AsteriskToken ? (INamedImportBindings)ParseNamespaceImport() : (INamedImportBindings)ParseNamedImportsOrExports(SyntaxKind.NamedImports); + } + + + return FinishNode(importClause); + } + + + public INode ParseModuleReference() + { + + return IsExternalModuleReference() + ? (INode)ParseExternalModuleReference() + : ParseEntityName(/*allowReservedWords*/ false); + } + + + public ExternalModuleReference ParseExternalModuleReference() + { + var node = new ExternalModuleReference() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.RequireKeyword); + + ParseExpected(SyntaxKind.OpenParenToken); + + node.Expression = ParseModuleSpecifier(); + + ParseExpected(SyntaxKind.CloseParenToken); + + return FinishNode(node); + } + + + public IExpression ParseModuleSpecifier() + { + if (Token() == SyntaxKind.StringLiteral) + { + var result = ParseLiteralNode(); + + InternIdentifier(((LiteralExpression)result).Text); + + return result; + } + else + { + + // We allow arbitrary expressions here, even though the grammar only allows string + // literals. We check to ensure that it is only a string literal later in the grammar + // check pass. + return ParseExpression(); + } + } + + + public NamespaceImport ParseNamespaceImport() + { + var namespaceImport = new NamespaceImport() { Pos = Scanner.GetStartPos() }; + + ParseExpected(SyntaxKind.AsteriskToken); + + ParseExpected(SyntaxKind.AsKeyword); + + namespaceImport.Name = ParseIdentifier(); + + return FinishNode(namespaceImport); + } + + + //public NamedImports parseNamedImportsOrExports(SyntaxKind.NamedImports kind) + //{ + //} + + + //public NamedExports parseNamedImportsOrExports(SyntaxKind.NamedExports kind) + //{ + //} + + + public INamedImportsOrExports ParseNamedImportsOrExports(SyntaxKind kind) + { + if (kind == SyntaxKind.NamedImports) + { + var node = new NamedImports { Pos = Scanner.GetStartPos() }; + node.Elements = ParseBracketedList(TsTypes.ParsingContext.ImportOrExportSpecifiers, ParseImportSpecifier, + SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + else + { + var node = new NamedExports { Pos = Scanner.GetStartPos() }; + node.Elements = ParseBracketedList(TsTypes.ParsingContext.ImportOrExportSpecifiers, ParseExportSpecifier, + SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); + + return FinishNode(node); + } + //var node = new NamedImports | NamedExports(); + + + //// NamedImports: + //// { } + //// { ImportsList } + //// { ImportsList, } + + //// ImportsList: + //// ImportSpecifier + //// ImportsList, ImportSpecifier + //node.elements = (List | List)parseBracketedList(ParsingContext.ImportOrExportSpecifiers, + // kind == SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier, + // SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); + + //return finishNode(node); + } + + + public ExportSpecifier ParseExportSpecifier() + { + var node = new ExportSpecifier { Pos = Scanner.GetStartPos() }; + var checkIdentifierIsKeyword = IsKeyword(Token()) && !IsIdentifier(); + var checkIdentifierStart = Scanner.GetTokenPos(); + var checkIdentifierEnd = Scanner.GetTextPos(); + var identifierName = ParseIdentifierName(); + if (Token() == SyntaxKind.AsKeyword) + { + + node.PropertyName = identifierName; + + ParseExpected(SyntaxKind.AsKeyword); + + checkIdentifierIsKeyword = IsKeyword(Token()) && !IsIdentifier(); + + checkIdentifierStart = Scanner.GetTokenPos(); + + checkIdentifierEnd = Scanner.GetTextPos(); + + node.Name = ParseIdentifierName(); + } + else + { + + node.Name = identifierName; + } + + return FinishNode(node); + //return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier); + } + + + public ImportSpecifier ParseImportSpecifier() + { + var node = new ImportSpecifier() { Pos = Scanner.GetStartPos() }; + var checkIdentifierIsKeyword = IsKeyword(Token()) && !IsIdentifier(); + var checkIdentifierStart = Scanner.GetTokenPos(); + var checkIdentifierEnd = Scanner.GetTextPos(); + var identifierName = ParseIdentifierName(); + if (Token() == SyntaxKind.AsKeyword) + { + + node.PropertyName = identifierName; + + ParseExpected(SyntaxKind.AsKeyword); + + checkIdentifierIsKeyword = IsKeyword(Token()) && !IsIdentifier(); + + checkIdentifierStart = Scanner.GetTokenPos(); + + checkIdentifierEnd = Scanner.GetTextPos(); + + node.Name = ParseIdentifierName(); + } + else + { + + node.Name = identifierName; + } + if (/*kind == SyntaxKind.ImportSpecifier && */checkIdentifierIsKeyword) + { + + // Report error identifier expected + ParseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, Diagnostics.Identifier_expected); + } + + return FinishNode(node); + + //return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier); + } + + + //public ImportOrExportSpecifier parseImportOrExportSpecifier(SyntaxKind kind) + //{ + // var node = new ImportSpecifier { pos = scanner.getStartPos() }; + // var checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); + // var checkIdentifierStart = scanner.getTokenPos(); + // var checkIdentifierEnd = scanner.getTextPos(); + // var identifierName = parseIdentifierName(); + // if (token() == SyntaxKind.AsKeyword) + // { + + // node.propertyName = identifierName; + + // parseExpected(SyntaxKind.AsKeyword); + + // checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); + + // checkIdentifierStart = scanner.getTokenPos(); + + // checkIdentifierEnd = scanner.getTextPos(); + + // node.name = parseIdentifierName(); + // } + // else + // { + + // node.name = identifierName; + // } + // if (kind == SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) + // { + + // // Report error identifier expected + // parseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, Diagnostics.Identifier_expected); + // } + + // return finishNode(node); + //} + + + public ExportDeclaration ParseExportDeclaration(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new ExportDeclaration() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + if (ParseOptional(SyntaxKind.AsteriskToken)) + { + + ParseExpected(SyntaxKind.FromKeyword); + + node.ModuleSpecifier = ParseModuleSpecifier(); + } + else + { + + node.ExportClause = (NamedExports)ParseNamedImportsOrExports(SyntaxKind.NamedExports); + if (Token() == SyntaxKind.FromKeyword || (Token() == SyntaxKind.StringLiteral && !Scanner.HasPrecedingLineBreak())) + { + + ParseExpected(SyntaxKind.FromKeyword); + + node.ModuleSpecifier = ParseModuleSpecifier(); + } + } + + ParseSemicolon(); + + return FinishNode(node); + } + + + public ExportAssignment ParseExportAssignment(int fullStart, NodeArray decorators, NodeArray modifiers) + { + var node = new ExportAssignment() { Pos = fullStart }; + + node.Decorators = decorators; + + node.Modifiers = modifiers; + if (ParseOptional(SyntaxKind.EqualsToken)) + { + + node.IsExportEquals = true; + } + else + { + + ParseExpected(SyntaxKind.DefaultKeyword); + } + + node.Expression = ParseAssignmentExpressionOrHigher(); + + ParseSemicolon(); + + return FinishNode(node); + } + + + public void ProcessReferenceComments(SourceFile sourceFile) + { + //var triviaScanner = new Scanner(sourceFile.languageVersion, /*skipTrivia*/false, LanguageVariant.Standard, sourceText); + //List referencedFiles = new List(); + //List typeReferenceDirectives = new List(); + ////(string path, string name)[] amdDependencies = []; + //List amdDependencies = new List(); + //string amdModuleName = null; + //CheckJsDirective checkJsDirective = null; + //while (true) + //{ + // var kind = triviaScanner.scan(); + // if (kind != SyntaxKind.SingleLineCommentTrivia) + // { + // if (isTrivia(kind)) + // { + + // continue; + // } + // else + // { + + // break; + // } + // } + // var range = new + // { + // kind = /*(SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia)*/triviaScanner.getToken(), + // pos = triviaScanner.getTokenPos(), + // end = triviaScanner.getTextPos() + // }; + // var comment = sourceText.substring(range.pos, range.end); + // var referencePathMatchResult = getFileReferenceFromReferencePath(comment, range); + // if (referencePathMatchResult) + // { + // var fileReference = referencePathMatchResult.fileReference; + + // sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib; + // var diagnosticMessage = referencePathMatchResult.diagnosticMessage; + // if (fileReference) + // { + // if (referencePathMatchResult.isTypeReferenceDirective) + // { + + // typeReferenceDirectives.Add(fileReference); + // } + // else + // { + + // referencedFiles.Add(fileReference); + // } + // } + // if (diagnosticMessage) + // { + + // parseDiagnostics.Add(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage)); + // } + // } + // else + // { + // var amdModuleNameRegEx = new Regex(@" /^\/\/\/\s* + { + + return HasModifier((INode)node, ModifierFlags.Export) + || node.Kind == SyntaxKind.ImportEqualsDeclaration && (node as ImportEqualsDeclaration)?.ModuleReference?.Kind == SyntaxKind.ExternalModuleReference + || node.Kind == SyntaxKind.ImportDeclaration + || node.Kind == SyntaxKind.ExportAssignment + || node.Kind == SyntaxKind.ExportDeclaration; + //? node : null; + } +); + } + + + + + + } + +} diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Scanner.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Scanner.cs new file mode 100644 index 0000000..ced3e5e --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Scanner.cs @@ -0,0 +1,2161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Zu.TypeScript.TsTypes; +using static Zu.TypeScript.TsParser.Core; +using CommentKind = Zu.TypeScript.TsTypes.SyntaxKind; + +namespace Zu.TypeScript.TsParser +{ + public delegate void ErrorCallback(DiagnosticMessage message, int? length); + + public class Scanner + { + private string _text; + // Current position (end position of text of current token) + private int _pos; + + // end of text + private int _end; + + // Start position of whitespace before current token + private int _startPos; + + // Start position of text of current token + private int _tokenPos; + + private SyntaxKind _token; + private int TokenInt => (int)_token; + private string _tokenValue; + private bool _precedingLineBreak; + private bool _hasExtendedUnicodeEscape; + private bool _tokenIsUnterminated; + private bool _skipTrivia; + public event ErrorCallback OnError; + private ScriptTarget _languageVersion; + private LanguageVariant _languageVariant; + + public int GetStartPos() => _startPos; + public int GetTextPos() => _pos; + public SyntaxKind GetToken() => _token; + public int GetTokenPos() => _tokenPos; + public string GetTokenText() => _text.substring(_tokenPos, _pos); + public string GetTokenValue() => _tokenValue; + public bool HasExtendedUnicodeEscape() => _hasExtendedUnicodeEscape; + public bool HasPrecedingLineBreak() => _precedingLineBreak; + public bool IsIdentifier() => _token == SyntaxKind.Identifier || _token > SyntaxKind.LastReservedWord; + public bool IsReservedWord() => _token >= SyntaxKind.FirstReservedWord && _token <= SyntaxKind.LastReservedWord; + public bool IsUnterminated() => _tokenIsUnterminated; + + + + + public Scanner(ScriptTarget languageVersion, bool skipTrivia, LanguageVariant languageVariant, string text, ErrorCallback onError = null, int start = 0, int? length = null) + { + this._languageVersion = languageVersion; + this._languageVariant = languageVariant; + this._skipTrivia = skipTrivia; + _pos = 0; + _end = 0; + _startPos = start; + _tokenPos = 0; + SetText(text, start, length); + } + public static Dictionary TextToToken = new Dictionary +{ +{ "abstract", SyntaxKind.AbstractKeyword }, +{ "any", SyntaxKind.AnyKeyword }, +{ "as", SyntaxKind.AsKeyword }, +{ "boolean", SyntaxKind.BooleanKeyword }, +{ "break", SyntaxKind.BreakKeyword }, +{ "case", SyntaxKind.CaseKeyword }, +{ "catch", SyntaxKind.CatchKeyword }, +{ "class", SyntaxKind.ClassKeyword }, +{ "continue", SyntaxKind.ContinueKeyword }, +{ "const", SyntaxKind.ConstKeyword }, +{ "constructor", SyntaxKind.ConstructorKeyword }, +{ "debugger", SyntaxKind.DebuggerKeyword }, +{ "declare", SyntaxKind.DeclareKeyword }, +{ "default", SyntaxKind.DefaultKeyword }, +{ "delete", SyntaxKind.DeleteKeyword }, +{ "do", SyntaxKind.DoKeyword }, +{ "else", SyntaxKind.ElseKeyword }, +{ "enum", SyntaxKind.EnumKeyword }, +{ "export", SyntaxKind.ExportKeyword }, +{ "extends", SyntaxKind.ExtendsKeyword }, +{ "false", SyntaxKind.FalseKeyword }, +{ "finally", SyntaxKind.FinallyKeyword }, +{ "for", SyntaxKind.ForKeyword }, +{ "from", SyntaxKind.FromKeyword }, +{ "function", SyntaxKind.FunctionKeyword }, +{ "get", SyntaxKind.GetKeyword }, +{ "if", SyntaxKind.IfKeyword }, +{ "implements", SyntaxKind.ImplementsKeyword }, +{ "import", SyntaxKind.ImportKeyword }, +{ "in", SyntaxKind.InKeyword }, +{ "instanceof", SyntaxKind.InstanceOfKeyword }, +{ "interface", SyntaxKind.InterfaceKeyword }, +{ "is", SyntaxKind.IsKeyword }, +{ "keyof", SyntaxKind.KeyOfKeyword }, +{ "let", SyntaxKind.LetKeyword }, +{ "module", SyntaxKind.ModuleKeyword }, +{ "namespace", SyntaxKind.NamespaceKeyword }, +{ "never", SyntaxKind.NeverKeyword }, +{ "new", SyntaxKind.NewKeyword }, +{ "null", SyntaxKind.NullKeyword }, +{ "number", SyntaxKind.NumberKeyword }, +{ "object", SyntaxKind.ObjectKeyword }, +{ "package", SyntaxKind.PackageKeyword }, +{ "private", SyntaxKind.PrivateKeyword }, +{ "protected", SyntaxKind.ProtectedKeyword }, +{ "public", SyntaxKind.PublicKeyword }, +{ "readonly", SyntaxKind.ReadonlyKeyword }, +{ "require", SyntaxKind.RequireKeyword }, +{ "global", SyntaxKind.GlobalKeyword }, +{ "return", SyntaxKind.ReturnKeyword }, +{ "set", SyntaxKind.SetKeyword }, +{ "static", SyntaxKind.StaticKeyword }, +{ "string", SyntaxKind.StringKeyword }, +{ "super", SyntaxKind.SuperKeyword }, +{ "switch", SyntaxKind.SwitchKeyword }, +{ "symbol", SyntaxKind.SymbolKeyword }, +{ "this", SyntaxKind.ThisKeyword }, +{ "throw", SyntaxKind.ThrowKeyword }, +{ "true", SyntaxKind.TrueKeyword }, +{ "try", SyntaxKind.TryKeyword }, +{ "type", SyntaxKind.TypeKeyword }, +{ "typeof", SyntaxKind.TypeOfKeyword }, +{ "undefined", SyntaxKind.UndefinedKeyword }, +{ "var", SyntaxKind.VarKeyword }, +{ "void", SyntaxKind.VoidKeyword }, +{ "while", SyntaxKind.WhileKeyword }, +{ "with", SyntaxKind.WithKeyword }, +{ "yield", SyntaxKind.YieldKeyword }, +{ "async", SyntaxKind.AsyncKeyword }, +{ "await", SyntaxKind.AwaitKeyword }, +{ "of", SyntaxKind.OfKeyword }, +{ "{", SyntaxKind.OpenBraceToken }, +{ "}", SyntaxKind.CloseBraceToken }, +{ "(", SyntaxKind.OpenParenToken }, +{ ")", SyntaxKind.CloseParenToken }, +{ "[", SyntaxKind.OpenBracketToken }, +{ "]", SyntaxKind.CloseBracketToken }, +{ ".", SyntaxKind.DotToken }, +{ "...", SyntaxKind.DotDotDotToken }, +{ ";", SyntaxKind.SemicolonToken }, +{ ",", SyntaxKind.CommaToken }, +{ "<", SyntaxKind.LessThanToken }, +{ ">", SyntaxKind.GreaterThanToken }, +{ "<=", SyntaxKind.LessThanEqualsToken }, +{ ">=", SyntaxKind.GreaterThanEqualsToken }, +{ "==", SyntaxKind.EqualsEqualsToken }, +{ "!=", SyntaxKind.ExclamationEqualsToken }, +{ "===", SyntaxKind.EqualsEqualsEqualsToken }, +{ "!==", SyntaxKind.ExclamationEqualsEqualsToken }, +{ "=>", SyntaxKind.EqualsGreaterThanToken }, +{ "+", SyntaxKind.PlusToken }, +{ "-", SyntaxKind.MinusToken }, +{ "**", SyntaxKind.AsteriskAsteriskToken }, +{ "*", SyntaxKind.AsteriskToken }, +{ "/", SyntaxKind.SlashToken }, +{ "%", SyntaxKind.PercentToken }, +{ "++", SyntaxKind.PlusPlusToken }, +{ "--", SyntaxKind.MinusMinusToken }, +{ "<<", SyntaxKind.LessThanLessThanToken }, +{ ">", SyntaxKind.GreaterThanGreaterThanToken }, +{ ">>>", SyntaxKind.GreaterThanGreaterThanGreaterThanToken }, +{ "&", SyntaxKind.AmpersandToken }, +{ "|", SyntaxKind.BarToken }, +{ "^", SyntaxKind.CaretToken }, +{ "!", SyntaxKind.ExclamationToken }, +{ "~", SyntaxKind.TildeToken }, +{ "&&", SyntaxKind.AmpersandAmpersandToken }, +{ "||", SyntaxKind.BarBarToken }, +{ "?", SyntaxKind.QuestionToken }, +{ ":", SyntaxKind.ColonToken }, +{ "=", SyntaxKind.EqualsToken }, +{ "+=", SyntaxKind.PlusEqualsToken }, +{ "-=", SyntaxKind.MinusEqualsToken }, +{ "*=", SyntaxKind.AsteriskEqualsToken }, +{ "**=", SyntaxKind.AsteriskAsteriskEqualsToken }, +{ "/=", SyntaxKind.SlashEqualsToken }, +{ "%=", SyntaxKind.PercentEqualsToken }, +{ "<<=", SyntaxKind.LessThanLessThanEqualsToken }, +{ ">>=", SyntaxKind.GreaterThanGreaterThanEqualsToken }, +{ ">>>=", SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken }, +{ "&=", SyntaxKind.AmpersandEqualsToken }, +{ "|=", SyntaxKind.BarEqualsToken }, +{ "^=", SyntaxKind.CaretEqualsToken }, +{ "@", SyntaxKind.AtToken }, +}; + public int[] UnicodeEs3IdentifierStart = { 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, }; + public int[] UnicodeEs3IdentifierPart = { 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, }; + public int[] UnicodeEs5IdentifierStart = { 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, }; + public int[] UnicodeEs5IdentifierPart = { 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, }; + private static int _mergeConflictMarkerLength = "<<<<<<<".Length; + private static Regex _shebangTriviaRegex = new Regex("/^#!.*/"); + + public static bool TokenIsIdentifierOrKeyword(SyntaxKind token) + { + return token >= SyntaxKind.Identifier; + } + + + public bool LookupInUnicodeMap(int code, int[] map) + { + if (code < map[0]) + { + return false; + } + var lo = 0; + int hi = map.Length; + int mid = 0; + while (lo + 1 < hi) + { + mid = lo + (hi - lo) / 2; + // mid has to be even to catch a range's beginning + mid -= mid % 2; + if (map[mid] <= code && code <= map[mid + 1]) + { + return true; + } + if (code < map[mid]) + { + hi = mid; + } + else + { + lo = mid + 2; + } + } + return false; + } + + + public bool IsUnicodeIdentifierStart(int code, ScriptTarget languageVersion) + { + return languageVersion >= ScriptTarget.Es5 ? + LookupInUnicodeMap(code, UnicodeEs5IdentifierStart) : + LookupInUnicodeMap(code, UnicodeEs3IdentifierStart); + } + + + public bool IsUnicodeIdentifierPart(int code, ScriptTarget languageVersion) + { + return languageVersion >= ScriptTarget.Es5 ? + LookupInUnicodeMap(code, UnicodeEs5IdentifierPart) : + LookupInUnicodeMap(code, UnicodeEs3IdentifierPart); + } + + + + public static string TokenToString(SyntaxKind t) + { + return TextToToken.FirstOrDefault(v => v.Value == t).Key; + } + + + public SyntaxKind StringToToken(string s) + { + return TextToToken[s]; + } + + public List ComputeLineStarts(string text) + { + List result = new List(); + var pos = 0; + var lineStart = 0; + while (pos < text.Length) + { + var ch = text.charCodeAt(pos); + pos++; + switch (ch) + { + case (int)CharacterCodes.CarriageReturn: + if (text.charCodeAt(pos) == (int)CharacterCodes.LineFeed) + { + pos++; + } + goto caseLabel2; + case (int)CharacterCodes.LineFeed: + caseLabel2: result.Add(lineStart); + lineStart = pos; + break; + default: + if (ch > (int)CharacterCodes.MaxAsciiCharacter && IsLineBreak(ch)) + { + result.Add(lineStart); + lineStart = pos; + } + break; + } + } + result.Add(lineStart); + return result; + } + + + public int GetPositionOfLineAndCharacter(SourceFile sourceFile, int line, int character) + { + return ComputePositionOfLineAndCharacter(GetLineStarts(sourceFile), line, character); + } + + + public int ComputePositionOfLineAndCharacter(int[] lineStarts, int line, int character) + { + Debug.Assert(line >= 0 && line < lineStarts.Length); + return lineStarts[line] + character; + } + + + + public int[] GetLineStarts(ISourceFileLike sourceFile) + { + return sourceFile.LineMap ?? (sourceFile.LineMap = ComputeLineStarts(sourceFile.Text).ToArray()); + } + + public LineAndCharacter ComputeLineAndCharacterOfPosition(int[] lineStarts, int position) + { + var lineNumber = BinarySearch(lineStarts, position); + if (lineNumber < 0) + { + // If the actual position was not found, + // the binary search returns the 2's-complement of the next line start + // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 + // then the search will return -2. + // + // We want the index of the previous line start, so we subtract 1. + // Review 2's-complement if this is confusing. + lineNumber = ~lineNumber - 1; + Debug.Assert(lineNumber != -1, "position cannot precede the beginning of the file"); + } + return new LineAndCharacter + { + Line = lineNumber, + Character = position - lineStarts[lineNumber] + }; + } + + + public LineAndCharacter GetLineAndCharacterOfPosition(SourceFile sourceFile, int position) + { + return ComputeLineAndCharacterOfPosition(GetLineStarts(sourceFile), position); + } + + + public static bool IsWhiteSpace(int ch) + { + return IsWhiteSpaceSingleLine(ch) || IsLineBreak(ch); + } + + + public static bool IsWhiteSpaceSingleLine(int ch) + { + // Note: nextLine is in the Zs space, and should be considered to be a whitespace. + // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. + return ch == (int)CharacterCodes.Space || + ch == (int)CharacterCodes.Tab || + ch == (int)CharacterCodes.VerticalTab || + ch == (int)CharacterCodes.FormFeed || + ch == (int)CharacterCodes.NonBreakingSpace || + ch == (int)CharacterCodes.NextLine || + ch == (int)CharacterCodes.Ogham || + ch >= (int)CharacterCodes.EnQuad && ch <= (int)CharacterCodes.ZeroWidthSpace || + ch == (int)CharacterCodes.NarrowNoBreakSpace || + ch == (int)CharacterCodes.MathematicalSpace || + ch == (int)CharacterCodes.IdeographicSpace || + ch == (int)CharacterCodes.ByteOrderMark; + } + + + public static bool IsLineBreak(int ch) + { + // ES5 7.3: + // The ECMAScript line terminator characters are listed in Table 3. + // Table 3: Line Terminator Characters + // Code Unit Value Name Formal Name + // \u000A Line Feed + // \u000D Carriage Return + // \u2028 Line separator + // \u2029 Paragraph separator + // Only the characters in Table 3 are treated as line terminators. Other new line or line + // breaking characters are treated as white space but not as line terminators. + + return ch == (int)CharacterCodes.LineFeed || + ch == (int)CharacterCodes.CarriageReturn || + ch == (int)CharacterCodes.LineSeparator || + ch == (int)CharacterCodes.ParagraphSeparator; + } + + + public bool IsDigit(int ch) + { + return ch >= (int)CharacterCodes._0 && ch <= (int)CharacterCodes._9; + } + + + public static bool IsOctalDigit(int ch) + { + return ch >= (int)CharacterCodes._0 && ch <= (int)CharacterCodes._7; + } + + + public bool CouldStartTrivia(string text, int pos) + { + var ch = text.charCodeAt(pos); + switch (ch) + { + case (int)CharacterCodes.CarriageReturn: + case (int)CharacterCodes.LineFeed: + case (int)CharacterCodes.Tab: + case (int)CharacterCodes.VerticalTab: + case (int)CharacterCodes.FormFeed: + case (int)CharacterCodes.Space: + case (int)CharacterCodes.Slash: + case (int)CharacterCodes.LessThan: + case (int)CharacterCodes.equals: + case (int)CharacterCodes.GreaterThan: + // Starts of conflict marker trivia + return true; + case (int)CharacterCodes.Hash: + // Only if its the beginning can we have #! trivia + return pos == 0; + default: + return ch > (int)CharacterCodes.MaxAsciiCharacter; + } + } + + + public static int SkipTriviaM(string text, int pos, bool stopAfterLineBreak = false, bool stopAtComments = false) + { + if (PositionIsSynthesized(pos)) + { + return pos; + } + while (true) + { + if (pos >= text.Length) return pos; + var ch = text.charCodeAt(pos); + switch (ch) + { + case (int)CharacterCodes.CarriageReturn: + if (pos + 1 >= text.Length) return pos; + if (text.charCodeAt(pos + 1) == (int)CharacterCodes.LineFeed) + { + pos++; + } + goto caseLabel2; + case (int)CharacterCodes.LineFeed: + caseLabel2: pos++; + if (stopAfterLineBreak) + { + return pos; + } + continue; + case (int)CharacterCodes.Tab: + case (int)CharacterCodes.VerticalTab: + case (int)CharacterCodes.FormFeed: + case (int)CharacterCodes.Space: + pos++; + continue; + case (int)CharacterCodes.Slash: + if (stopAtComments) + { + break; + } + if (pos + 1 >= text.Length) return pos; + if (text.charCodeAt(pos + 1) == (int)CharacterCodes.Slash) + { + pos += 2; + while (pos < text.Length) + { + if (IsLineBreak(text.charCodeAt(pos))) + { + break; + } + pos++; + } + continue; + } + if (pos + 1 >= text.Length) return pos; + if (text.charCodeAt(pos + 1) == (int)CharacterCodes.Asterisk) + { + pos += 2; + while (pos < text.Length) + { + if (pos + 1 >= text.Length) return pos; + if (text.charCodeAt(pos) == (int)CharacterCodes.Asterisk && text.charCodeAt(pos + 1) == (int)CharacterCodes.Slash) + { + pos += 2; + break; + } + pos++; + } + continue; + } + break; + case (int)CharacterCodes.LessThan: + case (int)CharacterCodes.equals: + case (int)CharacterCodes.GreaterThan: + if (IsConflictMarkerTrivia(text, pos)) + { + pos = ScanConflictMarkerTrivia(text, pos); + continue; + } + break; + case (int)CharacterCodes.Hash: + if (pos == 0 && IsShebangTrivia(text, pos)) + { + pos = ScanShebangTrivia(text, pos); + continue; + } + break; + default: + if (ch > (int)CharacterCodes.MaxAsciiCharacter && (IsWhiteSpace(ch))) + { + pos++; + continue; + } + break; + } + return pos; + } + } + + + public static bool IsConflictMarkerTrivia(string text, int pos) + { + Debug.Assert(pos >= 0); + if (pos == 0 || IsLineBreak(text.charCodeAt(pos - 1))) + { + var ch = text.charCodeAt(pos); + if ((pos + _mergeConflictMarkerLength) < text.Length) + { + for (var i = 0; i < _mergeConflictMarkerLength; i++) + { + if (text.charCodeAt(pos + i) != ch) + { + return false; + } + }; + return ch == (int)CharacterCodes.equals || + text.charCodeAt(pos + _mergeConflictMarkerLength) == (int)CharacterCodes.Space; + } + } + return false; + } + + + + public static int ScanConflictMarkerTrivia(string text, int pos, Action error = null) + { + error?.Invoke(Diagnostics.Merge_conflict_marker_encountered, _mergeConflictMarkerLength); + var ch = text.charCodeAt(pos); + var len = text.Length; + if (ch == (int)CharacterCodes.LessThan || ch == (int)CharacterCodes.GreaterThan) + { + while (pos < len && !IsLineBreak(text.charCodeAt(pos))) + { + pos++; + } + } + else + { + ////Debug.assert(ch == (int)CharacterCodes.equals); + while (pos < len) + { + var ch2 = text.charCodeAt(pos); + if (ch2 == (int)CharacterCodes.GreaterThan && IsConflictMarkerTrivia(text, pos)) + { + break; + } + pos++; + } + } + return pos; + } + public static bool IsShebangTrivia(string text, int pos) + { + // Shebangs check must only be done at the start of the file + Debug.Assert(pos == 0); + return _shebangTriviaRegex.test(text); + } + + + public static int ScanShebangTrivia(string text, int pos) + { + var shebang = _shebangTriviaRegex.exec(text)[0]; + pos = pos + shebang.Length; + return pos; + } + + + public static U IterateCommentRanges(bool reduce, string text, int pos, bool trailing, Func<(int pos, int end, CommentKind kind, bool hasTrailingNewLine, T state, U memo), U> cb, T state, U initial = default(U)) + { + int pendingPos = 0; + int pendingEnd = 0; + CommentKind pendingKind = SyntaxKind.Unknown; + bool pendingHasTrailingNewLine = false; + var hasPendingCommentRange = false; + var collecting = trailing || pos == 0; + var accumulator = initial; + while (pos >= 0 && pos < text.Length) + { + var ch = text.charCodeAt(pos); + switch (ch) + { + case (int)CharacterCodes.CarriageReturn: + if (text.charCodeAt(pos + 1) == (int)CharacterCodes.LineFeed) + { + pos++; + } + goto caseLabel2; + case (int)CharacterCodes.LineFeed: + caseLabel2: pos++; + if (trailing) + { + goto breakScan; + } + collecting = true; + if (hasPendingCommentRange) + { + pendingHasTrailingNewLine = true; + } + continue; + case (int)CharacterCodes.Tab: + case (int)CharacterCodes.VerticalTab: + case (int)CharacterCodes.FormFeed: + case (int)CharacterCodes.Space: + pos++; + continue; + case (int)CharacterCodes.Slash: + var nextChar = text.charCodeAt(pos + 1); + var hasTrailingNewLine = false; + if (nextChar == (int)CharacterCodes.Slash || nextChar == (int)CharacterCodes.Asterisk) + { + var kind = nextChar == (int)CharacterCodes.Slash ? SyntaxKind.SingleLineCommentTrivia : SyntaxKind.MultiLineCommentTrivia; + var startPos = pos; + pos += 2; + if (nextChar == (int)CharacterCodes.Slash) + { + while (pos < text.Length) + { + if (IsLineBreak(text.charCodeAt(pos))) + { + hasTrailingNewLine = true; + break; + } + pos++; + } + } + else + { + while (pos < text.Length) + { + if (text.charCodeAt(pos) == (int)CharacterCodes.Asterisk && text.charCodeAt(pos + 1) == (int)CharacterCodes.Slash) + { + pos += 2; + break; + } + pos++; + } + } + if (collecting) + { + if (hasPendingCommentRange) + { + accumulator = cb((pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator)); + if (!reduce && accumulator != null) + { + // If we are not reducing and we have a truthy result, return it. + return accumulator; + } + hasPendingCommentRange = false; + } + pendingPos = startPos; + pendingEnd = pos; + pendingKind = kind; + pendingHasTrailingNewLine = hasTrailingNewLine; + hasPendingCommentRange = true; + } + continue; + } + goto breakScan; + default: + if (ch > (int)CharacterCodes.MaxAsciiCharacter && (IsWhiteSpace(ch))) + { + if (hasPendingCommentRange && IsLineBreak(ch)) + { + pendingHasTrailingNewLine = true; + } + pos++; + continue; + } + goto breakScan; + } + } + breakScan: + if (hasPendingCommentRange) + { + accumulator = cb((pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator)); + } + return accumulator; + } + + + public U ForEachLeadingCommentRange(string text, int pos, Func<(int pos, int end, CommentKind kind, bool hasTrailingNewLine, T state, U memo), U> cb, T state) + { + return IterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); + } + + + public U ForEachTrailingCommentRange(string text, int pos, Func<(int pos, int end, CommentKind kind, bool hasTrailingNewLine, T state, U memo), U> cb, T state) + { + return IterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); + } + + + public static U ReduceEachLeadingCommentRange(string text, int pos, Func<(int pos, int end, CommentKind kind, bool hasTrailingNewLine, T state, U memo), U> cb, T state, U initial) + { + return IterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); + } + + + public static U ReduceEachTrailingCommentRange(string text, int pos, Func<(int pos, int end, CommentKind kind, bool hasTrailingNewLine, T state, U memo), U> cb, T state, U initial) + { + return IterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); + } + + + public static List AppendCommentRange((int pos, int end, CommentKind kind, bool hasTrailingNewLine, object _state, List comments) cb) + { + if (cb.comments == null) + { + cb.comments = new List(); + } + cb.comments.Add(new CommentRange { Kind = cb.kind, Pos = cb.pos, End = cb.end, HasTrailingNewLine = cb.hasTrailingNewLine }); + return cb.comments; + } + + + public static List GetLeadingCommentRanges(string text, int pos) + { + return ReduceEachLeadingCommentRange>(text, pos, AppendCommentRange, null, null) ?? new List(); + } + + + public static List GetTrailingCommentRanges(string text, int pos) + { + return ReduceEachTrailingCommentRange>(text, pos, AppendCommentRange, null, null) ?? new List(); + } + + + public string GetShebang(string text) + { + return _shebangTriviaRegex.test(text) + ? _shebangTriviaRegex.exec(text)[0] + : null; + } + + + public bool IsIdentifierStart(int ch, ScriptTarget languageVersion) + { + return ch >= (int)CharacterCodes.A && ch <= (int)CharacterCodes.Z || ch >= (int)CharacterCodes.a && ch <= (int)CharacterCodes.z || + ch == (int)CharacterCodes.Dollar || ch == (int)CharacterCodes._ || + ch > (int)CharacterCodes.MaxAsciiCharacter && IsUnicodeIdentifierStart(ch, languageVersion); + } + + + public bool IsIdentifierPart(int ch, ScriptTarget languageVersion) + { + return ch >= (int)CharacterCodes.A && ch <= (int)CharacterCodes.Z || ch >= (int)CharacterCodes.a && ch <= (int)CharacterCodes.z || + ch >= (int)CharacterCodes._0 && ch <= (int)CharacterCodes._9 || ch == (int)CharacterCodes.Dollar || ch == (int)CharacterCodes._ || + ch > (int)CharacterCodes.MaxAsciiCharacter && IsUnicodeIdentifierPart(ch, languageVersion); + } + + + public bool IsIdentifierText(string name, ScriptTarget languageVersion) + { + if (!IsIdentifierStart(name.charCodeAt(0), languageVersion)) + { + return false; + } + for (var i = 1; i < name.Length; i++) + { + if (!IsIdentifierPart(name.charCodeAt(i), languageVersion)) + { + return false; + } + }; + return true; + } + + + + + // export function createScanner() + + + + public void Error(DiagnosticMessage message, int length = 0) + { + OnError?.Invoke(message, length); + } + public string ScanNumber() + { + var start = _pos; + while (IsDigit(_text.charCodeAt(_pos))) + { + _pos++; + } + if (_text.charCodeAt(_pos) == (int)CharacterCodes.Dot) + { + _pos++; + while (IsDigit(_text.charCodeAt(_pos))) + { + _pos++; + } + } + var end = _pos; + if (_text.charCodeAt(_pos) == (int)CharacterCodes.E || _text.charCodeAt(_pos) == (int)CharacterCodes.e) + { + _pos++; + if (_text.charCodeAt(_pos) == (int)CharacterCodes.Plus || _text.charCodeAt(_pos) == (int)CharacterCodes.Minus) + { + _pos++; + } + if (IsDigit(_text.charCodeAt(_pos))) + { + _pos++; + while (IsDigit(_text.charCodeAt(_pos))) + { + _pos++; + } + end = _pos; + } + else + { + Error(Diagnostics.Digit_expected); + } + } + return "" + (_text.substring(start, end)); + } + + + public int ScanOctalDigits() + { + var start = _pos; + while (IsOctalDigit(_text.charCodeAt(_pos))) + { + _pos++; + } + return int.Parse(_text.substring(start, _pos)); + } + + + public int ScanExactNumberOfHexDigits(int count) + { + return ScanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false); + } + + + public int ScanMinimumNumberOfHexDigits(int count) + { + return ScanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true); + } + + + public int ScanHexDigits(int minCount, bool scanAsManyAsPossible) + { + var digits = 0; + var value = 0; + while (digits < minCount || scanAsManyAsPossible) + { + var ch = _text.charCodeAt(_pos); + if (ch >= (int)CharacterCodes._0 && ch <= (int)CharacterCodes._9) + { + value = value * 16 + ch - (int)CharacterCodes._0; + } + else + if (ch >= (int)CharacterCodes.A && ch <= (int)CharacterCodes.F) + { + value = value * 16 + ch - (int)CharacterCodes.A + 10; + } + else + if (ch >= (int)CharacterCodes.a && ch <= (int)CharacterCodes.f) + { + value = value * 16 + ch - (int)CharacterCodes.a + 10; + } + else + { + break; + } + _pos++; + digits++; + } + if (digits < minCount) + { + value = -1; + } + return value; + } + + + public string ScanString(bool allowEscapes = true) + { + var quote = _text.charCodeAt(_pos); + _pos++; + var result = ""; + var start = _pos; + while (true) + { + if (_pos >= _end) + { + result += _text.substring(start, _pos); + _tokenIsUnterminated = true; + Error(Diagnostics.Unterminated_string_literal); + break; + } + var ch = _text.charCodeAt(_pos); + if (ch == quote) + { + result += _text.substring(start, _pos); + _pos++; + break; + } + if (ch == (int)CharacterCodes.Backslash && allowEscapes) + { + result += _text.substring(start, _pos); + result += ScanEscapeSequence(); + start = _pos; + continue; + } + if (IsLineBreak(ch)) + { + result += _text.substring(start, _pos); + _tokenIsUnterminated = true; + Error(Diagnostics.Unterminated_string_literal); + break; + } + _pos++; + } + return result; + } + + + public SyntaxKind ScanTemplateAndSetTokenValue() + { + var startedWithBacktick = _text.charCodeAt(_pos) == (int)CharacterCodes.Backtick; + _pos++; + var start = _pos; + var contents = ""; + SyntaxKind resultingToken; + while (true) + { + if (_pos >= _end) + { + contents += _text.substring(start, _pos); + _tokenIsUnterminated = true; + Error(Diagnostics.Unterminated_template_literal); + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; + break; + } + var currChar = _text.charCodeAt(_pos); + if (currChar == (int)CharacterCodes.Backtick) + { + contents += _text.substring(start, _pos); + _pos++; + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; + break; + } + if (currChar == (int)CharacterCodes.Dollar && _pos + 1 < _end && _text.charCodeAt(_pos + 1) == (int)CharacterCodes.OpenBrace) + { + contents += _text.substring(start, _pos); + _pos += 2; + resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle; + break; + } + if (currChar == (int)CharacterCodes.Backslash) + { + contents += _text.substring(start, _pos); + contents += ScanEscapeSequence(); + start = _pos; + continue; + } + if (currChar == (int)CharacterCodes.CarriageReturn) + { + contents += _text.substring(start, _pos); + _pos++; + if (_pos < _end && _text.charCodeAt(_pos) == (int)CharacterCodes.LineFeed) + { + _pos++; + } + contents += "\n"; + start = _pos; + continue; + } + _pos++; + } + //Debug.assert(resultingToken != null); + _tokenValue = contents; + return resultingToken; + } + + + public string ScanEscapeSequence() + { + _pos++; + if (_pos >= _end) + { + Error(Diagnostics.Unexpected_end_of_text); + return ""; + } + var ch = _text.charCodeAt(_pos); + _pos++; + switch (ch) + { + case (int)CharacterCodes._0: + return "\0"; + case (int)CharacterCodes.b: + return "\b"; + case (int)CharacterCodes.t: + return "\t"; + case (int)CharacterCodes.n: + return "\n"; + case (int)CharacterCodes.v: + return "\v"; + case (int)CharacterCodes.f: + return "\f"; + case (int)CharacterCodes.r: + return "\r"; + case (int)CharacterCodes.SingleQuote: + return "\'"; + case (int)CharacterCodes.DoubleQuote: + return "\""; + case (int)CharacterCodes.u: + if (_pos < _end && _text.charCodeAt(_pos) == (int)CharacterCodes.OpenBrace) + { + _hasExtendedUnicodeEscape = true; + _pos++; + return ScanExtendedUnicodeEscape(); + } + // '\uDDDD' + return ScanHexadecimalEscape(/*numDigits*/ 4); + case (int)CharacterCodes.x: + // '\xDD' + return ScanHexadecimalEscape(/*numDigits*/ 2); + case (int)CharacterCodes.CarriageReturn: + if (_pos < _end && _text.charCodeAt(_pos) == (int)CharacterCodes.LineFeed) + { + _pos++; + } + goto caseLabel15; + case (int)CharacterCodes.LineFeed: + case (int)CharacterCodes.LineSeparator: + case (int)CharacterCodes.ParagraphSeparator: + caseLabel15: return ""; + default: + return ((char)ch).ToString(); + } + } + + + public string ScanHexadecimalEscape(int numDigits) + { + var escapedValue = ScanExactNumberOfHexDigits(numDigits); + if (escapedValue >= 0) + { + return String.fromCharCode(escapedValue); + } + else + { + Error(Diagnostics.Hexadecimal_digit_expected); + return ""; + } + } + + + public string ScanExtendedUnicodeEscape() + { + var escapedValue = ScanMinimumNumberOfHexDigits(1); + var isInvalidExtendedEscape = false; + if (escapedValue < 0) + { + Error(Diagnostics.Hexadecimal_digit_expected); + isInvalidExtendedEscape = true; + } + else + if (escapedValue > 0x10FFFF) + { + Error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); + isInvalidExtendedEscape = true; + } + if (_pos >= _end) + { + Error(Diagnostics.Unexpected_end_of_text); + isInvalidExtendedEscape = true; + } + else + if (_text.charCodeAt(_pos) == (int)CharacterCodes.CloseBrace) + { + // Only swallow the following character up if it's a '}'. + _pos++; + } + else + { + Error(Diagnostics.Unterminated_Unicode_escape_sequence); + isInvalidExtendedEscape = true; + } + if (isInvalidExtendedEscape) + { + return ""; + } + return Utf16EncodeAsString(escapedValue); + } + + + public string Utf16EncodeAsString(int codePoint) + { + Debug.Assert(0x0 <= codePoint && codePoint <= 0x10FFFF); + if (codePoint <= 65535) + { + return String.fromCharCode(codePoint); + } + var codeUnit1 = (int)Math.Floor(((double)codePoint - 65536) / 1024) + 0xD800; + var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00; + return String.fromCharCode(codeUnit1, codeUnit2); + } + + + public int PeekUnicodeEscape() + { + if (_pos + 5 < _end && _text.charCodeAt(_pos + 1) == (int)CharacterCodes.u) + { + var start = _pos; + _pos += 2; + var value = ScanExactNumberOfHexDigits(4); + _pos = start; + return value; + } + return -1; + } + + + public string ScanIdentifierParts() + { + var result = ""; + var start = _pos; + while (_pos < _end) + { + var ch = _text.charCodeAt(_pos); + if (IsIdentifierPart(ch, _languageVersion)) + { + _pos++; + } + else + if (ch == (int)CharacterCodes.Backslash) + { + ch = PeekUnicodeEscape(); + if (!(ch >= 0 && IsIdentifierPart(ch, _languageVersion))) + { + break; + } + result += _text.substring(start, _pos); + result += String.fromCharCode(ch); + // Valid Unicode escape is always six characters + _pos += 6; + start = _pos; + } + else + { + break; + } + } + result += _text.substring(start, _pos); + return result; + } + + + public SyntaxKind GetIdentifierToken() + { + var len = _tokenValue.Length; + if (len >= 2 && len <= 11) + { + var ch = _tokenValue.charCodeAt(0); + if (ch >= (int)CharacterCodes.a && ch <= (int)CharacterCodes.z) + { + if (TextToToken.ContainsKey(_tokenValue)) + { + _token = TextToToken[_tokenValue]; + return _token; + } + } + } + _token = SyntaxKind.Identifier; + return _token; + } + + + public int ScanBinaryOrOctalDigits(int @base) + { + Debug.Assert(@base == 2 || @base == 8, "Expected either @base 2 or @base 8"); + var value = 0; + var numberOfDigits = 0; + while (true) + { + var ch = _text.charCodeAt(_pos); + var valueOfCh = ch - (int)CharacterCodes._0; + if (!IsDigit(ch) || valueOfCh >= @base) + { + break; + } + value = value * @base + valueOfCh; + _pos++; + numberOfDigits++; + } + if (numberOfDigits == 0) + { + return -1; + } + return value; + } + + + public SyntaxKind Scan() + { + _startPos = _pos; + _hasExtendedUnicodeEscape = false; + _precedingLineBreak = false; + _tokenIsUnterminated = false; + while (true) + { + _tokenPos = _pos; + if (_pos >= _end) + { + _token = SyntaxKind.EndOfFileToken; + return _token; + } + var ch = _text.charCodeAt(_pos); + if (ch == (int)CharacterCodes.Hash && _pos == 0 && IsShebangTrivia(_text, _pos)) + { + _pos = ScanShebangTrivia(_text, _pos); + if (_skipTrivia) + { + continue; + } + else + { + _token = SyntaxKind.ShebangTrivia; + return _token; + } + } + switch (ch) + { + case (int)CharacterCodes.LineFeed: + case (int)CharacterCodes.CarriageReturn: + _precedingLineBreak = true; + if (_skipTrivia) + { + _pos++; + continue; + } + else + { + if (ch == (int)CharacterCodes.CarriageReturn && _pos + 1 < _end && _text.charCodeAt(_pos + 1) == (int)CharacterCodes.LineFeed) + { + _pos += 2; + } + else + { + _pos++; + } + _token = SyntaxKind.NewLineTrivia; + return _token; + } + goto caseLabel6; + case (int)CharacterCodes.Tab: + case (int)CharacterCodes.VerticalTab: + case (int)CharacterCodes.FormFeed: + case (int)CharacterCodes.Space: + caseLabel6: if (_skipTrivia) + { + _pos++; + continue; + } + else + { + while (_pos < _end && IsWhiteSpaceSingleLine(_text.charCodeAt(_pos))) + { + _pos++; + } + _token = SyntaxKind.WhitespaceTrivia; + return _token; + } + goto caseLabel7; + case (int)CharacterCodes.Exclamation: + caseLabel7: if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + if (_text.charCodeAt(_pos + 2) == (int)CharacterCodes.equals) + { + _pos += 3; + _token = SyntaxKind.ExclamationEqualsEqualsToken; + return _token; + } + _pos += 2; + _token = SyntaxKind.ExclamationEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.ExclamationToken; + return _token; + case (int)CharacterCodes.DoubleQuote: + case (int)CharacterCodes.SingleQuote: + _tokenValue = ScanString(); + _token = SyntaxKind.StringLiteral; + return _token; + case (int)CharacterCodes.Backtick: + _token = ScanTemplateAndSetTokenValue(); + return _token; + case (int)CharacterCodes.Percent: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.PercentEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.PercentToken; + return _token; + case (int)CharacterCodes.Ampersand: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Ampersand) + { + _pos += 2; + _token = SyntaxKind.AmpersandAmpersandToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.AmpersandEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.AmpersandToken; + return _token; + case (int)CharacterCodes.OpenParen: + _pos++; + _token = SyntaxKind.OpenParenToken; + return _token; + case (int)CharacterCodes.CloseParen: + _pos++; + _token = SyntaxKind.CloseParenToken; + return _token; + case (int)CharacterCodes.Asterisk: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.AsteriskEqualsToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Asterisk) + { + if (_text.charCodeAt(_pos + 2) == (int)CharacterCodes.equals) + { + _pos += 3; + _token = SyntaxKind.AsteriskAsteriskEqualsToken; + return _token; + } + _pos += 2; + _token = SyntaxKind.AsteriskAsteriskToken; + return _token; + } + _pos++; + _token = SyntaxKind.AsteriskToken; + return _token; + case (int)CharacterCodes.Plus: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Plus) + { + _pos += 2; + _token = SyntaxKind.PlusPlusToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.PlusEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.PlusToken; + return _token; + case (int)CharacterCodes.Comma: + _pos++; + _token = SyntaxKind.CommaToken; + return _token; + case (int)CharacterCodes.Minus: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Minus) + { + _pos += 2; + _token = SyntaxKind.MinusMinusToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.MinusEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.MinusToken; + return _token; + case (int)CharacterCodes.Dot: + if (IsDigit(_text.charCodeAt(_pos + 1))) + { + _tokenValue = ScanNumber(); + _token = SyntaxKind.NumericLiteral; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Dot && _text.charCodeAt(_pos + 2) == (int)CharacterCodes.Dot) + { + _pos += 3; + _token = SyntaxKind.DotDotDotToken; + return _token; + } + _pos++; + _token = SyntaxKind.DotToken; + return _token; + case (int)CharacterCodes.Slash: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Slash) + { + _pos += 2; + while (_pos < _end) + { + if (IsLineBreak(_text.charCodeAt(_pos))) + { + break; + } + _pos++; + } + if (_skipTrivia) + { + continue; + } + else + { + _token = SyntaxKind.SingleLineCommentTrivia; + return _token; + } + } + + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Asterisk) + { + _pos += 2; + var commentClosed = false; + while (_pos < _end) + { + var ch2 = _text.charCodeAt(_pos); + if (ch2 == (int)CharacterCodes.Asterisk && _text.charCodeAt(_pos + 1) == (int)CharacterCodes.Slash) + { + _pos += 2; + commentClosed = true; + break; + } + if (IsLineBreak(ch2)) + { + _precedingLineBreak = true; + } + _pos++; + } + if (!commentClosed) + { + Error(Diagnostics.Asterisk_Slash_expected); + } + if (_skipTrivia) + { + continue; + } + else + { + _tokenIsUnterminated = !commentClosed; + _token = SyntaxKind.MultiLineCommentTrivia; + return _token; + } + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.SlashEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.SlashToken; + return _token; + case (int)CharacterCodes._0: + if (_pos + 2 < _end && (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.X || _text.charCodeAt(_pos + 1) == (int)CharacterCodes.x)) + { + _pos += 2; + var value = ScanMinimumNumberOfHexDigits(1); + if (value < 0) + { + Error(Diagnostics.Hexadecimal_digit_expected); + value = 0; + } + _tokenValue = "" + value; + _token = SyntaxKind.NumericLiteral; + return _token; + } + else + if (_pos + 2 < _end && (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.B || _text.charCodeAt(_pos + 1) == (int)CharacterCodes.b)) + { + _pos += 2; + var value = ScanBinaryOrOctalDigits(/* base */ 2); + if (value < 0) + { + Error(Diagnostics.Binary_digit_expected); + value = 0; + } + _tokenValue = "" + value; + _token = SyntaxKind.NumericLiteral; + return _token; + } + else + if (_pos + 2 < _end && (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.O || _text.charCodeAt(_pos + 1) == (int)CharacterCodes.o)) + { + _pos += 2; + var value = ScanBinaryOrOctalDigits(/* base */ 8); + if (value < 0) + { + Error(Diagnostics.Octal_digit_expected); + value = 0; + } + _tokenValue = "" + value; + _token = SyntaxKind.NumericLiteral; + return _token; + } + if (_pos + 1 < _end && IsOctalDigit(_text.charCodeAt(_pos + 1))) + { + _tokenValue = "" + ScanOctalDigits(); + _token = SyntaxKind.NumericLiteral; + return _token; + } + goto caseLabel30; + case (int)CharacterCodes._1: + case (int)CharacterCodes._2: + case (int)CharacterCodes._3: + case (int)CharacterCodes._4: + case (int)CharacterCodes._5: + case (int)CharacterCodes._6: + case (int)CharacterCodes._7: + case (int)CharacterCodes._8: + case (int)CharacterCodes._9: + caseLabel30: _tokenValue = ScanNumber(); + _token = SyntaxKind.NumericLiteral; + return _token; + case (int)CharacterCodes.Colon: + _pos++; + _token = SyntaxKind.ColonToken; + return _token; + case (int)CharacterCodes.Semicolon: + _pos++; + _token = SyntaxKind.SemicolonToken; + return _token; + case (int)CharacterCodes.LessThan: + if (IsConflictMarkerTrivia(_text, _pos)) + { + _pos = ScanConflictMarkerTrivia(_text, _pos, Error); + if (_skipTrivia) + { + continue; + } + else + { + _token = SyntaxKind.ConflictMarkerTrivia; + return _token; + } + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.LessThan) + { + if (_text.charCodeAt(_pos + 2) == (int)CharacterCodes.equals) + { + _pos += 3; + _token = SyntaxKind.LessThanLessThanEqualsToken; + return _token; + } + _pos += 2; + _token = SyntaxKind.LessThanLessThanToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.LessThanEqualsToken; + return _token; + } + if (_languageVariant == LanguageVariant.Jsx && + _text.charCodeAt(_pos + 1) == (int)CharacterCodes.Slash && + _text.charCodeAt(_pos + 2) != (int)CharacterCodes.Asterisk) + { + _pos += 2; + _token = SyntaxKind.LessThanSlashToken; + return _token; + } + _pos++; + _token = SyntaxKind.LessThanToken; + return _token; + case (int)CharacterCodes.equals: + if (IsConflictMarkerTrivia(_text, _pos)) + { + _pos = ScanConflictMarkerTrivia(_text, _pos, Error); + if (_skipTrivia) + { + continue; + } + else + { + _token = SyntaxKind.ConflictMarkerTrivia; + return _token; + } + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + if (_text.charCodeAt(_pos + 2) == (int)CharacterCodes.equals) + { + _pos += 3; + _token = SyntaxKind.EqualsEqualsEqualsToken; + return _token; + } + _pos += 2; + _token = SyntaxKind.EqualsEqualsToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.GreaterThan) + { + _pos += 2; + _token = SyntaxKind.EqualsGreaterThanToken; + return _token; + } + _pos++; + _token = SyntaxKind.EqualsToken; + return _token; + case (int)CharacterCodes.GreaterThan: + if (IsConflictMarkerTrivia(_text, _pos)) + { + _pos = ScanConflictMarkerTrivia(_text, _pos, Error); + if (_skipTrivia) + { + continue; + } + else + { + _token = SyntaxKind.ConflictMarkerTrivia; + return _token; + } + } + _pos++; + _token = SyntaxKind.GreaterThanToken; + return _token; + case (int)CharacterCodes.Question: + _pos++; + _token = SyntaxKind.QuestionToken; + return _token; + case (int)CharacterCodes.OpenBracket: + _pos++; + _token = SyntaxKind.OpenBracketToken; + return _token; + case (int)CharacterCodes.CloseBracket: + _pos++; + _token = SyntaxKind.CloseBracketToken; + return _token; + case (int)CharacterCodes.Caret: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.CaretEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.CaretToken; + return _token; + case (int)CharacterCodes.OpenBrace: + _pos++; + _token = SyntaxKind.OpenBraceToken; + return _token; + case (int)CharacterCodes.Bar: + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Bar) + { + _pos += 2; + _token = SyntaxKind.BarBarToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.BarEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.BarToken; + return _token; + case (int)CharacterCodes.CloseBrace: + _pos++; + _token = SyntaxKind.CloseBraceToken; + return _token; + case (int)CharacterCodes.Tilde: + _pos++; + _token = SyntaxKind.TildeToken; + return _token; + case (int)CharacterCodes.At: + _pos++; + _token = SyntaxKind.AtToken; + return _token; + case (int)CharacterCodes.Backslash: + var cookedChar = PeekUnicodeEscape(); + if (cookedChar >= 0 && IsIdentifierStart(cookedChar, _languageVersion)) + { + _pos += 6; + _tokenValue = String.fromCharCode(cookedChar) + ScanIdentifierParts(); + _token = GetIdentifierToken(); + return _token; + } + Error(Diagnostics.Invalid_character); + _pos++; + _token = SyntaxKind.Unknown; + return _token; + default: + if (IsIdentifierStart(ch, _languageVersion)) + { + _pos++; + while (_pos < _end && IsIdentifierPart(ch = _text.charCodeAt(_pos), _languageVersion)) _pos++; + _tokenValue = _text.substring(_tokenPos, _pos); + if (ch == (int)CharacterCodes.Backslash) + { + _tokenValue += ScanIdentifierParts(); + } + return _token = GetIdentifierToken(); + } + else if (IsWhiteSpaceSingleLine(ch)) + { + _pos++; + continue; + } + else if (IsLineBreak(ch)) + { + _precedingLineBreak = true; + _pos++; + continue; + } + Error(Diagnostics.Invalid_character); + _pos++; + _token = SyntaxKind.Unknown; + return _token; + } + } + } + + + public SyntaxKind ReScanGreaterToken() + { + if (_token == SyntaxKind.GreaterThanToken) + { + if (_text.charCodeAt(_pos) == (int)CharacterCodes.GreaterThan) + { + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.GreaterThan) + { + if (_text.charCodeAt(_pos + 2) == (int)CharacterCodes.equals) + { + _pos += 3; + _token = SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken; + return _token; + } + _pos += 2; + _token = SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + return _token; + } + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.equals) + { + _pos += 2; + _token = SyntaxKind.GreaterThanGreaterThanEqualsToken; + return _token; + } + _pos++; + _token = SyntaxKind.GreaterThanGreaterThanToken; + return _token; + } + if (_text.charCodeAt(_pos) == (int)CharacterCodes.equals) + { + _pos++; + _token = SyntaxKind.GreaterThanEqualsToken; + return _token; + } + } + return _token; + } + + + public SyntaxKind ReScanSlashToken() + { + if (_token == SyntaxKind.SlashToken || _token == SyntaxKind.SlashEqualsToken) + { + var p = _tokenPos + 1; + var inEscape = false; + var inCharacterClass = false; + while (true) + { + if (p >= _end) + { + _tokenIsUnterminated = true; + Error(Diagnostics.Unterminated_regular_expression_literal); + break; + } + var ch = _text.charCodeAt(p); + if (IsLineBreak(ch)) + { + _tokenIsUnterminated = true; + Error(Diagnostics.Unterminated_regular_expression_literal); + break; + } + if (inEscape) + { + // Parsing an escape character; + // reset the flag and just advance to the next char. + inEscape = false; + } + else + if (ch == (int)CharacterCodes.Slash && !inCharacterClass) + { + // A slash within a character class is permissible, + // but in general it signals the end of the regexp literal. + p++; + break; + } + else + if (ch == (int)CharacterCodes.OpenBracket) + { + inCharacterClass = true; + } + else + if (ch == (int)CharacterCodes.Backslash) + { + inEscape = true; + } + else + if (ch == (int)CharacterCodes.CloseBracket) + { + inCharacterClass = false; + } + p++; + } + while (p < _end && IsIdentifierPart(_text.charCodeAt(p), _languageVersion)) + { + p++; + } + _pos = p; + _tokenValue = _text.substring(_tokenPos, _pos); + _token = SyntaxKind.RegularExpressionLiteral; + } + return _token; + } + + + public SyntaxKind ReScanTemplateToken() + { + Debug.Assert(_token == SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'"); + _pos = _tokenPos; + _token = ScanTemplateAndSetTokenValue(); + return _token; + } + + + public SyntaxKind ReScanJsxToken() + { + _pos = _tokenPos = _startPos; + _token = ScanJsxToken(); + return _token; + } + + + public SyntaxKind ScanJsxToken() + { + _startPos = _tokenPos = _pos; + if (_pos >= _end) + { + _token = SyntaxKind.EndOfFileToken; + return _token; + } + var @char = _text.charCodeAt(_pos); + if (@char == (int)CharacterCodes.LessThan) + { + if (_text.charCodeAt(_pos + 1) == (int)CharacterCodes.Slash) + { + _pos += 2; + _token = SyntaxKind.LessThanSlashToken; + return _token; + } + _pos++; + _token = SyntaxKind.LessThanToken; + return _token; + } + if (@char == (int)CharacterCodes.OpenBrace) + { + _pos++; + _token = SyntaxKind.OpenBraceToken; + return _token; + } + while (_pos < _end) + { + _pos++; + @char = _text.charCodeAt(_pos); + if (@char == (int)CharacterCodes.OpenBrace) + { + break; + } + if (@char == (int)CharacterCodes.LessThan) + { + if (IsConflictMarkerTrivia(_text, _pos)) + { + _pos = ScanConflictMarkerTrivia(_text, _pos, Error); + _token = SyntaxKind.ConflictMarkerTrivia; + return _token; + } + break; + } + } + _token = SyntaxKind.JsxText; + return _token; + } + + + public SyntaxKind ScanJsxIdentifier() + { + if (TokenIsIdentifierOrKeyword(_token)) + { + var firstCharPosition = _pos; + while (_pos < _end) + { + var ch = _text.charCodeAt(_pos); + if (ch == (int)CharacterCodes.Minus || ((firstCharPosition == _pos) ? IsIdentifierStart(ch, _languageVersion) : IsIdentifierPart(ch, _languageVersion))) + { + _pos++; + } + else + { + break; + } + } + _tokenValue += _text.Substring(firstCharPosition, _pos - firstCharPosition); + } + return _token; + } + + + public SyntaxKind ScanJsxAttributeValue() + { + _startPos = _pos; + switch (_text.charCodeAt(_pos)) + { + case (int)CharacterCodes.DoubleQuote: + case (int)CharacterCodes.SingleQuote: + _tokenValue = ScanString(/*allowEscapes*/ false); + _token = SyntaxKind.StringLiteral; + return _token; + default: + // If this scans anything other than `{`, it's a parse error. + return Scan(); + } + } + + + public SyntaxKind ScanJsDocToken() + { + if (_pos >= _end) + { + _token = SyntaxKind.EndOfFileToken; + return _token; + } + _startPos = _pos; + _tokenPos = _pos; + var ch = _text.charCodeAt(_pos); + switch (ch) + { + case (int)CharacterCodes.Tab: + case (int)CharacterCodes.VerticalTab: + case (int)CharacterCodes.FormFeed: + case (int)CharacterCodes.Space: + while (_pos < _end && IsWhiteSpaceSingleLine(_text.charCodeAt(_pos))) + { + _pos++; + } + _token = SyntaxKind.WhitespaceTrivia; + return _token; + case (int)CharacterCodes.At: + _pos++; + _token = SyntaxKind.AtToken; + return _token; + case (int)CharacterCodes.LineFeed: + case (int)CharacterCodes.CarriageReturn: + _pos++; + _token = SyntaxKind.NewLineTrivia; + return _token; + case (int)CharacterCodes.Asterisk: + _pos++; + _token = SyntaxKind.AsteriskToken; + return _token; + case (int)CharacterCodes.OpenBrace: + _pos++; + _token = SyntaxKind.OpenBraceToken; + return _token; + case (int)CharacterCodes.CloseBrace: + _pos++; + _token = SyntaxKind.CloseBraceToken; + return _token; + case (int)CharacterCodes.OpenBracket: + _pos++; + _token = SyntaxKind.OpenBracketToken; + return _token; + case (int)CharacterCodes.CloseBracket: + _pos++; + _token = SyntaxKind.CloseBracketToken; + return _token; + case (int)CharacterCodes.equals: + _pos++; + _token = SyntaxKind.EqualsToken; + return _token; + case (int)CharacterCodes.Comma: + _pos++; + _token = SyntaxKind.CommaToken; + return _token; + case (int)CharacterCodes.Dot: + _pos++; + _token = SyntaxKind.DotToken; + return _token; + } + if (IsIdentifierStart(ch, ScriptTarget.Latest)) + { + _pos++; + while (IsIdentifierPart(_text.charCodeAt(_pos), ScriptTarget.Latest) && _pos < _end) + { + _pos++; + } + _token = SyntaxKind.Identifier; + return _token; + } + else + { + _pos += 1; + _token = SyntaxKind.Unknown; + return _token; + } + } + + + public T SpeculationHelper(Func callback, bool isLookahead) + { + var savePos = _pos; + var saveStartPos = _startPos; + var saveTokenPos = _tokenPos; + var saveToken = _token; + var saveTokenValue = _tokenValue; + var savePrecedingLineBreak = _precedingLineBreak; + var result = callback(); + if (result == null || ((result is bool) && Convert.ToBoolean(result) == false) || isLookahead) + { + _pos = savePos; + _startPos = saveStartPos; + _tokenPos = saveTokenPos; + _token = saveToken; + _tokenValue = saveTokenValue; + _precedingLineBreak = savePrecedingLineBreak; + } + return result; + } + + + public T ScanRange(int? start, int length, Func callback) + { + var saveEnd = _end; + var savePos = _pos; + var saveStartPos = _startPos; + var saveTokenPos = _tokenPos; + var saveToken = _token; + var savePrecedingLineBreak = _precedingLineBreak; + var saveTokenValue = _tokenValue; + var saveHasExtendedUnicodeEscape = _hasExtendedUnicodeEscape; + var saveTokenIsUnterminated = _tokenIsUnterminated; + SetText(_text, start, length); + var result = callback(); + _end = saveEnd; + _pos = savePos; + _startPos = saveStartPos; + _tokenPos = saveTokenPos; + _token = saveToken; + _precedingLineBreak = savePrecedingLineBreak; + _tokenValue = saveTokenValue; + _hasExtendedUnicodeEscape = saveHasExtendedUnicodeEscape; + _tokenIsUnterminated = saveTokenIsUnterminated; + return result; + } + + + public T LookAhead(Func callback) + { + return SpeculationHelper(callback, /*isLookahead*/ true); + } + + + public T TryScan(Func callback) + { + return SpeculationHelper(callback, /*isLookahead*/ false); + } + + + public string GetText() + { + return _text; + } + + + public void SetText(string newText, int? start = null, int? length = null) + { + _text = newText ?? ""; + _end = length == null ? _text.Length : (int)start + (int)length; + SetTextPos(start ?? 0); + } + + + public void SetOnError(ErrorCallback errorCallback) + { + OnError = errorCallback; + } + + + public void SetScriptTarget(ScriptTarget scriptTarget) + { + _languageVersion = scriptTarget; + } + + + public void SetLanguageVariant(LanguageVariant variant) + { + _languageVariant = variant; + } + + + public void SetTextPos(int textPos) + { + Debug.Assert(textPos >= 0); + _pos = textPos; + _startPos = textPos; + _tokenPos = textPos; + _token = SyntaxKind.Unknown; + _precedingLineBreak = false; + _tokenValue = null; + _hasExtendedUnicodeEscape = false; + _tokenIsUnterminated = false; + } + + + + } +} diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Ts.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Ts.cs new file mode 100644 index 0000000..585f2a6 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Ts.cs @@ -0,0 +1,584 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript.TsParser +{ + public class Ts + { + public static INode VisitNode(Func cbNode, INode node) + { + if (node != null) + return cbNode(node); + return null; + } + + + public static T VisitList(Func cbNodes, INode[] nodes) + { + if (nodes != null) + return cbNodes(nodes); + return default(T); + } + + + public static INode VisitNodeArray(Func cbNodes, INode[] nodes) + { + if (nodes != null) + return cbNodes(nodes); + return null; + } + + public static INode VisitEachNode(Func cbNode, List nodes) + { + if (nodes != null) + foreach (var node in nodes) + { + var result = cbNode(node); + if (result != null) + return result; + } + return null; + } + + + public static INode ForEachChild(INode node, Func cbNode, Func cbNodeArray = null) + { + if (node == null) + return null; + Func, INode> visitNodes = (o1, o2) => + { + var list = o2?.Cast().ToList(); + if (list != null) + if (cbNodeArray == null) + return VisitEachNode(cbNode, list); + else + return cbNodeArray(list.ToArray()); + return null; + }; + var cbNodes = cbNodeArray; + switch (node.Kind) + { + case SyntaxKind.QualifiedName: + + return VisitNode(cbNode, (node as QualifiedName)?.Left) ?? + VisitNode(cbNode, (node as QualifiedName)?.Right); + case SyntaxKind.TypeParameter: + + return VisitNode(cbNode, (node as TypeParameterDeclaration)?.Name) ?? + VisitNode(cbNode, (node as TypeParameterDeclaration)?.Constraint) ?? + VisitNode(cbNode, (node as TypeParameterDeclaration)?.Default) ?? + VisitNode(cbNode, (node as TypeParameterDeclaration)?.Expression); + case SyntaxKind.ShorthandPropertyAssignment: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ShorthandPropertyAssignment)?.Name) ?? + VisitNode(cbNode, (node as ShorthandPropertyAssignment)?.QuestionToken) ?? + VisitNode(cbNode, (node as ShorthandPropertyAssignment)?.EqualsToken) ?? + VisitNode(cbNode, (node as ShorthandPropertyAssignment)?.ObjectAssignmentInitializer); + case SyntaxKind.SpreadAssignment: + + return VisitNode(cbNode, (node as SpreadAssignment)?.Expression); + case SyntaxKind.Parameter: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.PropertyName) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.DotDotDotToken) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.Name) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.QuestionToken) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.Type) ?? + VisitNode(cbNode, (node as IVariableLikeDeclaration)?.Initializer); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + visitNodes(cbNodes, (node as ISignatureDeclaration)?.TypeParameters) ?? + visitNodes(cbNodes, (node as ISignatureDeclaration)?.Parameters) ?? + VisitNode(cbNode, (node as ISignatureDeclaration)?.Type); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as IFunctionLikeDeclaration)?.AsteriskToken) ?? + VisitNode(cbNode, (node as IFunctionLikeDeclaration)?.Name) ?? + VisitNode(cbNode, (node as IFunctionLikeDeclaration)?.QuestionToken) ?? + visitNodes(cbNodes, (node as IFunctionLikeDeclaration)?.TypeParameters) ?? + visitNodes(cbNodes, (node as IFunctionLikeDeclaration)?.Parameters) ?? + VisitNode(cbNode, (node as IFunctionLikeDeclaration)?.Type) ?? + VisitNode(cbNode, (node as ArrowFunction)?.EqualsGreaterThanToken) ?? + VisitNode(cbNode, (node as IFunctionLikeDeclaration)?.Body); + case SyntaxKind.TypeReference: + + return VisitNode(cbNode, (node as TypeReferenceNode)?.TypeName) ?? + visitNodes(cbNodes, (node as TypeReferenceNode)?.TypeArguments); + case SyntaxKind.TypePredicate: + + return VisitNode(cbNode, (node as TypePredicateNode)?.ParameterName) ?? + VisitNode(cbNode, (node as TypePredicateNode)?.Type); + case SyntaxKind.TypeQuery: + + return VisitNode(cbNode, (node as TypeQueryNode)?.ExprName); + case SyntaxKind.TypeLiteral: + + return visitNodes(cbNodes, (node as TypeLiteralNode)?.Members); + case SyntaxKind.ArrayType: + + return VisitNode(cbNode, (node as ArrayTypeNode)?.ElementType); + case SyntaxKind.TupleType: + + return visitNodes(cbNodes, (node as TupleTypeNode)?.ElementTypes); + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + + return visitNodes(cbNodes, (node as IUnionOrIntersectionTypeNode)?.Types); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.TypeOperator: + + return VisitNode(cbNode, (node as ParenthesizedTypeNode)?.Type ?? (node as TypeOperatorNode)?.Type); + case SyntaxKind.IndexedAccessType: + + return VisitNode(cbNode, (node as IndexedAccessTypeNode)?.ObjectType) ?? + VisitNode(cbNode, (node as IndexedAccessTypeNode)?.IndexType); + case SyntaxKind.MappedType: + + return VisitNode(cbNode, (node as MappedTypeNode)?.ReadonlyToken) ?? + VisitNode(cbNode, (node as MappedTypeNode)?.TypeParameter) ?? + VisitNode(cbNode, (node as MappedTypeNode)?.QuestionToken) ?? + VisitNode(cbNode, (node as MappedTypeNode)?.Type); + case SyntaxKind.LiteralType: + + return VisitNode(cbNode, (node as LiteralTypeNode)?.Literal); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + + return visitNodes(cbNodes, ((IBindingPattern) node).Elements); + case SyntaxKind.ArrayLiteralExpression: + + return visitNodes(cbNodes, (node as ArrayLiteralExpression)?.Elements); + case SyntaxKind.ObjectLiteralExpression: + + return visitNodes(cbNodes, (node as ObjectLiteralExpression)?.Properties); + case SyntaxKind.PropertyAccessExpression: + + return VisitNode(cbNode, (node as PropertyAccessExpression)?.Expression) ?? + VisitNode(cbNode, (node as PropertyAccessExpression)?.Name); + case SyntaxKind.ElementAccessExpression: + + return VisitNode(cbNode, (node as ElementAccessExpression)?.Expression) ?? + VisitNode(cbNode, (node as ElementAccessExpression)?.ArgumentExpression); + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + + return VisitNode(cbNode, (node as CallExpression)?.Expression) ?? + visitNodes(cbNodes, (node as CallExpression)?.TypeArguments) ?? + visitNodes(cbNodes, (node as CallExpression)?.Arguments); + case SyntaxKind.TaggedTemplateExpression: + + return VisitNode(cbNode, (node as TaggedTemplateExpression)?.Tag) ?? + VisitNode(cbNode, (node as TaggedTemplateExpression)?.Template); + case SyntaxKind.TypeAssertionExpression: + + return VisitNode(cbNode, (node as TypeAssertion)?.Type) ?? + VisitNode(cbNode, (node as TypeAssertion)?.Expression); + case SyntaxKind.ParenthesizedExpression: + + return VisitNode(cbNode, (node as ParenthesizedExpression)?.Expression); + case SyntaxKind.DeleteExpression: + + return VisitNode(cbNode, (node as DeleteExpression)?.Expression); + case SyntaxKind.TypeOfExpression: + + return VisitNode(cbNode, (node as TypeOfExpression)?.Expression); + case SyntaxKind.VoidExpression: + + return VisitNode(cbNode, (node as VoidExpression)?.Expression); + case SyntaxKind.PrefixUnaryExpression: + + return VisitNode(cbNode, (node as PrefixUnaryExpression)?.Operand); + case SyntaxKind.YieldExpression: + + return VisitNode(cbNode, (node as YieldExpression)?.AsteriskToken) ?? + VisitNode(cbNode, (node as YieldExpression)?.Expression); + case SyntaxKind.AwaitExpression: + + return VisitNode(cbNode, (node as AwaitExpression)?.Expression); + case SyntaxKind.PostfixUnaryExpression: + + return VisitNode(cbNode, (node as PostfixUnaryExpression)?.Operand); + case SyntaxKind.BinaryExpression: + + return VisitNode(cbNode, (node as BinaryExpression)?.Left) ?? + VisitNode(cbNode, (node as BinaryExpression)?.OperatorToken) ?? + VisitNode(cbNode, (node as BinaryExpression)?.Right); + case SyntaxKind.AsExpression: + + return VisitNode(cbNode, (node as AsExpression)?.Expression) ?? + VisitNode(cbNode, (node as AsExpression)?.Type); + case SyntaxKind.NonNullExpression: + + return VisitNode(cbNode, (node as NonNullExpression)?.Expression); + case SyntaxKind.MetaProperty: + + return VisitNode(cbNode, (node as MetaProperty)?.Name); + case SyntaxKind.ConditionalExpression: + + return VisitNode(cbNode, (node as ConditionalExpression)?.Condition) ?? + VisitNode(cbNode, (node as ConditionalExpression)?.QuestionToken) ?? + VisitNode(cbNode, (node as ConditionalExpression)?.WhenTrue) ?? + VisitNode(cbNode, (node as ConditionalExpression)?.ColonToken) ?? + VisitNode(cbNode, (node as ConditionalExpression)?.WhenFalse); + case SyntaxKind.SpreadElement: + + return VisitNode(cbNode, (node as SpreadElement)?.Expression); + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + + return visitNodes(cbNodes, (node as Block)?.Statements); + case SyntaxKind.SourceFile: + + return visitNodes(cbNodes, (node as SourceFile)?.Statements) ?? + VisitNode(cbNode, (node as SourceFile)?.EndOfFileToken); + case SyntaxKind.VariableStatement: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as VariableStatement)?.DeclarationList); + case SyntaxKind.VariableDeclarationList: + + return visitNodes(cbNodes, (node as VariableDeclarationList)?.Declarations); + case SyntaxKind.ExpressionStatement: + + return VisitNode(cbNode, (node as ExpressionStatement)?.Expression); + case SyntaxKind.IfStatement: + + return VisitNode(cbNode, (node as IfStatement)?.Expression) ?? + VisitNode(cbNode, (node as IfStatement)?.ThenStatement) ?? + VisitNode(cbNode, (node as IfStatement)?.ElseStatement); + case SyntaxKind.DoStatement: + + return VisitNode(cbNode, (node as DoStatement)?.Statement) ?? + VisitNode(cbNode, (node as DoStatement)?.Expression); + case SyntaxKind.WhileStatement: + + return VisitNode(cbNode, (node as WhileStatement)?.Expression) ?? + VisitNode(cbNode, (node as WhileStatement)?.Statement); + case SyntaxKind.ForStatement: + + return VisitNode(cbNode, (node as ForStatement)?.Initializer) ?? + VisitNode(cbNode, (node as ForStatement)?.Condition) ?? + VisitNode(cbNode, (node as ForStatement)?.Incrementor) ?? + VisitNode(cbNode, (node as ForStatement)?.Statement); + case SyntaxKind.ForInStatement: + + return VisitNode(cbNode, (node as ForInStatement)?.Initializer) ?? + VisitNode(cbNode, (node as ForInStatement)?.Expression) ?? + VisitNode(cbNode, (node as ForInStatement)?.Statement); + case SyntaxKind.ForOfStatement: + + return VisitNode(cbNode, (node as ForOfStatement)?.AwaitModifier) ?? + VisitNode(cbNode, (node as ForOfStatement)?.Initializer) ?? + VisitNode(cbNode, (node as ForOfStatement)?.Expression) ?? + VisitNode(cbNode, (node as ForOfStatement)?.Statement); + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + + return VisitNode(cbNode, (node as IBreakOrContinueStatement)?.Label); + case SyntaxKind.ReturnStatement: + + return VisitNode(cbNode, (node as ReturnStatement)?.Expression); + case SyntaxKind.WithStatement: + + return VisitNode(cbNode, (node as WithStatement)?.Expression) ?? + VisitNode(cbNode, (node as WithStatement)?.Statement); + case SyntaxKind.SwitchStatement: + + return VisitNode(cbNode, (node as SwitchStatement)?.Expression) ?? + VisitNode(cbNode, (node as SwitchStatement)?.CaseBlock); + case SyntaxKind.CaseBlock: + + return visitNodes(cbNodes, (node as CaseBlock)?.Clauses); + case SyntaxKind.CaseClause: + + return VisitNode(cbNode, (node as CaseClause)?.Expression) ?? + visitNodes(cbNodes, (node as CaseClause)?.Statements); + case SyntaxKind.DefaultClause: + + return visitNodes(cbNodes, (node as DefaultClause)?.Statements); + case SyntaxKind.LabeledStatement: + + return VisitNode(cbNode, (node as LabeledStatement)?.Label) ?? + VisitNode(cbNode, (node as LabeledStatement)?.Statement); + case SyntaxKind.ThrowStatement: + + return VisitNode(cbNode, (node as ThrowStatement)?.Expression); + case SyntaxKind.TryStatement: + + return VisitNode(cbNode, (node as TryStatement)?.TryBlock) ?? + VisitNode(cbNode, (node as TryStatement)?.CatchClause) ?? + VisitNode(cbNode, (node as TryStatement)?.FinallyBlock); + case SyntaxKind.CatchClause: + + return VisitNode(cbNode, (node as CatchClause)?.VariableDeclaration) ?? + VisitNode(cbNode, (node as CatchClause)?.Block); + case SyntaxKind.Decorator: + + return VisitNode(cbNode, (node as Decorator)?.Expression); + case SyntaxKind.ClassDeclaration: + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ClassDeclaration)?.Name) ?? + visitNodes(cbNodes, (node as ClassDeclaration)?.TypeParameters) ?? + visitNodes(cbNodes, (node as ClassDeclaration)?.HeritageClauses) ?? + visitNodes(cbNodes, (node as ClassDeclaration)?.Members); + case SyntaxKind.ClassExpression: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ClassExpression)?.Name) ?? + visitNodes(cbNodes, (node as ClassExpression)?.TypeParameters) ?? + visitNodes(cbNodes, (node as ClassExpression)?.HeritageClauses) ?? + visitNodes(cbNodes, (node as ClassExpression)?.Members); + case SyntaxKind.InterfaceDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as InterfaceDeclaration)?.Name) ?? + visitNodes(cbNodes, (node as InterfaceDeclaration)?.TypeParameters) ?? + visitNodes(cbNodes, (node as InterfaceDeclaration)?.HeritageClauses) ?? + visitNodes(cbNodes, (node as InterfaceDeclaration)?.Members); + case SyntaxKind.TypeAliasDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as TypeAliasDeclaration)?.Name) ?? + visitNodes(cbNodes, (node as TypeAliasDeclaration)?.TypeParameters) ?? + VisitNode(cbNode, (node as TypeAliasDeclaration)?.Type); + case SyntaxKind.EnumDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as EnumDeclaration)?.Name) ?? + visitNodes(cbNodes, (node as EnumDeclaration)?.Members); + case SyntaxKind.EnumMember: + + return VisitNode(cbNode, (node as EnumMember)?.Name) ?? + VisitNode(cbNode, (node as EnumMember)?.Initializer); + case SyntaxKind.ModuleDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ModuleDeclaration)?.Name) ?? + VisitNode(cbNode, (node as ModuleDeclaration)?.Body); + case SyntaxKind.ImportEqualsDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ImportEqualsDeclaration)?.Name) ?? + VisitNode(cbNode, (node as ImportEqualsDeclaration)?.ModuleReference); + case SyntaxKind.ImportDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ImportDeclaration)?.ImportClause) ?? + VisitNode(cbNode, (node as ImportDeclaration)?.ModuleSpecifier); + case SyntaxKind.ImportClause: + + return VisitNode(cbNode, (node as ImportClause)?.Name) ?? + VisitNode(cbNode, (node as ImportClause)?.NamedBindings); + case SyntaxKind.NamespaceExportDeclaration: + + return VisitNode(cbNode, (node as NamespaceExportDeclaration)?.Name); + case SyntaxKind.NamespaceImport: + + return VisitNode(cbNode, (node as NamespaceImport)?.Name); + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + + if (node is NamedImports) return visitNodes(cbNodes, (node as NamedImports)?.Elements); + else return visitNodes(cbNodes, (node as NamedExports)?.Elements); + case SyntaxKind.ExportDeclaration: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ExportDeclaration)?.ExportClause) ?? + VisitNode(cbNode, (node as ExportDeclaration)?.ModuleSpecifier); + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return VisitNode(cbNode, (node as IMportOrExportSpecifier)?.PropertyName ?? + VisitNode(cbNode, (node as IMportOrExportSpecifier)?.Name)); + case SyntaxKind.ExportAssignment: + + return visitNodes(cbNodes, node.Decorators) ?? + visitNodes(cbNodes, node.Modifiers) ?? + VisitNode(cbNode, (node as ExportAssignment)?.Expression); + case SyntaxKind.TemplateExpression: + + return VisitNode(cbNode, (node as TemplateExpression)?.Head) ?? + visitNodes(cbNodes, (node as TemplateExpression)?.TemplateSpans); + case SyntaxKind.TemplateSpan: + + return VisitNode(cbNode, (node as TemplateSpan)?.Expression) ?? + VisitNode(cbNode, (node as TemplateSpan)?.Literal); + case SyntaxKind.ComputedPropertyName: + + return VisitNode(cbNode, (node as ComputedPropertyName)?.Expression); + case SyntaxKind.HeritageClause: + + return visitNodes(cbNodes, (node as HeritageClause)?.Types); + case SyntaxKind.ExpressionWithTypeArguments: + + return VisitNode(cbNode, (node as ExpressionWithTypeArguments)?.Expression) ?? + visitNodes(cbNodes, (node as ExpressionWithTypeArguments)?.TypeArguments); + case SyntaxKind.ExternalModuleReference: + + return VisitNode(cbNode, (node as ExternalModuleReference)?.Expression); + case SyntaxKind.MissingDeclaration: + + return visitNodes(cbNodes, node.Decorators); + case SyntaxKind.JsxElement: + + return VisitNode(cbNode, (node as JsxElement)?.OpeningElement) ?? + visitNodes(cbNodes, (node as JsxElement)?.JsxChildren) ?? + VisitNode(cbNode, (node as JsxElement)?.ClosingElement); + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + return VisitNode(cbNode, + (node as JsxSelfClosingElement)?.TagName ?? (node as JsxOpeningElement)?.TagName) ?? + VisitNode(cbNode, + (node as JsxSelfClosingElement)?.Attributes ?? (node as JsxOpeningElement)?.Attributes); + case SyntaxKind.JsxAttributes: + + return visitNodes(cbNodes, (node as JsxAttributes)?.Properties); + case SyntaxKind.JsxAttribute: + + return VisitNode(cbNode, (node as JsxAttribute)?.Name) ?? + VisitNode(cbNode, (node as JsxAttribute)?.Initializer); + case SyntaxKind.JsxSpreadAttribute: + + return VisitNode(cbNode, (node as JsxSpreadAttribute)?.Expression); + case SyntaxKind.JsxExpression: + + return VisitNode(cbNode, (node as JsxExpression).DotDotDotToken) ?? + VisitNode(cbNode, (node as JsxExpression).Expression); + case SyntaxKind.JsxClosingElement: + + return VisitNode(cbNode, (node as JsxClosingElement)?.TagName); + case SyntaxKind.JsDocTypeExpression: + + return VisitNode(cbNode, (node as JsDocTypeExpression)?.Type); + case SyntaxKind.JsDocUnionType: + + return visitNodes(cbNodes, (node as JsDocUnionType)?.Types); + case SyntaxKind.JsDocTupleType: + + return visitNodes(cbNodes, (node as JsDocTupleType)?.Types); + case SyntaxKind.JsDocArrayType: + + return VisitNode(cbNode, (node as JsDocArrayType)?.ElementType); + case SyntaxKind.JsDocNonNullableType: + + return VisitNode(cbNode, (node as JsDocNonNullableType)?.Type); + case SyntaxKind.JsDocNullableType: + + return VisitNode(cbNode, (node as JsDocNullableType)?.Type); + case SyntaxKind.JsDocRecordType: + + return VisitNode(cbNode, (node as JsDocRecordType)?.Literal); + case SyntaxKind.JsDocTypeReference: + + return VisitNode(cbNode, (node as JsDocTypeReference)?.Name) ?? + visitNodes(cbNodes, (node as JsDocTypeReference)?.TypeArguments); + case SyntaxKind.JsDocOptionalType: + + return VisitNode(cbNode, (node as JsDocOptionalType)?.Type); + case SyntaxKind.JsDocFunctionType: + + return visitNodes(cbNodes, (node as JsDocFunctionType)?.Parameters) ?? + VisitNode(cbNode, (node as JsDocFunctionType)?.Type); + case SyntaxKind.JsDocVariadicType: + + return VisitNode(cbNode, (node as JsDocVariadicType)?.Type); + case SyntaxKind.JsDocConstructorType: + + return VisitNode(cbNode, (node as JsDocConstructorType)?.Type); + case SyntaxKind.JsDocThisType: + + return VisitNode(cbNode, (node as JsDocThisType)?.Type); + case SyntaxKind.JsDocRecordMember: + + return VisitNode(cbNode, (node as JsDocRecordMember)?.Name) ?? + VisitNode(cbNode, (node as JsDocRecordMember)?.Type); + case SyntaxKind.JsDocComment: + + return visitNodes(cbNodes, (node as JsDoc)?.Tags); + case SyntaxKind.JsDocParameterTag: + + return VisitNode(cbNode, (node as JsDocParameterTag)?.PreParameterName) ?? + VisitNode(cbNode, (node as JsDocParameterTag)?.TypeExpression) ?? + VisitNode(cbNode, (node as JsDocParameterTag)?.PostParameterName); + case SyntaxKind.JsDocReturnTag: + + return VisitNode(cbNode, (node as JsDocReturnTag)?.TypeExpression); + case SyntaxKind.JsDocTypeTag: + + return VisitNode(cbNode, (node as JsDocTypeTag)?.TypeExpression); + case SyntaxKind.JsDocAugmentsTag: + + return VisitNode(cbNode, (node as JsDocAugmentsTag)?.TypeExpression); + case SyntaxKind.JsDocTemplateTag: + + return visitNodes(cbNodes, (node as JsDocTemplateTag)?.TypeParameters); + case SyntaxKind.JsDocTypedefTag: + + return VisitNode(cbNode, (node as JsDocTypedefTag)?.TypeExpression) ?? + VisitNode(cbNode, (node as JsDocTypedefTag)?.FullName) ?? + VisitNode(cbNode, (node as JsDocTypedefTag)?.Name) ?? + VisitNode(cbNode, (node as JsDocTypedefTag)?.JsDocTypeLiteral); + case SyntaxKind.JsDocTypeLiteral: + + return visitNodes(cbNodes, (node as JsDocTypeLiteral)?.JsDocPropertyTags); + case SyntaxKind.JsDocPropertyTag: + + return VisitNode(cbNode, (node as JsDocPropertyTag)?.TypeExpression) ?? + VisitNode(cbNode, (node as JsDocPropertyTag)?.Name); + case SyntaxKind.PartiallyEmittedExpression: + + return VisitNode(cbNode, (node as PartiallyEmittedExpression)?.Expression); + case SyntaxKind.JsDocLiteralType: + + return VisitNode(cbNode, (node as JsDocLiteralType)?.Literal); + } + return null; + } + + private static INode VisitNodes(Func cbNodes, List list) + { + throw new NotImplementedException(); + } + + + public bool IsExternalModule(SourceFile file) + { + return file.ExternalModuleIndicator != null; + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/TsExtensions.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/TsExtensions.cs new file mode 100644 index 0000000..1d1aeb6 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/TsExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace Zu.TypeScript.TsParser +{ + public static class TsExtensions + { + public static int charCodeAt(this string str, int pos) => (int)str[pos]; + //public static int length(this string str) => str.Length; + public static string substring(this string str, int start, int? end = null) + { + return end == null ? str.Substring(start) : str.Substring(start, (int)end - start); + } + public static string[] exec(this Regex r, string text) => r.Match(text).Captures.Cast().ToArray(); + public static bool test(this Regex r, string text) => r.IsMatch(text); + public static void pop(this List list) => list.RemoveAt(0); + + + } + public static class String + { + internal static string fromCharCode(params int[] codes) + { + var sb = new StringBuilder(); + foreach (var c in codes) + { + sb.Append((char)c); + } + return sb.ToString(); + } + public static string slice(this string str, int start, int end = int.MaxValue) + { + if (start < 0) + start += str.Length; + if (end < 0) + end += str.Length; + + start = Math.Min(Math.Max(start, 0), str.Length); + end = Math.Min(Math.Max(end, 0), str.Length); + if (end <= start) + return string.Empty; + + return str.Substring(start, end - start); + } + + } +} diff --git a/generators/CssInCSharp.Ast.TypeScript/Parser/Utilities.cs b/generators/CssInCSharp.Ast.TypeScript/Parser/Utilities.cs new file mode 100644 index 0000000..7d65aef --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/Parser/Utilities.cs @@ -0,0 +1,257 @@ +using System.Collections.Generic; +using System.Linq; +using Zu.TypeScript.TsTypes; +using static Zu.TypeScript.TsParser.Factory; +using static Zu.TypeScript.TsParser.Scanner; +using static Zu.TypeScript.TsParser.Ts; + +namespace Zu.TypeScript.TsParser +{ + public class Utilities + { + public static int GetFullWidth(INode node) + { + return (node.End ?? 0) - (node.Pos ?? 0); + } + + + public static INode ContainsParseError(INode node) + { + AggregateChildData(node); + + return (node.Flags & NodeFlags.ThisNodeOrAnySubNodesHasError) != 0 ? node : null; + } + + + public static void AggregateChildData(INode node) + { + if ((node.Flags & NodeFlags.HasAggregatedChildData) != 0) + { + var thisNodeOrAnySubNodesHasError = (node.Flags & NodeFlags.ThisNodeHasError) != 0 || + ForEachChild(node, ContainsParseError) != null; + if (thisNodeOrAnySubNodesHasError) + node.Flags |= NodeFlags.ThisNodeOrAnySubNodesHasError; + + + node.Flags |= NodeFlags.HasAggregatedChildData; + } + } + + + public static bool NodeIsMissing(INode node) + { + if (node == null) + return true; + + + return node.Pos == node.End && node.Pos >= 0 && node.Kind != SyntaxKind.EndOfFileToken; + } + + + public static string GetTextOfNodeFromSourceText(string sourceText, INode node) + { + if (NodeIsMissing(node)) + return ""; + + + return sourceText.substring(SkipTriviaM(sourceText, node.Pos ?? 0), node.End); + } + + + public static string EscapeIdentifier(string identifier) + { + return identifier.Length >= 2 && identifier.charCodeAt(0) == (int) CharacterCodes._ && + identifier.charCodeAt(1) == (int) CharacterCodes._ + ? "_" + identifier + : identifier; + } + + + public static List GetLeadingCommentRangesOfNodeFromText(INode node, string text) + { + return GetLeadingCommentRanges(text, node.Pos ?? 0); + } + + + public static List GetJsDocCommentRanges(INode node, string text) + { + var commentRanges = node.Kind == SyntaxKind.Parameter || + node.Kind == SyntaxKind.TypeParameter || + node.Kind == SyntaxKind.FunctionExpression || + node.Kind == SyntaxKind.ArrowFunction + ? GetTrailingCommentRanges(text, node.Pos ?? 0).Concat(GetLeadingCommentRanges(text, node.Pos ?? 0)) + : GetLeadingCommentRangesOfNodeFromText(node, text); + if (commentRanges == null) commentRanges = new List(); + return commentRanges.Where(comment => + text.charCodeAt((comment.Pos ?? 0) + 1) == (int) CharacterCodes.Asterisk && + text.charCodeAt((comment.Pos ?? 0) + 2) == (int) CharacterCodes.Asterisk && + text.charCodeAt((comment.Pos ?? 0) + 3) != (int) CharacterCodes.Slash) + .ToList(); + } + + + public static bool IsKeyword(SyntaxKind token) + { + return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword; + } + + + public static bool IsTrivia(SyntaxKind token) + { + return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken; + } + + + public static bool IsModifierKind(SyntaxKind token) + { + switch (token) + { + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.StaticKeyword: + + return true; + } + + return false; + } + + + public static bool IsParameterDeclaration(IVariableLikeDeclaration node) + { + var root = GetRootDeclaration(node); + + return root.Kind == SyntaxKind.Parameter; + } + + + public static INode GetRootDeclaration(INode node) + { + while (node.Kind == SyntaxKind.BindingElement) + node = node.Parent.Parent; + + return node; + } + + + public static bool HasModifiers(Node node) + { + return GetModifierFlags(node) != ModifierFlags.None; + } + + + public static bool HasModifier(INode node, ModifierFlags flags) + { + return (GetModifierFlags(node) & flags) != 0; + } + + + public static ModifierFlags GetModifierFlags(INode node) + { + if ((node.ModifierFlagsCache & ModifierFlags.HasComputedFlags) != 0) + return node.ModifierFlagsCache & ~ModifierFlags.HasComputedFlags; + var flags = ModifierFlags.None; + if (node.Modifiers != null) + foreach (var modifier in node.Modifiers) + flags |= ModifierToFlag(modifier.Kind); + if (node.Flags.HasFlag(NodeFlags.NestedNamespace) || node.Kind == SyntaxKind.Identifier && + ((Identifier) node).IsInJsDocNamespace) + flags |= ModifierFlags.Export; + + + node.ModifierFlagsCache = flags | ModifierFlags.HasComputedFlags; + + return flags; + } + + + public static ModifierFlags ModifierToFlag(SyntaxKind token) + { + switch (token) + { + case SyntaxKind.StaticKeyword: + return ModifierFlags.Static; + case SyntaxKind.PublicKeyword: + return ModifierFlags.Public; + case SyntaxKind.ProtectedKeyword: + return ModifierFlags.Protected; + case SyntaxKind.PrivateKeyword: + return ModifierFlags.Private; + case SyntaxKind.AbstractKeyword: + return ModifierFlags.Abstract; + case SyntaxKind.ExportKeyword: + return ModifierFlags.Export; + case SyntaxKind.DeclareKeyword: + return ModifierFlags.Ambient; + case SyntaxKind.ConstKeyword: + return ModifierFlags.Const; + case SyntaxKind.DefaultKeyword: + return ModifierFlags.Default; + case SyntaxKind.AsyncKeyword: + return ModifierFlags.Async; + case SyntaxKind.ReadonlyKeyword: + return ModifierFlags.Readonly; + } + + return ModifierFlags.None; + } + + + public static bool IsLogicalOperator(SyntaxKind token) + { + return token == SyntaxKind.BarBarToken + || token == SyntaxKind.AmpersandAmpersandToken + || token == SyntaxKind.ExclamationToken; + } + + + public static bool IsAssignmentOperator(SyntaxKind token) + { + return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; + } + + + public static bool IsLeftHandSideExpressionKind(SyntaxKind kind) + { + return kind == SyntaxKind.PropertyAccessExpression + || kind == SyntaxKind.ElementAccessExpression + || kind == SyntaxKind.NewExpression + || kind == SyntaxKind.CallExpression + || kind == SyntaxKind.JsxElement + || kind == SyntaxKind.JsxSelfClosingElement + || kind == SyntaxKind.TaggedTemplateExpression + || kind == SyntaxKind.ArrayLiteralExpression + || kind == SyntaxKind.ParenthesizedExpression + || kind == SyntaxKind.ObjectLiteralExpression + || kind == SyntaxKind.ClassExpression + || kind == SyntaxKind.FunctionExpression + || kind == SyntaxKind.Identifier + || kind == SyntaxKind.RegularExpressionLiteral + || kind == SyntaxKind.NumericLiteral + || kind == SyntaxKind.StringLiteral + || kind == SyntaxKind.NoSubstitutionTemplateLiteral + || kind == SyntaxKind.TemplateExpression + || kind == SyntaxKind.FalseKeyword + || kind == SyntaxKind.NullKeyword + || kind == SyntaxKind.ThisKeyword + || kind == SyntaxKind.TrueKeyword + || kind == SyntaxKind.SuperKeyword + || kind == SyntaxKind.NonNullExpression + || kind == SyntaxKind.MetaProperty; + } + + + public static bool IsLeftHandSideExpression(IExpression node) + { + return IsLeftHandSideExpressionKind(SkipPartiallyEmittedExpressions(node).Kind); + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/TsTypes/Enums.cs b/generators/CssInCSharp.Ast.TypeScript/TsTypes/Enums.cs new file mode 100644 index 0000000..03a6d5d --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TsTypes/Enums.cs @@ -0,0 +1,939 @@ +using System; + +namespace Zu.TypeScript.TsTypes +{ + [Flags] + public enum NodeFlags + { + None = 0, + Let = 1 << 0, // Variable declaration + Const = 1 << 1, // Variable declaration + NestedNamespace = 1 << 2, // Namespace declaration + Synthesized = 1 << 3, // Node was synthesized during transformation + Namespace = 1 << 4, // Namespace declaration + ExportContext = 1 << 5, // Export context (initialized by binding) + ContainsThis = 1 << 6, // Interface contains references to "this" + HasImplicitReturn = 1 << 7, // If function implicitly returns on one of codepaths (initialized by binding) + + HasExplicitReturn = + 1 << 8, // If function has explicit reachable return on one of codepaths (initialized by binding) + GlobalAugmentation = 1 << 9, // Set if module declaration is an augmentation for the global scope + HasAsyncFunctions = 1 << 10, // If the file has async functions (initialized by binding) + DisallowInContext = 1 << 11, // If node was parsed in a context where 'in-expressions' are not allowed + YieldContext = 1 << 12, // If node was parsed in the 'yield' context created when parsing a generator + DecoratorContext = 1 << 13, // If node was parsed as part of a decorator + AwaitContext = 1 << 14, // If node was parsed in the 'await' context created when parsing an async function + ThisNodeHasError = 1 << 15, // If the parser encountered an error when parsing the code that created this node + JavaScriptFile = 1 << 16, // If node was parsed in a JavaScript + ThisNodeOrAnySubNodesHasError = 1 << 17, // If this node or any of its children had an error + HasAggregatedChildData = 1 << 18, // If we've computed data from children and cached it in this node + + BlockScoped = Let | Const, + + ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn, + ReachabilityAndEmitFlags = ReachabilityCheckFlags | HasAsyncFunctions, + + // Parsing context flags + ContextFlags = DisallowInContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile, + + // Exclude these flags when parsing a Type + TypeExcludesFlags = YieldContext | AwaitContext + } + + public enum ParsingContext + { + SourceElements, // Elements in source file + BlockStatements, // Statements in block + SwitchClauses, // Clauses in switch statement + SwitchClauseStatements, // Statements in switch clause + TypeMembers, // Members in interface or type literal + ClassMembers, // Members in class declaration + EnumMembers, // Members in enum declaration + HeritageClauseElement, // Elements in a heritage clause + VariableDeclarations, // Variable declarations in variable statement + ObjectBindingElements, // Binding elements in object binding list + ArrayBindingElements, // Binding elements in array binding list + ArgumentExpressions, // Expressions in argument list + ObjectLiteralMembers, // Members in object literal + JsxAttributes, // Attributes in jsx element + JsxChildren, // Things between opening and closing JSX tags + ArrayLiteralMembers, // Members in array literal + Parameters, // Parameters in parameter list + RestProperties, // Property names in a rest type list + TypeParameters, // Type parameters in type parameter list + TypeArguments, // Type arguments in type argument list + TupleElementTypes, // Element types in tuple element type list + HeritageClauses, // Heritage clauses for a class or interface declaration. + ImportOrExportSpecifiers, // Named import clause's import specifier list + JSDocFunctionParameters, + JSDocTypeArguments, + JSDocRecordMembers, + JSDocTupleTypes, + Count // Number of parsing contexts + } + + public enum Tristate + { + False, + True, + Unknown + } + + public enum JSDocState + { + BeginningOfLine, + SawAsterisk, + SavingComments + } + + public enum ModifierFlags + { + None = 0, + Export = 1 << 0, // Declarations + Ambient = 1 << 1, // Declarations + Public = 1 << 2, // Property/Method + Private = 1 << 3, // Property/Method + Protected = 1 << 4, // Property/Method + Static = 1 << 5, // Property/Method + Readonly = 1 << 6, // Property/Method + Abstract = 1 << 7, // Class/Method/ConstructSignature + Async = 1 << 8, // Property/Method/Function + Default = 1 << 9, // Function/Class (export default declaration) + Const = 1 << 11, // Variable declaration + HasComputedFlags = 1 << 29, // Modifier flags have been computed + + AccessibilityModifier = Public | Private | Protected, + + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. + ParameterPropertyModifier = AccessibilityModifier | Readonly, + NonPublicAccessibilityModifier = Private | Protected, + + TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const, + ExportDefault = Export | Default + } + + public enum JsxFlags + { + None = 0, + + /** An element from a named property of the JSX.IntrinsicElements interface */ + IntrinsicNamedElement = 1 << 0, + + /** An element inferred from the string index signature of the JSX.IntrinsicElements interface */ + IntrinsicIndexedElement = 1 << 1, + + IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement + } + + public enum RelationComparisonResult + { + Succeeded = 1, // Should be truthy + Failed = 2, + FailedAndReported = 3 + } + + public enum GeneratedIdentifierKind + { + None, // Not automatically generated. + Auto, // Automatically generated identifier. + Loop, // Automatically generated identifier with a preference for '_i'. + Unique, // Unique name based on the 'text' property. + Node // Unique name based on the node in the 'original' property. + } + + public enum FlowFlags + { + Unreachable = 1 << 0, // Unreachable code + Start = 1 << 1, // Start of flow graph + BranchLabel = 1 << 2, // Non-looping junction + LoopLabel = 1 << 3, // Looping junction + Assignment = 1 << 4, // Assignment + TrueCondition = 1 << 5, // Condition known to be true + FalseCondition = 1 << 6, // Condition known to be false + SwitchClause = 1 << 7, // Switch statement clause + ArrayMutation = 1 << 8, // Potential array mutation + Referenced = 1 << 9, // Referenced as antecedent once + Shared = 1 << 10, // Referenced as antecedent more than once + PreFinally = 1 << 11, // Injected edge that links pre-finally label and pre-try flow + AfterFinally = 1 << 12, // Injected edge that links post-finally flow with the rest of the graph + Label = BranchLabel | LoopLabel, + Condition = TrueCondition | FalseCondition + } + + public enum ExitStatus + { + // Compiler ran successfully. Either this was a simple do-nothing compilation (for example, + // when -version or -help was provided, or this was a normal compilation, no diagnostics + // were produced, and all outputs were generated successfully. + Success = 0, + + // Diagnostics were produced and because of them no code was generated. + DiagnosticsPresentOutputsSkipped = 1, + + // Diagnostics were produced and outputs were generated in spite of them. + DiagnosticsPresentOutputsGenerated = 2 + } + + public enum NodeBuilderFlags + { + None = 0, + AllowThisInObjectLiteral = 1 << 0, + AllowQualifedNameInPlaceOfIdentifier = 1 << 1, + AllowTypeParameterInQualifiedName = 1 << 2, + AllowAnonymousIdentifier = 1 << 3, + AllowEmptyUnionOrIntersection = 1 << 4, + AllowEmptyTuple = 1 << 5 + } + + public enum TypeFormatFlags + { + None = 0x00000000, + WriteArrayAsGenericType = 0x00000001, // Write Array instead T[] + UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal + NoTruncation = 0x00000004, // Don't truncate typeToString result + WriteArrowStyleSignature = 0x00000008, // Write arrow style signature + + WriteOwnNameForAnyLike = + 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc) + + WriteTypeArgumentsOfSignature = + 0x00000020, // Write the type arguments instead of type parameters of the signature + InElementType = 0x00000040, // Writing an array or union element type + + UseFullyQualifiedType = + 0x00000080, // Write out the fully qualified type name (eg. Module.Type, instead of Type) + InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type + InTypeAlias = 0x00000200, // Writing type in type alias declaration + + UseTypeAliasValue = + 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file. + SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type. + AddUndefined = 0x00001000 // Add undefined to types of initialized, non-optional parameters + } + + public enum SymbolFormatFlags + { + None = 0x00000000, + + // Write symbols's type argument if it is instantiated symbol + // eg. class C { p: T } <-- Show p as C.p here + // var a: C; + // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p + WriteTypeParametersOrArguments = 0x00000001, + + // Use only external alias information to get the symbol name in the given context + // eg. module m { export class c { } } import x = m.c; + // When this flag is specified m.c will be used to refer to the class instead of alias symbol x + UseOnlyExternalAliasing = 0x00000002 + } + + public enum SymbolAccessibility + { + Accessible, + NotAccessible, + CannotBeNamed + } + + public enum SyntheticSymbolKind + { + UnionOrIntersection, + Spread + } + + public enum TypePredicateKind + { + This, + Identifier + } + + public enum TypeReferenceSerializationKind + { + Unknown, // The TypeReferenceNode could not be resolved. The type name + + // should be emitted using a safe fallback. + TypeWithConstructSignatureAndValue, // The TypeReferenceNode resolves to a type with a constructor + + // function that can be reached at runtime (e.g. a `class` + // declaration or a `var` declaration for the static side + // of a type, such as the global `Promise` type in lib.d.ts). + VoidNullableOrNeverType, // The TypeReferenceNode resolves to a Void-like, Nullable, or Never type. + NumberLikeType, // The TypeReferenceNode resolves to a Number-like type. + StringLikeType, // The TypeReferenceNode resolves to a String-like type. + BooleanType, // The TypeReferenceNode resolves to a Boolean-like type. + ArrayLikeType, // The TypeReferenceNode resolves to an Array-like type. + EsSymbolType, // The TypeReferenceNode resolves to the ESSymbol type. + Promise, // The TypeReferenceNode resolved to the global Promise constructor symbol. + TypeWithCallSignature, // The TypeReferenceNode resolves to a Function type or a type + + // with call signatures. + ObjectType // The TypeReferenceNode resolves to any other type. + } + + public enum SymbolFlags + { + None = 0, + FunctionScopedVariable = 1 << 0, // Variable (var) or parameter + BlockScopedVariable = 1 << 1, // A block-scoped variable (let or const) + Property = 1 << 2, // Property or enum member + EnumMember = 1 << 3, // Enum member + Function = 1 << 4, // Function + Class = 1 << 5, // Class + Interface = 1 << 6, // Interface + ConstEnum = 1 << 7, // Const enum + RegularEnum = 1 << 8, // Enum + ValueModule = 1 << 9, // Instantiated module + NamespaceModule = 1 << 10, // Uninstantiated module + TypeLiteral = 1 << 11, // Type Literal or mapped type + ObjectLiteral = 1 << 12, // Object Literal + Method = 1 << 13, // Method + Constructor = 1 << 14, // Constructor + GetAccessor = 1 << 15, // Get accessor + SetAccessor = 1 << 16, // Set accessor + Signature = 1 << 17, // Call, construct, or index signature + TypeParameter = 1 << 18, // Type parameter + TypeAlias = 1 << 19, // Type alias + ExportValue = 1 << 20, // Exported value marker (see comment in declareModuleMember in binder) + ExportType = 1 << 21, // Exported type marker (see comment in declareModuleMember in binder) + ExportNamespace = 1 << 22, // Exported namespace marker (see comment in declareModuleMember in binder) + Alias = 1 << 23, // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker) + Prototype = 1 << 24, // Prototype property (no source representation) + ExportStar = 1 << 25, // Export * declaration + Optional = 1 << 26, // Optional property + Transient = 1 << 27, // Transient symbol (created during type check) + + Enum = RegularEnum | ConstEnum, + Variable = FunctionScopedVariable | BlockScopedVariable, + + Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | + SetAccessor, + Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, + Namespace = ValueModule | NamespaceModule | Enum, + Module = ValueModule | NamespaceModule, + Accessor = GetAccessor | SetAccessor, + + // Variables can be redeclared, but can not redeclare a block-scoped declaration with the + // same name, or any other value that is not a variable, e.g. ValueModule or Class + FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable, + + // Block-scoped declarations are not allowed to be re-declared + // they can not merge with anything in the value space + BlockScopedVariableExcludes = Value, + + ParameterExcludes = Value, + PropertyExcludes = None, + EnumMemberExcludes = Value | Type, + FunctionExcludes = Value & ~(Function | ValueModule), + ClassExcludes = (Value | Type) & ~(ValueModule | Interface), // class-interface mergability done in checker.ts + InterfaceExcludes = Type & ~(Interface | Class), + + RegularEnumExcludes = + (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules + ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums + ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule), + NamespaceModuleExcludes = 0, + MethodExcludes = Value & ~Method, + GetAccessorExcludes = Value & ~SetAccessor, + SetAccessorExcludes = Value & ~GetAccessor, + TypeParameterExcludes = Type & ~TypeParameter, + TypeAliasExcludes = Type, + AliasExcludes = Alias, + + ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Alias, + + ExportHasLocal = Function | Class | Enum | ValueModule, + + HasExports = Class | Enum | Module, + HasMembers = Class | Interface | TypeLiteral | ObjectLiteral, + + BlockScoped = BlockScopedVariable | Class | Enum, + + PropertyOrAccessor = Property | Accessor, + Export = ExportNamespace | ExportType | ExportValue, + + ClassMember = Method | Accessor | Property, + + /* @internal */ + // The set of things we consider semantically classifiable. Used to speed up the LS during + // classification. + Classifiable = Class | Enum | TypeAlias | Interface | TypeParameter | Module + } + + public enum CheckFlags + { + Instantiated = 1 << 0, // Instantiated symbol + SyntheticProperty = 1 << 1, // Property in union or intersection type + SyntheticMethod = 1 << 2, // Method in union or intersection type + Readonly = 1 << 3, // Readonly transient symbol + Partial = 1 << 4, // Synthetic property present in some but not all constituents + HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents + ContainsPublic = 1 << 6, // Synthetic property with public constituent(s) + ContainsProtected = 1 << 7, // Synthetic property with protected constituent(s) + ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s) + ContainsStatic = 1 << 9, // Synthetic property with static constituent(s) + Synthetic = SyntheticProperty | SyntheticMethod + } + + public enum NodeCheckFlags + { + TypeChecked = 0x00000001, // Node has been type checked + LexicalThis = 0x00000002, // Lexical 'this' reference + CaptureThis = 0x00000004, // Lexical 'this' used in body + CaptureNewTarget = 0x00000008, // Lexical 'new.target' used in body + SuperInstance = 0x00000100, // Instance 'super' reference + SuperStatic = 0x00000200, // Static 'super' reference + ContextChecked = 0x00000400, // Contextual types have been assigned + AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'. + AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'. + CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions) + + EnumValuesComputed = + 0x00004000, // Values for enum members have been computed, and any errors have been reported for them. + + LexicalModuleMergesWithClass = + 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration. + LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure + CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function + + BlockScopedBindingInLoop = + 0x00040000, // Block-scoped binding with declaration nested inside iteration statement + + ClassWithBodyScopedClassBinding = + 0x00080000, // Decorated class that contains a binding to itself inside of the class body. + BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body. + + NeedsLoopOutParameter = + 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop + AssignmentsMarked = 0x00400000, // Parameter assignments have been marked + + ClassWithConstructorReference = + 0x00800000, // Class that contains a binding to its constructor inside of the class body. + ConstructorReferenceInClass = 0x01000000 // Binding to a class constructor inside of the class's body. + } + + public enum TypeFlags + { + Any = 1 << 0, + String = 1 << 1, + Number = 1 << 2, + Boolean = 1 << 3, + Enum = 1 << 4, + StringLiteral = 1 << 5, + NumberLiteral = 1 << 6, + BooleanLiteral = 1 << 7, + EnumLiteral = 1 << 8, + EsSymbol = 1 << 9, // Type of symbol primitive introduced in ES6 + Void = 1 << 10, + Undefined = 1 << 11, + Null = 1 << 12, + Never = 1 << 13, // Never type + TypeParameter = 1 << 14, // Type parameter + Object = 1 << 15, // Object type + Union = 1 << 16, // Union (T | U) + Intersection = 1 << 17, // Intersection (T & U) + Index = 1 << 18, // keyof T + IndexedAccess = 1 << 19, // T[K] + + /* @internal */ + FreshLiteral = 1 << 20, // Fresh literal type + + /* @internal */ + ContainsWideningType = 1 << 21, // Type is or contains undefined or null widening type + + /* @internal */ + ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type + + /* @internal */ + ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type + NonPrimitive = 1 << 24, // intrinsic object type + + /* @internal */ + JsxAttributes = 1 << 25, // Jsx attributes type + + /* @internal */ + Nullable = Undefined | Null, + Literal = StringLiteral | NumberLiteral | BooleanLiteral | EnumLiteral, + StringOrNumberLiteral = StringLiteral | NumberLiteral, + + /* @internal */ + DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null, + PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean, + + /* @internal */ + Intrinsic = Any | String | Number | Boolean | BooleanLiteral | EsSymbol | Void | Undefined | Null | Never | + NonPrimitive, + + /* @internal */ + Primitive = String | Number | Boolean | Enum | EsSymbol | Void | Undefined | Null | Literal, + StringLike = String | StringLiteral | Index, + NumberLike = Number | NumberLiteral | Enum | EnumLiteral, + BooleanLike = Boolean | BooleanLiteral, + EnumLike = Enum | EnumLiteral, + UnionOrIntersection = Union | Intersection, + StructuredType = Object | Union | Intersection, + StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess, + TypeVariable = TypeParameter | IndexedAccess, + + // 'Narrowable' types are types where narrowing actually narrows. + // This *should* be every type other than null, undefined, void, and never + Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | + BooleanLike | EsSymbol | NonPrimitive, + NotUnionOrUnit = Any | EsSymbol | Object | NonPrimitive, + + /* @internal */ + RequiresWidening = ContainsWideningType | ContainsObjectLiteral, + + /* @internal */ + PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType + } + + public enum ObjectFlags + { + Class = 1 << 0, // Class + Interface = 1 << 1, // Interface + Reference = 1 << 2, // Generic type reference + Tuple = 1 << 3, // Synthesized generic tuple type + Anonymous = 1 << 4, // Anonymous + Mapped = 1 << 5, // Mapped + Instantiated = 1 << 6, // Instantiated anonymous or mapped type + ObjectLiteral = 1 << 7, // Originates in an object literal + EvolvingArray = 1 << 8, // Evolving array type + ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties + ClassOrInterface = Class | Interface + } + + public enum SignatureKind + { + Call, + Construct + } + + public enum IndexKind + { + String, + Number + } + + public enum SpecialPropertyAssignmentKind + { + None, + + /// exports.name = expr + ExportsProperty, + + /// module.exports = expr + ModuleExports, + + /// className.prototype.name = expr + PrototypeProperty, + + /// this.name = expr + ThisProperty, + + // F.name = expr + Property + } + + public enum DiagnosticCategory + { + Warning, + Error, + Message, + Unknown + } + + public enum ModuleResolutionKind + { + Classic = 1, + NodeJs = 2 + } + + public enum ModuleKind + { + None = 0, + CommonJs = 1, + Amd = 2, + Umd = 3, + System = 4, + Es2015 = 5 + } + + public enum JsxEmit + { + None = 0, + Preserve = 1, + React = 2, + ReactNative = 3 + } + + public enum NewLineKind + { + CarriageReturnLineFeed = 0, + LineFeed = 1 + } + + public enum ScriptKind + { + Unknown = 0, + Js = 1, + Jsx = 2, + Ts = 3, + Tsx = 4, + External = 5 + } + + public enum ScriptTarget + { + Es3 = 0, + Es5 = 1, + Es2015 = 2, + Es2016 = 3, + Es2017 = 4, + EsNext = 5, + Latest = EsNext + } + + public enum LanguageVariant + { + Standard, + Jsx + } + + public enum DiagnosticStyle + { + Simple, + Pretty + } + + public enum WatchDirectoryFlags + { + None = 0, + Recursive = 1 << 0 + } + + public enum CharacterCodes + { + NullCharacter = 0, + MaxAsciiCharacter = 0x7F, + + LineFeed = 0x0A, // \n + CarriageReturn = 0x0D, // \r + LineSeparator = 0x2028, + ParagraphSeparator = 0x2029, + NextLine = 0x0085, + + // Unicode 3.0 space characters + Space = 0x0020, // " " + NonBreakingSpace = 0x00A0, // + EnQuad = 0x2000, + EmQuad = 0x2001, + EnSpace = 0x2002, + EmSpace = 0x2003, + ThreePerEmSpace = 0x2004, + FourPerEmSpace = 0x2005, + SixPerEmSpace = 0x2006, + FigureSpace = 0x2007, + PunctuationSpace = 0x2008, + ThinSpace = 0x2009, + HairSpace = 0x200A, + ZeroWidthSpace = 0x200B, + NarrowNoBreakSpace = 0x202F, + IdeographicSpace = 0x3000, + MathematicalSpace = 0x205F, + Ogham = 0x1680, + + _ = 0x5F, + Dollar = 0x24, + + _0 = 0x30, + _1 = 0x31, + _2 = 0x32, + _3 = 0x33, + _4 = 0x34, + _5 = 0x35, + _6 = 0x36, + _7 = 0x37, + _8 = 0x38, + _9 = 0x39, + + a = 0x61, + b = 0x62, + c = 0x63, + d = 0x64, + e = 0x65, + f = 0x66, + g = 0x67, + h = 0x68, + i = 0x69, + j = 0x6A, + k = 0x6B, + l = 0x6C, + m = 0x6D, + n = 0x6E, + o = 0x6F, + p = 0x70, + q = 0x71, + r = 0x72, + s = 0x73, + t = 0x74, + u = 0x75, + v = 0x76, + w = 0x77, + x = 0x78, + y = 0x79, + z = 0x7A, + + A = 0x41, + B = 0x42, + C = 0x43, + D = 0x44, + E = 0x45, + F = 0x46, + G = 0x47, + H = 0x48, + I = 0x49, + J = 0x4A, + K = 0x4B, + L = 0x4C, + M = 0x4D, + N = 0x4E, + O = 0x4F, + P = 0x50, + Q = 0x51, + R = 0x52, + S = 0x53, + T = 0x54, + U = 0x55, + V = 0x56, + W = 0x57, + X = 0x58, + Y = 0x59, + Z = 0x5a, + + Ampersand = 0x26, // & + Asterisk = 0x2A, // * + At = 0x40, // @ + Backslash = 0x5C, // \ + Backtick = 0x60, // ` + Bar = 0x7C, // | + Caret = 0x5E, // ^ + CloseBrace = 0x7D, // } + CloseBracket = 0x5D, // ] + CloseParen = 0x29, // ) + Colon = 0x3A, // : + Comma = 0x2C, // , + Dot = 0x2E, // . + DoubleQuote = 0x22, // " + equals = 0x3D, // = + Exclamation = 0x21, // ! + GreaterThan = 0x3E, // > + Hash = 0x23, // # + LessThan = 0x3C, // < + Minus = 0x2D, // - + OpenBrace = 0x7B, // { + OpenBracket = 0x5B, // [ + OpenParen = 0x28, // ( + Percent = 0x25, // % + Plus = 0x2B, // + + Question = 0x3F, // ? + Semicolon = 0x3B, // ; + SingleQuote = 0x27, // ' + Slash = 0x2F, // / + Tilde = 0x7E, // ~ + + Backspace = 0x08, // \b + FormFeed = 0x0C, // \f + ByteOrderMark = 0xFEFF, + Tab = 0x09, // \t + VerticalTab = 0x0B // \v + } + + public enum Extension + { + Ts, + Tsx, + Dts, + Js, + Jsx, + LastTypeScriptExtension = Dts + } + + public enum TransformFlags + { + None = 0, + + // Facts + // - Flags used to indicate that a node or subtree contains syntax that requires transformation. + TypeScript = 1 << 0, + ContainsTypeScript = 1 << 1, + ContainsJsx = 1 << 2, + ContainsEsNext = 1 << 3, + ContainsEs2017 = 1 << 4, + ContainsEs2016 = 1 << 5, + Es2015 = 1 << 6, + ContainsEs2015 = 1 << 7, + Generator = 1 << 8, + ContainsGenerator = 1 << 9, + DestructuringAssignment = 1 << 10, + ContainsDestructuringAssignment = 1 << 11, + + // Markers + // - Flags used to indicate that a subtree contains a specific transformation. + ContainsDecorators = 1 << 12, + ContainsPropertyInitializer = 1 << 13, + ContainsLexicalThis = 1 << 14, + ContainsCapturedLexicalThis = 1 << 15, + ContainsLexicalThisInComputedPropertyName = 1 << 16, + ContainsDefaultValueAssignments = 1 << 17, + ContainsParameterPropertyAssignments = 1 << 18, + ContainsSpread = 1 << 19, + ContainsObjectSpread = 1 << 20, + ContainsRest = ContainsSpread, + ContainsObjectRest = ContainsObjectSpread, + ContainsComputedPropertyName = 1 << 21, + ContainsBlockScopedBinding = 1 << 22, + ContainsBindingPattern = 1 << 23, + ContainsYield = 1 << 24, + ContainsHoistedDeclarationOrCompletion = 1 << 25, + + HasComputedFlags = 1 << 29, // Transform flags have been computed. + + // Assertions + // - Bitmasks that are used to assert facts about the syntax of a node and its subtree. + AssertTypeScript = TypeScript | ContainsTypeScript, + AssertJsx = ContainsJsx, + AssertEsNext = ContainsEsNext, + AssertEs2017 = ContainsEs2017, + AssertEs2016 = ContainsEs2016, + AssertEs2015 = Es2015 | ContainsEs2015, + AssertGenerator = Generator | ContainsGenerator, + AssertDestructuringAssignment = DestructuringAssignment | ContainsDestructuringAssignment, + + // Scope Exclusions + // - Bitmasks that exclude flags from propagating out of a specific context + // into the subtree flags of their container. + NodeExcludes = TypeScript | Es2015 | DestructuringAssignment | Generator | HasComputedFlags, + + ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | + ContainsLexicalThis | ContainsParameterPropertyAssignments | + ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | + ContainsBindingPattern | ContainsObjectRest, + + FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | + ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | + ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | + ContainsBindingPattern | ContainsObjectRest, + + ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | + ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | + ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest, + + MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | + ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | + ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest, + + ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | + ContainsCapturedLexicalThis | ContainsComputedPropertyName | + ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName, + + ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | + ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion, + TypeExcludes = ~ContainsTypeScript, + + ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | + ContainsLexicalThisInComputedPropertyName | ContainsObjectSpread, + ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpread, + VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRest, + ParameterExcludes = NodeExcludes, + CatchClauseExcludes = NodeExcludes | ContainsObjectRest, + BindingPatternExcludes = NodeExcludes | ContainsRest, + + // Masks + // - Additional bitmasks + TypeScriptClassSyntaxMask = ContainsParameterPropertyAssignments | ContainsPropertyInitializer | + ContainsDecorators, + Es2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments + } + + public enum EmitFlags + { + SingleLine = 1 << 0, // The contents of this node should be emitted on a single line. + AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node. + NoSubstitution = 1 << 2, // Disables further substitution of an expression. + CapturesThis = 1 << 3, // The function captures a lexical `this` + NoLeadingSourceMap = 1 << 4, // Do not emit a leading source map location for this node. + NoTrailingSourceMap = 1 << 5, // Do not emit a trailing source map location for this node. + NoSourceMap = NoLeadingSourceMap | NoTrailingSourceMap, // Do not emit a source map location for this node. + NoNestedSourceMaps = 1 << 6, // Do not emit source map locations for children of this node. + NoTokenLeadingSourceMaps = 1 << 7, // Do not emit leading source map location for token nodes. + NoTokenTrailingSourceMaps = 1 << 8, // Do not emit trailing source map location for token nodes. + + NoTokenSourceMaps = + NoTokenLeadingSourceMaps | + NoTokenTrailingSourceMaps, // Do not emit source map locations for tokens of this node. + NoLeadingComments = 1 << 9, // Do not emit leading comments for this node. + NoTrailingComments = 1 << 10, // Do not emit trailing comments for this node. + NoComments = NoLeadingComments | NoTrailingComments, // Do not emit comments for this node. + NoNestedComments = 1 << 11, + HelperName = 1 << 12, + + ExportName = + 1 << + 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal). + + LocalName = + 1 << 14, // Ensure an export prefix is not added for an identifier that points to an exported declaration. + + Indented = + 1 << + 15, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter). + NoIndentation = 1 << 16, // Do not indent the node. + AsyncFunctionBody = 1 << 17, + ReuseTempVariableScope = 1 << 18, // Reuse the existing temp variable scope during emit. + + CustomPrologue = + 1 << + 19, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed). + NoHoisting = 1 << 20, // Do not hoist this declaration in --module system + + HasEndOfDeclarationMarker = + 1 << 21 // Declaration has an associated NotEmittedStatement to mark the end of the declaration + } + + public enum ExternalEmitHelpers + { + Extends = 1 << 0, // __extends (used by the ES2015 class transformation) + Assign = 1 << 1, // __assign (used by Jsx and ESNext object spread transformations) + Rest = 1 << 2, // __rest (used by ESNext object rest transformation) + Decorate = 1 << 3, // __decorate (used by TypeScript decorators transformation) + Metadata = 1 << 4, // __metadata (used by TypeScript decorators transformation) + Param = 1 << 5, // __param (used by TypeScript decorators transformation) + Awaiter = 1 << 6, // __awaiter (used by ES2017 async functions transformation) + Generator = 1 << 7, // __generator (used by ES2015 generator transformation) + Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations) + Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation) + Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations) + AsyncGenerator = 1 << 11, // __asyncGenerator (used by ES2017 async generator transformation) + AsyncDelegator = 1 << 12, // __asyncDelegator (used by ES2017 async generator yield* transformation) + AsyncValues = 1 << 13, // __asyncValues (used by ES2017 for..await..of transformation) + + // Helpers included by ES2015 for..of + ForOfIncludes = Values, + + // Helpers included by ES2017 for..await..of + ForAwaitOfIncludes = AsyncValues, + + // Helpers included by ES2015 spread + SpreadIncludes = Read | Spread, + + FirstEmitHelper = Extends, + LastEmitHelper = AsyncValues + } + + public enum EmitHint + { + SourceFile, // Emitting a SourceFile + Expression, // Emitting an Expression + IdentifierName, // Emitting an IdentifierName + Unspecified // Emitting an otherwise unspecified node + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/TsTypes/Node.cs b/generators/CssInCSharp.Ast.TypeScript/TsTypes/Node.cs new file mode 100644 index 0000000..7401d84 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TsTypes/Node.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Zu.TypeScript.TsParser; + +namespace Zu.TypeScript.TsTypes +{ + public class Node : TextRange, INode + { + public List Children { get; set; } = new List(); + public ITypeScriptAST Ast { get; set; } + + public string SourceStr + { + get => Ast.SourceStr; + set => Ast.SourceStr = value; + } + + public string IdentifierStr => Kind == SyntaxKind.Identifier + ? GetText() + : Children.FirstOrDefault(v => v.Kind == SyntaxKind.Identifier)?.GetText().Trim(); + + public int ParentId { get; set; } + public int Depth { get; set; } + public int NodeStart { get; set; } = -1; + public SyntaxKind Kind { get; set; } + public NodeFlags Flags { get; set; } + public ModifierFlags ModifierFlagsCache { get; set; } + public TransformFlags TransformFlags { get; set; } + public NodeArray Decorators { get; set; } + public /*ModifiersArray*/NodeArray Modifiers { get; set; } + public int Id { get; set; } + public INode Parent { get; set; } + public Node Original { get; set; } + public bool StartsOnNewLine { get; set; } + public List JsDoc { get; set; } + public List JsDocCache { get; set; } + public Symbol Symbol { get; set; } + public SymbolTable Locals { get; set; } + public Node NextContainer { get; set; } + public Symbol LocalSymbol { get; set; } + public FlowNode FlowNode { get; set; } + public EmitNode EmitNode { get; set; } + + public Type ContextualType { get; set; } + public TypeMapper ContextualMapper { get; set; } + + public int TagInt { get; set; } + + public void MakeChildren(TypeScriptAST ast) + { + Children = new List(); + Ts.ForEachChild(this, node => + { + if (node == null) + return null; + var n = (Node)node; + n.Ast = ast; + n.Depth = Depth + 1; + n.Parent = this; + if (n.Pos != null) n.NodeStart = Scanner.SkipTriviaM(SourceStr, (int)n.Pos); + Children.Add(n); + n.MakeChildren(ast); + return null; + }); + } + + public string GetText(string source = null) + { + if (source == null) source = SourceStr; + if (NodeStart == -1) + if (Pos != null && End != null) return source.Substring((int)Pos, (int)End - (int)Pos); + else return null; + + if (End != null) return source.Substring(NodeStart, (int)End - NodeStart); + return null; + } + + public string GetTextWithComments(string source = null) + { + if (source == null) source = SourceStr; + if (Pos != null && End != null) + return source.Substring((int)Pos, (int)End - (int)Pos); + return null; + } + + public override string ToString() + { + var posStr = $" [{Pos}, {End}]"; + + return $"{Enum.GetName(typeof(SyntaxKind), Kind)} {posStr} {IdentifierStr}"; + } + + public string ToString(bool withPos) + { + if (withPos) + { + var posStr = $" [{Pos}, {End}]"; + + return $"{Enum.GetName(typeof(SyntaxKind), Kind)} {posStr} {IdentifierStr}"; + } + return $"{Enum.GetName(typeof(SyntaxKind), Kind)} {IdentifierStr}"; + } + public Node First => Children.FirstOrDefault(); + public Node Last => Children.LastOrDefault(); + public int Count => Children.Count; + + public IEnumerable OfKind(SyntaxKind kind) => GetDescendants(false).OfKind(kind); + + public IEnumerable GetDescendants(bool includeSelf = true) + { + if (includeSelf) yield return this; + + foreach (var descendant in Children) + { + foreach (var ch in descendant.GetDescendants()) + yield return ch; + } + } + public string GetTreeString(bool withPos = true) + { + var sb = new StringBuilder(); + var descendants = GetDescendants().ToList(); + foreach (var node in descendants) + { + //var anc = node.GetAncestors().ToList(); + for (int i = 1; i < node.Depth; i++) //anc.Count() + { + sb.Append(" "); + } + sb.AppendLine(node.ToString(withPos)); + } + return sb.ToString(); + } + + } + + public interface INode : ITextRange + { + SyntaxKind Kind { get; set; } + NodeFlags Flags { get; set; } + ModifierFlags ModifierFlagsCache { get; set; } + TransformFlags TransformFlags { get; set; } + + NodeArray Decorators { get; set; } + + /*ModifiersArray*/ + NodeArray Modifiers { get; set; } + + int Id { get; set; } + INode Parent { get; set; } + List Children { get; set; } + int Depth { get; set; } + Node Original { get; set; } + bool StartsOnNewLine { get; set; } + List JsDoc { get; set; } + List JsDocCache { get; set; } + Symbol Symbol { get; set; } + SymbolTable Locals { get; set; } + Node NextContainer { get; set; } + Symbol LocalSymbol { get; set; } + FlowNode FlowNode { get; set; } + EmitNode EmitNode { get; set; } + Type ContextualType { get; set; } + TypeMapper ContextualMapper { get; set; } + int TagInt { get; set; } + + string GetText(string source = null); + string GetTextWithComments(string source = null); + string GetTreeString(bool withPos = true); + + string ToString(bool withPos); + Node First { get; } + Node Last { get; } + int Count { get; } + + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/TsTypes/NodeExtensions.cs b/generators/CssInCSharp.Ast.TypeScript/TsTypes/NodeExtensions.cs new file mode 100644 index 0000000..dfb7da2 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TsTypes/NodeExtensions.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace Zu.TypeScript.TsTypes +{ + public static class NodeExtensions + { + public static IEnumerable GetDescendants(this INode node, bool includeSelf = true) + { + if (includeSelf) yield return node; + + foreach (var descendant in node.Children) + foreach (var ch in descendant.GetDescendants()) + yield return ch; + } + + public static IEnumerable GetAncestors(this INode node) + { + var current = node.Parent; + + while (current != null) + { + yield return current; + current = current.Parent; + } + } + public static IEnumerable OfKind(this IEnumerable nodes, SyntaxKind kind) + { + foreach (var node in nodes) + { + if (node.Kind == kind) yield return node; + } + } + + public static IEnumerable OfKind(this IEnumerable nodes, SyntaxKind kind) + { + foreach (var node in nodes) + { + if (node.Kind == kind) yield return node; + } + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/TsTypes/SyntaxKind.cs b/generators/CssInCSharp.Ast.TypeScript/TsTypes/SyntaxKind.cs new file mode 100644 index 0000000..7064f01 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TsTypes/SyntaxKind.cs @@ -0,0 +1,399 @@ +namespace Zu.TypeScript.TsTypes +{ + public enum SyntaxKind + { + Unknown, + EndOfFileToken, + SingleLineCommentTrivia, + MultiLineCommentTrivia, + NewLineTrivia, + WhitespaceTrivia, + + // We detect and preserve #! on the first line + ShebangTrivia, + + // We detect and provide better error recovery when we encounter a git merge marker. This + // allows us to edit files with git-conflict markers in them in a much more pleasant manner. + ConflictMarkerTrivia, + + // Literals + NumericLiteral, + StringLiteral, + JsxText, + RegularExpressionLiteral, + NoSubstitutionTemplateLiteral, + + // Pseudo-literals + TemplateHead, + TemplateMiddle, + TemplateTail, + + // Punctuation + OpenBraceToken, + CloseBraceToken, + OpenParenToken, + CloseParenToken, + OpenBracketToken, + CloseBracketToken, + DotToken, + DotDotDotToken, + SemicolonToken, + CommaToken, + LessThanToken, + LessThanSlashToken, + GreaterThanToken, + LessThanEqualsToken, + GreaterThanEqualsToken, + EqualsEqualsToken, + ExclamationEqualsToken, + EqualsEqualsEqualsToken, + ExclamationEqualsEqualsToken, + EqualsGreaterThanToken, + PlusToken, + MinusToken, + AsteriskToken, + AsteriskAsteriskToken, + SlashToken, + PercentToken, + PlusPlusToken, + MinusMinusToken, + LessThanLessThanToken, + GreaterThanGreaterThanToken, + GreaterThanGreaterThanGreaterThanToken, + AmpersandToken, + BarToken, + CaretToken, + ExclamationToken, + TildeToken, + AmpersandAmpersandToken, + BarBarToken, + QuestionToken, + ColonToken, + AtToken, + + // Assignments + EqualsToken, + PlusEqualsToken, + MinusEqualsToken, + AsteriskEqualsToken, + AsteriskAsteriskEqualsToken, + SlashEqualsToken, + PercentEqualsToken, + LessThanLessThanEqualsToken, + GreaterThanGreaterThanEqualsToken, + GreaterThanGreaterThanGreaterThanEqualsToken, + AmpersandEqualsToken, + BarEqualsToken, + CaretEqualsToken, + + // Identifiers + Identifier, + + // Reserved words + BreakKeyword, + CaseKeyword, + CatchKeyword, + ClassKeyword, + ConstKeyword, + ContinueKeyword, + DebuggerKeyword, + DefaultKeyword, + DeleteKeyword, + DoKeyword, + ElseKeyword, + EnumKeyword, + ExportKeyword, + ExtendsKeyword, + FalseKeyword, + FinallyKeyword, + ForKeyword, + FunctionKeyword, + IfKeyword, + ImportKeyword, + InKeyword, + InstanceOfKeyword, + NewKeyword, + NullKeyword, + ReturnKeyword, + SuperKeyword, + SwitchKeyword, + ThisKeyword, + ThrowKeyword, + TrueKeyword, + TryKeyword, + TypeOfKeyword, + VarKeyword, + VoidKeyword, + WhileKeyword, + WithKeyword, + + // Strict mode reserved words + ImplementsKeyword, + InterfaceKeyword, + LetKeyword, + PackageKeyword, + PrivateKeyword, + ProtectedKeyword, + PublicKeyword, + StaticKeyword, + YieldKeyword, + + // Contextual keywords + AbstractKeyword, + AsKeyword, + AnyKeyword, + AsyncKeyword, + AwaitKeyword, + BooleanKeyword, + ConstructorKeyword, + DeclareKeyword, + GetKeyword, + IsKeyword, + KeyOfKeyword, + ModuleKeyword, + NamespaceKeyword, + NeverKeyword, + ReadonlyKeyword, + RequireKeyword, + NumberKeyword, + ObjectKeyword, + SetKeyword, + StringKeyword, + SymbolKeyword, + TypeKeyword, + UndefinedKeyword, + FromKeyword, + GlobalKeyword, + OfKeyword, // LastKeyword and LastToken + + // Parse tree nodes + + // Names + QualifiedName, + ComputedPropertyName, + + // Signature elements + TypeParameter, + Parameter, + Decorator, + + // TypeMember + PropertySignature, + PropertyDeclaration, + MethodSignature, + MethodDeclaration, + Constructor, + GetAccessor, + SetAccessor, + CallSignature, + ConstructSignature, + IndexSignature, + + // Type + TypePredicate, + TypeReference, + FunctionType, + ConstructorType, + TypeQuery, + TypeLiteral, + ArrayType, + TupleType, + UnionType, + IntersectionType, + ParenthesizedType, + ThisType, + TypeOperator, + IndexedAccessType, + MappedType, + LiteralType, + + // Binding patterns + ObjectBindingPattern, + ArrayBindingPattern, + BindingElement, + + // Expression + ArrayLiteralExpression, + ObjectLiteralExpression, + PropertyAccessExpression, + ElementAccessExpression, + CallExpression, + NewExpression, + TaggedTemplateExpression, + TypeAssertionExpression, + ParenthesizedExpression, + FunctionExpression, + ArrowFunction, + DeleteExpression, + TypeOfExpression, + VoidExpression, + AwaitExpression, + PrefixUnaryExpression, + PostfixUnaryExpression, + BinaryExpression, + ConditionalExpression, + TemplateExpression, + YieldExpression, + SpreadElement, + ClassExpression, + OmittedExpression, + ExpressionWithTypeArguments, + AsExpression, + NonNullExpression, + MetaProperty, + + // Misc + TemplateSpan, + SemicolonClassElement, + + // Element + Block, + VariableStatement, + EmptyStatement, + ExpressionStatement, + IfStatement, + DoStatement, + WhileStatement, + ForStatement, + ForInStatement, + ForOfStatement, + ContinueStatement, + BreakStatement, + ReturnStatement, + WithStatement, + SwitchStatement, + LabeledStatement, + ThrowStatement, + TryStatement, + DebuggerStatement, + VariableDeclaration, + VariableDeclarationList, + FunctionDeclaration, + ClassDeclaration, + InterfaceDeclaration, + TypeAliasDeclaration, + EnumDeclaration, + ModuleDeclaration, + ModuleBlock, + CaseBlock, + NamespaceExportDeclaration, + ImportEqualsDeclaration, + ImportDeclaration, + ImportClause, + NamespaceImport, + NamedImports, + ImportSpecifier, + ExportAssignment, + ExportDeclaration, + NamedExports, + ExportSpecifier, + MissingDeclaration, + + // Module references + ExternalModuleReference, + + // JSX + JsxElement, + JsxSelfClosingElement, + JsxOpeningElement, + JsxClosingElement, + JsxAttribute, + JsxAttributes, + JsxSpreadAttribute, + JsxExpression, + + // Clauses + CaseClause, + DefaultClause, + HeritageClause, + CatchClause, + + // Property assignments + PropertyAssignment, + ShorthandPropertyAssignment, + SpreadAssignment, + + // Enum + EnumMember, + + // Top-level nodes + SourceFile, + Bundle, + + // JSDoc nodes + JsDocTypeExpression, + + // The * type + JsDocAllType, + + // The ? type + JsDocUnknownType, + JsDocArrayType, + JsDocUnionType, + JsDocTupleType, + JsDocNullableType, + JsDocNonNullableType, + JsDocRecordType, + JsDocRecordMember, + JsDocTypeReference, + JsDocOptionalType, + JsDocFunctionType, + JsDocVariadicType, + JsDocConstructorType, + JsDocThisType, + JsDocComment, + JsDocTag, + JsDocAugmentsTag, + JsDocParameterTag, + JsDocReturnTag, + JsDocTypeTag, + JsDocTemplateTag, + JsDocTypedefTag, + JsDocPropertyTag, + JsDocTypeLiteral, + JsDocLiteralType, + + // Synthesized list + SyntaxList, + + // Transformation nodes + NotEmittedStatement, + PartiallyEmittedExpression, + MergeDeclarationMarker, + EndOfDeclarationMarker, + + // Enum value count + Count, + + // Markers + FirstAssignment = EqualsToken, + LastAssignment = CaretEqualsToken, + FirstCompoundAssignment = PlusEqualsToken, + LastCompoundAssignment = CaretEqualsToken, + FirstReservedWord = BreakKeyword, + LastReservedWord = WithKeyword, + FirstKeyword = BreakKeyword, + LastKeyword = OfKeyword, + FirstFutureReservedWord = ImplementsKeyword, + LastFutureReservedWord = YieldKeyword, + FirstTypeNode = TypePredicate, + LastTypeNode = LiteralType, + FirstPunctuation = OpenBraceToken, + LastPunctuation = CaretEqualsToken, + FirstToken = Unknown, + LastToken = LastKeyword, + FirstTriviaToken = SingleLineCommentTrivia, + LastTriviaToken = ConflictMarkerTrivia, + FirstLiteralToken = NumericLiteral, + LastLiteralToken = NoSubstitutionTemplateLiteral, + FirstTemplateToken = NoSubstitutionTemplateLiteral, + LastTemplateToken = TemplateTail, + FirstBinaryOperator = LessThanToken, + LastBinaryOperator = CaretEqualsToken, + FirstNode = QualifiedName, + FirstJsDocNode = JsDocTypeExpression, + LastJsDocNode = JsDocLiteralType, + FirstJsDocTagNode = JsDocComment, + LastJsDocTagNode = JsDocLiteralType + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.Ast.TypeScript/TsTypes/TsTypes.cs b/generators/CssInCSharp.Ast.TypeScript/TsTypes/TsTypes.cs new file mode 100644 index 0000000..5eb0338 --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TsTypes/TsTypes.cs @@ -0,0 +1,3698 @@ +using System.Collections.Generic; +using System.Linq; +using CommentKind = Zu.TypeScript.TsTypes.SyntaxKind; + +namespace Zu.TypeScript.TsTypes +{ + public class Map : List + { + } + + public class MapLike : List + { + } + + public class ReadonlyArray : List + { + } + + public class OpenBracketToken : Token + { + } + + public class DotDotDotToken : Token + { + public DotDotDotToken() + { + Kind = SyntaxKind.DotDotDotToken; + } + } + + public class DotToken : Token + { + public DotToken() + { + Kind = SyntaxKind.DotToken; + } + } + + public class QuestionToken : Token + { + public QuestionToken() + { + Kind = SyntaxKind.QuestionToken; + } + } + + public class ColonToken : Token + { + public ColonToken() + { + Kind = SyntaxKind.ColonToken; + } + } + + public class EqualsToken : Token + { + public EqualsToken() + { + Kind = SyntaxKind.EqualsToken; + } + } + + public class AsteriskToken : Token + { + public AsteriskToken() + { + Kind = SyntaxKind.AsteriskToken; + } + } + + public class EqualsGreaterThanToken : Token + { + public EqualsGreaterThanToken() + { + Kind = SyntaxKind.EqualsGreaterThanToken; + } + } + + public class EndOfFileToken : Token + { + public EndOfFileToken() + { + Kind = SyntaxKind.EndOfFileToken; + } + } + + public class AtToken : Token + { + public AtToken() + { + Kind = SyntaxKind.AtToken; + } + } + + public class ReadonlyToken : Token + { + public ReadonlyToken() + { + Kind = SyntaxKind.ReadonlyKeyword; + } + } + + public class AwaitKeywordToken : Token + { + public AwaitKeywordToken() + { + Kind = SyntaxKind.AwaitKeyword; + } + } + + public class Modifier : Node + { + } + + public class ModifiersArray : NodeArray + { + } + + public interface IEntityName : INode + { + } + + public interface IPropertyName : INode + { + } + + public interface IDeclarationName : INode + { + } + + public interface IBindingName : INode + { + } + + public interface IObjectLiteralElementLike : INode + { + } + + public interface IBindingPattern : INode + { + NodeArray Elements { get; set; } + } + + public interface IArrayBindingElement : INode + { + } + + public interface IAccessorDeclaration : ISignatureDeclaration, IClassElement, IObjectLiteralElementLike + { + //object _classElementBrand { get; set; } + IBlockOrExpression Body { get; set; } // Block | Expression + } + + public interface IFunctionOrConstructorTypeNode : ISignatureDeclaration, ITypeNode + { + } + + public interface IUnionOrIntersectionTypeNode : ITypeNode + { + NodeArray Types { get; set; } + } + + //{ + // //public BinaryOperatorToken() { kind = SyntaxKind.BinaryOperator; } + //} + public class AssignmentOperatorToken : Token + { + } + + public interface IDestructuringAssignment : INode // AssignmentExpression + { + } + + public interface IBindingOrAssignmentElement : INode + { + } + + public interface IBindingOrAssignmentElementRestIndicator : INode + { + } + + public interface IBindingOrAssignmentElementTarget : INode + { + } + + public interface IObjectBindingOrAssignmentPattern : INode + { + } + + public interface IArrayBindingOrAssignmentPattern : INode + { + } + + public interface IAssignmentPattern : INode + { + } + + public interface IBindingOrAssignmentPattern : INode + { + } + + public class FunctionBody : Block + { + } + + public interface IConciseBody : INode + { + } + + public interface ITemplateLiteral : INode + { + } + + public interface IEntityNameExpression : INode + { + } + + public interface IEntityNameOrEntityNameExpression : INode + { + } + + public interface ISuperProperty : INode + { + } + + public interface ICallLikeExpression : INode + { + } + + public interface IAssertionExpression : IExpression + { + } + + public interface IJsxOpeningLikeElement : IExpression + { + } + + public interface IJsxAttributeLike : IObjectLiteralElement + { + } + + public interface IJsxTagNameExpression : IExpression + { + } + + public interface IJsxChild : INode + { + } + + public interface IBlockLike : INode + { + } + + public interface IForInitializer : INode + { + } + + public interface IBreakOrContinueStatement : IStatement + { + Identifier Label { get; set; } + } + + public interface ICaseOrDefaultClause : INode + { + } + + public interface IDeclarationWithTypeParameters : INode + { + } + + public interface IModuleName : INode + { + } + + public interface IModuleBody : INode + { + } + + public interface INamespaceBody : INode + { + } + + public interface IJsDocNamespaceBody : INode + { + } + + public interface IModuleReference : INode + { + } + + public interface INamedImportBindings : INode, INamedImportsOrExports + { + } + + public interface INamedImportsOrExports : INode + { + } + + public interface IMportOrExportSpecifier : IDeclaration + { + Identifier PropertyName { get; set; } + } + + public interface IJsDocTypeReferencingNode : IJsDocType + { + } + + public class FlowType : object + { + } + + public class ITypePredicate : TypePredicateBase + { + } + + public interface IAnyImportSyntax : INode + { + } + + public class SymbolTable : Map + { + } + + public interface IDestructuringPattern : INode + { + } + + public interface IBaseType : IType + { + } + + public interface IStructuredType : IType + { + } + + public class CompilerOptionsValue : object + { + } + + public class CommandLineOption : CommandLineOptionBase + { + } + + public class TransformerFactory + { + } + + public class Transformer + { + } + + public class Visitor + { + } + + public class VisitResult : object + { + } + + public class MapLike + { + } + + public class Map + { + public int Size { get; set; } + } + + public class Iterator + { + } + + public class FileMap + { + } + + public interface ITextRange + { + int? Pos { get; set; } + int? End { get; set; } + } + + public class TextRange : ITextRange + { + public int? Pos { get; set; } + public int? End { get; set; } + } + + public class NodeArray : List, ITextRange + { + public NodeArray() + { + } + + public NodeArray(T[] elements) + : base(elements.ToList()) + { + } + + public bool HasTrailingComma { get; set; } + public TransformFlags TransformFlags { get; set; } + public int? Pos { get; set; } + public int? End { get; set; } + } + + public class Token : Node + { + } + + public class Identifier : PrimaryExpression, IJsxTagNameExpression, IEntityName, IPropertyName + { + public Identifier() + { + Kind = SyntaxKind.Identifier; + } + + public string Text { get; set; } + public SyntaxKind OriginalKeywordKind { get; set; } + public GeneratedIdentifierKind AutoGenerateKind { get; set; } + public int AutoGenerateId { get; set; } + public bool IsInJsDocNamespace { get; set; } + } + + public class TransientIdentifier : Identifier + { + public Symbol ResolvedSymbol { get; set; } + } + + public class GeneratedIdentifier : Identifier + { + } + + public class QualifiedName : Node, IEntityName + { + public QualifiedName() + { + Kind = SyntaxKind.QualifiedName; + } + + public IEntityName Left { get; set; } + public Identifier Right { get; set; } + } + + public interface IDeclaration : INode + { + object DeclarationBrand { get; set; } + INode Name { get; set; } + } + + public class Declaration : Node, IDeclaration + { + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + } + + public interface IDeclarationStatement : INode, IDeclaration, IStatement + { + //Node name { get; set; } // Identifier | StringLiteral | NumericLiteral + } + + public class DeclarationStatement : Node, IDeclarationStatement, IDeclaration, IStatement + { + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object StatementBrand { get; set; } + } + + public class ComputedPropertyName : Node, IPropertyName + { + public ComputedPropertyName() + { + Kind = SyntaxKind.ComputedPropertyName; + } + + public IExpression Expression { get; set; } + } + + public class Decorator : Node + { + public Decorator() + { + Kind = SyntaxKind.Decorator; + } + + public /*LeftHandSideExpression*/IExpression Expression { get; set; } + } + + public class TypeParameterDeclaration : Declaration + { + public TypeParameterDeclaration() + { + Kind = SyntaxKind.TypeParameter; + } + + public ITypeNode Constraint { get; set; } + public ITypeNode Default { get; set; } + public IExpression Expression { get; set; } + } + + public interface ISignatureDeclaration : IDeclaration + { + NodeArray TypeParameters { get; set; } + NodeArray Parameters { get; set; } + ITypeNode Type { get; set; } + } + + public class SignatureDeclaration : Declaration, ISignatureDeclaration + { + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + } + + public class CallSignatureDeclaration : Declaration, ISignatureDeclaration, ITypeElement + { + public CallSignatureDeclaration() + { + Kind = SyntaxKind.CallSignature; + } + + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public class ConstructSignatureDeclaration : Declaration, ISignatureDeclaration, ITypeElement + { + public ConstructSignatureDeclaration() + { + Kind = SyntaxKind.ConstructSignature; + } + + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public class VariableDeclaration : Declaration, IVariableLikeDeclaration + { + public VariableDeclaration() + { + Kind = SyntaxKind.VariableDeclaration; + } + + public ITypeNode Type { get; set; } + public IExpression Initializer { get; set; } + public IPropertyName PropertyName { get; set; } + public DotDotDotToken DotDotDotToken { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public interface IVariableDeclarationListOrExpression : INode + { + } + + public interface IVariableDeclarationList : INode, IVariableDeclarationListOrExpression + { + NodeArray Declarations { get; set; } + } + + public class VariableDeclarationList : Node, IVariableDeclarationList + { + public VariableDeclarationList() + { + Kind = SyntaxKind.VariableDeclarationList; + } + + public NodeArray Declarations { get; set; } + } + + public class ParameterDeclaration : Declaration, IVariableLikeDeclaration + { + public ParameterDeclaration() + { + Kind = SyntaxKind.Parameter; + } + + public DotDotDotToken DotDotDotToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public ITypeNode Type { get; set; } + public IExpression Initializer { get; set; } + public IPropertyName PropertyName { get; set; } + } + + public class BindingElement : Declaration, IArrayBindingElement, IVariableLikeDeclaration + { + public BindingElement() + { + Kind = SyntaxKind.BindingElement; + } + + public IPropertyName PropertyName { get; set; } + public DotDotDotToken DotDotDotToken { get; set; } + public IExpression Initializer { get; set; } + public QuestionToken QuestionToken { get; set; } + public ITypeNode Type { get; set; } + } + + public class PropertySignature : TypeElement, IVariableLikeDeclaration + { + public PropertySignature() + { + Kind = SyntaxKind.PropertySignature; + } + + public ITypeNode Type { get; set; } + public IExpression Initializer { get; set; } + public IPropertyName PropertyName { get; set; } + public DotDotDotToken DotDotDotToken { get; set; } + } + + public class PropertyDeclaration : ClassElement, IVariableLikeDeclaration + { + public PropertyDeclaration() + { + Kind = SyntaxKind.PropertyDeclaration; + } + + public QuestionToken QuestionToken { get; set; } + public ITypeNode Type { get; set; } + public IExpression Initializer { get; set; } + public IPropertyName PropertyName { get; set; } + public DotDotDotToken DotDotDotToken { get; set; } + } + + public interface IObjectLiteralElement : IDeclaration + { + object ObjectLiteralBrandBrand { get; set; } + } + + public class ObjectLiteralElement : Declaration, IObjectLiteralElement + { + public object ObjectLiteralBrandBrand { get; set; } + } + + public class PropertyAssignment : ObjectLiteralElement, IObjectLiteralElementLike, IVariableLikeDeclaration + { + public PropertyAssignment() + { + Kind = SyntaxKind.PropertyAssignment; + } + + public QuestionToken QuestionToken { get; set; } + public IExpression Initializer { get; set; } + public IPropertyName PropertyName { get; set; } + public DotDotDotToken DotDotDotToken { get; set; } + public ITypeNode Type { get; set; } + } + + public class ShorthandPropertyAssignment : ObjectLiteralElement, IObjectLiteralElementLike + { + public ShorthandPropertyAssignment() + { + Kind = SyntaxKind.ShorthandPropertyAssignment; + } + + public QuestionToken QuestionToken { get; set; } + public Token EqualsToken { get; set; } // Token + public IExpression ObjectAssignmentInitializer { get; set; } + } + + public class SpreadAssignment : ObjectLiteralElement, IObjectLiteralElementLike + { + public SpreadAssignment() + { + Kind = SyntaxKind.SpreadAssignment; + } + + public IExpression Expression { get; set; } + } + + public interface IVariableLikeDeclaration : IDeclaration + { + IPropertyName PropertyName { get; set; } + DotDotDotToken DotDotDotToken { get; set; } + QuestionToken QuestionToken { get; set; } + ITypeNode Type { get; set; } + IExpression Initializer { get; set; } + } + + public class PropertyLikeDeclaration : Declaration + { + } + + public class ObjectBindingPattern : Node, IBindingPattern + { + public ObjectBindingPattern() + { + Kind = SyntaxKind.ObjectBindingPattern; + } + + public NodeArray Elements { get; set; } + } + + public class ArrayBindingPattern : Node, IBindingPattern + { + public ArrayBindingPattern() + { + Kind = SyntaxKind.ArrayBindingPattern; + } + + public NodeArray Elements { get; set; } + } + + public interface IFunctionLikeDeclaration : ISignatureDeclaration + { + object FunctionLikeDeclarationBrand { get; set; } + AsteriskToken AsteriskToken { get; set; } + QuestionToken QuestionToken { get; set; } + IBlockOrExpression Body { get; set; } // Block | Expression + } + + public class FunctionLikeDeclaration : SignatureDeclaration, IFunctionLikeDeclaration + { + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + } + + public class FunctionDeclaration : Node, IFunctionLikeDeclaration, IDeclarationStatement + { + public FunctionDeclaration() + { + Kind = SyntaxKind.FunctionDeclaration; + } + + public object StatementBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + } + + public class MethodSignature : Declaration, ISignatureDeclaration, ITypeElement, IFunctionLikeDeclaration + { + public MethodSignature() + { + Kind = SyntaxKind.MethodSignature; + } + + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public class MethodDeclaration : Declaration, IFunctionLikeDeclaration, IClassElement, IObjectLiteralElement, + IObjectLiteralElementLike + { + public MethodDeclaration() + { + Kind = SyntaxKind.MethodDeclaration; + } + + public object ClassElementBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object ObjectLiteralBrandBrand { get; set; } + } + + public class ConstructorDeclaration : Declaration, IFunctionLikeDeclaration, IClassElement + { + public ConstructorDeclaration() + { + Kind = SyntaxKind.Constructor; + } + + public object ClassElementBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + } + + public class SemicolonClassElement : ClassElement + { + public SemicolonClassElement() + { + Kind = SyntaxKind.SemicolonClassElement; + } + } + + public class GetAccessorDeclaration : Declaration, IFunctionLikeDeclaration, IClassElement, IObjectLiteralElement, + IAccessorDeclaration + { + public GetAccessorDeclaration() + { + Kind = SyntaxKind.GetAccessor; + } + + public object ClassElementBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object ObjectLiteralBrandBrand { get; set; } + } + + public class SetAccessorDeclaration : Declaration, IFunctionLikeDeclaration, IClassElement, IObjectLiteralElement, + IAccessorDeclaration + { + public SetAccessorDeclaration() + { + Kind = SyntaxKind.SetAccessor; + } + + public object ClassElementBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object ObjectLiteralBrandBrand { get; set; } + } + + public class IndexSignatureDeclaration : Declaration, ISignatureDeclaration, IClassElement, ITypeElement + { + public IndexSignatureDeclaration() + { + Kind = SyntaxKind.IndexSignature; + } + + public object ClassElementBrand { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public interface ITypeNode : INode + { + object TypeNodeBrand { get; set; } + } + + public class TypeNode : Node, ITypeNode + { + public object TypeNodeBrand { get; set; } + } + + public interface IKeywordTypeNode : ITypeNode + { + } + + public class KeywordTypeNode : TypeNode, IKeywordTypeNode + { + } + + public class ThisTypeNode : TypeNode + { + public ThisTypeNode() + { + Kind = SyntaxKind.ThisType; + } + } + + public class FunctionTypeNode : Node, ITypeNode, IFunctionOrConstructorTypeNode + { + public FunctionTypeNode() + { + Kind = SyntaxKind.FunctionType; + } + + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class ConstructorTypeNode : Node, ITypeNode, IFunctionOrConstructorTypeNode + { + public ConstructorTypeNode() + { + Kind = SyntaxKind.ConstructorType; + } + + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class TypeReferenceNode : TypeNode + { + public TypeReferenceNode() + { + Kind = SyntaxKind.TypeReference; + } + + public IEntityName TypeName { get; set; } + public NodeArray TypeArguments { get; set; } + } + + public class TypePredicateNode : TypeNode + { + public TypePredicateNode() + { + Kind = SyntaxKind.TypePredicate; + } + + public Node ParameterName { get; set; } // Identifier | ThisTypeNode + public ITypeNode Type { get; set; } + } + + public class TypeQueryNode : TypeNode + { + public TypeQueryNode() + { + Kind = SyntaxKind.TypeQuery; + } + + public IEntityName ExprName { get; set; } + } + + public class TypeLiteralNode : Node, ITypeNode, IDeclaration + { + public TypeLiteralNode() + { + Kind = SyntaxKind.TypeLiteral; + } + + public NodeArray Members { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class ArrayTypeNode : TypeNode + { + public ArrayTypeNode() + { + Kind = SyntaxKind.ArrayType; + } + + public ITypeNode ElementType { get; set; } + } + + public class TupleTypeNode : TypeNode + { + public TupleTypeNode() + { + Kind = SyntaxKind.TupleType; + } + + public NodeArray ElementTypes { get; set; } + } + + public class UnionTypeNode : TypeNode, IUnionOrIntersectionTypeNode + { + public UnionTypeNode() + { + Kind = SyntaxKind.UnionType; + } + + public NodeArray Types { get; set; } + } + + public class IntersectionTypeNode : TypeNode, IUnionOrIntersectionTypeNode + { + public IntersectionTypeNode() + { + Kind = SyntaxKind.IntersectionType; + } + + public NodeArray Types { get; set; } + } + + public class ParenthesizedTypeNode : TypeNode + { + public ParenthesizedTypeNode() + { + Kind = SyntaxKind.ParenthesizedType; + } + + public ITypeNode Type { get; set; } + } + + public class TypeOperatorNode : ParenthesizedTypeNode + { + public TypeOperatorNode() + { + Kind = SyntaxKind.TypeOperator; + } + + public SyntaxKind Operator { get; set; } = SyntaxKind.KeyOfKeyword; + } + + public class IndexedAccessTypeNode : TypeNode + { + public IndexedAccessTypeNode() + { + Kind = SyntaxKind.IndexedAccessType; + } + + public ITypeNode ObjectType { get; set; } + public ITypeNode IndexType { get; set; } + } + + public class MappedTypeNode : Node, ITypeNode, IDeclaration + { + public MappedTypeNode() + { + Kind = SyntaxKind.MappedType; + } + + public ReadonlyToken ReadonlyToken { get; set; } + public TypeParameterDeclaration TypeParameter { get; set; } + public QuestionToken QuestionToken { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class LiteralTypeNode : TypeNode + { + public LiteralTypeNode() + { + Kind = SyntaxKind.LiteralType; + } + + public IExpression Literal { get; set; } + } + + public class StringLiteral : LiteralExpression, IPropertyName + { + public StringLiteral() + { + Kind = SyntaxKind.StringLiteral; + } + + public Node TextSourceNode { get; set; } // Identifier | StringLiteral | NumericLiteral + } + + public interface IExpression : IBlockOrExpression, IVariableDeclarationListOrExpression + { + object ExpressionBrand { get; set; } + } + + public class Expression : Node, IExpression + { + public object ExpressionBrand { get; set; } + } + + public class OmittedExpression : Expression, IArrayBindingElement + { + public OmittedExpression() + { + Kind = SyntaxKind.OmittedExpression; + } + } + + public class PartiallyEmittedExpression : LeftHandSideExpression + { + public PartiallyEmittedExpression() + { + Kind = SyntaxKind.PartiallyEmittedExpression; + } + + public IExpression Expression { get; set; } + } + + public interface IUnaryExpression : IExpression + { + object UnaryExpressionBrand { get; set; } + } + + public class UnaryExpression : Expression, IUnaryExpression + { + public object UnaryExpressionBrand { get; set; } + } + + public interface IIncrementExpression : IUnaryExpression + { + object IncrementExpressionBrand { get; set; } + } + + public class IncrementExpression : UnaryExpression, IIncrementExpression + { + public object IncrementExpressionBrand { get; set; } + } + + public class PrefixUnaryExpression : IncrementExpression + { + public PrefixUnaryExpression() + { + Kind = SyntaxKind.PrefixUnaryExpression; + } + + public /*PrefixUnaryOperator*/SyntaxKind Operator { get; set; } + public /*UnaryExpression*/IExpression Operand { get; set; } + } + + public class PostfixUnaryExpression : IncrementExpression + { + public PostfixUnaryExpression() + { + Kind = SyntaxKind.PostfixUnaryExpression; + } + + public /*LeftHandSideExpression*/IExpression Operand { get; set; } + public /*PostfixUnaryOperator*/SyntaxKind Operator { get; set; } + } + + public interface ILeftHandSideExpression : IIncrementExpression + { + object LeftHandSideExpressionBrand { get; set; } + } + + public class LeftHandSideExpression : IncrementExpression, ILeftHandSideExpression + { + public object LeftHandSideExpressionBrand { get; set; } + } + + public interface IMemberExpression : ILeftHandSideExpression + { + object MemberExpressionBrand { get; set; } + } + + public class MemberExpression : LeftHandSideExpression, IMemberExpression + { + public object MemberExpressionBrand { get; set; } + } + + public interface IPrimaryExpression : IMemberExpression + { + object PrimaryExpressionBrand { get; set; } + } + + public class PrimaryExpression : MemberExpression, IPrimaryExpression, IJsxTagNameExpression + { + public object PrimaryExpressionBrand { get; set; } + } + + public class NullLiteral : Node, IPrimaryExpression, ITypeNode + { + public NullLiteral() + { + Kind = SyntaxKind.NullKeyword; + } + + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class BooleanLiteral : Node, IPrimaryExpression, ITypeNode + { + public BooleanLiteral() + { + Kind = SyntaxKind.BooleanKeyword; + } + + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + public object TypeNodeBrand { get; set; } + } + + public class ThisExpression : Node, IPrimaryExpression, IKeywordTypeNode + { + public ThisExpression() + { + Kind = SyntaxKind.ThisKeyword; + } + + public object TypeNodeBrand { get; set; } + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + } + + public class SuperExpression : PrimaryExpression + { + public SuperExpression() + { + Kind = SyntaxKind.SuperKeyword; + } + } + + public class DeleteExpression : UnaryExpression + { + public DeleteExpression() + { + Kind = SyntaxKind.DeleteExpression; + } + + public /*UnaryExpression*/IExpression Expression { get; set; } + } + + public class TypeOfExpression : UnaryExpression + { + public TypeOfExpression() + { + Kind = SyntaxKind.TypeOfExpression; + } + + public /*UnaryExpression*/IExpression Expression { get; set; } + } + + public class VoidExpression : UnaryExpression + { + public VoidExpression() + { + Kind = SyntaxKind.VoidExpression; + } + + public /*UnaryExpression*/IExpression Expression { get; set; } + } + + public class AwaitExpression : UnaryExpression + { + public AwaitExpression() + { + Kind = SyntaxKind.AwaitExpression; + } + + public /*UnaryExpression*/IExpression Expression { get; set; } + } + + public class YieldExpression : Expression + { + public YieldExpression() + { + Kind = SyntaxKind.YieldExpression; + } + + public AsteriskToken AsteriskToken { get; set; } + public IExpression Expression { get; set; } + } + + public class BinaryExpression : Node, IExpression, IDeclaration + { + public BinaryExpression() + { + Kind = SyntaxKind.BinaryExpression; + } + + public IExpression Left { get; set; } + public /*BinaryOperator*/Token OperatorToken { get; set; } + public IExpression Right { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object ExpressionBrand { get; set; } + } + + public class AssignmentExpression : BinaryExpression + { + } + + public class ObjectDestructuringAssignment : AssignmentExpression + { + } + + public class ArrayDestructuringAssignment : AssignmentExpression + { + } + + public class ConditionalExpression : Expression + { + public ConditionalExpression() + { + Kind = SyntaxKind.ConditionalExpression; + } + + public IExpression Condition { get; set; } + public QuestionToken QuestionToken { get; set; } + public IExpression WhenTrue { get; set; } + public ColonToken ColonToken { get; set; } + public IExpression WhenFalse { get; set; } + } + + public class FunctionExpression : Node, IPrimaryExpression, IFunctionLikeDeclaration + { + public FunctionExpression() + { + Kind = SyntaxKind.FunctionExpression; + } + + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + } + + public interface IBlockOrExpression : INode + { + } + + public class ArrowFunction : Node, IExpression, IFunctionLikeDeclaration + { + public ArrowFunction() + { + Kind = SyntaxKind.ArrowFunction; + } + + public EqualsGreaterThanToken EqualsGreaterThanToken { get; set; } + public object ExpressionBrand { get; set; } + public object FunctionLikeDeclarationBrand { get; set; } + public AsteriskToken AsteriskToken { get; set; } + public QuestionToken QuestionToken { get; set; } + public IBlockOrExpression Body { get; set; } // Block | Expression + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + } + + public interface ILiteralLikeNode : INode + { + string Text { get; set; } + bool IsUnterminated { get; set; } + bool HasExtendedUnicodeEscape { get; set; } + bool IsOctalLiteral { get; set; } + } + + public class LiteralLikeNode : Node, ILiteralLikeNode + { + public string Text { get; set; } + public bool IsUnterminated { get; set; } + public bool HasExtendedUnicodeEscape { get; set; } + public bool IsOctalLiteral { get; set; } + } + + public interface ILiteralExpression : ILiteralLikeNode, IPrimaryExpression + { + object LiteralExpressionBrand { get; set; } + } + + public class LiteralExpression : Node, ILiteralExpression, IPrimaryExpression + { + public object LiteralExpressionBrand { get; set; } + public string Text { get; set; } + public bool IsUnterminated { get; set; } + public bool HasExtendedUnicodeEscape { get; set; } + public bool IsOctalLiteral { get; set; } + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + + public object ExpressionBrand { get; set; } + //} + + // }; + // text = literalLikeNode.text, + // { + // return new LiteralExpression + // throw new NotImplementedException(); + //{ + + //internal static LiteralExpression Make(LiteralLikeNode literalLikeNode) + } + + public class RegularExpressionLiteral : LiteralExpression + { + public RegularExpressionLiteral() + { + Kind = SyntaxKind.RegularExpressionLiteral; + } + } + + public class NoSubstitutionTemplateLiteral : LiteralExpression + { + public NoSubstitutionTemplateLiteral() + { + Kind = SyntaxKind.NoSubstitutionTemplateLiteral; + } + } + + public class NumericLiteral : LiteralExpression, IPropertyName + { + public NumericLiteral() + { + Kind = SyntaxKind.NumericLiteral; + } + } + + public class TemplateHead : LiteralLikeNode + { + public TemplateHead() + { + Kind = SyntaxKind.TemplateHead; + } + } + + public class TemplateMiddle : LiteralLikeNode + { + public TemplateMiddle() + { + Kind = SyntaxKind.TemplateMiddle; + } + } + + public class TemplateTail : LiteralLikeNode + { + public TemplateTail() + { + Kind = SyntaxKind.TemplateTail; + } + } + + public class TemplateExpression : PrimaryExpression + { + public TemplateExpression() + { + Kind = SyntaxKind.TemplateExpression; + } + + public TemplateHead Head { get; set; } + public NodeArray TemplateSpans { get; set; } + } + + public class TemplateSpan : Node + { + public TemplateSpan() + { + Kind = SyntaxKind.TemplateSpan; + } + + public IExpression Expression { get; set; } + public ILiteralLikeNode Literal { get; set; } // TemplateMiddle | TemplateTail + } + + public class ParenthesizedExpression : PrimaryExpression + { + public ParenthesizedExpression() + { + Kind = SyntaxKind.ParenthesizedExpression; + } + + public IExpression Expression { get; set; } + } + + public class ArrayLiteralExpression : PrimaryExpression + { + public ArrayLiteralExpression() + { + Kind = SyntaxKind.ArrayLiteralExpression; + } + + public NodeArray Elements { get; set; } + public bool MultiLine { get; set; } + } + + public class SpreadElement : Expression + { + public SpreadElement() + { + Kind = SyntaxKind.SpreadElement; + } + + public IExpression Expression { get; set; } + } + + public class ObjectLiteralExpressionBase : Node, IPrimaryExpression, IDeclaration + { + public NodeArray Properties { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + } + + public class ObjectLiteralExpression : ObjectLiteralExpressionBase + { + public ObjectLiteralExpression() + { + Kind = SyntaxKind.ObjectLiteralExpression; + } + + public bool MultiLine { get; set; } + } + + public class PropertyAccessExpression : Node, IMemberExpression, IDeclaration, IJsxTagNameExpression + { + public PropertyAccessExpression() + { + Kind = SyntaxKind.PropertyAccessExpression; + } + + public IExpression Expression { get; set; } //LeftHandSideExpression + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + } + + public class SuperPropertyAccessExpression : PropertyAccessExpression + { + } + + public class PropertyAccessEntityNameExpression : PropertyAccessExpression + { + public object PropertyAccessExpressionLikeQualifiedNameBrand { get; set; } + } + + public class ElementAccessExpression : MemberExpression + { + public ElementAccessExpression() + { + Kind = SyntaxKind.ElementAccessExpression; + } + + public IExpression Expression { get; set; } //LeftHandSideExpression + public IExpression ArgumentExpression { get; set; } + } + + public class SuperElementAccessExpression : ElementAccessExpression + { + } + + public class CallExpression : Node, IMemberExpression, IDeclaration + { + public CallExpression() + { + Kind = SyntaxKind.CallExpression; + } + + public /*LeftHandSideExpression*/IExpression Expression { get; set; } + public NodeArray TypeArguments { get; set; } + public NodeArray Arguments { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + } + + public class SuperCall : CallExpression + { + } + + public class ExpressionWithTypeArguments : TypeNode + { + public ExpressionWithTypeArguments() + { + Kind = SyntaxKind.ExpressionWithTypeArguments; + } + + public /*LeftHandSideExpression*/IExpression Expression { get; set; } + public NodeArray TypeArguments { get; set; } + } + + public class NewExpression : CallExpression, IPrimaryExpression, IDeclaration + { + public NewExpression() + { + Kind = SyntaxKind.NewExpression; + } + + public object PrimaryExpressionBrand { get; set; } + } + + public class TaggedTemplateExpression : MemberExpression + { + public TaggedTemplateExpression() + { + Kind = SyntaxKind.TaggedTemplateExpression; + } + + public IExpression Tag { get; set; } //LeftHandSideExpression + public Node Template { get; set; } //TemplateLiteral + } + + public class AsExpression : Expression + { + public AsExpression() + { + Kind = SyntaxKind.AsExpression; + } + + public IExpression Expression { get; set; } + public ITypeNode Type { get; set; } + } + + public class TypeAssertion : UnaryExpression + { + public TypeAssertion() + { + Kind = SyntaxKind.TypeAssertionExpression; + } + + public ITypeNode Type { get; set; } + public /*UnaryExpression*/IExpression Expression { get; set; } + } + + public class NonNullExpression : /*LeftHandSideExpression*/MemberExpression + { + public NonNullExpression() + { + Kind = SyntaxKind.NonNullExpression; + } + + public IExpression Expression { get; set; } + } + + public class MetaProperty : PrimaryExpression + { + public MetaProperty() + { + Kind = SyntaxKind.MetaProperty; + } + + public SyntaxKind KeywordToken { get; set; } + public Identifier Name { get; set; } + } + + public class JsxElement : PrimaryExpression, IJsxChild + { + public JsxElement() + { + Kind = SyntaxKind.JsxElement; + } + + public /*JsxOpeningElement*/IExpression OpeningElement { get; set; } + public NodeArray JsxChildren { get; set; } + public JsxClosingElement ClosingElement { get; set; } + } + + public class JsxAttributes : ObjectLiteralExpressionBase // JsxAttributeLike> + { + public JsxAttributes() + { + Kind = SyntaxKind.JsxAttributes; + } + } + + public class JsxOpeningElement : JsxSelfClosingElement + { + public JsxOpeningElement() + { + Kind = SyntaxKind.JsxOpeningElement; + } + } + + public class JsxSelfClosingElement : PrimaryExpression, IJsxChild + { + public JsxSelfClosingElement() + { + Kind = SyntaxKind.JsxSelfClosingElement; + } + + public IJsxTagNameExpression TagName { get; set; } + public JsxAttributes Attributes { get; set; } + } + + public class JsxAttribute : ObjectLiteralElement + { + public JsxAttribute() + { + Kind = SyntaxKind.JsxAttribute; + } + + public Node Initializer { get; set; } // StringLiteral | JsxExpression + } + + public class JsxSpreadAttribute : ObjectLiteralElement + { + public JsxSpreadAttribute() + { + Kind = SyntaxKind.JsxSpreadAttribute; + } + + public IExpression Expression { get; set; } + } + + public class JsxClosingElement : Node + { + public JsxClosingElement() + { + Kind = SyntaxKind.JsxClosingElement; + } + + public IJsxTagNameExpression TagName { get; set; } + } + + public class JsxExpression : Expression, IJsxChild + { + public JsxExpression() + { + Kind = SyntaxKind.JsxExpression; + } + + public Token DotDotDotToken { get; set; } // Token + public IExpression Expression { get; set; } + } + + public class JsxText : Node, IJsxChild + { + public JsxText() + { + Kind = SyntaxKind.JsxText; + } + } + + public interface IStatement : INode + { + object StatementBrand { get; set; } + } + + public class Statement : Node, IStatement + { + public object StatementBrand { get; set; } + } + + public class NotEmittedStatement : Statement + { + public NotEmittedStatement() + { + Kind = SyntaxKind.NotEmittedStatement; + } + } + + public class EndOfDeclarationMarker : Statement + { + public EndOfDeclarationMarker() + { + Kind = SyntaxKind.EndOfDeclarationMarker; + } + } + + public class MergeDeclarationMarker : Statement + { + public MergeDeclarationMarker() + { + Kind = SyntaxKind.MergeDeclarationMarker; + } + } + + public class EmptyStatement : Statement + { + public EmptyStatement() + { + Kind = SyntaxKind.EmptyStatement; + } + } + + public class DebuggerStatement : Statement + { + public DebuggerStatement() + { + Kind = SyntaxKind.DebuggerStatement; + } + } + + public class MissingDeclaration : Node, IDeclarationStatement, IClassElement, IObjectLiteralElement, ITypeElement + { + public MissingDeclaration() + { + Kind = SyntaxKind.MissingDeclaration; + } + + public object ClassElementBrand { get; set; } + public INode Name { get; set; } + public object DeclarationBrand { get; set; } + public object StatementBrand { get; set; } + public object ObjectLiteralBrandBrand { get; set; } + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public class Block : Statement, IBlockOrExpression + { + public Block() + { + Kind = SyntaxKind.Block; + } + + public NodeArray Statements { get; set; } + public bool MultiLine { get; set; } + } + + public class VariableStatement : Statement + { + public VariableStatement() + { + Kind = SyntaxKind.VariableStatement; + } + + public IVariableDeclarationList DeclarationList { get; set; } + } + + public class ExpressionStatement : Statement + { + public ExpressionStatement() + { + Kind = SyntaxKind.ExpressionStatement; + } + + public IExpression Expression { get; set; } + } + + public class PrologueDirective : ExpressionStatement + { + } + + public class IfStatement : Statement + { + public IfStatement() + { + Kind = SyntaxKind.IfStatement; + } + + public IExpression Expression { get; set; } + public IStatement ThenStatement { get; set; } + public IStatement ElseStatement { get; set; } + } + + public class IterationStatement : Statement + { + public IStatement Statement { get; set; } + } + + public class DoStatement : IterationStatement + { + public DoStatement() + { + Kind = SyntaxKind.DoStatement; + } + + public IExpression Expression { get; set; } + } + + public class WhileStatement : IterationStatement + { + public WhileStatement() + { + Kind = SyntaxKind.WhileStatement; + } + + public IExpression Expression { get; set; } + } + + public class ForStatement : IterationStatement + { + public ForStatement() + { + Kind = SyntaxKind.ForStatement; + } + + public /*ForInitializer*/IVariableDeclarationListOrExpression Initializer { get; set; } + public IExpression Condition { get; set; } + public IExpression Incrementor { get; set; } + } + + public class ForInStatement : IterationStatement + { + public ForInStatement() + { + Kind = SyntaxKind.ForInStatement; + } + + public /*ForInitializer*/IVariableDeclarationListOrExpression Initializer { get; set; } + public IExpression Expression { get; set; } + } + + public class ForOfStatement : IterationStatement + { + public ForOfStatement() + { + Kind = SyntaxKind.ForOfStatement; + } + + public AwaitKeywordToken AwaitModifier { get; set; } + public /*ForInitializer*/IVariableDeclarationListOrExpression Initializer { get; set; } + public IExpression Expression { get; set; } + } + + public class BreakStatement : Statement, IBreakOrContinueStatement + { + public BreakStatement() + { + Kind = SyntaxKind.BreakStatement; + } + + public Identifier Label { get; set; } + } + + public class ContinueStatement : Statement, IBreakOrContinueStatement + { + public ContinueStatement() + { + Kind = SyntaxKind.ContinueStatement; + } + + public Identifier Label { get; set; } + } + + public class ReturnStatement : Statement + { + public ReturnStatement() + { + Kind = SyntaxKind.ReturnStatement; + } + + public IExpression Expression { get; set; } + } + + public class WithStatement : Statement + { + public WithStatement() + { + Kind = SyntaxKind.WithStatement; + } + + public IExpression Expression { get; set; } + public IStatement Statement { get; set; } + } + + public class SwitchStatement : Statement + { + public SwitchStatement() + { + Kind = SyntaxKind.SwitchStatement; + } + + public IExpression Expression { get; set; } + public CaseBlock CaseBlock { get; set; } + public bool PossiblyExhaustive { get; set; } + } + + public class CaseBlock : Node + { + public CaseBlock() + { + Kind = SyntaxKind.CaseBlock; + } + + public NodeArray Clauses { get; set; } + } + + public class CaseClause : Node, ICaseOrDefaultClause + { + public CaseClause() + { + Kind = SyntaxKind.CaseClause; + } + + public IExpression Expression { get; set; } + public NodeArray Statements { get; set; } + } + + public class DefaultClause : Node, ICaseOrDefaultClause + { + public DefaultClause() + { + Kind = SyntaxKind.DefaultClause; + } + + public NodeArray Statements { get; set; } + } + + public class LabeledStatement : Statement + { + public LabeledStatement() + { + Kind = SyntaxKind.LabeledStatement; + } + + public Identifier Label { get; set; } + public IStatement Statement { get; set; } + } + + public class ThrowStatement : Statement + { + public ThrowStatement() + { + Kind = SyntaxKind.ThrowStatement; + } + + public IExpression Expression { get; set; } + } + + public class TryStatement : Statement + { + public TryStatement() + { + Kind = SyntaxKind.TryStatement; + } + + public Block TryBlock { get; set; } + public CatchClause CatchClause { get; set; } + public Block FinallyBlock { get; set; } + } + + public class CatchClause : Node + { + public CatchClause() + { + Kind = SyntaxKind.CatchClause; + } + + public VariableDeclaration VariableDeclaration { get; set; } + public Block Block { get; set; } + } + + public interface IClassLikeDeclaration : IDeclaration + { + NodeArray TypeParameters { get; set; } + NodeArray HeritageClauses { get; set; } + NodeArray Members { get; set; } + } + + public class ClassLikeDeclaration : Declaration, IClassLikeDeclaration + { + public NodeArray TypeParameters { get; set; } + public NodeArray HeritageClauses { get; set; } + public NodeArray Members { get; set; } + } + + public class ClassDeclaration : Node, IClassLikeDeclaration, IDeclarationStatement + { + public ClassDeclaration() + { + Kind = SyntaxKind.ClassDeclaration; + } + + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray HeritageClauses { get; set; } + public NodeArray Members { get; set; } + public object DeclarationBrand { get; set; } + public object StatementBrand { get; set; } + } + + public class ClassExpression : Node, IClassLikeDeclaration, IPrimaryExpression + { + public ClassExpression() + { + Kind = SyntaxKind.ClassExpression; + } + + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray HeritageClauses { get; set; } + public NodeArray Members { get; set; } + public object DeclarationBrand { get; set; } + public object PrimaryExpressionBrand { get; set; } + public object MemberExpressionBrand { get; set; } + public object LeftHandSideExpressionBrand { get; set; } + public object IncrementExpressionBrand { get; set; } + public object UnaryExpressionBrand { get; set; } + public object ExpressionBrand { get; set; } + } + + public interface IClassElement : IDeclaration + { + object ClassElementBrand { get; set; } + } + + public class ClassElement : Declaration, IClassElement + { + public object ClassElementBrand { get; set; } + } + + public interface ITypeElement : IDeclaration + { + object TypeElementBrand { get; set; } + QuestionToken QuestionToken { get; set; } + } + + public class TypeElement : Declaration, ITypeElement + { + public object TypeElementBrand { get; set; } + public QuestionToken QuestionToken { get; set; } + } + + public class InterfaceDeclaration : DeclarationStatement + { + public InterfaceDeclaration() + { + Kind = SyntaxKind.InterfaceDeclaration; + } + + public NodeArray TypeParameters { get; set; } + public NodeArray HeritageClauses { get; set; } + public NodeArray Members { get; set; } + } + + public class HeritageClause : Node + { + public HeritageClause() + { + Kind = SyntaxKind.HeritageClause; + } + + public SyntaxKind Token { get; set; } // SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword + public NodeArray Types { get; set; } + } + + public class TypeAliasDeclaration : DeclarationStatement + { + public TypeAliasDeclaration() + { + Kind = SyntaxKind.TypeAliasDeclaration; + } + + public NodeArray TypeParameters { get; set; } + public ITypeNode Type { get; set; } + } + + public class EnumMember : Declaration + { + public EnumMember() + { + Kind = SyntaxKind.EnumMember; + } + + public IExpression Initializer { get; set; } + } + + public class EnumDeclaration : DeclarationStatement + { + public EnumDeclaration() + { + Kind = SyntaxKind.EnumDeclaration; + } + + public NodeArray Members { get; set; } + } + + public class ModuleDeclaration : DeclarationStatement + { + public ModuleDeclaration() + { + Kind = SyntaxKind.ModuleDeclaration; + } + + public /*ModuleDeclaration*/INode Body { get; set; } // ModuleBody | JSDocNamespaceDeclaration + } + + public class NamespaceDeclaration : ModuleDeclaration + { + } + + public class JsDocNamespaceDeclaration : ModuleDeclaration + { + } + + public class ModuleBlock : Block + { + public ModuleBlock() + { + Kind = SyntaxKind.ModuleBlock; + } + } + + public class ImportEqualsDeclaration : DeclarationStatement + { + public ImportEqualsDeclaration() + { + Kind = SyntaxKind.ImportEqualsDeclaration; + } + + public /*ModuleReference*/INode ModuleReference { get; set; } + } + + public class ExternalModuleReference : Node + { + public ExternalModuleReference() + { + Kind = SyntaxKind.ExternalModuleReference; + } + + public IExpression Expression { get; set; } + } + + public class ImportDeclaration : Statement + { + public ImportDeclaration() + { + Kind = SyntaxKind.ImportDeclaration; + } + + public ImportClause ImportClause { get; set; } + public IExpression ModuleSpecifier { get; set; } + } + + public class ImportClause : Declaration + { + public ImportClause() + { + Kind = SyntaxKind.ImportClause; + } + + public INamedImportBindings NamedBindings { get; set; } + } + + public class NamespaceImport : Declaration, INamedImportBindings + { + public NamespaceImport() + { + Kind = SyntaxKind.NamespaceImport; + } + } + + public class NamespaceExportDeclaration : DeclarationStatement + { + public NamespaceExportDeclaration() + { + Kind = SyntaxKind.NamespaceExportDeclaration; + } + } + + public class ExportDeclaration : DeclarationStatement + { + public ExportDeclaration() + { + Kind = SyntaxKind.ExportDeclaration; + } + + public NamedExports ExportClause { get; set; } + public IExpression ModuleSpecifier { get; set; } + } + + public class NamedImports : Node, INamedImportsOrExports, INamedImportBindings + { + public NamedImports() + { + Kind = SyntaxKind.NamedImports; + } + + public NodeArray Elements { get; set; } + } + + public class NamedExports : Node, INamedImportsOrExports + { + public NamedExports() + { + Kind = SyntaxKind.NamedExports; + } + + public NodeArray Elements { get; set; } + } + + public class ImportSpecifier : Declaration, IMportOrExportSpecifier + { + public ImportSpecifier() + { + Kind = SyntaxKind.ImportSpecifier; + } + + public Identifier PropertyName { get; set; } + } + + public class ExportSpecifier : Declaration, IMportOrExportSpecifier + { + public ExportSpecifier() + { + Kind = SyntaxKind.ExportSpecifier; + } + + public Identifier PropertyName { get; set; } + } + + public class ExportAssignment : DeclarationStatement + { + public ExportAssignment() + { + Kind = SyntaxKind.ExportAssignment; + } + + public bool IsExportEquals { get; set; } + public IExpression Expression { get; set; } + } + + public class FileReference : TextRange + { + public string FileName { get; set; } + } + + public class CheckJsDirective : TextRange + { + public bool Enabled { get; set; } + } + + public class CommentRange : TextRange + { + public bool HasTrailingNewLine { get; set; } + public CommentKind Kind { get; set; } + } + + public class SynthesizedComment : CommentRange + { + public string Text { get; set; } + } + + public class JsDocTypeExpression : Node + { + public JsDocTypeExpression() + { + Kind = SyntaxKind.JsDocTypeExpression; + } + + public IJsDocType Type { get; set; } + } + + public interface IJsDocType : ITypeNode + { + object JsDocTypeBrand { get; set; } + } + + public class JsDocType : TypeNode, IJsDocType + { + public object JsDocTypeBrand { get; set; } + } + + public class JsDocAllType : JsDocType + { + public JsDocAllType() + { + Kind = SyntaxKind.JsDocAllType; + } + } + + public class JsDocUnknownType : JsDocType + { + public JsDocUnknownType() + { + Kind = SyntaxKind.JsDocUnknownType; + } + } + + public class JsDocArrayType : JsDocType + { + public JsDocArrayType() + { + Kind = SyntaxKind.JsDocArrayType; + } + + public IJsDocType ElementType { get; set; } + } + + public class JsDocUnionType : JsDocType + { + public JsDocUnionType() + { + Kind = SyntaxKind.JsDocUnionType; + } + + public NodeArray Types { get; set; } + } + + public class JsDocTupleType : JsDocType + { + public JsDocTupleType() + { + Kind = SyntaxKind.JsDocTupleType; + } + + public NodeArray Types { get; set; } + } + + public class JsDocNonNullableType : JsDocType + { + public JsDocNonNullableType() + { + Kind = SyntaxKind.JsDocNonNullableType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocNullableType : JsDocType + { + public JsDocNullableType() + { + Kind = SyntaxKind.JsDocNullableType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocRecordType : JsDocType + { + public JsDocRecordType() + { + Kind = SyntaxKind.JsDocRecordType; + } + + public TypeLiteralNode Literal { get; set; } + } + + public class JsDocTypeReference : JsDocType + { + public JsDocTypeReference() + { + Kind = SyntaxKind.JsDocTypeReference; + } + + public IEntityName Name { get; set; } + public NodeArray TypeArguments { get; set; } + } + + public class JsDocOptionalType : JsDocType + { + public JsDocOptionalType() + { + Kind = SyntaxKind.JsDocOptionalType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocFunctionType : Node, IJsDocType, ISignatureDeclaration + { + public JsDocFunctionType() + { + Kind = SyntaxKind.JsDocFunctionType; + } + + public object JsDocTypeBrand { get; set; } + public object TypeNodeBrand { get; set; } + public INode Name { get; set; } + public NodeArray TypeParameters { get; set; } + public NodeArray Parameters { get; set; } + public ITypeNode Type { get; set; } + public object DeclarationBrand { get; set; } + } + + public class JsDocVariadicType : JsDocType + { + public JsDocVariadicType() + { + Kind = SyntaxKind.JsDocVariadicType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocConstructorType : JsDocType + { + public JsDocConstructorType() + { + Kind = SyntaxKind.JsDocConstructorType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocThisType : JsDocType + { + public JsDocThisType() + { + Kind = SyntaxKind.JsDocThisType; + } + + public IJsDocType Type { get; set; } + } + + public class JsDocLiteralType : JsDocType + { + public JsDocLiteralType() + { + Kind = SyntaxKind.JsDocLiteralType; + } + + public LiteralTypeNode Literal { get; set; } + } + + public class JsDocRecordMember : PropertySignature + { + public JsDocRecordMember() + { + Kind = SyntaxKind.JsDocRecordMember; + } + } + + public class JsDoc : Node + { + public NodeArray Tags { get; set; } + public string Comment { get; set; } + } + + public interface IJsDocTag : INode + { + AtToken AtToken { get; set; } + Identifier TagName { get; set; } + string Comment { get; set; } + } + + public class JsDocTag : Node, IJsDocTag + { + public JsDocTag() + { + Kind = SyntaxKind.JsDocTag; + } + + public AtToken AtToken { get; set; } + public Identifier TagName { get; set; } + public string Comment { get; set; } + } + + public class JsDocUnknownTag : JsDocTag + { + } + + public class JsDocAugmentsTag : JsDocTag + { + public JsDocAugmentsTag() + { + Kind = SyntaxKind.JsDocAugmentsTag; + } + + public JsDocTypeExpression TypeExpression { get; set; } + } + + public class JsDocTemplateTag : JsDocTag + { + public JsDocTemplateTag() + { + Kind = SyntaxKind.JsDocTemplateTag; + } + + public NodeArray TypeParameters { get; set; } + } + + public class JsDocReturnTag : JsDocTag + { + public JsDocReturnTag() + { + Kind = SyntaxKind.JsDocReturnTag; + } + + public JsDocTypeExpression TypeExpression { get; set; } + } + + public class JsDocTypeTag : JsDocTag + { + public JsDocTypeTag() + { + Kind = SyntaxKind.JsDocTypeTag; + } + + public JsDocTypeExpression TypeExpression { get; set; } + } + + public class JsDocTypedefTag : Node, IJsDocTag, IDeclaration + { + public JsDocTypedefTag() + { + Kind = SyntaxKind.JsDocTypedefTag; + } + + public INode FullName { get; set; } // JSDocNamespaceDeclaration | Identifier + public JsDocTypeExpression TypeExpression { get; set; } + public JsDocTypeLiteral JsDocTypeLiteral { get; set; } + public object DeclarationBrand { get; set; } + public INode Name { get; set; } + public AtToken AtToken { get; set; } + public Identifier TagName { get; set; } + public string Comment { get; set; } + } + + public class JsDocPropertyTag : Node, IJsDocTag, ITypeElement + { + public JsDocPropertyTag() + { + Kind = SyntaxKind.JsDocPropertyTag; + } + + public JsDocTypeExpression TypeExpression { get; set; } + public AtToken AtToken { get; set; } + public Identifier TagName { get; set; } + public string Comment { get; set; } + public object TypeElementBrand { get; set; } + public INode Name { get; set; } + public QuestionToken QuestionToken { get; set; } + public object DeclarationBrand { get; set; } + } + + public class JsDocTypeLiteral : JsDocType + { + public JsDocTypeLiteral() + { + Kind = SyntaxKind.JsDocTypeLiteral; + } + + public NodeArray JsDocPropertyTags { get; set; } + public JsDocTypeTag JsDocTypeTag { get; set; } + } + + public class JsDocParameterTag : JsDocTag + { + public JsDocParameterTag() + { + Kind = SyntaxKind.JsDocParameterTag; + } + + public Identifier PreParameterName { get; set; } + public JsDocTypeExpression TypeExpression { get; set; } + public Identifier PostParameterName { get; set; } + public Identifier ParameterName { get; set; } + public bool IsBracketed { get; set; } + } + + public interface IFlowLock + { + bool Locked { get; set; } + } + + public class FlowLock : IFlowLock + { + public bool Locked { get; set; } + } + + public class AfterFinallyFlow : IFlowNode, IFlowLock + { + public FlowNode Antecedent { get; set; } + public bool Locked { get; set; } + public FlowFlags Flags { get; set; } + public int Id { get; set; } + } + + public class PreFinallyFlow : FlowNode + { + public FlowNode Antecedent { get; set; } + public FlowLock Lock { get; set; } + } + + public interface IFlowNode + { + FlowFlags Flags { get; set; } + int Id { get; set; } + } + + public class FlowNode : IFlowNode + { + public FlowFlags Flags { get; set; } + public int Id { get; set; } + } + + public class FlowStart : FlowNode + { + public Node Container { get; set; } // FunctionExpression | ArrowFunction | MethodDeclaration + } + + public class FlowLabel : FlowNode + { + public FlowNode[] Antecedents { get; set; } + } + + public class FlowAssignment : FlowNode + { + public Node Node { get; set; } // Expression | VariableDeclaration | BindingElement + public FlowNode Antecedent { get; set; } + } + + public class FlowCondition : FlowNode + { + public IExpression Expression { get; set; } + public FlowNode Antecedent { get; set; } + } + + public class FlowSwitchClause : FlowNode + { + public SwitchStatement SwitchStatement { get; set; } + public int ClauseStart { get; set; } + public int ClauseEnd { get; set; } + public FlowNode Antecedent { get; set; } + } + + public class FlowArrayMutation : FlowNode + { + public Node Node { get; set; } // CallExpression | BinaryExpression + public FlowNode Antecedent { get; set; } + } + + public class IncompleteType + { + public TypeFlags Flags { get; set; } + public Type Type { get; set; } + } + + public class AmdDependency + { + public string Path { get; set; } + public string Name { get; set; } + } + + public interface ISourceFileLike + { + string Text { get; set; } + int[] LineMap { get; set; } + } + + public class SourceFile : Declaration, ISourceFileLike + { + public SourceFile() + { + Kind = SyntaxKind.SourceFile; + } + + public NodeArray Statements { get; set; } + public Token EndOfFileToken { get; set; } // Token + public string FileName { get; set; } + public AmdDependency[] AmdDependencies { get; set; } + public string ModuleName { get; set; } + public FileReference[] ReferencedFiles { get; set; } + public FileReference[] TypeReferenceDirectives { get; set; } + public LanguageVariant LanguageVariant { get; set; } + public bool IsDeclarationFile { get; set; } + public Map RenamedDependencies { get; set; } + public bool HasNoDefaultLib { get; set; } + public ScriptTarget LanguageVersion { get; set; } + public ScriptKind ScriptKind { get; set; } + public INode ExternalModuleIndicator { get; set; } + public Node CommonJsModuleIndicator { get; set; } + public List Identifiers { get; set; } + public int NodeCount { get; set; } + public int IdentifierCount { get; set; } + public int SymbolCount { get; set; } + public List ParseDiagnostics { get; set; } + public List AdditionalSyntacticDiagnostics { get; set; } + public List BindDiagnostics { get; set; } + public Map ClassifiableNames { get; set; } + public Map ResolvedModules { get; set; } + public Map ResolvedTypeReferenceDirectiveNames { get; set; } + public LiteralExpression[] Imports { get; set; } + public LiteralExpression[] ModuleAugmentations { get; set; } + public PatternAmbientModule[] PatternAmbientModules { get; set; } + public string[] AmbientModuleNames { get; set; } + public TextRange CheckJsDirective { get; set; } // CheckJsDirective + public string Text { get; set; } + public int[] LineMap { get; set; } + } + + public class Bundle : Node + { + public Bundle() + { + Kind = SyntaxKind.Bundle; + } + + public SourceFile[] SourceFiles { get; set; } + } + + public class ScriptReferenceHost + { + } + + public class ParseConfigHost + { + public bool UseCaseSensitiveFileNames { get; set; } + } + + public class WriteFileCallback + { + } + + public class CancellationToken + { + } + + public class Program : ScriptReferenceHost + { + public bool StructureIsReused { get; set; } + } + + public class CustomTransformers + { + public TransformerFactory[] Before { get; set; } + public TransformerFactory[] After { get; set; } + } + + public class SourceMapSpan + { + public int EmittedLine { get; set; } + public int EmittedColumn { get; set; } + public int SourceLine { get; set; } + public int SourceColumn { get; set; } + public int NameIndex { get; set; } + public int SourceIndex { get; set; } + } + + public class SourceMapData + { + public string SourceMapFilePath { get; set; } + public string JsSourceMappingUrl { get; set; } + public string SourceMapFile { get; set; } + public string SourceMapSourceRoot { get; set; } + public string[] SourceMapSources { get; set; } + public string[] SourceMapSourcesContent { get; set; } + public string[] InputSourceFileNames { get; set; } + public string[] SourceMapNames { get; set; } + public string SourceMapMappings { get; set; } + public SourceMapSpan[] SourceMapDecodedMappings { get; set; } + } + + public class EmitResult + { + public bool EmitSkipped { get; set; } + public Diagnostic[] Diagnostics { get; set; } + public string[] EmittedFiles { get; set; } + public SourceMapData[] SourceMaps { get; set; } + } + + public class TypeCheckerHost + { + } + + public class TypeChecker + { + } + + public class SymbolDisplayBuilder + { + } + + public class SymbolWriter + { + } + + public class TypePredicateBase + { + public TypePredicateKind Kind { get; set; } + public Type Type { get; set; } + } + + public class ThisTypePredicate : TypePredicateBase + { + public ThisTypePredicate() + { + Kind = TypePredicateKind.This; + } + } + + public class IdentifierTypePredicate : TypePredicateBase + { + public IdentifierTypePredicate() + { + Kind = TypePredicateKind.Identifier; + } + + public string ParameterName { get; set; } + public int ParameterIndex { get; set; } + } + + public class SymbolVisibilityResult + { + public SymbolAccessibility Accessibility { get; set; } + public IAnyImportSyntax[] AliasesToMakeVisible { get; set; } + public string ErrorSymbolName { get; set; } + public Node ErrorNode { get; set; } + } + + public class SymbolAccessibilityResult : SymbolVisibilityResult + { + public string ErrorModuleName { get; set; } + } + + public class EmitResolver + { + } + + public interface ISymbol + { + SymbolFlags Flags { get; set; } + string Name { get; set; } + Declaration[] Declarations { get; set; } + Declaration ValueDeclaration { get; set; } + SymbolTable Members { get; set; } + SymbolTable Exports { get; set; } + SymbolTable GlobalExports { get; set; } + int Id { get; set; } + int MergeId { get; set; } + Symbol Parent { get; set; } + Symbol ExportSymbol { get; set; } + bool ConstEnumOnlyModule { get; set; } + bool IsReferenced { get; set; } + bool IsReplaceableByMethod { get; set; } + bool IsAssigned { get; set; } + } + + public class Symbol : ISymbol + { + public SymbolFlags Flags { get; set; } + public string Name { get; set; } + public Declaration[] Declarations { get; set; } + public Declaration ValueDeclaration { get; set; } + public SymbolTable Members { get; set; } + public SymbolTable Exports { get; set; } + public SymbolTable GlobalExports { get; set; } + public int Id { get; set; } + public int MergeId { get; set; } + public Symbol Parent { get; set; } + public Symbol ExportSymbol { get; set; } + public bool ConstEnumOnlyModule { get; set; } + public bool IsReferenced { get; set; } + public bool IsReplaceableByMethod { get; set; } + public bool IsAssigned { get; set; } + } + + public interface ISymbolLinks + { + Symbol Target { get; set; } + Type Type { get; set; } + Type DeclaredType { get; set; } + TypeParameter[] TypeParameters { get; set; } + Type InferredClassType { get; set; } + Map Instantiations { get; set; } + TypeMapper Mapper { get; set; } + bool Referenced { get; set; } + UnionOrIntersectionType ContainingType { get; set; } + Symbol LeftSpread { get; set; } + Symbol RightSpread { get; set; } + Symbol MappedTypeOrigin { get; set; } + bool IsDiscriminantProperty { get; set; } + SymbolTable ResolvedExports { get; set; } + bool ExportsChecked { get; set; } + bool TypeParametersChecked { get; set; } + bool IsDeclarationWithCollidingName { get; set; } + BindingElement BindingElement { get; set; } + bool ExportsSomeValue { get; set; } + } + + public class SymbolLinks : ISymbolLinks + { + public Symbol Target { get; set; } + public Type Type { get; set; } + public Type DeclaredType { get; set; } + public TypeParameter[] TypeParameters { get; set; } + public Type InferredClassType { get; set; } + public Map Instantiations { get; set; } + public TypeMapper Mapper { get; set; } + public bool Referenced { get; set; } + public UnionOrIntersectionType ContainingType { get; set; } + public Symbol LeftSpread { get; set; } + public Symbol RightSpread { get; set; } + public Symbol MappedTypeOrigin { get; set; } + public bool IsDiscriminantProperty { get; set; } + public SymbolTable ResolvedExports { get; set; } + public bool ExportsChecked { get; set; } + public bool TypeParametersChecked { get; set; } + public bool IsDeclarationWithCollidingName { get; set; } + public BindingElement BindingElement { get; set; } + public bool ExportsSomeValue { get; set; } + } + + public class TransientSymbol : ISymbol, ISymbolLinks + { + public CheckFlags CheckFlags { get; set; } + public SymbolFlags Flags { get; set; } + public string Name { get; set; } + public Declaration[] Declarations { get; set; } + public Declaration ValueDeclaration { get; set; } + public SymbolTable Members { get; set; } + public SymbolTable Exports { get; set; } + public SymbolTable GlobalExports { get; set; } + public int Id { get; set; } + public int MergeId { get; set; } + public Symbol Parent { get; set; } + public Symbol ExportSymbol { get; set; } + public bool ConstEnumOnlyModule { get; set; } + public bool IsReferenced { get; set; } + public bool IsReplaceableByMethod { get; set; } + public bool IsAssigned { get; set; } + public Symbol Target { get; set; } + public Type Type { get; set; } + public Type DeclaredType { get; set; } + public TypeParameter[] TypeParameters { get; set; } + public Type InferredClassType { get; set; } + public Map Instantiations { get; set; } + public TypeMapper Mapper { get; set; } + public bool Referenced { get; set; } + public UnionOrIntersectionType ContainingType { get; set; } + public Symbol LeftSpread { get; set; } + public Symbol RightSpread { get; set; } + public Symbol MappedTypeOrigin { get; set; } + public bool IsDiscriminantProperty { get; set; } + public SymbolTable ResolvedExports { get; set; } + public bool ExportsChecked { get; set; } + public bool TypeParametersChecked { get; set; } + public bool IsDeclarationWithCollidingName { get; set; } + public BindingElement BindingElement { get; set; } + public bool ExportsSomeValue { get; set; } + } + + public class Pattern + { + public string Prefix { get; set; } + public string Suffix { get; set; } + } + + public class PatternAmbientModule + { + public Pattern Pattern { get; set; } + public Symbol Symbol { get; set; } + } + + public class NodeLinks + { + public NodeCheckFlags Flags { get; set; } + public Type ResolvedType { get; set; } + public Signature ResolvedSignature { get; set; } + public Symbol ResolvedSymbol { get; set; } + public IndexInfo ResolvedIndexInfo { get; set; } + public bool MaybeTypePredicate { get; set; } + public int EnumMemberValue { get; set; } + public bool IsVisible { get; set; } + public bool HasReportedStatementInAmbientContext { get; set; } + public JsxFlags JsxFlags { get; set; } + public Type ResolvedJsxElementAttributesType { get; set; } + public bool HasSuperCall { get; set; } + public ExpressionStatement SuperCall { get; set; } + public Type[] SwitchTypes { get; set; } + } + + public interface IType + { + TypeFlags Flags { get; set; } + int Id { get; set; } + Symbol Symbol { get; set; } + IDestructuringPattern Pattern { get; set; } + Symbol AliasSymbol { get; set; } + Type[] AliasTypeArguments { get; set; } + } + + public class Type : IType + { + public TypeFlags Flags { get; set; } + public int Id { get; set; } + public Symbol Symbol { get; set; } + public IDestructuringPattern Pattern { get; set; } + public Symbol AliasSymbol { get; set; } + public Type[] AliasTypeArguments { get; set; } + } + + public class IntrinsicType : Type + { + public string IntrinsicName { get; set; } + } + + public class LiteralType : Type + { + public string Text { get; set; } + public LiteralType FreshType { get; set; } + public LiteralType RegularType { get; set; } + } + + public class EnumType : Type + { + public EnumLiteralType[] MemberTypes { get; set; } + } + + public class EnumLiteralType : LiteralType + { + } + + public interface IObjectType : IType + { + ObjectFlags ObjectFlags { get; set; } + } + + public class ObjectType : Type, IObjectType + { + public ObjectFlags ObjectFlags { get; set; } + } + + public interface IInterfaceType : IObjectType + { + TypeParameter[] TypeParameters { get; set; } + TypeParameter[] OuterTypeParameters { get; set; } + TypeParameter[] LocalTypeParameters { get; set; } + TypeParameter ThisType { get; set; } + Type ResolvedBaseConstructorType { get; set; } + IBaseType[] ResolvedBaseTypes { get; set; } + } + + public class InterfaceType : ObjectType, IInterfaceType + { + public TypeParameter[] TypeParameters { get; set; } + public TypeParameter[] OuterTypeParameters { get; set; } + public TypeParameter[] LocalTypeParameters { get; set; } + public TypeParameter ThisType { get; set; } + public Type ResolvedBaseConstructorType { get; set; } + public IBaseType[] ResolvedBaseTypes { get; set; } + } + + public class InterfaceTypeWithDeclaredMembers : InterfaceType + { + public Symbol[] DeclaredProperties { get; set; } + public Signature[] DeclaredCallSignatures { get; set; } + public Signature[] DeclaredConstructSignatures { get; set; } + public IndexInfo DeclaredStringIndexInfo { get; set; } + public IndexInfo DeclaredNumberIndexInfo { get; set; } + } + + public interface ITypeReference : IObjectType + { + GenericType Target { get; set; } + Type[] TypeArguments { get; set; } + } + + public class TypeReference : ObjectType, ITypeReference + { + public GenericType Target { get; set; } + public Type[] TypeArguments { get; set; } + } + + public class GenericType : ObjectType, IInterfaceType, ITypeReference + { + public Map Instantiations { get; set; } + public TypeParameter[] TypeParameters { get; set; } + public TypeParameter[] OuterTypeParameters { get; set; } + public TypeParameter[] LocalTypeParameters { get; set; } + public TypeParameter ThisType { get; set; } + public Type ResolvedBaseConstructorType { get; set; } + public IBaseType[] ResolvedBaseTypes { get; set; } + public GenericType Target { get; set; } + public Type[] TypeArguments { get; set; } + } + + public interface IUnionOrIntersectionType : IType + { + Type[] Types { get; set; } + SymbolTable PropertyCache { get; set; } + Symbol[] ResolvedProperties { get; set; } + IndexType ResolvedIndexType { get; set; } + Type ResolvedBaseConstraint { get; set; } + bool CouldContainTypeVariables { get; set; } + } + + public class UnionOrIntersectionType : Type, IUnionOrIntersectionType + { + public Type[] Types { get; set; } + public SymbolTable PropertyCache { get; set; } + public Symbol[] ResolvedProperties { get; set; } + public IndexType ResolvedIndexType { get; set; } + public Type ResolvedBaseConstraint { get; set; } + public bool CouldContainTypeVariables { get; set; } + } + + public interface IUnionType : IUnionOrIntersectionType + { + } + + public class UnionType : UnionOrIntersectionType, IUnionType + { + } + + public class IntersectionType : UnionOrIntersectionType + { + public Type ResolvedApparentType { get; set; } + } + + public class AnonymousType : ObjectType + { + public AnonymousType Target { get; set; } + public TypeMapper Mapper { get; set; } + } + + public class MappedType : ObjectType + { + public MappedTypeNode Declaration { get; set; } + public TypeParameter TypeParameter { get; set; } + public Type ConstraintType { get; set; } + public Type TemplateType { get; set; } + public Type ModifiersType { get; set; } + public TypeMapper Mapper { get; set; } + } + + public class EvolvingArrayType : ObjectType + { + public Type ElementType { get; set; } + public Type FinalArrayType { get; set; } + } + + public class ResolvedType : Type, IObjectType, IUnionOrIntersectionType + { + public SymbolTable Members { get; set; } + public Symbol[] Properties { get; set; } + public Signature[] CallSignatures { get; set; } + public Signature[] ConstructSignatures { get; set; } + public IndexInfo StringIndexInfo { get; set; } + public IndexInfo NumberIndexInfo { get; set; } + public ObjectFlags ObjectFlags { get; set; } + public Type[] Types { get; set; } + public SymbolTable PropertyCache { get; set; } + public Symbol[] ResolvedProperties { get; set; } + public IndexType ResolvedIndexType { get; set; } + public Type ResolvedBaseConstraint { get; set; } + public bool CouldContainTypeVariables { get; set; } + } + + public class FreshObjectLiteralType : ResolvedType + { + public ResolvedType RegularType { get; set; } + } + + public class IterableOrIteratorType : Type, IObjectType, IUnionType + { + public Type IteratedTypeOfIterable { get; set; } + public Type IteratedTypeOfIterator { get; set; } + public Type IteratedTypeOfAsyncIterable { get; set; } + public Type IteratedTypeOfAsyncIterator { get; set; } + public ObjectFlags ObjectFlags { get; set; } + public Type[] Types { get; set; } + public SymbolTable PropertyCache { get; set; } + public Symbol[] ResolvedProperties { get; set; } + public IndexType ResolvedIndexType { get; set; } + public Type ResolvedBaseConstraint { get; set; } + public bool CouldContainTypeVariables { get; set; } + } + + public class PromiseOrAwaitableType : Type, IObjectType, IUnionType + { + public Type PromiseTypeOfPromiseConstructor { get; set; } + public Type PromisedTypeOfPromise { get; set; } + public Type AwaitedTypeOfType { get; set; } + public ObjectFlags ObjectFlags { get; set; } + public Type[] Types { get; set; } + public SymbolTable PropertyCache { get; set; } + public Symbol[] ResolvedProperties { get; set; } + public IndexType ResolvedIndexType { get; set; } + public Type ResolvedBaseConstraint { get; set; } + public bool CouldContainTypeVariables { get; set; } + } + + public class TypeVariable : Type + { + public Type ResolvedBaseConstraint { get; set; } + public IndexType ResolvedIndexType { get; set; } + } + + public class TypeParameter : TypeVariable + { + public Type Constraint { get; set; } + public Type Default { get; set; } + public TypeParameter Target { get; set; } + public TypeMapper Mapper { get; set; } + public bool IsThisType { get; set; } + public Type ResolvedDefaultType { get; set; } + } + + public class IndexedAccessType : TypeVariable + { + public Type ObjectType { get; set; } + public Type IndexType { get; set; } + public Type Constraint { get; set; } + } + + public class IndexType : Type + { + public Type Type { get; set; } // TypeVariable | UnionOrIntersectionType + } + + public class Signature + { + public SignatureDeclaration Declaration { get; set; } + public TypeParameter[] TypeParameters { get; set; } + public Symbol[] Parameters { get; set; } + public Symbol ThisParameter { get; set; } + public Type ResolvedReturnType { get; set; } + public int MinArgumentCount { get; set; } + public bool HasRestParameter { get; set; } + public bool HasLiteralTypes { get; set; } + public Signature Target { get; set; } + public TypeMapper Mapper { get; set; } + public Signature[] UnionSignatures { get; set; } + public Signature ErasedSignatureCache { get; set; } + public ObjectType IsolatedSignatureType { get; set; } + public ITypePredicate TypePredicate { get; set; } + public Map Instantiations { get; set; } + } + + public class IndexInfo + { + public Type Type { get; set; } + public bool IsReadonly { get; set; } + public SignatureDeclaration Declaration { get; set; } + } + + public class TypeMapper + { + public Type[] MappedTypes { get; set; } + public Type[] Instantiations { get; set; } + public InferenceContext Context { get; set; } + } + + public class TypeInferences + { + public Type[] Primary { get; set; } + public Type[] Secondary { get; set; } + public bool TopLevel { get; set; } + public bool IsFixed { get; set; } + } + + public class InferenceContext + { + public Signature Signature { get; set; } + public bool InferUnionTypes { get; set; } + public TypeInferences[] Inferences { get; set; } + public Type[] InferredTypes { get; set; } + public TypeMapper Mapper { get; set; } + public int FailedTypeParameterIndex { get; set; } + public bool UseAnyForNoInferences { get; set; } + } + + public class JsFileExtensionInfo + { + public string Extension { get; set; } + public bool IsMixedContent { get; set; } + } + + public class DiagnosticMessage + { + public string Key { get; set; } + public DiagnosticCategory Category { get; set; } + public int Code { get; set; } + public string Message { get; set; } + } + + public class DiagnosticMessageChain + { + public string MessageText { get; set; } + public DiagnosticCategory Category { get; set; } + public int Code { get; set; } + public DiagnosticMessageChain Next { get; set; } + } + + public class Diagnostic + { + public SourceFile File { get; set; } + public int Start { get; set; } + public int Length { get; set; } + public object MessageText { get; set; } // string | DiagnosticMessageChain + public DiagnosticCategory Category { get; set; } + public int Code { get; set; } + } + + public class PluginImport + { + public string Name { get; set; } + } + + public class CompilerOptions + { + public bool All { get; set; } + public bool AllowJs { get; set; } + public bool AllowNonTsExtensions { get; set; } + public bool AllowSyntheticDefaultImports { get; set; } + public bool AllowUnreachableCode { get; set; } + public bool AllowUnusedLabels { get; set; } + public bool AlwaysStrict { get; set; } + public string BaseUrl { get; set; } + public string Charset { get; set; } + public bool CheckJs { get; set; } + public string ConfigFilePath { get; set; } + public bool Declaration { get; set; } + public string DeclarationDir { get; set; } + public bool Diagnostics { get; set; } + public bool ExtendedDiagnostics { get; set; } + public bool DisableSizeLimit { get; set; } + public bool DownlevelIteration { get; set; } + public bool EmitBom { get; set; } + public bool EmitDecoratorMetadata { get; set; } + public bool ExperimentalDecorators { get; set; } + public bool ForceConsistentCasingInFileNames { get; set; } + public bool Help { get; set; } + public bool ImportHelpers { get; set; } + public bool Init { get; set; } + public bool InlineSourceMap { get; set; } + public bool InlineSources { get; set; } + public bool IsolatedModules { get; set; } + public JsxEmit Jsx { get; set; } + public string[] Lib { get; set; } + public bool ListEmittedFiles { get; set; } + public bool ListFiles { get; set; } + public string Locale { get; set; } + public string MapRoot { get; set; } + public int MaxNodeModuleJsDepth { get; set; } + public ModuleKind Module { get; set; } + public ModuleResolutionKind ModuleResolution { get; set; } + public NewLineKind NewLine { get; set; } + public bool NoEmit { get; set; } + public bool NoEmitForJsFiles { get; set; } + public bool NoEmitHelpers { get; set; } + public bool NoEmitOnError { get; set; } + public bool NoErrorTruncation { get; set; } + public bool NoFallthroughCasesInSwitch { get; set; } + public bool NoImplicitAny { get; set; } + public bool NoImplicitReturns { get; set; } + public bool NoImplicitThis { get; set; } + public bool NoUnusedLocals { get; set; } + public bool NoUnusedParameters { get; set; } + public bool NoImplicitUseStrict { get; set; } + public bool NoLib { get; set; } + public bool NoResolve { get; set; } + public string Out { get; set; } + public string OutDir { get; set; } + public string OutFile { get; set; } + public MapLike Paths { get; set; } + public PluginImport[] Plugins { get; set; } + public bool PreserveConstEnums { get; set; } + public string Project { get; set; } + public DiagnosticStyle Pretty { get; set; } + public string ReactNamespace { get; set; } + public string JsxFactory { get; set; } + public bool RemoveComments { get; set; } + public string RootDir { get; set; } + public string[] RootDirs { get; set; } + public bool SkipLibCheck { get; set; } + public bool SkipDefaultLibCheck { get; set; } + public bool SourceMap { get; set; } + public string SourceRoot { get; set; } + public bool Strict { get; set; } + public bool StrictNullChecks { get; set; } + public bool StripInternal { get; set; } + public bool SuppressExcessPropertyErrors { get; set; } + public bool SuppressImplicitAnyIndexErrors { get; set; } + public bool SuppressOutputPathCheck { get; set; } + public ScriptTarget Target { get; set; } + public bool TraceResolution { get; set; } + public string[] Types { get; set; } + public string[] TypeRoots { get; set; } + public bool Version { get; set; } + public bool Watch { get; set; } + } + + public class TypeAcquisition + { + public bool EnableAutoDiscovery { get; set; } + public bool Enable { get; set; } + public string[] Include { get; set; } + public string[] Exclude { get; set; } + } + + public class DiscoverTypingsInfo + { + public string[] FileNames { get; set; } + public string ProjectRootPath { get; set; } + public string SafeListPath { get; set; } + public Map PackageNameToTypingLocation { get; set; } + public TypeAcquisition TypeAcquisition { get; set; } + public CompilerOptions CompilerOptions { get; set; } + public ReadonlyArray UnresolvedImports { get; set; } + } + + public class LineAndCharacter + { + public int Line { get; set; } + public int Character { get; set; } + } + + public class ParsedCommandLine + { + public CompilerOptions Options { get; set; } + public TypeAcquisition TypeAcquisition { get; set; } + public string[] FileNames { get; set; } + public object Raw { get; set; } + public Diagnostic[] Errors { get; set; } + public MapLike WildcardDirectories { get; set; } + public bool CompileOnSave { get; set; } + } + + public class ExpandResult + { + public string[] FileNames { get; set; } + public MapLike WildcardDirectories { get; set; } + } + + public class CommandLineOptionBase + { + public string Name { get; set; } + public object Type { get; set; } // "string" | "number" | "boolean" | "object" | "list" | Map + public bool IsFilePath { get; set; } + public string ShortName { get; set; } + public DiagnosticMessage Description { get; set; } + public DiagnosticMessage ParamType { get; set; } + public bool IsTsConfigOnly { get; set; } + public bool IsCommandLineOnly { get; set; } + public bool ShowInSimplifiedHelpView { get; set; } + public DiagnosticMessage Category { get; set; } + } + + public class CommandLineOptionOfPrimitiveType : CommandLineOptionBase + { + } + + public class CommandLineOptionOfCustomType : CommandLineOptionBase + { + } + + public class TsConfigOnlyOption : CommandLineOptionBase + { + } + + public class CommandLineOptionOfListType : CommandLineOptionBase + { + public CommandLineOptionBase + Element + { + get; + set; + } // CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption + } + + public class ModuleResolutionHost + { + } + + public class ResolvedModule + { + public string ResolvedFileName { get; set; } + public bool IsExternalLibraryImport { get; set; } + } + + public class ResolvedModuleFull : ResolvedModule + { + public Extension Extension { get; set; } + } + + public class ResolvedModuleWithFailedLookupLocations + { + public ResolvedModule ResolvedModule { get; set; } // ResolvedModuleFull + public string[] FailedLookupLocations { get; set; } + } + + public class ResolvedTypeReferenceDirective + { + public bool Primary { get; set; } + public string ResolvedFileName { get; set; } + } + + public class ResolvedTypeReferenceDirectiveWithFailedLookupLocations + { + public ResolvedTypeReferenceDirective ResolvedTypeReferenceDirective { get; set; } + public string[] FailedLookupLocations { get; set; } + } + + public class CompilerHost : ModuleResolutionHost + { + public WriteFileCallback WriteFile { get; set; } + } + + public class EmitNode + { + public Node[] AnnotatedNodes { get; set; } + public EmitFlags Flags { get; set; } + public SynthesizedComment[] LeadingComments { get; set; } + public SynthesizedComment[] TrailingComments { get; set; } + public TextRange CommentRange { get; set; } + public TextRange SourceMapRange { get; set; } + public TextRange[] TokenSourceMapRanges { get; set; } + public int ConstantValue { get; set; } + public Identifier ExternalHelpersModuleName { get; set; } + public EmitHelper[] Helpers { get; set; } + } + + public class EmitHelper + { + public string Name { get; set; } + public bool Scoped { get; set; } + public string Text { get; set; } + public int Priority { get; set; } + } + + public class EmitHost : ScriptReferenceHost + { + public WriteFileCallback WriteFile { get; set; } + } + + public class TransformationContext + { + // onSubstituteNode { get; set; } + // onEmitNode { get; set; } + } + + public class TransformationResult + { + public T[] Transformed { get; set; } + public Diagnostic[] Diagnostics { get; set; } + } + + public class Printer + { + } + + public class PrintHandlers + { + // onEmitSourceMapOfNode { get; set; } + // onEmitSourceMapOfToken { get; set; } + // onEmitSourceMapOfPosition { get; set; } + // onEmitHelpers { get; set; } + // onSetSourceFile { get; set; } + // onBeforeEmitNodeArray { get; set; } + // onAfterEmitNodeArray { get; set; } + } + + public class PrinterOptions + { + public ScriptTarget Target { get; set; } + public bool RemoveComments { get; set; } + public NewLineKind NewLine { get; set; } + public bool SourceMap { get; set; } + public bool InlineSourceMap { get; set; } + public bool ExtendedDiagnostics { get; set; } + } + + public class EmitTextWriter + { + } + + public class TextSpan + { + public int Start { get; set; } + public int Length { get; set; } + } + + public class TextChangeRange + { + public TextSpan Span { get; set; } + public int NewLength { get; set; } + } + + public class DiagnosticCollection + { + } + + public class SyntaxList : Node + { + public SyntaxList() + { + Kind = SyntaxKind.SyntaxList; + } + + public Node[] _children { get; set; } + } + + public class MissingNode : Identifier + { + } +} diff --git a/generators/CssInCSharp.Ast.TypeScript/TypeScriptAST.cs b/generators/CssInCSharp.Ast.TypeScript/TypeScriptAST.cs new file mode 100644 index 0000000..b6634df --- /dev/null +++ b/generators/CssInCSharp.Ast.TypeScript/TypeScriptAST.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Zu.TypeScript.TsParser; +using Zu.TypeScript.TsTypes; + +namespace Zu.TypeScript +{ + public interface ITypeScriptAST + { + ScriptTarget ScriptTarget { get; set; } + string SourceStr { get; set; } + Node RootNode { get; set; } + string GetTreeString(bool withPos); + IEnumerable GetDescendants(); + void MakeAST(string source, string fileName = "fileName.ts", bool setChildren = true); + } + public class TypeScriptAST: ITypeScriptAST + { + public ScriptTarget ScriptTarget { get; set; } = ScriptTarget.Latest; //ES6 + public string SourceStr { get; set; } + public Node RootNode { get; set; } + + public TypeScriptAST(string source = null, string fileName = "fileName.ts", bool setChildren = true) + { + if (source != null) + { + MakeAST(source, fileName, setChildren); + } + } + + public void MakeAST(string source, string fileName = "fileName.ts", bool setChildren = true) + { + SourceStr = source; + var parser = new Parser(); + var sourceFile = parser.ParseSourceFile(fileName, source, ScriptTarget, null, false, ScriptKind.Ts); + RootNode = sourceFile; + RootNode.Ast = this; + if (setChildren) + { + childrenMade = true; + RootNode.MakeChildren(this); + } + //RootNode.GetDescendants().ToList().ForEach((n) => n.AST = this); + } + + private bool childrenMade = false; + public IEnumerable OfKind(SyntaxKind kind) => RootNode?.OfKind(kind); + public IEnumerable GetDescendants() + { + if (!childrenMade && RootNode != null) + { + RootNode.MakeChildren(this); + childrenMade = true; + } + return RootNode?.GetDescendants(); + } + + public string GetTreeString(bool withPos = true) + { + return RootNode?.GetTreeString(withPos); + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.CommandLine/Configuration.cs b/generators/CssInCSharp.CommandLine/Configuration.cs new file mode 100644 index 0000000..bc55d84 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/Configuration.cs @@ -0,0 +1,113 @@ +using System.Text.RegularExpressions; +using CssInCSharp.Generator; +using RulesEngine.Models; + +namespace CssInCSharp.CommandLine +{ + internal class Configuration + { + public ConverterType Converter { get; set; } = ConverterType.Ts; + + public CSharpOptions CsOptions { get; set; } = new(); + + public List Include { get; set; } = []; + + public List Exclude { get; set; } = []; + + public List TypeInferences { get; set; } = []; + + public void AddIncludeItem(string src, string dest) + { + Include.Add(new IncludeItem + { + Src = src, + Dest = dest + }); + } + + public CSharpOptions CloneCsOptions() + { + return Util.Mapper.Map(CsOptions, new CSharpOptions()); + } + } + + internal class IncludeItem + { + public string? Src { get; set; } + public string? Dest { get; set; } + public CSharpOptions? CsOptions { get; set; } + + public IncludeItem Update() + { + UpdateNamePrefix(); + UpdateDefaultClassName(); + UpdateDefaultExportMethodName(); + CsOptions?.SetContextVariables(); + return this; + } + + private void UpdateNamePrefix() + { + if (CsOptions is not { NamePrefix: not null }) return; + var name = ParseName(CsOptions.NamePrefix); + if (!string.IsNullOrEmpty(name)) + { + CsOptions.NamePrefix = Util.PurifyFileName(name); + } + } + + private void UpdateDefaultClassName() + { + if (CsOptions is not { DefaultExportClassName: not null }) return; + var name = ParseName(CsOptions.DefaultExportClassName); + if (!string.IsNullOrEmpty(name)) + { + CsOptions.DefaultExportClassName = Util.PurifyFileName(name); + } + } + + private void UpdateDefaultExportMethodName() + { + if (CsOptions is not { DefaultExportMethodName: not null }) return; + var name = ParseName(CsOptions.DefaultExportMethodName); + if (!string.IsNullOrEmpty(name)) + { + CsOptions.DefaultExportMethodName = Util.PurifyFileName(name); + } + } + + private string? ParseName(string option) + { + var match = Regex.Match(option, @"(\{(dir|file):?(\S*)\})\w*"); + if (!match.Success) return null; + if (match.Groups.Count < 3) return null; + if (Dest == null) return null; + + var replace = match.Groups[1].Value; + var type = match.Groups[2].Value; + var param = match.Groups[3].Value; + + string name; + if (type == "dir") + { + var dir = Path.GetDirectoryName(Dest)!; + if (!string.IsNullOrEmpty(param)) + { + dir = Path.GetDirectoryName(Path.GetFullPath(Path.Join(Dest, param))); + } + + name = Path.GetFileName(dir); + } + else + { + name = Path.GetFileNameWithoutExtension(Dest); + } + + if (!string.IsNullOrEmpty(name)) + { + name = option.Replace(replace, name); + } + return name; + } + } +} diff --git a/generators/CssInCSharp.CommandLine/ConvertCommand.cs b/generators/CssInCSharp.CommandLine/ConvertCommand.cs new file mode 100644 index 0000000..de9162b --- /dev/null +++ b/generators/CssInCSharp.CommandLine/ConvertCommand.cs @@ -0,0 +1,92 @@ +using System.CommandLine; +using CssInCSharp.Generator; +using RulesEngine.Models; + +namespace CssInCSharp.CommandLine +{ + internal class ConvertCommand : Command + { + public ConvertCommand() : base("convert", "Convert css file to c#.") + { + var configOption = new Option( + aliases: ["--config", "-c"], + description: "Specify the configuration file.", + getDefaultValue: () => "cssincs.json"); + var sourceOption = new Option( + aliases: ["--source", "-s"], + description: "Source file path."); + var destOption = new Option( + aliases: ["--dest", "-d"], + description: "Dest file path, Default as same as source file."); + var typeOption = new Option( + aliases: ["--type", "-t"], + description: "Converter type."); + var dryRunOption = new Option( + aliases: ["--dry-run"], + description: "Dry run and output code to console."); + this.Add(configOption); + this.Add(sourceOption); + this.Add(destOption); + this.Add(typeOption); + this.Add(dryRunOption); + this.SetHandler(ExecAsync, configOption, typeOption, sourceOption, destOption, dryRunOption); + } + + private async Task ExecAsync(string configFile, ConverterType type, string src, string dest, bool dryRun) + { + var config = new Configuration(); + if (File.Exists(configFile)) + { + var json = await File.ReadAllTextAsync(configFile); + config = json.FromJson(); + } + else if (!string.IsNullOrEmpty(src)) + { + config.Converter = type; + config.AddIncludeItem(src, dest); + } + else + { + Console.WriteLine("`config` or `src` parameter, one must be specified."); + return; + } + + var exclude = config.Exclude.SelectMany(x => Util.GetFiles(x)); + var items = config.Include.SelectMany(x => Util.GetFiles(x.Src).Except(exclude), (inc, file) => + { + var global = config.CloneCsOptions(); + if (inc.CsOptions != null) + { + Util.Mapper.Map(inc.CsOptions, global); + } + + return new IncludeItem + { + Src = file.FullPath, + Dest = Util.GetDest(file.Dir, file.FullPath, inc.Dest, ".cs"), + CsOptions = global + }.Update(); + }); + + // init rule engine + InferenceEngine.Initialize(config.TypeInferences); + + foreach (var item in items) + { + var converter = ConverterFactory.Create(config.Converter, item.CsOptions); + var content = await File.ReadAllTextAsync(item.Src); + var filenName = Path.GetFileName(item.Src); + Console.WriteLine($"Convert: {item.Src}"); + var code = converter.Convert(content, filenName); + if (dryRun) + { + Console.WriteLine(code); + } + else + { + await Util.WriteAllTextAsync(item.Dest, code); + } + } + } + } +} diff --git a/generators/CssInCSharp.CommandLine/CssInCSharp.CommandLine.csproj b/generators/CssInCSharp.CommandLine/CssInCSharp.CommandLine.csproj new file mode 100644 index 0000000..8fc1701 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/CssInCSharp.CommandLine.csproj @@ -0,0 +1,32 @@ + + + + Exe + net9.0 + enable + enable + true + cssincs + + + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/generators/CssInCSharp.CommandLine/InitCommand.cs b/generators/CssInCSharp.CommandLine/InitCommand.cs new file mode 100644 index 0000000..08207be --- /dev/null +++ b/generators/CssInCSharp.CommandLine/InitCommand.cs @@ -0,0 +1,31 @@ +using System.CommandLine; + +namespace CssInCSharp.CommandLine +{ + internal class InitCommand : Command + { + public InitCommand() : base("init", "Init an empty configuration file.") + { + var configOption = new Option( + aliases: ["--config", "-c"], + description: "Specify the configuration file.", + getDefaultValue: () => "cssincs.json"); + this.Add(configOption); + this.SetHandler(ExecAsync, configOption); + } + + public async Task ExecAsync(string configFile) + { + configFile = Path.GetFullPath(configFile); + // create an empty configuration. + if (File.Exists(configFile)) + { + Console.WriteLine("The cssincs.json file already exists."); + return; + } + var config = new Configuration(); + config.AddIncludeItem("./src/**/*.ts", "./dest"); + await Util.WriteAllTextAsync(configFile, config.ToJson()); + } + } +} diff --git a/generators/CssInCSharp.CommandLine/Program.cs b/generators/CssInCSharp.CommandLine/Program.cs new file mode 100644 index 0000000..d4b52fa --- /dev/null +++ b/generators/CssInCSharp.CommandLine/Program.cs @@ -0,0 +1,33 @@ +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Help; +using System.CommandLine.Parsing; +using CssInCSharp.CommandLine; +using Spectre.Console; + +var returnCode = 0; +var rootCommand = new RootCommand("CssInCSharp") +{ + new InitCommand(), + new ConvertCommand(), +}; +rootCommand.TreatUnmatchedTokensAsErrors = false; +rootCommand.SetHandler((context) => +{ + if (context.ParseResult.Tokens.Count == 0) + { + context.HelpBuilder.Write(rootCommand, Console.Out); + } +}); +var parser = new CommandLineBuilder(rootCommand) + .UseDefaults() + .UseHelp(ctx => + { + ctx.HelpBuilder + .CustomizeLayout(_ => HelpBuilder.Default.GetLayout().Skip(1).Prepend(_ => + AnsiConsole.Write( + new FigletText(rootCommand.Description!)))); + }) + .Build(); +await parser.InvokeAsync(args); +return returnCode; diff --git a/generators/CssInCSharp.CommandLine/Properties/launchSettings.json b/generators/CssInCSharp.CommandLine/Properties/launchSettings.json new file mode 100644 index 0000000..3da6e77 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "CssInCSharp.CommandLine": { + "commandName": "Project", + "commandLineArgs": "convert -c cssincs.json --dry-run" + } + } +} \ No newline at end of file diff --git a/generators/CssInCSharp.CommandLine/Util.cs b/generators/CssInCSharp.CommandLine/Util.cs new file mode 100644 index 0000000..e1fc496 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/Util.cs @@ -0,0 +1,129 @@ +using Microsoft.Extensions.FileSystemGlobbing; +using System.Text.Json.Serialization; +using System.Text.Json; +using System.Text.RegularExpressions; +using AutoMapper; +using CssInCSharp.Generator; + +namespace CssInCSharp.CommandLine; + +public static class Util +{ + public static readonly IMapper Mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap() + .ForMember(x => x.Usings, opt => + { + opt.PreCondition((src, dest, srcMember) => src.Usings is { Count: > 0 }); + }) + .ForMember(x => x.Replacements, opt => + { + opt.PreCondition((src, dest, srcMember) => src.Replacements is { Count: > 0 }); + }); + }).CreateMapper(); + + public static async Task WriteAllTextAsync(string path, string content) + { + var destDir = Path.GetDirectoryName(path); + if (!Directory.Exists(destDir)) + { + Directory.CreateDirectory(destDir); + } + await File.WriteAllTextAsync(path, content); + } + + public static IEnumerable GetFiles(string path) + { + path = Path.GetFullPath(path); + var dir = ""; + var pattern = ""; + var index = path.IndexOf("*"); + if (index > 0) + { + dir = path.Substring(0, index); + pattern = path.Substring(index); + } + else + { + dir = Path.GetDirectoryName(path); + pattern = path.Substring(dir.Length + 1); + } + var matcher = new Matcher(); + matcher.AddInclude(pattern); + return matcher.GetResultsInFullPath(dir).Select(x => new MatchFile + { + Dir = dir, + Pattern = pattern, + FullPath = x + }); + } + + public static string GetDest(string dir, string file, string dest, string ext) + { + if (!string.IsNullOrEmpty(dest) && !IsFolder(dest)) return Path.GetFullPath(dest); + dest = Path.GetFullPath(dest ?? dir); + var destFile = Path.Combine(dest, file.Substring(dir.Length)); + var destFolder = Path.GetDirectoryName(destFile); + var destFileName = Path.GetFileNameWithoutExtension(destFile); + return Path.Combine(destFolder, destFileName + ext); + } + + public static bool IsFolder(string path) + { + try + { + var attr = File.GetAttributes(path); + return (attr & FileAttributes.Directory) == FileAttributes.Directory; + } + catch (Exception e) + { + return false; + } + } + + public static string PurifyFileName(string fileName) + { + // remove "-" + return Regex.Replace(fileName, @"-(\w)", match => match.Groups[1].Value.ToUpper()); + } + + public static string ToJson(this T obj) + { + var settings = new JsonSerializerOptions + { + WriteIndented = true + }; + settings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + return JsonSerializer.Serialize(obj, settings); + } + + public static T? FromJson(this string json) + { + var settings = new JsonSerializerOptions(); + settings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + return JsonSerializer.Deserialize(json, settings); + } +} + +public class MatchFile : IEquatable +{ + public string Dir { get; set; } = default!; + public string Pattern { get; set; } = default!; + public string FullPath { get; set; } = default!; + + public bool Equals(MatchFile? other) + { + if (other == null) return false; + return FullPath == other.FullPath; + } + + public override bool Equals(object? obj) + { + return Equals(obj as MatchFile); + } + + public override int GetHashCode() + { + return HashCode.Combine(FullPath); + } +} diff --git a/generators/CssInCSharp.CommandLine/cssincs.json b/generators/CssInCSharp.CommandLine/cssincs.json new file mode 100644 index 0000000..0a2c6f8 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/cssincs.json @@ -0,0 +1,24 @@ +{ + "Converter": "Ts", + "Include": [ + { + "Src": "./index.ts", + "Dest": "./index.cs" + } + ], + "Exclude": [], + "TypeInferences": [ + { + "RuleName": "ObjectTypeInfer_CSSObject", + "Expression": "Kind == \"ObjectType\" && ((HasIndexer && Properties == null) || HasAny(\"width\", \"display\", \"position\", \"color\", \"direction\", \"flex\", \"background\"))", + "Actions": { + "OnSuccess": { + "Name": "OutputExpression", + "Context": { + "Expression": "\"CSSObject\"" + } + } + } + } + ] +} \ No newline at end of file diff --git a/generators/CssInCSharp.CommandLine/index.ts b/generators/CssInCSharp.CommandLine/index.ts new file mode 100644 index 0000000..4698c73 --- /dev/null +++ b/generators/CssInCSharp.CommandLine/index.ts @@ -0,0 +1,7 @@ +const genMotionStyle: GenerateStyle = (token) => { + return { + [componentCls]: { + [`&-${direction}`]: "str".sub(() => ({})), + }, + }; +}; \ No newline at end of file diff --git a/generators/CssInCSharp.Generator/AstGenerateException.cs b/generators/CssInCSharp.Generator/AstGenerateException.cs new file mode 100644 index 0000000..6f5e0ce --- /dev/null +++ b/generators/CssInCSharp.Generator/AstGenerateException.cs @@ -0,0 +1,18 @@ +namespace CssInCSharp.Generator; + +public class AstGenerateException: Exception +{ + public int StartLine { get; } + public int EndLine { get; } + public string SourceCode { get; } + + public AstGenerateException(int start, int end, string sourceCode) : base(@$"Generate ast failed, source file line: {start} {end}, source code:\n +======================================== +{sourceCode} +========================================") + { + StartLine = start; + EndLine = end; + SourceCode = sourceCode; + } +} diff --git a/generators/CssInCSharp.Generator/CSharpOptions.cs b/generators/CssInCSharp.Generator/CSharpOptions.cs new file mode 100644 index 0000000..82cb560 --- /dev/null +++ b/generators/CssInCSharp.Generator/CSharpOptions.cs @@ -0,0 +1,89 @@ +using System.Text.RegularExpressions; + +namespace CssInCSharp.Generator; + +public class CSharpOptions +{ + private readonly Dictionary _contextVariables = new Dictionary(); + public List Usings { get; set; } = ["System", "CssInCSharp"]; + public string Namespace { get; set; } = "CssInCSharp"; + public string NamePrefix { get; set; } = default!; + public string DefaultObjectType { get; set; } = "object"; + public string DefaultReturnType { get; set; } = "object"; + public string DefaultParameterType { get; set; } = "object"; + public string DefaultVariableType { get; set; } = "object"; + public string DefaultExportClassName { get; set; } = "GeneratedStyle"; + public string DefaultExportMethodName { get; set; } = "Default"; + public string DefaultExportType { get; set; } = "object"; + public bool UsePartialClass { get; set; } = false; + public bool UseStaticMethod { get; set; } = false; + public bool UsePascalCase { get; set; } = false; + public bool UseAnonymousType { get; set; } = false; + public List Replacements { get; set; } = []; + + public void SetContextVariables() + { + _contextVariables[nameof(Namespace)] = Namespace; + _contextVariables[nameof(NamePrefix)] = NamePrefix; + _contextVariables[nameof(DefaultReturnType)] = DefaultReturnType; + _contextVariables[nameof(DefaultParameterType)] = DefaultParameterType; + _contextVariables[nameof(DefaultVariableType)] = DefaultVariableType; + _contextVariables[nameof(DefaultExportClassName)] = DefaultExportClassName; + _contextVariables[nameof(DefaultExportMethodName)] = DefaultExportMethodName; + _contextVariables[nameof(DefaultExportType)] = DefaultExportType; + } + + public string Replace(string input) + { + if (Replacements.Count <= 0) + { + return input; + } + + foreach (var item in Replacements) + { + input = item.Replace(input, _contextVariables); + } + + return input; + } +} + +public class MatchItem +{ + public string Pattern { get; set; } = default!; + + public string Value { get; set; } = default!; + + public MatchItem() + { + } + + public MatchItem(string pattern, string value) + { + Pattern = pattern; + Value = value; + } + + public string GetValue(Dictionary context) + { + var match = Regex.Match(Value, @"\w*(\{(\w+)\})\w*"); + if (match is { Success: true, Groups.Count: >= 3 }) + { + var replace = match.Groups[1].ToString(); + var key = match.Groups[2].ToString(); + if (context.TryGetValue(key, out var value)) + { + return Value.Replace(replace, value); + } + } + + return Value; + } + + public string Replace(string input, Dictionary context) + { + var value = GetValue(context); + return Regex.Replace(input, Pattern, value); + } +} diff --git a/generators/CssInCSharp.Generator/CssGenerator.cs b/generators/CssInCSharp.Generator/CssGenerator.cs new file mode 100644 index 0000000..365ea4b --- /dev/null +++ b/generators/CssInCSharp.Generator/CssGenerator.cs @@ -0,0 +1,16 @@ +using Microsoft.CodeAnalysis; + +namespace CssInCSharp.Generator +{ + [Generator] + public class CssGenerator : ISourceGenerator + { + public void Initialize(GeneratorInitializationContext context) + { + } + + public void Execute(GeneratorExecutionContext context) + { + } + } +} diff --git a/generators/CssInCSharp.Generator/CssInCSharp.Generator.csproj b/generators/CssInCSharp.Generator/CssInCSharp.Generator.csproj new file mode 100644 index 0000000..2008875 --- /dev/null +++ b/generators/CssInCSharp.Generator/CssInCSharp.Generator.csproj @@ -0,0 +1,18 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + + diff --git a/generators/CssInCSharp.Generator/DefaultConverter.cs b/generators/CssInCSharp.Generator/DefaultConverter.cs new file mode 100644 index 0000000..554ffc4 --- /dev/null +++ b/generators/CssInCSharp.Generator/DefaultConverter.cs @@ -0,0 +1,35 @@ +namespace CssInCSharp.Generator +{ + public enum ConverterType + { + Ts, + Sass, + Less, + Css + } + + public interface IConverter + { + string Convert(string content, string fileName); + } + + public class DefaultConverter : IConverter + { + public string Convert(string content, string fileName) + { + return string.Empty; + } + } + + public class ConverterFactory + { + public static IConverter Create(ConverterType type , CSharpOptions? option) + { + return type switch + { + ConverterType.Ts => new TypeScriptConverter(option), + _ => new DefaultConverter(), + }; + } + } +} diff --git a/generators/CssInCSharp.Generator/Extensions/EnumerableExtensions.cs b/generators/CssInCSharp.Generator/Extensions/EnumerableExtensions.cs new file mode 100644 index 0000000..8096a96 --- /dev/null +++ b/generators/CssInCSharp.Generator/Extensions/EnumerableExtensions.cs @@ -0,0 +1,25 @@ +namespace CssInCSharp.Generator.Extensions +{ + public static class EnumerableExtensions + { + public static IEnumerable Separate(this IEnumerable source, T separator, bool separateEnd = false) + { + using var enumerator = source.GetEnumerator(); + var hasNext = enumerator.MoveNext(); + while (hasNext) + { + var current = enumerator.Current; + hasNext = enumerator.MoveNext(); + yield return current; + if (separateEnd) + { + yield return separator; + } + else if (hasNext) + { + yield return separator; + } + } + } + } +} diff --git a/generators/CssInCSharp.Generator/Extensions/NodeExtensions.cs b/generators/CssInCSharp.Generator/Extensions/NodeExtensions.cs new file mode 100644 index 0000000..af169d9 --- /dev/null +++ b/generators/CssInCSharp.Generator/Extensions/NodeExtensions.cs @@ -0,0 +1,133 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Ts = Zu.TypeScript; + +namespace CssInCSharp.Generator.Extensions; + +internal static class NodeExtensions +{ + private static string[] _htmlTags = [ + "a", + "bdi", + "blockquote", + "button", + "code", + "fill", + "i", + "img", + "input", + "kbd", + "li", + "mark", + "ol", + "pre", + "span", + "stroke", + "strong", + "svg", + "table", + "td", + "textarea", + "th", + "to", + "ul", + ]; + + public static MemberDeclarationSyntax AddMemberNodes(this MemberDeclarationSyntax node, params MemberDeclarationSyntax[] members) + { + switch (node) + { + case NamespaceDeclarationSyntax namespaceDeclaration: + return namespaceDeclaration.AddMembers(members); + case ClassDeclarationSyntax classDeclaration: + return classDeclaration.AddMembers(members); + default: throw new Exception(""); + } + } + + public static bool IsNodeType(this SyntaxNode node) + { + return node.GetType().IsAssignableFrom(typeof(T)); + } + + public static bool IsMember(this Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.SourceFile: + case Ts.TsTypes.SyntaxKind.InterfaceDeclaration: + case Ts.TsTypes.SyntaxKind.VariableDeclaration: + case Ts.TsTypes.SyntaxKind.VariableStatement: + case Ts.TsTypes.SyntaxKind.FunctionDeclaration: + case Ts.TsTypes.SyntaxKind.PropertySignature: + case Ts.TsTypes.SyntaxKind.ExportAssignment: + case Ts.TsTypes.SyntaxKind.TypeAliasDeclaration: + return true; + default: return false; + } + } + + public static bool IsHtmlTag(this Ts.TsTypes.INode node) + { + if (node.Kind == Ts.TsTypes.SyntaxKind.Identifier) + { + var tag = node.GetText(); + return _htmlTags.Contains(tag); + } + return false; + } + + public static bool IsIndexerProperty(this Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.StringLiteral: + case Ts.TsTypes.SyntaxKind.ComputedPropertyName: + case Ts.TsTypes.SyntaxKind.TemplateExpression: + return true; + default: return false; + } + } + + public static bool IsPropertyAssignment(this Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.ObjectLiteralExpression: + return true; + default: return false; + } + } + + public static bool IsProperty(this Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.PropertyAssignment: + case Ts.TsTypes.SyntaxKind.SpreadAssignment: + case Ts.TsTypes.SyntaxKind.ShorthandPropertyAssignment: + return true; + default: return false; + } + } + + public static bool IsUnsupportedStatement(this Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.TypeAliasDeclaration: + return true; + default: return false; + } + } + + public static T AsType(this SyntaxNode node) where T: SyntaxNode + { + return (T)node; + } + + public static T AsType(this Ts.TsTypes.INode node) where T: Ts.TsTypes.INode + { + return (T)node; + } +} diff --git a/generators/CssInCSharp.Generator/Extensions/StringExtensions.cs b/generators/CssInCSharp.Generator/Extensions/StringExtensions.cs new file mode 100644 index 0000000..eb01cb4 --- /dev/null +++ b/generators/CssInCSharp.Generator/Extensions/StringExtensions.cs @@ -0,0 +1,37 @@ +namespace CssInCSharp.Generator.Extensions +{ + internal static class StringExtensions + { + public static string FormatValue(this string str) + { + // todo: + return str.Trim('\''); + } + + public static string Purify(this string str) + { + return str.Trim('\''); + } + + public static string ToType(this string type) + { + switch (type) + { + case "double": + case "bool": + case "string": + case "object": + return type; + default: return type.ToPascalCase(); + } + } + + public static string ToPascalCase(this string input) => + input switch + { + null => throw new ArgumentNullException(nameof(input)), + "" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)), + _ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1)) + }; + } +} diff --git a/generators/CssInCSharp.Generator/TypeInference.cs b/generators/CssInCSharp.Generator/TypeInference.cs new file mode 100644 index 0000000..feccfdb --- /dev/null +++ b/generators/CssInCSharp.Generator/TypeInference.cs @@ -0,0 +1,57 @@ +using CssInCSharp.Generator.Extensions; +using RulesEngine.Actions; +using RulesEngine.Models; + +namespace CssInCSharp.Generator +{ + public static class InferenceEngine + { + private static RulesEngine.RulesEngine? _engine; + + public static void Initialize(List rules) + { + if (rules.Count <= 0) return; + var workflows = new Workflow[] + { + new Workflow() + { + WorkflowName = "TypeInference", + Rules = rules + } + }; + var reSettings = new ReSettings(); + reSettings.CustomActions = new Dictionary>() + { + }; + + _engine = new RulesEngine.RulesEngine(workflows, reSettings); + } + + public static string Infer(object token, string defaultValue) + { + if (_engine == null) return defaultValue; + var ruleName = string.Empty; + try + { + var results = _engine.ExecuteAllRulesAsync("TypeInference", token).GetAwaiter().GetResult(); + if (results != null) + { + foreach (var result in results) + { + ruleName = result.Rule.RuleName; + if (result.IsSuccess) + { + // If there are multiple matching results, the first one is used. + return result.ActionResult.Output.ToString()!.ToType(); + } + } + } + } + catch (Exception ex) + { + throw new TypeInferenceException(ruleName, ex.Message); + } + return defaultValue; + } + } +} diff --git a/generators/CssInCSharp.Generator/TypeInferenceException.cs b/generators/CssInCSharp.Generator/TypeInferenceException.cs new file mode 100644 index 0000000..5f1c56c --- /dev/null +++ b/generators/CssInCSharp.Generator/TypeInferenceException.cs @@ -0,0 +1,12 @@ +namespace CssInCSharp.Generator +{ + internal class TypeInferenceException : Exception + { + public string RuleName { get; set; } + + public TypeInferenceException(string ruleName, string message): base($"RuleName {ruleName}, {message}") + { + RuleName = ruleName; + } + } +} diff --git a/generators/CssInCSharp.Generator/TypeScriptConverter.cs b/generators/CssInCSharp.Generator/TypeScriptConverter.cs new file mode 100644 index 0000000..c0b7386 --- /dev/null +++ b/generators/CssInCSharp.Generator/TypeScriptConverter.cs @@ -0,0 +1,1334 @@ +using CssInCSharp.Generator.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Text.RegularExpressions; +using Ts = Zu.TypeScript; + +namespace CssInCSharp.Generator +{ + public class TypeScriptConverter : IConverter + { + private readonly CSharpOptions _options; + + public TypeScriptConverter(CSharpOptions? options = null) + { + _options = options ?? new CSharpOptions(); + } + + public string Convert(string content, string fileName) + { + var tsAst = new Ts.TypeScriptAST(content, fileName); + var csAst = Generate(tsAst.RootNode); + var code = csAst.NormalizeWhitespace().ToFullString(); + return _options.Replace(code); + } + + private CompilationUnitSyntax Generate(Ts.TsTypes.INode node) + { + // usings + var usings = SyntaxFactory.List(_options.Usings.Select(GenerateUsing)); + + // namespace + var @namespace = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(_options.Namespace)); + + // members + var members = GenerateMemberDeclaration(node); + @namespace = @namespace.AddMembers(members); + + return SyntaxFactory.CompilationUnit() + .WithUsings(usings) + .AddMembers(@namespace); + } + + private UsingDirectiveSyntax GenerateUsing(string usingStr) + { + var strs = usingStr.Split("="); + if (strs.Length > 1) + { + return SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(strs[1].Trim())).WithAlias(SyntaxFactory.NameEquals(strs[0].Trim())); + } + + strs = usingStr.Split("static"); + if (strs.Length > 1) + { + return SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(strs[1].Trim())).WithStaticKeyword(SyntaxFactory.Token(SyntaxKind.StaticKeyword)); + } + + return SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName(usingStr)); + } + + private MemberDeclarationSyntax? GenerateMemberDeclaration(Ts.TsTypes.INode node) + { + MemberDeclarationSyntax? csNode = null; + if (node.IsMember()) + { + csNode = GenerateCSharpAst(node).AsT0.AsType(); + } + if (csNode != null) + { + foreach (var child in node.Children) + { + var childNode = GenerateMemberDeclaration(child); + if (childNode != null) + { + csNode = csNode.AddMemberNodes(childNode); + } + } + } + return csNode; + } + + private SyntaxNodeOrList GenerateCSharpAst(Ts.TsTypes.INode node, NodeContext? context = null) + { + try + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.ArrowFunction: + { + var n = node.AsType(); + var funcName = context?.FuncName ?? string.Empty; + var returnType = n.Type?.GetText() ?? InferReturnType(n, funcName); + var statements = new List(); + var bindingCounter = 0; + var parameters = n.Parameters.Select(x => + { + LiteralExpressionSyntax? initializer = null; + string? defaultValue = null; + // todo: csharp does not support variable as default value + if (x.Initializer != null && x.Initializer.Kind != Ts.TsTypes.SyntaxKind.Identifier) + { + initializer = GenerateCSharpAst(x.Initializer).AsType(); + defaultValue = initializer.GetText().ToString(); + } + + string pName; + /* + * ObjectBinding + * ts: + * function Func(p1, { p2, p3 }) { + * } + * c# + * void Func(object p1, object binding) + * { + * var p2 = binding.p2; + * var p3 = binding.p3; + * } + */ + if (x.Name.Kind == Ts.TsTypes.SyntaxKind.ObjectBindingPattern) + { + pName = $"binding{bindingCounter}"; + statements.AddRange(GenerateCSharpAst(x.Name, new NodeContext { Initializer = pName }).AsT1.Cast()); + bindingCounter++; + } + else + { + pName = x.Name.GetText(); + } + + TypeSyntax pType; + if (x.Type != null) + { + var type = GetType(x.Type); + if (type == _options.DefaultParameterType) + { + type = InferParameterType(x, funcName, pName, defaultValue); + } + + pType = SyntaxFactory.ParseTypeName(type); + } + else + { + pType = SyntaxFactory.ParseTypeName(InferParameterType(x, funcName, pName, defaultValue)); + } + + var parameter = SyntaxFactory.Parameter(SyntaxFactory.Identifier(pName)) + .WithType(pType); + if (initializer != null) + { + parameter = parameter.WithDefault(SyntaxFactory.EqualsValueClause(initializer)); + } + + return parameter; + }).ToArray(); + + var funcBody = n.Body; + switch (funcBody.Kind) + { + case Ts.TsTypes.SyntaxKind.Block: + { + var statement = GenerateCSharpAst(funcBody, new NodeContext() { ReturnType = returnType }).AsT1.Cast(); + statements.AddRange(statement); + break; + } + case Ts.TsTypes.SyntaxKind.ParenthesizedExpression: + { + var expression = funcBody.AsType(); + var statement = GenerateCSharpAst(expression.Expression, new NodeContext() { ReturnType = returnType }).AsType(); + statements.Add(SyntaxFactory.ReturnStatement(statement)); + break; + } + default: + { + var statement = GenerateCSharpAst(funcBody, new NodeContext() { ReturnType = returnType }).AsType(); + statements.Add(SyntaxFactory.ReturnStatement(statement)); + break; + } + } + + if (context is { UseLambda: true }) + { + return SyntaxFactory.ParenthesizedLambdaExpression(SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters)), SyntaxFactory.Block(statements)); + } + else + { + SyntaxToken[] tokens = _options.UseStaticMethod + ? [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)] + : [SyntaxFactory.Token(SyntaxKind.PublicKeyword)]; + var methodDeclaration = SyntaxFactory + .MethodDeclaration(SyntaxFactory.ParseTypeName(returnType), Format(funcName)) + .AddModifiers(tokens); + methodDeclaration = methodDeclaration.AddParameterListParameters(parameters); + return methodDeclaration.WithBody(SyntaxFactory.Block(statements)); + } + } + case Ts.TsTypes.SyntaxKind.ArrayLiteralExpression: + { + var n = node.AsType(); + var elements = n.Elements + .Where(x => x.Kind != Ts.TsTypes.SyntaxKind.SpreadElement) // remove SpreadElement + .Select(x => (SyntaxNodeOrToken)GenerateCSharpAst(x).AsT0) + .Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)); + + var type = context is { ReturnType: not null } ? context.ReturnType : InferArrayType(n); + var arrayType = SyntaxFactory.ArrayType(SyntaxFactory.IdentifierName(type)) + .WithRankSpecifiers( + SyntaxFactory.SingletonList( + SyntaxFactory.ArrayRankSpecifier( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.OmittedArraySizeExpression())))); + + var arrayCreation = SyntaxFactory.ArrayCreationExpression(arrayType) + .WithInitializer + ( + SyntaxFactory.InitializerExpression(SyntaxKind.ArrayInitializerExpression, SyntaxFactory.SeparatedList(elements)) + ); + + /* + * typescript + * var arr = [ + * { }, + * ...anotherArray + * ]; + * c# + * var arr = new object[] { + * new {} + * }.Union(anotherArray).ToArray(); + */ + ExpressionSyntax chain = arrayCreation; + var toArray = false; + foreach (var element in n.Elements.Where(x => x.Kind == Ts.TsTypes.SyntaxKind.SpreadElement)) + { + toArray = true; + var el = element.AsType(); + chain = SyntaxFactory.InvocationExpression( + SyntaxFactory.MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + chain, + SyntaxFactory.IdentifierName("Union") + ) + ).WithArgumentList( + SyntaxFactory.ArgumentList( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Argument(SyntaxFactory.IdentifierName(el.IdentifierStr)) + ) + ) + ); + } + + if (toArray) + { + return SyntaxFactory.InvocationExpression( + SyntaxFactory.MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + chain, + SyntaxFactory.IdentifierName("ToArray") + ) + ); + } + + return arrayCreation; + } + case Ts.TsTypes.SyntaxKind.AsExpression: + { + var n = node.AsType(); + var variable = GenerateCSharpAst(n.Expression).AsType(); + if (n.Type.Kind == Ts.TsTypes.SyntaxKind.TypeReference) + { + var typeNode = n.Type.AsType(); + if (typeNode.TypeName.Kind == Ts.TsTypes.SyntaxKind.MissingDeclaration) + { + return variable; + } + } + + var type = GetType(n.Type); + if (type == "double") + { + return SyntaxFactory.InvocationExpression( + SyntaxFactory.MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + SyntaxFactory.IdentifierName("Convert"), + SyntaxFactory.IdentifierName("ToDouble") + ) + ).WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(variable)))); + } + + return SyntaxFactory.BinaryExpression + ( + SyntaxKind.AsExpression, + variable, + SyntaxFactory.IdentifierName(type) + ); + } + case Ts.TsTypes.SyntaxKind.BinaryExpression: + { + var n = node.AsType(); + var operatorToken = GenerateOperatorToken(n.OperatorToken); + var left = GenerateCSharpAst(n.Left).AsType(); + var right = GenerateCSharpAst(n.Right).AsType(); + return SyntaxFactory.BinaryExpression(operatorToken, left, right); + } + case Ts.TsTypes.SyntaxKind.Block: + { + var n = node.AsType(); + var statements = new List(); + foreach (var statement in n.Statements) + { + if (statement.IsUnsupportedStatement()) continue; + var r = GenerateCSharpAst(statement, new NodeContext { IsLocalDeclaration = true, ReturnType = context?.ReturnType }); + if (r.IsT1) + { + statements.AddRange(r.AsT1); + } + else if (r.AsT0 != null) + { + statements.Add(r.AsT0); + } + } + + return statements; + } + case Ts.TsTypes.SyntaxKind.CallExpression: + { + var n = node.AsType(); + var args = new List(); + foreach (var argument in n.Arguments) + { + var ctx = new NodeContext() { FuncName = n.IdentifierStr, UseLambda = true }; + if (argument.Kind == Ts.TsTypes.SyntaxKind.ObjectLiteralExpression) + { + ctx.ReturnType = InferArgumentType(n); + } + + args.Add(SyntaxFactory.Argument(GenerateCSharpAst(argument, ctx).AsType())); + } + + return SyntaxFactory.InvocationExpression + ( + FormatNode(n.Expression).AsType(), + SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(args.Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)))) + ); + } + case Ts.TsTypes.SyntaxKind.ComputedPropertyName: + { + var n = node.AsType(); + return GenerateCSharpAst(n.Expression); + } + case Ts.TsTypes.SyntaxKind.ConditionalExpression: + { + var n = node.AsType(); + if (n.WhenFalse.Kind == Ts.TsTypes.SyntaxKind.MissingDeclaration) + { + return GenerateCSharpAst(n.WhenTrue, new NodeContext() { ConditionalToken = n.IdentifierStr }); + } + else if (n.WhenTrue.Kind == Ts.TsTypes.SyntaxKind.MissingDeclaration) + { + return GenerateCSharpAst(n.WhenFalse, new NodeContext() { ConditionalToken = n.IdentifierStr }); + } + else + { + var condition = GenerateCSharpAst(n.Condition).AsType(); + var whenTrue = GenerateCSharpAst(n.WhenTrue).AsType(); + var whenFalse = GenerateCSharpAst(n.WhenFalse).AsType(); + return SyntaxFactory.ConditionalExpression( + condition, + whenTrue, + whenFalse); + } + } + case Ts.TsTypes.SyntaxKind.ElementAccessExpression: + { + var n = node.AsType(); + var argExp = SyntaxFactory.Argument(GenerateCSharpAst(n.ArgumentExpression).AsType()); + return SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName(n.IdentifierStr)) + .WithArgumentList(SyntaxFactory.BracketedArgumentList(SyntaxFactory.SeparatedList(new ArgumentSyntax[] { argExp }))); + } + case Ts.TsTypes.SyntaxKind.ExportAssignment: + { + var n = node.AsType(); + SyntaxToken[] tokens = _options.UseStaticMethod + ? [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)] + : [SyntaxFactory.Token(SyntaxKind.PublicKeyword)]; + var funcName = _options.DefaultExportMethodName; + var returnType = InferReturnType(null, funcName); + var methodDeclaration = SyntaxFactory + .MethodDeclaration(SyntaxFactory.ParseTypeName(returnType), Format(funcName)) + .AddModifiers(tokens); + var exp = GenerateCSharpAst(n.Expression, new NodeContext() { UseLambda = true }).AsType(); + return methodDeclaration.WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(exp))); + } + case Ts.TsTypes.SyntaxKind.FalseKeyword: + { + return SyntaxFactory.LiteralExpression( + SyntaxKind.FalseLiteralExpression); + } + case Ts.TsTypes.SyntaxKind.ForStatement: + { + var n = node.AsType(); + var initializer = GenerateCSharpAst(n.Initializer).AsType(); + var condition = GenerateCSharpAst(n.Condition).AsType(); + var incrementor = GenerateCSharpAst(n.Incrementor).AsType(); + var body = SyntaxFactory.Block(); + return SyntaxFactory.ForStatement(body) + .WithDeclaration(initializer) + .WithCondition(condition) + .WithIncrementors(SyntaxFactory.SingletonSeparatedList(incrementor)); + } + case Ts.TsTypes.SyntaxKind.HeritageClause: + { + var n = node.AsType(); + return n.Types.Select(x => + { + if (x.TypeArguments is { Count: > 0 }) + { + var args = x.TypeArguments + .Select(x => (SyntaxNodeOrToken)SyntaxFactory.IdentifierName(x.GetText().Purify())) + .Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)); + + return (SyntaxNodeOrToken)SyntaxFactory.SimpleBaseType(SyntaxFactory + .GenericName(x.IdentifierStr) + .WithTypeArgumentList( + SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(args)))); + } + else + { + return (SyntaxNodeOrToken)SyntaxFactory.SimpleBaseType( + SyntaxFactory.IdentifierName(x.IdentifierStr)); + } + }).Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)).ToList(); + } + case Ts.TsTypes.SyntaxKind.Identifier: + { + var txt = node.GetText(); + // todo: filter ts keyword + if (txt == "undefined") + { + return SyntaxFactory.IdentifierName("default"); + } + + return SyntaxFactory.IdentifierName(txt); + } + case Ts.TsTypes.SyntaxKind.InterfaceDeclaration: + { + var n = node.AsType(); + var classDeclaration = SyntaxFactory + .ClassDeclaration(n.IdentifierStr) + .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); + if (n.HeritageClauses is { Count: > 0 }) + { + var heritageClauses = n.HeritageClauses.SelectMany(x => GenerateCSharpAst(x).AsT2); + classDeclaration = classDeclaration.WithBaseList + ( + SyntaxFactory.BaseList(SyntaxFactory.SeparatedList(heritageClauses)) + ); + } + + return classDeclaration; + } + case Ts.TsTypes.SyntaxKind.IntersectionType: + { + var n = node.AsType(); + var types = n.Types.Where(x => x.Kind != Ts.TsTypes.SyntaxKind.TypeLiteral) + .Select(x => (SyntaxNodeOrToken)GenerateCSharpAst(x).AsT0) + .Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)).ToList(); + return types; + } + case Ts.TsTypes.SyntaxKind.NewExpression: + { + var n = node.AsType(); + var args = n.Arguments + .Select(x => (SyntaxNodeOrToken)SyntaxFactory.Argument(GenerateCSharpAst(x).AsType())) + .Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)); + + return SyntaxFactory.ObjectCreationExpression(SyntaxFactory.IdentifierName(n.IdentifierStr)) + .WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(args))); + } + case Ts.TsTypes.SyntaxKind.NonNullExpression: + { + var n = node.AsType(); + return SyntaxFactory.PostfixUnaryExpression( + SyntaxKind.SuppressNullableWarningExpression, + SyntaxFactory.IdentifierName(n.IdentifierStr) + ); + } + case Ts.TsTypes.SyntaxKind.NumericLiteral: + { + var n = node.AsType(); + return SyntaxFactory.LiteralExpression + ( + SyntaxKind.NumericLiteralExpression, + SyntaxFactory.Literal(System.Convert.ToDouble(n.Text)) + ); + } + case Ts.TsTypes.SyntaxKind.ObjectBindingPattern: + { + var n = node.AsType(); + var initializer = context?.Initializer ?? string.Empty; + var bindings = new List(); + foreach (var el in n.Elements) + { + var item = (el as Ts.TsTypes.BindingElement)!; + var name = item.Name.GetText(); + var property = Format(item.PropertyName?.GetText() ?? name); + var variable = SyntaxFactory + .VariableDeclaration(SyntaxFactory.ParseTypeName("var")) + .AddVariables + ( + SyntaxFactory.VariableDeclarator(name).WithInitializer + ( + SyntaxFactory.EqualsValueClause + ( + SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(initializer), + SyntaxFactory.IdentifierName(property)) + ) + ) + ); + bindings.Add(SyntaxFactory.LocalDeclarationStatement(variable)); + } + + return bindings; + } + case Ts.TsTypes.SyntaxKind.ObjectLiteralExpression: + { + var n = node.AsType(); + var objectType = InferObjectType(n, context?.ReturnType); + /* + * todo: should not use return for property, return type only used for Function return eg: + * return { + * a: 'value' + * }; + */ + var assignments = n.Properties + .Where(x => x.IsProperty()) + .Select(x => (SyntaxNodeOrToken)GenerateCSharpAst(x, new NodeContext { ReturnType = objectType }).AsType()); + if (_options.UseAnonymousType) + { + return SyntaxFactory.AnonymousObjectCreationExpression() + .WithInitializers + ( + SyntaxFactory.SeparatedList(assignments.Select(x => SyntaxFactory.AnonymousObjectMemberDeclarator(x.AsNode().AsType()))) + ); + } + + return SyntaxFactory + .ObjectCreationExpression(SyntaxFactory.IdentifierName(objectType)) + .WithInitializer + ( + SyntaxFactory.InitializerExpression + ( + SyntaxKind.ObjectInitializerExpression, + SyntaxFactory.SeparatedList(assignments.Separate(SyntaxFactory.Token(SyntaxKind.CommaToken), true)) + ) + ); + } + case Ts.TsTypes.SyntaxKind.ParenthesizedExpression: + { + var n = node.AsType(); + return SyntaxFactory.ParenthesizedExpression(GenerateCSharpAst(n.Expression) + .AsType()); + } + case Ts.TsTypes.SyntaxKind.PostfixUnaryExpression: + { + var n = node.AsType(); + return SyntaxFactory.PostfixUnaryExpression( + GenerateOperatorToken(n.Operator), + SyntaxFactory.IdentifierName(n.IdentifierStr)); + } + case Ts.TsTypes.SyntaxKind.PrefixUnaryExpression: + { + var n = node.AsType(); + return SyntaxFactory.PrefixUnaryExpression + ( + SyntaxKind.UnaryMinusExpression, + GenerateCSharpAst(n.Operand).AsType() + ); + } + case Ts.TsTypes.SyntaxKind.PropertyAccessExpression: + { + var n = node.AsType(); + if (context is { ConditionalToken: not null }) + { + return SyntaxFactory.ConditionalAccessExpression( + SyntaxFactory.IdentifierName(context.ConditionalToken), + SyntaxFactory.MemberBindingExpression( + SyntaxFactory.IdentifierName(Format(n.Name.GetText())))); + } + + var expression = GenerateCSharpAst(n.Expression).AsType(); + return SyntaxFactory.MemberAccessExpression + ( + SyntaxKind.SimpleMemberAccessExpression, + expression, + SyntaxFactory.IdentifierName(Format(n.Name.GetText())) + ); + } + case Ts.TsTypes.SyntaxKind.PropertyAssignment: + { + var n = node.AsType(); + var initializer = n.Initializer; + ExpressionSyntax left; + if (n.Name.IsHtmlTag()) + { + left = SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName("")) + .WithArgumentList( + SyntaxFactory.BracketedArgumentList( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(n.Name.GetText())))))); + } + else + { + left = FormatNode(n.Name).AsType(); + if (n.Name.IsIndexerProperty()) + { + left = SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName("")) + .WithArgumentList( + SyntaxFactory.BracketedArgumentList( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Argument(left)))); + } + } + + var right = GenerateCSharpAst(initializer, context).AsType(); + return SyntaxFactory.AssignmentExpression + ( + SyntaxKind.SimpleAssignmentExpression, + left, + right + ); + } + case Ts.TsTypes.SyntaxKind.PropertySignature: + { + var n = node.AsType(); + var type = InferPropertyType(n); + return SyntaxFactory + .PropertyDeclaration(SyntaxFactory.ParseTypeName(type), Format(n.IdentifierStr)) + .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) + .AddAccessorListAccessors + ( + SyntaxFactory + .AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)), + SyntaxFactory + .AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) + ); + } + case Ts.TsTypes.SyntaxKind.ReturnStatement: + { + var n = node.AsType(); + return SyntaxFactory.ReturnStatement(GenerateCSharpAst(n.Expression, context).AsType()); + } + case Ts.TsTypes.SyntaxKind.ShorthandPropertyAssignment: + { + var n = node.AsType(); + var left = FormatNode(n.Name).AsType(); + var right = SyntaxFactory.IdentifierName(n.Name.GetText()); + return SyntaxFactory.AssignmentExpression + ( + SyntaxKind.SimpleAssignmentExpression, + left, + right + ); + } + case Ts.TsTypes.SyntaxKind.SpreadAssignment: + { + var n = node.AsType(); + var expression = GenerateCSharpAst(n.Expression).AsType(); + if (n.Parent.IsPropertyAssignment()) + { + var field = SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName("")) + .WithArgumentList( + SyntaxFactory.BracketedArgumentList( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Argument(SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, + SyntaxFactory.Literal("...")))))); + return SyntaxFactory.AssignmentExpression + ( + SyntaxKind.SimpleAssignmentExpression, + field, + expression + ); + } + + return expression; + } + case Ts.TsTypes.SyntaxKind.SourceFile: + { + SyntaxToken[] tokens = _options.UsePartialClass + ? [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)] + : [SyntaxFactory.Token(SyntaxKind.PublicKeyword)]; + return SyntaxFactory.ClassDeclaration(Format(_options.DefaultExportClassName)).AddModifiers(tokens); + } + case Ts.TsTypes.SyntaxKind.StringLiteral: + { + var n = node.AsType(); + return SyntaxFactory.LiteralExpression + ( + SyntaxKind.StringLiteralExpression, + SyntaxFactory.Literal(n.Text) + ); + } + case Ts.TsTypes.SyntaxKind.TemplateExpression: + { + var n = node.AsType(); + var spans = new List(); + foreach (var span in n.TemplateSpans) + { + var expression = GenerateCSharpAst(span.Expression).AsType(); + if (span.Expression.Kind == Ts.TsTypes.SyntaxKind.ConditionalExpression) + { + /* + * typescript: + * const str = `${true ? '123' : 'qwe'}`; + * csharp: + * var str = $"{(true ? "123" : "qwe")}"; + */ + expression = SyntaxFactory.ParenthesizedExpression(expression); + } + + spans.Add(SyntaxFactory.Interpolation(expression)); + spans.Add(SyntaxFactory.InterpolatedStringText( + SyntaxFactory.Token( + SyntaxFactory.TriviaList(), + SyntaxKind.InterpolatedStringTextToken, + span.Literal.Text, + "", + SyntaxFactory.TriviaList()))); + } + + return SyntaxFactory.InterpolatedStringExpression + ( + SyntaxFactory.Token(SyntaxKind.InterpolatedVerbatimStringStartToken), + SyntaxFactory.List(spans) + ); + } + case Ts.TsTypes.SyntaxKind.TrueKeyword: + { + return SyntaxFactory.LiteralExpression( + SyntaxKind.TrueLiteralExpression); + } + case Ts.TsTypes.SyntaxKind.TypeAliasDeclaration: + { + var n = node.AsType(); + var classDeclaration = SyntaxFactory.ClassDeclaration(Format(n.IdentifierStr)).AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); + switch (n.Type.Kind) + { + case Ts.TsTypes.SyntaxKind.UnionType: + { + return default; + } + case Ts.TsTypes.SyntaxKind.TypeLiteral: + { + var members = GenerateCSharpAst(n.Type).AsT1; + foreach (var member in members) + { + classDeclaration = classDeclaration.AddMembers(member.AsType()); + } + + return classDeclaration; + } + case Ts.TsTypes.SyntaxKind.IntersectionType: + { + var inter = n.Type.AsType(); + var type = inter.Types.FirstOrDefault(x => x.Kind == Ts.TsTypes.SyntaxKind.TypeLiteral); + if (type != null) + { + var members = GenerateCSharpAst(type).AsT1; + foreach (var member in members) + { + classDeclaration = classDeclaration.AddMembers(member.AsType()); + } + } + + goto default; + } + default: + var r = GenerateCSharpAst(n.Type); + var baseClasses = new List(); + if (r.IsT2) + { + baseClasses = r.AsT2; + } + else + { + baseClasses.Add(r.AsT0); + } + + if (baseClasses is { Count: > 0 }) + { + classDeclaration = classDeclaration.WithBaseList + ( + SyntaxFactory.BaseList(SyntaxFactory.SeparatedList(baseClasses)) + ); + } + + return classDeclaration; + } + } + case Ts.TsTypes.SyntaxKind.TypeLiteral: + { + var n = node.AsType(); + return n.Members.Select(x => GenerateCSharpAst(x).AsT0).ToList(); + } + case Ts.TsTypes.SyntaxKind.TypeReference: + { + var n = node.AsType(); + if (n.TypeArguments is { Count: > 0 }) + { + var args = n.TypeArguments + .Select(x => (SyntaxNodeOrToken)SyntaxFactory.IdentifierName(x.GetText().Purify())) + .Separate(SyntaxFactory.Token(SyntaxKind.CommaToken)); + + return SyntaxFactory.SimpleBaseType(SyntaxFactory + .GenericName(n.IdentifierStr) + .WithTypeArgumentList( + SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(args)))); + } + else + { + return SyntaxFactory.SimpleBaseType( + SyntaxFactory.IdentifierName(n.IdentifierStr)); + } + } + case Ts.TsTypes.SyntaxKind.FirstTemplateToken: + { + var n = node.AsType(); + return SyntaxFactory.LiteralExpression + ( + SyntaxKind.StringLiteralExpression, + SyntaxFactory.Literal(n.Text) + ); + } + case Ts.TsTypes.SyntaxKind.VariableDeclaration: + { + var n = node.AsType(); + var c = new NodeContext() { UseLambda = true }; + if (n.Type is { Kind: Ts.TsTypes.SyntaxKind.TypeReference }) + { + c.ReturnType = n.Type.AsType().IdentifierStr; + } + + var identifier = GenerateCSharpAst(n.Initializer, c).AsType(); + return SyntaxFactory + .VariableDeclaration(SyntaxFactory.IdentifierName("var")) + .AddVariables + ( + SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(n.IdentifierStr)).WithInitializer(SyntaxFactory.EqualsValueClause(identifier)) + ); + } + case Ts.TsTypes.SyntaxKind.VariableDeclarationList: + { + var n = node.AsType(); + var variables = n.Declarations.Select(x => + { + var identifier = GenerateCSharpAst(x.Initializer).AsType(); + return SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(x.IdentifierStr)).WithInitializer(SyntaxFactory.EqualsValueClause(identifier)); + }); + return SyntaxFactory + .VariableDeclaration(SyntaxFactory.IdentifierName("var")) + .WithVariables(SyntaxFactory.SeparatedList(variables)); + } + case Ts.TsTypes.SyntaxKind.VariableStatement: + { + var n = node.AsType(); + // todo: ast parser error, it should not be empty. + if (n.DeclarationList.Declarations.Count <= 0) return default; + var declaration = n.DeclarationList.Declarations[0]; + if (context is { IsLocalDeclaration: true }) + { + if (declaration.Name.Kind == Ts.TsTypes.SyntaxKind.ObjectBindingPattern) + { + var initializer = declaration.Initializer?.GetText() ?? string.Empty; + return GenerateCSharpAst(declaration.Name, new NodeContext() + { + Initializer = initializer + }); + } + + return SyntaxFactory.LocalDeclarationStatement(GenerateCSharpAst(declaration).AsType()); + } + + if (declaration.Initializer.Kind == Ts.TsTypes.SyntaxKind.Identifier && declaration.Name.Kind != Ts.TsTypes.SyntaxKind.Identifier) + { + var initializer = declaration.Initializer?.GetText() ?? string.Empty; + return GenerateCSharpAst(declaration.Name, new NodeContext + { + Initializer = initializer + }); + } + else if (declaration.Initializer.Kind == Ts.TsTypes.SyntaxKind.ArrowFunction) + { + var funcName = declaration.Name.GetText(); + return GenerateCSharpAst(declaration.Initializer, new NodeContext + { + FuncName = funcName + }); + } + else + { + var name = declaration.Name.GetText(); + var type = InferVariableType(declaration); + var variableDeclaration = SyntaxFactory + .VariableDeclaration(SyntaxFactory.IdentifierName(type)) + .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(name)))); + var expression = GenerateCSharpAst(declaration.Initializer).AsType(); + var equalsValueClause = SyntaxFactory.EqualsValueClause(expression); + SyntaxToken[] tokens = _options.UseStaticMethod + ? [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)] + : [SyntaxFactory.Token(SyntaxKind.PublicKeyword)]; + return SyntaxFactory.FieldDeclaration + ( + variableDeclaration.WithVariables + ( + SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(name)) + .WithInitializer(equalsValueClause)) + ) + ) + .WithModifiers(SyntaxFactory.TokenList(tokens)); + } + } + default: return default; + } + } + catch (TypeInferenceException) + { + throw; + } + catch (AstGenerateException) + { + throw; + } + catch (Exception ex) + { + var n = node.AsType(); + var start = GetLineNumber(n.SourceStr, n.NodeStart); + var end = GetLineNumber(n.SourceStr, n.End.Value); + var len = n.End.Value - n.NodeStart; + var code = n.SourceStr.Substring(n.NodeStart, len); + throw new AstGenerateException(start, end, code); + } + } + + private SyntaxKind GenerateOperatorToken(Ts.TsTypes.SyntaxKind node) + { + switch (node) + { + case Ts.TsTypes.SyntaxKind.MinusMinusToken: + return SyntaxKind.PostDecrementExpression; + case Ts.TsTypes.SyntaxKind.PlusPlusToken: + return SyntaxKind.PostIncrementExpression; + default: + throw new Exception("Typescript SyntaxKind map error."); + } + } + + private SyntaxKind GenerateOperatorToken(Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.AmpersandAmpersandToken: + return SyntaxKind.LogicalAndExpression; + case Ts.TsTypes.SyntaxKind.AsteriskToken: + return SyntaxKind.MultiplyExpression; + case Ts.TsTypes.SyntaxKind.BarBarToken: + return SyntaxKind.CoalesceExpression; + case Ts.TsTypes.SyntaxKind.EqualsEqualsToken: + case Ts.TsTypes.SyntaxKind.EqualsEqualsEqualsToken: + return SyntaxKind.EqualsExpression; + case Ts.TsTypes.SyntaxKind.GreaterThanToken: + return SyntaxKind.GreaterThanExpression; + case Ts.TsTypes.SyntaxKind.GreaterThanEqualsToken: + return SyntaxKind.GreaterThanOrEqualExpression; + case Ts.TsTypes.SyntaxKind.LessThanToken: + return SyntaxKind.LessThanExpression; + case Ts.TsTypes.SyntaxKind.LessThanEqualsToken: + return SyntaxKind.LessThanOrEqualExpression; + case Ts.TsTypes.SyntaxKind.MinusToken: + return SyntaxKind.SubtractExpression; + case Ts.TsTypes.SyntaxKind.PlusToken: + return SyntaxKind.AddExpression; + case Ts.TsTypes.SyntaxKind.SlashToken: + return SyntaxKind.DivideExpression; + default: + throw new Exception("Typescript SyntaxKind map error."); + } + } + + private SyntaxNodeOrList FormatNode(Ts.TsTypes.INode node) + { + if (node.Kind == Ts.TsTypes.SyntaxKind.Identifier) + { + return SyntaxFactory.IdentifierName(Format(node.GetText())); + } + + return GenerateCSharpAst(node); + } + + private string GetType(Ts.TsTypes.INode node) + { + switch (node.Kind) + { + case Ts.TsTypes.SyntaxKind.BooleanKeyword: + return "bool"; + case Ts.TsTypes.SyntaxKind.NumberKeyword: + return "double"; + case Ts.TsTypes.SyntaxKind.StringKeyword: + return "string"; + case Ts.TsTypes.SyntaxKind.IndexedAccessType: + { + /* + * typescript: + * interface A { + * defaultPadding: CSSProperties['padding'] + * } + */ + var type = node.AsType(); + var objectType = type.ObjectType.GetText(); + var indexType = type.IndexType.GetText(); + var token = new IndexedAccessType(_options, objectType, indexType); + return InferenceEngine.Infer(token, objectType); + } + case Ts.TsTypes.SyntaxKind.UnionType: + { + var unionType = node.AsType(); + // if type is 'a' | 'b' or 1 | 2 + if (unionType.Types.All(x => x.Kind == Ts.TsTypes.SyntaxKind.LiteralType)) + { + var t = unionType.Types.First().AsType(); + switch (t.Literal.Kind) + { + case Ts.TsTypes.SyntaxKind.StringLiteral: + return "string"; + case Ts.TsTypes.SyntaxKind.NumericLiteral: + return "double"; + } + } + // todo: eg: string | number | bool | object + var types = unionType.Types.Select(x => x.GetText()).ToArray(); + var token = new UnionType(_options, types); + return InferenceEngine.Infer(token, _options.DefaultObjectType); + } + default: + { + return node.GetText(); + } + } + } + + private string Format(string text) + { + if (_options.UsePascalCase) + { + return text.ToPascalCase(); + } + + return text; + } + + private string InferObjectType(Ts.TsTypes.ObjectLiteralExpression node, string? defaultType = null) + { + var token = new ObjectType(_options); + if (node.Properties != null) + { + var properties = node.Properties.Where(x => x.Kind == Ts.TsTypes.SyntaxKind.PropertyAssignment).Select(x => x.AsType()); + token.Properties = properties + .Where(x => !x.Name.IsIndexerProperty()) + .Select(x => x.Name.GetText()).ToArray(); + if (token.Properties.Length <= 0) token.Properties = null; + if (properties.Any(x => x.Name.IsIndexerProperty())) + { + token.HasIndexer = true; + } + else if(node.Properties.Any(x => x.Kind == Ts.TsTypes.SyntaxKind.SpreadAssignment)) + { + token.HasIndexer = true; + } + } + + return InferenceEngine.Infer(token, defaultType ?? _options.DefaultObjectType); + } + + private string InferReturnType(Ts.TsTypes.ArrowFunction? node, string funcName) + { + if (node == null) + { + var token = new ReturnType(_options, funcName); + return InferenceEngine.Infer(token, _options.DefaultReturnType); + } + else + { + string? valueType = null; + Ts.TsTypes.INode? returnValue = null; + if (node.Body.Kind == Ts.TsTypes.SyntaxKind.Block) + { + var statement = node.Body.AsType().Statements + .Where(x => x.Kind == Ts.TsTypes.SyntaxKind.ReturnStatement) + .Select(x => x.AsType()) + .FirstOrDefault(); + + if (statement is { Expression.Kind: Ts.TsTypes.SyntaxKind.ObjectLiteralExpression }) + { + returnValue = statement.Expression; + valueType = "object"; + } + + if (statement is { Expression.Kind: Ts.TsTypes.SyntaxKind.ArrayLiteralExpression }) + { + valueType = "array"; + } + } + + if (node.Body.Kind == Ts.TsTypes.SyntaxKind.ParenthesizedExpression) + { + var exp = node.Body.AsType().Expression; + if (exp.Kind == Ts.TsTypes.SyntaxKind.ObjectLiteralExpression) + { + returnValue = exp; + valueType = "object"; + } + } + + if (node.Body.Kind == Ts.TsTypes.SyntaxKind.ArrayLiteralExpression) + { + valueType = "array"; + } + + var token = new ReturnType(_options, funcName, valueType); + var returnType = InferenceEngine.Infer(token, _options.DefaultReturnType); + if (returnType != _options.DefaultReturnType) + { + return returnType; + } + + if (returnValue == null) + { + return _options.DefaultReturnType; + } + else + { + switch (valueType) + { + case "object": + return InferObjectType(returnValue.AsType()); + } + } + + return _options.DefaultReturnType; + } + } + + private string InferParameterType(Ts.TsTypes.ParameterDeclaration node, string funcName, string name, string? defaultValue) + { + // try parse default value + if (defaultValue != null) + { + if (double.TryParse(defaultValue, out _)) + { + return "double"; + } + + if (bool.TryParse(defaultValue, out _)) + { + return "bool"; + } + + if (Regex.IsMatch(defaultValue, @"^""\w*""$")) + { + return "string"; + } + } + + var token = new ParameterType(_options, name, funcName, defaultValue); + return InferenceEngine.Infer(token, _options.DefaultParameterType); + } + + private string InferPropertyType(Ts.TsTypes.PropertySignature node) + { + var token = new PropertyType(_options, node.IdentifierStr); + if (node.Type.Kind == Ts.TsTypes.SyntaxKind.IndexedAccessType) + { + var type = node.Type.AsType(); + var objectType = type.ObjectType.GetText(); + var indexType = type.IndexType.GetText(); + token.IndexedAccessType = new IndexedAccessType(_options, objectType, indexType); + } + else if (node.Type.Kind == Ts.TsTypes.SyntaxKind.UnionType) + { + var unionType = node.Type.AsType(); + var types = unionType.Types.Select(x => x.GetText()).ToArray(); + token.UnionType = new UnionType(_options, types); + } + + return InferenceEngine.Infer(token, GetType(node.Type)); + } + + private string InferVariableType(Ts.TsTypes.VariableDeclaration node) + { + if (node.Initializer.Kind == Ts.TsTypes.SyntaxKind.NewExpression) + { + var exp = node.Initializer.AsType().Expression; + return exp.GetText(); + } + return _options.DefaultVariableType; + } + + private string InferArrayType(Ts.TsTypes.ArrayLiteralExpression node) + { + var element = node.Elements.FirstOrDefault(); + if (element == null) return "object"; + + if (element.Kind == Ts.TsTypes.SyntaxKind.StringLiteral) + { + return "string"; + } + return "object"; + } + + private string InferArgumentType(Ts.TsTypes.CallExpression node) + { + // todo: how to parse Type to + if (node.TypeArguments is { Count: > 0 }) + { + var typeArgument = node.TypeArguments[0]; + if (typeArgument.Kind == Ts.TsTypes.SyntaxKind.IntersectionType) + { + var intersectionType = typeArgument.AsType(); + if (intersectionType.Types is { Count: > 0 }) + { + var type = intersectionType.Types[0]; + if (type.Kind == Ts.TsTypes.SyntaxKind.TypeReference) + { + return type.AsType().IdentifierStr; + } + } + } + + if (typeArgument.Kind == Ts.TsTypes.SyntaxKind.TypeReference) + { + return typeArgument.AsType().IdentifierStr; + } + } + + return "object"; + } + + private static int GetLineNumber(string text, int index) + { + if (index < 0 || index > text.Length) + throw new ArgumentOutOfRangeException(nameof(index), "Index is out of the range of the text."); + + var line = 1; + for (var i = 0; i < index; i++) + { + if (text[i] == '\n') + line++; + } + + return line; + } + } + + public class NodeContext + { + public string? ReturnType { get; set; } + public string? Initializer { get; set; } + public string? FuncName { get; set; } + public bool UseLambda { get; set; } + public string? ConditionalToken { get; set; } + public bool IsLocalDeclaration { get; set; } + } + + public struct SyntaxNodeOrList + { + private readonly int _index; + private readonly SyntaxNode _value0; + private readonly List _value1; + private readonly List _value2; + + private SyntaxNodeOrList( + int index, + SyntaxNode value0 = default, + List value1 = default, + List value2 = default) + { + _index = index; + _value0 = value0; + _value1 = value1; + _value2 = value2; + } + + public static implicit operator SyntaxNodeOrList(SyntaxNode t) => new(0, value0: t); + public static implicit operator SyntaxNodeOrList(List t) => new(1, value1: t); + public static implicit operator SyntaxNodeOrList(List t) => new(2, value2: t); + + public T AsType() where T : SyntaxNode + { + return _index == 0 ? + (T)_value0 : + throw new InvalidOperationException($"Cannot return as T0 as result is T{_index}"); + } + + public bool IsType() + { + if (_index == 0) + { + return _value0.GetType().IsAssignableFrom(typeof(T)); + } + + return false; + } + + public bool IsT0 => _index == 0; + public bool IsT1 => _index == 1; + public bool IsT2 => _index == 2; + + public SyntaxNode AsT0 => + _index == 0 ? + _value0 : + throw new InvalidOperationException($"Cannot return as T0 as result is T{_index}"); + + public List AsT1 => + _index == 1 ? + _value1 : + throw new InvalidOperationException($"Cannot return as T1 as result is T{_index}"); + + public List AsT2 => + _index == 2 ? + _value2 : + throw new InvalidOperationException($"Cannot return as T2 as result is T{_index}"); + } +} diff --git a/generators/CssInCSharp.Generator/TypeToken.cs b/generators/CssInCSharp.Generator/TypeToken.cs new file mode 100644 index 0000000..f80d970 --- /dev/null +++ b/generators/CssInCSharp.Generator/TypeToken.cs @@ -0,0 +1,137 @@ +namespace CssInCSharp.Generator +{ + public class ObjectType + { + public string Kind { get; set; } = nameof(ObjectType); + public CSharpOptions CsOptions { get; set; } + public string[]? Properties { get; set; } + public bool HasIndexer { get; set; } + public ObjectType(CSharpOptions options) + { + CsOptions = options; + } + + public bool HasKey(string key) + { + return Properties != null && Properties.Contains(key); + } + + public bool HasAny(params string[] keys) + { + return Properties != null && Properties.Any(keys.Contains); + } + + public bool HasAll(params string[] keys) + { + return Properties != null && keys.All(Properties.Contains); + } + } + + public class ReturnType + { + public string Kind { get; set; } = nameof(ReturnType); + public CSharpOptions CsOptions { get; set; } + public string FunctionName { get; set; } + public string? ValueType { get; set; } + + public ReturnType(CSharpOptions options, string funcName, string? valueType = null) + { + FunctionName = funcName; + CsOptions = options; + ValueType = valueType; + } + } + + public class ParameterType + { + public string Kind { get; set; } = nameof(ParameterType); + public CSharpOptions CsOptions { get; set; } + public string Name { get; set; } + public string FunctionName { get; set; } + public string? DefaultValue { get; set; } + public ParameterType(CSharpOptions options, string name, string functionName, string? defaultValue) + { + CsOptions = options; + Name = name; + FunctionName = functionName; + DefaultValue = defaultValue; + } + } + + public class PropertyType + { + public string Kind { get; set; } = nameof(PropertyType); + + public CSharpOptions CsOptions { get; set; } + + public string Name { get; set; } + + public IndexedAccessType? IndexedAccessType { get; set; } + + public UnionType? UnionType { get; set; } + + public PropertyType(CSharpOptions options, string name, IndexedAccessType? indexedAccessType = null, UnionType? unionType = null) + { + CsOptions = options; + Name = name; + IndexedAccessType = indexedAccessType; + UnionType = unionType; + } + + public bool ContainsAny(params string[] keys) + { + foreach (var key in keys) + { + if (Name.Contains(key)) + { + return true; + } + } + + return false; + } + } + + public class IndexedAccessType + { + public string Kind { get; set; } = nameof(IndexedAccessType); + + public CSharpOptions CsOptions { get; set; } + + public string ObjectType { get; set; } + + public string IndexType { get; set; } + + public IndexedAccessType(CSharpOptions options, string objectType, string indexType) + { + CsOptions = options; + ObjectType = objectType; + IndexType = indexType; + } + } + + public class UnionType + { + public string Kind { get; set; } = nameof(UnionType); + + public CSharpOptions CsOptions { get; set; } + + public string[] Types { get; set; } + + public UnionType(CSharpOptions options, string[] types) + { + CsOptions = options; + Types = types; + } + + public bool HasAny(params string[] keys) + { + return Types.Any(keys.Contains); + } + + public bool HasAll(params string[] keys) + { + return keys.All(Types.Contains); + } + } +} diff --git a/generators/Generator.sln b/generators/Generator.sln new file mode 100644 index 0000000..139da2c --- /dev/null +++ b/generators/Generator.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{810921B6-B6EF-4337-9801-451BED454526}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CssInCSharp.Ast.TypeScript", "CssInCSharp.Ast.TypeScript\CssInCSharp.Ast.TypeScript.csproj", "{8C55A694-4D2F-4C9D-9E03-B62A0120082D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CssInCSharp.Generator", "CssInCSharp.Generator\CssInCSharp.Generator.csproj", "{3055588C-7DC4-41D5-A295-E245E17CB968}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CssInCSharp.CommandLine", "CssInCSharp.CommandLine\CssInCSharp.CommandLine.csproj", "{D21682D4-234F-4215-8F8B-89FF53F26832}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C55A694-4D2F-4C9D-9E03-B62A0120082D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C55A694-4D2F-4C9D-9E03-B62A0120082D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C55A694-4D2F-4C9D-9E03-B62A0120082D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C55A694-4D2F-4C9D-9E03-B62A0120082D}.Release|Any CPU.Build.0 = Release|Any CPU + {3055588C-7DC4-41D5-A295-E245E17CB968}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3055588C-7DC4-41D5-A295-E245E17CB968}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3055588C-7DC4-41D5-A295-E245E17CB968}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3055588C-7DC4-41D5-A295-E245E17CB968}.Release|Any CPU.Build.0 = Release|Any CPU + {D21682D4-234F-4215-8F8B-89FF53F26832}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D21682D4-234F-4215-8F8B-89FF53F26832}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D21682D4-234F-4215-8F8B-89FF53F26832}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D21682D4-234F-4215-8F8B-89FF53F26832}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {8C55A694-4D2F-4C9D-9E03-B62A0120082D} = {810921B6-B6EF-4337-9801-451BED454526} + {3055588C-7DC4-41D5-A295-E245E17CB968} = {810921B6-B6EF-4337-9801-451BED454526} + {D21682D4-234F-4215-8F8B-89FF53F26832} = {810921B6-B6EF-4337-9801-451BED454526} + EndGlobalSection +EndGlobal diff --git a/generators/README.md b/generators/README.md new file mode 100644 index 0000000..799bc03 --- /dev/null +++ b/generators/README.md @@ -0,0 +1,113 @@ +# CssInCSharp Generator + +In order to be able to migrate cssinjs style code or css style files to C# code, CssInCSharp implements a code migration tool. + +## Usage +Install the command-line tools +```sh +dotnet tool install -g CssInCSharp.CommandLine +``` + +```sh +cssincs --help + +Usage: + CssInCSharp.CommandLine [command] [options] [[--] ...]] + +Options: + --version Show version information + -?, -h, --help Show help and usage information + +Commands: + init Init an empty configuration file. + convert Convert css file to c#. +Additional Arguments: + Arguments passed to the application that is being run. +``` + +## Examples +- `cssincs init` + + Initialize an empty profile `cssincs.json`. + +- `cssincs convert -c cssincs.json` + + Use the specified profile for conversions. + +- `cssincs convert -t ts -s src/style.ts -d dest/style.cs` + + Convert the specified TS file to C# code. + +## Options + +- `--config, -c` + + Specify the profile for conversion. eg: ./cssincs.json + +- `--source, -s` + + Source file path. This parameter is required if no profile is specified. eg: `./src/style.ts`, or use file globbing eg: `./src/**/*.ts`. + +- `--dest, -d` + + The destination file, if not specified, will be output to the source file path. + +- `--type, -t` + + The converter type supports `ts, css, less` etc. + +- `--dry-run` + + Dry run and output the result to the console. + +## Profile +Profile is recommended when you need to do a lot of file conversions or when you need to control the content of the output code. + +Full profile example: + +```json +{ + "Converter": "ts", + "CsOptions": { + "Usings": [ + "System", + "CssInCSharp", + "CssInCSharp.Colors", + "static CssInCSharp.Css.CSSUtil", + "Keyframes = CssInCSharp.Keyframe" + ], + "Namespace": "CssInCSharp.Styles", + "NamePrefix": "{dir:../../}", + "DefaultReturnType": "object", + "DefaultParameterType": "object", + "DefaultFieldType": "object", + "DefaultClassName": "{dir:../../}Style", + "DefaultExportMethodName": "{file}Default", + "UsePascalCase": true, + "UsePartialClass": true, + "UseStaticMethod": true, + "UseTypeInference": true, + "TypeInferences": [ + { + "Pattern": "^token$", + "Value": "{NamePrefix}Token" + } + ], + "Replacements": [ + { + "Pattern": "FullToken(\\<\\w*\\>)?", + "Value": "ComponentToken" + } + ] + }, + "Include": [ + { + "Src": "../ant-design/components/**/style/*.ts", + "Dest": "./components" + } + ], + "Exclude": [ + "../ant-design/components/style/*.ts" + ] +} +```