Example #1
0
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List <UnsavedFile> unsavedFiles, Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var response = await dataAssociation.Solution.Server.Highlight(file.FilePath, unsavedFiles.FirstOrDefault()?.Contents);

            if (response != null)
            {
                foreach (var highlight in response.Highlights)
                {
                    result.SyntaxHighlightingData.Add(new LineColumnSyntaxHighlightingData
                    {
                        StartLine   = highlight.StartLine,
                        EndLine     = highlight.EndLine,
                        StartColumn = highlight.StartColumn,
                        EndColumn   = highlight.EndColumn,
                        Type        = ToAvalonHighlightType(highlight.Kind)
                    });
                }

                dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);
            }

            return(result);
        }
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(IEditor editor, List <UnsavedFile> unsavedFiles, Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var textLength = 0;

            await Dispatcher.UIThread.InvokeAsync(() => { textLength = editor.Document.TextLength; });

            var dataAssociation = GetAssociatedData(editor);

            var document = GetDocument(dataAssociation, editor.SourceFile);

            if (document == null)
            {
                return(result);
            }

            // Example how to get file specific diagnostics.

            /*var model = await document.GetSemanticModelAsync();
             *
             * var diagnostics = model.GetDiagnostics();*/

            try
            {
                var highlightData = await Classifier.GetClassifiedSpansAsync(document, new Microsoft.CodeAnalysis.Text.TextSpan(0, textLength));

                foreach (var span in highlightData)
                {
                    result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData {
                        Start = span.TextSpan.Start, Length = span.TextSpan.Length, Type = FromRoslynType(span.ClassificationType)
                    });
                }
            }
            catch (NullReferenceException)
            {
            }

            result.IndexItems = await IndexBuilder.Compute(document);

            return(result);
        }
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(IEnumerable <UnsavedFile> unsavedFiles,
                                                                     Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var clangUnsavedFiles = new List <ClangUnsavedFile>();

            clangUnsavedFiles.AddRange(unsavedFiles.Select(f => new ClangUnsavedFile(f.FileName, f.Contents)));

            var diagnostics = new List <Diagnostic>();

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                try
                {
                    var translationUnit = GetAndParseTranslationUnit(clangUnsavedFiles);

                    if (translationUnit != null)
                    {
                        if (_editor.SourceFile != null && translationUnit != null)
                        {
                            ScanTokens(translationUnit, result.SyntaxHighlightingData);

                            GenerateHighlightData(translationUnit.GetCursor(), result.SyntaxHighlightingData, result.IndexItems);
                        }

                        GenerateDiagnostics(translationUnit.DiagnosticSet.Items, translationUnit, _editor.SourceFile, diagnostics);
                    }
                }
                catch (Exception)
                {
                }
            });

            var errorList = IoC.Get <IErrorList>();

            errorList.Remove((this, _editor.SourceFile));
            errorList.Create((this, _editor.SourceFile), _editor.SourceFile.FilePath, DiagnosticSourceKind.Analysis, diagnostics.ToImmutableArray());

            return(result);
        }
Example #4
0
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List <UnsavedFile> unsavedFiles,
                                                                     Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var clangUnsavedFiles = new List <ClangUnsavedFile>();

            clangUnsavedFiles.AddRange(unsavedFiles.Select(f => new ClangUnsavedFile(f.FileName, f.Contents)));

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                try
                {
                    var translationUnit = GetAndParseTranslationUnit(file, clangUnsavedFiles);

                    if (translationUnit != null)
                    {
                        if (file != null && translationUnit != null)
                        {
                            ScanTokens(translationUnit, result.SyntaxHighlightingData);

                            GenerateHighlightData(translationUnit.GetCursor(), result.SyntaxHighlightingData);
                        }

                        dataAssociation.TextMarkerService.Clear();

                        GenerateDiagnostics(translationUnit.DiagnosticSet.Items, translationUnit, file.Project, result.Diagnostics, dataAssociation.TextMarkerService);
                    }
                }
                catch (Exception e)
                {
                }
            });

            dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);

            return(result);
        }
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(IEditor editor, List <UnsavedFile> unsavedFiles,
                                                                     Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(editor.SourceFile);

            var clangUnsavedFiles = new List <ClangUnsavedFile>();

            clangUnsavedFiles.AddRange(unsavedFiles.Select(f => new ClangUnsavedFile(f.FileName, f.Contents)));

            var diagnostics = new List <Diagnostic>();

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                try
                {
                    var translationUnit = GetAndParseTranslationUnit(editor, clangUnsavedFiles);

                    if (translationUnit != null)
                    {
                        if (editor.SourceFile != null && translationUnit != null)
                        {
                            ScanTokens(translationUnit, result.SyntaxHighlightingData);

                            GenerateHighlightData(translationUnit.GetCursor(), result.SyntaxHighlightingData, result.IndexItems);
                        }

                        GenerateDiagnostics(translationUnit.DiagnosticSet.Items, translationUnit, editor.SourceFile, diagnostics);
                    }
                }
                catch (Exception e)
                {
                }
            });

            DiagnosticsUpdated?.Invoke(this, new DiagnosticsUpdatedEventArgs(this, editor.SourceFile, diagnostics.Count > 0 ? DiagnosticsUpdatedKind.DiagnosticsCreated : DiagnosticsUpdatedKind.DiagnosticsRemoved, diagnostics.ToImmutableArray()));

            return(result);
        }
Example #6
0
        private void HighlightNode(INode node, CodeAnalysisResults result)
        {
            var highlightData = new OffsetSyntaxHighlightingData();
            int startPos = 0, endPos = 0;

            // This will add highlighting data for declarations, but it will not show up because it is set to highlight as None
            if (node is IDeclaration)
            {
                var declaration = (IDeclaration)node;
                startPos = declaration.Position;
                endPos   = declaration.End;
                if (startPos >= 0 && endPos > 0)
                {
                    if (node is VariableDeclaration)
                    {
                        // For variables, we only want to highlight the name, not the expression
                        startPos = ((VariableDeclaration)node).Name.Position;
                        endPos   = ((VariableDeclaration)node).Name.End;
                    }
                    else if (node is ClassDeclaration)
                    {
                        // For classes, we only want to highlight the name, not the entire contents
                        startPos = ((ClassDeclaration)node).Name.Position;
                        endPos   = ((ClassDeclaration)node).Name.End;
                    }
                    else if (node is FunctionDeclaration)
                    {
                        // For functions, we only want to highlight the name, not the body
                        startPos = ((FunctionDeclaration)node).Name.Position;
                        endPos   = ((FunctionDeclaration)node).Name.End;
                    }

                    highlightData.Start  = startPos;
                    highlightData.Length = endPos - startPos;
                    result.SyntaxHighlightingData.Add(highlightData);
                }
            }
            // Originally, we meant to highlight CallExpression
            // We are leaving this out because the language service
            // marks the entire call, including the parameters, as part
            // of the call. This ends up looking weird.
            //else if (node is ExpressionStatement)
            //{
            //    var expressionNode = ((ExpressionStatement)node).Expression;
            //    // TODO: Highlight expressions
            //    if (expressionNode.Kind == SyntaxKind.CallExpression)
            //    {
            //        startPos = expressionNode.Position;
            //        endPos = expressionNode.End;
            //        highlightData.Type = HighlightType.CallExpression;
            //    }
            //    highlightData.Start = startPos;
            //    highlightData.Length = endPos - startPos;
            //    result.SyntaxHighlightingData.Add(highlightData);
            //}

            // This section will adjust highlight data, and set the highlight type
            switch (node.Kind)
            {
            case SyntaxKind.ClassDeclaration:
                var classDeclaration = node as ClassDeclaration;
                highlightData.Type = HighlightType.ClassName;
                foreach (var member in classDeclaration.Members)
                {
                    HighlightNode(member, result);
                }
                break;

            case SyntaxKind.MethodDeclaration:
                var methodDeclaration = node as MethodDeclaration;
                highlightData.Type = HighlightType.Identifier;
                // TODO: Child nodes
                foreach (var statement in methodDeclaration.Body.Statements)
                {
                    HighlightNode(statement, result);
                }
                break;

            case SyntaxKind.Constructor:
                highlightData.Type = HighlightType.Identifier;
                break;

            case SyntaxKind.VariableStatement:
                var variableStatement = node as VariableStatement;
                foreach (var declaration in variableStatement.DeclarationList.Declarations)
                {
                    HighlightNode(declaration, result);
                }
                break;

            case SyntaxKind.VariableDeclaration:
                highlightData.Type = HighlightType.Identifier;
                break;

            default:
                // lol
                break;
            }
        }
Example #7
0
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file,
                                                                     List <UnsavedFile> unsavedFiles, Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var currentUnsavedFile = unsavedFiles.FirstOrDefault(f => f.FileName == file.FilePath);
            var currentFileConts   = currentUnsavedFile?.Contents ?? File.ReadAllText(file.FilePath);
            var currentFileName    = currentUnsavedFile?.FileName ?? file.FilePath;
            TypeScriptSyntaxTree syntaxTree;
            // Only one analyzer at a time; the JS engine is single-threaded. TODO: Workaround with multiple JS engines
            await analysisThreadSemaphore.WaitAsync();

            try
            {
                syntaxTree = await _typeScriptContext.BuildAstAsync(currentFileName, currentFileConts);
            }
            catch (JavaScriptException)
            {
                return(new CodeAnalysisResults
                {
                    Diagnostics = new TextSegmentCollection <Diagnostic>
                    {
                        new Diagnostic
                        {
                            Project = file.Project,
                            Line = 1,
                            Spelling = "Code analysis language service call failed.",
                            StartOffset = 0,
                            File = file.Name,
                            Level = DiagnosticLevel.Error,
                        }
                    }
                });
            }
            finally
            {
                analysisThreadSemaphore.Release();
            }

#if DEBUG
            var syntaxTreeJsonDebug = JsonConvert.SerializeObject(syntaxTree);
#endif

            var lineCommentMatches = LineCommentPattern.Matches(currentFileConts);
            foreach (Match commentMatch in lineCommentMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = commentMatch.Index,
                    Length = commentMatch.Length,
                    Type   = HighlightType.Comment
                });
            }

            var blockCommentMatches = BlockCommentPattern.Matches(currentFileConts);
            foreach (Match commentMatch in blockCommentMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = commentMatch.Index,
                    Length = commentMatch.Length,
                    Type   = HighlightType.Comment
                });
            }

            // Highlight keywords
            var keywordMatches = KeywordPattern.Matches(currentFileConts);
            foreach (Match keywordMatch in keywordMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = keywordMatch.Index,
                    Length = keywordMatch.Length,
                    Type   = HighlightType.Keyword
                });
            }

            // Recursively highlight and analyze from parse tree
            foreach (var rootStatement in syntaxTree.Statements)
            {
                HighlightNode(rootStatement, result);
            }

            // Diagnostics

            // Language service has diagnostics
            foreach (var diagnostic in syntaxTree.ParseDiagnostics)
            {
                // Convert diagnostics
                result.Diagnostics.Add(new Diagnostic
                {
                    Project     = file.Project,
                    Line        = GetLineNumber(currentFileConts, diagnostic.Start), // TODO
                    StartOffset = diagnostic.Start,
                    EndOffset   = diagnostic.Start + diagnostic.Length,
                    Spelling    = diagnostic.MessageText,
                    Level       = diagnostic.Category == TSBridge.Ast.Diagnostics.Diagnostic.DiagnosticCategory.Error
                        ? DiagnosticLevel.Error
                        : DiagnosticLevel.Warning
                });
            }

            result.Diagnostics.Add(new Diagnostic
            {
                Project     = file.Project,
                Line        = 1,
                Spelling    = "Code analysis for TypeScript is experimental and unstable. Use with caution.",
                StartOffset = 0,
                File        = file.Name,
                Level       = DiagnosticLevel.Warning,
            });

            return(result);
        }
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List <UnsavedFile> unsavedFiles,
                                                                     Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var clangUnsavedFiles = new List <ClangUnsavedFile>();

            foreach (var unsavedFile in unsavedFiles)
            {
                clangUnsavedFiles.Add(new ClangUnsavedFile(unsavedFile.FileName, unsavedFile.Contents));
            }

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                var translationUnit = GetAndParseTranslationUnit(file, clangUnsavedFiles);

                if (file != null)
                {
                    var callbacks = new ClangIndexerCallbacks();

                    callbacks.IndexDeclaration += (handle, e) =>
                    {
                        if (e.Cursor.Spelling != null && e.Location.SourceLocation.IsFromMainFile)
                        {
                            switch (e.Cursor.Kind)
                            {
                            case NClang.CursorKind.FunctionDeclaration:
                            case NClang.CursorKind.CXXMethod:
                            case NClang.CursorKind.Constructor:
                            case NClang.CursorKind.Destructor:
                            case NClang.CursorKind.VarDeclaration:
                            case NClang.CursorKind.ParmDeclaration:
                            case NClang.CursorKind.StructDeclaration:
                            case NClang.CursorKind.ClassDeclaration:
                            case NClang.CursorKind.TypedefDeclaration:
                            case NClang.CursorKind.ClassTemplate:
                            case NClang.CursorKind.EnumDeclaration:
                            case NClang.CursorKind.UnionDeclaration:
                                result.IndexItems.Add(new IndexEntry(e.Cursor.Spelling, e.Cursor.CursorExtent.Start.FileLocation.Offset,
                                                                     e.Cursor.CursorExtent.End.FileLocation.Offset, (CursorKind)e.Cursor.Kind));
                                break;
                            }


                            switch (e.Cursor.Kind)
                            {
                            case NClang.CursorKind.StructDeclaration:
                            case NClang.CursorKind.ClassDeclaration:
                            case NClang.CursorKind.TypedefDeclaration:
                            case NClang.CursorKind.ClassTemplate:
                            case NClang.CursorKind.EnumDeclaration:
                            case NClang.CursorKind.UnionDeclaration:
                            case NClang.CursorKind.CXXBaseSpecifier:
                                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                                {
                                    Start  = e.Cursor.CursorExtent.Start.FileLocation.Offset,
                                    Length = e.Cursor.CursorExtent.End.FileLocation.Offset - e.Cursor.CursorExtent.Start.FileLocation.Offset,
                                    Type   = HighlightType.ClassName
                                });
                                break;
                            }
                        }
                    };

                    callbacks.IndexEntityReference += (handle, e) =>
                    {
                        if (e.Cursor.Spelling != null && e.Location.SourceLocation.IsFromMainFile)
                        {
                            switch (e.Cursor.Kind)
                            {
                            case NClang.CursorKind.TypeReference:
                            case NClang.CursorKind.CXXBaseSpecifier:
                            case NClang.CursorKind.TemplateReference:
                                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                                {
                                    Start  = e.Cursor.CursorExtent.Start.FileLocation.Offset,
                                    Length = e.Cursor.CursorExtent.End.FileLocation.Offset - e.Cursor.CursorExtent.Start.FileLocation.Offset,
                                    Type   = HighlightType.ClassName
                                });
                                break;
                            }
                        }
                    };

                    if (translationUnit != null)
                    {
                        var tokens = translationUnit.Tokenize(translationUnit.GetCursor().CursorExtent);
                        //var annotatedTokens = tokens.Annotate();           //TODO see if this can provide us with additional data.

                        foreach (var token in tokens.Tokens)
                        {
                            var highlightData    = new OffsetSyntaxHighlightingData();
                            highlightData.Start  = token.Extent.Start.FileLocation.Offset;
                            highlightData.Length = token.Extent.End.FileLocation.Offset - highlightData.Start;


                            switch (token.Kind)
                            {
                            case TokenKind.Comment:
                                highlightData.Type = HighlightType.Comment;
                                break;

                            case TokenKind.Identifier:
                                highlightData.Type = HighlightType.Identifier;
                                break;

                            case TokenKind.Punctuation:
                                highlightData.Type = HighlightType.Punctuation;
                                break;

                            case TokenKind.Keyword:
                                highlightData.Type = HighlightType.Keyword;
                                break;

                            case TokenKind.Literal:
                                highlightData.Type = HighlightType.Literal;
                                break;
                            }

                            result.SyntaxHighlightingData.Add(highlightData);
                        }

                        var indexAction = index.CreateIndexAction();
                        indexAction.IndexTranslationUnit(IntPtr.Zero, new[] { callbacks }, IndexOptionFlags.SkipParsedBodiesInSession,
                                                         translationUnit);
                        indexAction.Dispose();
                    }
                }

                dataAssociation.TextMarkerService.Clear();

                var diags = translationUnit.DiagnosticSet.Items;

                foreach (var diagnostic in diags)
                {
                    if (diagnostic.Location.IsFromMainFile)
                    {
                        var diag = new Diagnostic
                        {
                            Project     = file.Project,
                            StartOffset = diagnostic.Location.FileLocation.Offset,
                            Line        = diagnostic.Location.FileLocation.Line,
                            Spelling    = diagnostic.Spelling,
                            File        = diagnostic.Location.FileLocation.File.FileName,
                            Level       = (DiagnosticLevel)diagnostic.Severity
                        };


                        result.Diagnostics.Add(diag);

                        var data =
                            dataAssociation.TranslationUnit.GetLocationForOffset(dataAssociation.TranslationUnit.GetFile(file.Location),
                                                                                 diag.StartOffset);
                        var length = 0;

                        if (diagnostic.RangeCount > 0)
                        {
                            length = Math.Abs(diagnostic.GetDiagnosticRange(0).End.FileLocation.Offset - diag.StartOffset);
                        }

                        if (diagnostic.FixItCount > 0)
                        {
                            // TODO implement fixits.
                        }

                        Color markerColor;

                        switch (diag.Level)
                        {
                        case DiagnosticLevel.Error:
                        case DiagnosticLevel.Fatal:
                            markerColor = Color.FromRgb(253, 45, 45);
                            break;

                        case DiagnosticLevel.Warning:
                            markerColor = Color.FromRgb(255, 207, 40);
                            break;

                        default:
                            markerColor = Color.FromRgb(0, 42, 74);
                            break;
                        }

                        dataAssociation.TextMarkerService.Create(diag.StartOffset, length, diag.Spelling, markerColor);
                    }
                }
            });

            dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);

            return(result);
        }
        public async Task<CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List<UnsavedFile> unsavedFiles, Func<bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var response = await dataAssociation.Solution.Server.Highlight(file.FilePath, unsavedFiles.FirstOrDefault()?.Contents);

            if (response != null)
            {
                foreach (var highlight in response.Highlights)
                {
                    result.SyntaxHighlightingData.Add(new LineColumnSyntaxHighlightingData
                    {
                        StartLine = highlight.StartLine,
                        EndLine = highlight.EndLine,
                        StartColumn = highlight.StartColumn,
                        EndColumn = highlight.EndColumn,
                        Type = ToAvalonHighlightType(highlight.Kind)
                    });
                }

                dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);
            }

            return result;
        }
Example #10
0
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List <UnsavedFile> unsavedFiles,
                                                                     Func <bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var clangUnsavedFiles = new List <ClangUnsavedFile>();

            foreach (var unsavedFile in unsavedFiles)
            {
                clangUnsavedFiles.Add(new ClangUnsavedFile(unsavedFile.FileName, unsavedFile.Contents));
            }

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                var translationUnit = GetAndParseTranslationUnit(file, clangUnsavedFiles);

                if (file != null)
                {
                    if (translationUnit != null)
                    {
                        ScanTokens(translationUnit, result.SyntaxHighlightingData);

                        var cursor = translationUnit.GetCursor();

                        cursor.VisitChildren((current, parent, ptr) =>
                        {
                            if (current.Location.IsFromMainFile)
                            {
                                var highlight = CreateOffsetData(current, parent);

                                if (highlight != null)
                                {
                                    result.SyntaxHighlightingData.Add(highlight);
                                }

                                return(ChildVisitResult.Recurse);
                            }

                            if (current.Location.IsInSystemHeader)
                            {
                                return(ChildVisitResult.Continue);
                            }

                            return(ChildVisitResult.Recurse);
                        }, IntPtr.Zero);
                    }
                }

                dataAssociation.TextMarkerService.Clear();

                var diags = translationUnit.DiagnosticSet.Items;

                foreach (var diagnostic in diags)
                {
                    if (diagnostic.Location.IsFromMainFile)
                    {
                        var diag = new Diagnostic
                        {
                            Project     = file.Project,
                            StartOffset = diagnostic.Location.FileLocation.Offset,
                            Line        = diagnostic.Location.FileLocation.Line,
                            Spelling    = diagnostic.Spelling,
                            File        = diagnostic.Location.FileLocation.File.FileName,
                            Level       = (DiagnosticLevel)diagnostic.Severity
                        };


                        var cursor = translationUnit.GetCursor(diagnostic.Location);

                        var tokens = translationUnit.Tokenize(cursor.CursorExtent);

                        foreach (var token in tokens.Tokens)
                        {
                            if (token.Location == diagnostic.Location)
                            {
                                diag.EndOffset = diag.StartOffset + token.Spelling.Length;
                            }
                        }

                        result.Diagnostics.Add(diag);
                        tokens.Dispose();

                        Color markerColor;

                        switch (diag.Level)
                        {
                        case DiagnosticLevel.Error:
                        case DiagnosticLevel.Fatal:
                            markerColor = Color.FromRgb(253, 45, 45);
                            break;

                        case DiagnosticLevel.Warning:
                            markerColor = Color.FromRgb(255, 207, 40);
                            break;

                        default:
                            markerColor = Color.FromRgb(0, 42, 74);
                            break;
                        }

                        dataAssociation.TextMarkerService.Create(diag.StartOffset, diag.Length, diag.Spelling, markerColor);
                    }
                }
            });

            dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);

            return(result);
        }
        public async Task<CodeAnalysisResults> RunCodeAnalysisAsync(ISourceFile file, List<UnsavedFile> unsavedFiles,
            Func<bool> interruptRequested)
        {
            var result = new CodeAnalysisResults();

            var dataAssociation = GetAssociatedData(file);

            var clangUnsavedFiles = new List<ClangUnsavedFile>();

            foreach (var unsavedFile in unsavedFiles)
            {
                clangUnsavedFiles.Add(new ClangUnsavedFile(unsavedFile.FileName, unsavedFile.Contents));
            }

            await clangAccessJobRunner.InvokeAsync(() =>
            {
                var translationUnit = GetAndParseTranslationUnit(file, clangUnsavedFiles);

                if (file != null)
                {
                    if (translationUnit != null)
                    {
                        ScanTokens(translationUnit, result.SyntaxHighlightingData);

                        var cursor = translationUnit.GetCursor();

                        cursor.VisitChildren((current, parent, ptr) =>
                        {
                            if (current.Location.IsFromMainFile)
                            {
                                var highlight = CreateOffsetData(current, parent);

                                if (highlight != null)
                                {
                                    result.SyntaxHighlightingData.Add(highlight);
                                }

                                return ChildVisitResult.Recurse;
                            }

                            if(current.Location.IsInSystemHeader)
                            {
                                return ChildVisitResult.Continue;
                            }

                            return ChildVisitResult.Recurse;
                        }, IntPtr.Zero);
                    }
                }

                dataAssociation.TextMarkerService.Clear();

                var diags = translationUnit.DiagnosticSet.Items;

                foreach (var diagnostic in diags)
                {
                    if (diagnostic.Location.IsFromMainFile)
                    {
                        var diag = new Diagnostic
                        {
                            Project = file.Project,
                            StartOffset = diagnostic.Location.FileLocation.Offset,
                            Line = diagnostic.Location.FileLocation.Line,
                            Spelling = diagnostic.Spelling,
                            File = diagnostic.Location.FileLocation.File.FileName,
                            Level = (DiagnosticLevel)diagnostic.Severity
                        };


                        var cursor = translationUnit.GetCursor(diagnostic.Location);

                        var tokens = translationUnit.Tokenize(cursor.CursorExtent);

                        foreach (var token in tokens.Tokens)
                        {
                            if (token.Location == diagnostic.Location)
                            {
                                diag.EndOffset = diag.StartOffset + token.Spelling.Length;
                            }
                        }

                        result.Diagnostics.Add(diag);
                        tokens.Dispose();

                        Color markerColor;

                        switch (diag.Level)
                        {
                            case DiagnosticLevel.Error:
                            case DiagnosticLevel.Fatal:
                                markerColor = Color.FromRgb(253, 45, 45);
                                break;

                            case DiagnosticLevel.Warning:
                                markerColor = Color.FromRgb(255, 207, 40);
                                break;

                            default:
                                markerColor = Color.FromRgb(0, 42, 74);
                                break;
                        }

                        dataAssociation.TextMarkerService.Create(diag.StartOffset, diag.Length, diag.Spelling, markerColor);
                    }
                }
            });

            dataAssociation.TextColorizer.SetTransformations(result.SyntaxHighlightingData);

            return result;
        }
        public async Task <CodeAnalysisResults> RunCodeAnalysisAsync(
            IEnumerable <UnsavedFile> unsavedFiles, Func <bool> interruptRequested)
        {
            var errorList   = IoC.Get <IErrorList>();
            var result      = new CodeAnalysisResults();
            var diagnostics = new List <Diagnostic>();

            var file            = _editor.SourceFile;
            var dataAssociation = GetAssociatedData(file);

            var currentUnsavedFile = unsavedFiles.FirstOrDefault(f => f.FileName == file.FilePath);
            var currentFileConts   = currentUnsavedFile?.Contents ?? File.ReadAllText(file.FilePath);
            var currentFileName    = currentUnsavedFile?.FileName ?? file.FilePath;
            TypeScriptSyntaxTree syntaxTree;
            // Only one analyzer at a time; the JS engine is single-threaded. TODO: Workaround with multiple JS engines
            await analysisThreadSemaphore.WaitAsync();

            try
            {
                syntaxTree = await _typeScriptContext.BuildAstAsync(currentFileName, currentFileConts);
            }
            catch (JavaScriptException)
            {
                diagnostics.Add(new Diagnostic(
                                    0, 0,
                                    _editor.SourceFile.Project.Name,
                                    _editor.SourceFile.Location,
                                    0,
                                    "Code analysis language service call failed.",
                                    "INT001",
                                    DiagnosticLevel.Error,
                                    DiagnosticCategory.Compiler));

                errorList.Remove((this, _editor.SourceFile));
                errorList.Create((this, _editor.SourceFile), null, DiagnosticSourceKind.Analysis, diagnostics.ToImmutableArray());

                return(new CodeAnalysisResults());
            }
            finally
            {
                analysisThreadSemaphore.Release();
            }

#if DEBUG
            var syntaxTreeJsonDebug = JsonConvert.SerializeObject(syntaxTree);
#endif

            var lineCommentMatches = LineCommentPattern.Matches(currentFileConts);
            foreach (Match commentMatch in lineCommentMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = commentMatch.Index,
                    Length = commentMatch.Length,
                    Type   = HighlightType.Comment
                });
            }

            var blockCommentMatches = BlockCommentPattern.Matches(currentFileConts);
            foreach (Match commentMatch in blockCommentMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = commentMatch.Index,
                    Length = commentMatch.Length,
                    Type   = HighlightType.Comment
                });
            }

            // Highlight keywords
            var keywordMatches = KeywordPattern.Matches(currentFileConts);
            foreach (Match keywordMatch in keywordMatches)
            {
                result.SyntaxHighlightingData.Add(new OffsetSyntaxHighlightingData
                {
                    Start  = keywordMatch.Index,
                    Length = keywordMatch.Length,
                    Type   = HighlightType.Keyword
                });
            }

            // Recursively highlight and analyze from parse tree
            foreach (var rootStatement in syntaxTree.Statements)
            {
                HighlightNode(rootStatement, result);
            }

            // Diagnostics
            foreach (var diagnostic in syntaxTree.ParseDiagnostics)
            {
                // Convert diagnostics
                diagnostics.Add(new Diagnostic(
                                    diagnostic.Start,
                                    diagnostic.Length,
                                    _editor.SourceFile.Project.Name,
                                    _editor.SourceFile.Location,
                                    GetLineNumber(currentFileConts, diagnostic.Start),
                                    diagnostic.MessageText,
                                    "INT002",
                                    diagnostic.Category == TSBridge.Ast.Diagnostics.Diagnostic.DiagnosticCategory.Error
                        ? DiagnosticLevel.Error
                        : DiagnosticLevel.Warning,
                                    DiagnosticCategory.Compiler
                                    ));
            }

            diagnostics.Add(new Diagnostic(
                                0,
                                0,
                                _editor.SourceFile.Project.Name,
                                _editor.SourceFile.Location,
                                0,
                                "Code analysis for TypeScript is experimental and unstable. Use with caution.",
                                "INT003",
                                DiagnosticLevel.Warning,
                                DiagnosticCategory.Compiler));

            errorList.Remove((this, _editor.SourceFile));
            errorList.Create((this, _editor.SourceFile), null, DiagnosticSourceKind.Analysis, diagnostics.ToImmutableArray());

            return(result);
        }