internal SyntaxTree(string sourceText,
                            SyntaxNode root,
                            SyntaxTokenList tokens,
                            IReadOnlyList<TextLineExtent> textLines,
                            IReadOnlyList<Diagnostic> diagnostics,
                            FileInfo fileInfo,
                            Encoding encoding) {

            _sourceText  = sourceText ?? String.Empty;
            _root        = root;
            _fileInfo        = fileInfo;
            _encoding    = encoding;
            _diagnostics = diagnostics ?? Enumerable.Empty<Diagnostic>().ToList();
            _tokens      = tokens      ?? new SyntaxTokenList();
            _textLines   = textLines   ?? new List<TextLineExtent>();
        }
 void CheckNonNullChild(SyntaxNode node) {
     Assert.That(node, Is.Not.Null);
     foreach (var child in node.ChildNodes()) {
         CheckNonNullChild(child);
     }
 }
        static SyntaxTokenList PostprocessTokens(List<SyntaxToken> tokens, NavCommonTokenStream cts, SyntaxNode syntax, CancellationToken cancellationToken) {

            var result = new List<SyntaxToken>(cts.AllTokens.Count);
            tokens.Sort((x, y) => x.Start - y.Start);

            // Wir haben bereits die signifikanten Token (T) im GrammarVisitor erstellt.
            // Wir können nicht alle Tokens hier ermitteln, da der Visitor viel mehr Kontextinformationen
            // hat. Somit wird aus einem "Identifier" z.B. je nach Kontext ein Keyword, oder Symbol (=> Classification).
            // Was uns hier jedoch noch fehlt sind vor allem die Whitespaces (w) und "unbekannten" (u),
            // die der Parser nie zu Gesicht bekommt. Der TokenStream liefert uns alle Token
            // (candidates = c):
            // -T---TTT---T----T-- <= bereits im Visitor erfasste Token
            // ccccccccccccccccccc <= alle Tokens (candidates)
            // wTwwwTTTwwwTwwwwTuu <= die Tokens, wie wir sie hier haben wollen
            var index = 0;
            foreach (var candidate in cts.AllTokens) {

                cancellationToken.ThrowIfCancellationRequested();

                if (index < tokens.Count) {
                    var existing = tokens[index];
                    // Das Token wurde bereits im Visitor erfasst (T)
                    if (existing.Start == candidate.StartIndex) {
                        result.Add(existing);
                        index++;
                        continue;
                    }
                }
                // Das Token existiert noch nicht, da es der Parser/Visitor offensichtlich nicht "erwischt hat" (t, u)
                SyntaxTokenClassification tokenClassification;
                switch (candidate.Channel) {
                    case NavGrammarLexer.TriviaChannel:
                        switch (candidate.Type) {
                            case NavGrammarLexer.NewLine:
                                tokenClassification = SyntaxTokenClassification.Whitespace;
                                break;
                            case NavGrammarLexer.Whitespace:
                                tokenClassification = SyntaxTokenClassification.Whitespace;
                                break;
                            case NavGrammarLexer.SingleLineComment:
                                tokenClassification = SyntaxTokenClassification.Comment;
                                break;
                            case NavGrammarLexer.MultiLineComment:
                                tokenClassification = SyntaxTokenClassification.Comment;
                                break;
                            case NavGrammarLexer.Unknown:
                                tokenClassification = SyntaxTokenClassification.Skiped;
                                break;
                            default:
                                // Wir haben sonst eigentlich nix im Trivia Channel
                                throw new ArgumentException();
                        }
                        break;
                    case Lexer.DefaultTokenChannel:
                        tokenClassification = SyntaxTokenClassification.Skiped;
                        break;
                    default:
                        throw new ArgumentException();
                }
                
                //TODO: hier evtl. den "echten" Parent herausfinden...
                SyntaxNode parent = syntax;
                result.Add(SyntaxTokenFactory.CreateToken(candidate, tokenClassification, parent));
            }

            return new SyntaxTokenList(result);
        }
        internal SyntaxToken(SyntaxNode parent, SyntaxTokenType type, SyntaxTokenClassification classification, TextExtent extent) {
            _extent  = extent;
            _parent  = parent;

            _classificationAndType = ((int)type << TypeBitShift) | ((int)classification << ClassificationBitShift);
        }