private void ScanTokens(NClang.ClangTranslationUnit tu, SyntaxHighlightDataList result) { var tokens = tu.Tokenize(tu.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; result.Add(highlightData); break; case TokenKind.Keyword: highlightData.Type = HighlightType.Keyword; result.Add(highlightData); break; } } }
private void ScanTokens(NClang.ClangTranslationUnit tu, SyntaxHighlightDataList result) { var tokens = tu.Tokenize(tu.GetCursor().CursorExtent); foreach (var token in tokens.Tokens) { var highlightData = new OffsetSyntaxHighlightingData { 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; result.Add(highlightData); break; case TokenKind.Keyword: highlightData.Type = HighlightType.Keyword; result.Add(highlightData); break; } } }
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; } }
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); }