/// <summary> /// Inspects the syntax tree and reports the comments starting with the expected prefixes. /// </summary> /// <param name="tree">Parsed syntax tree</param> /// <param name="rules">Rules of the inspection</param> /// <returns>List of comments starting with the given prefixes</returns> public static IEnumerable <Record> Inspect(SyntaxTree tree, Rules rules) { var root = (CompilationUnitSyntax)tree.GetRoot(); var irrelevantRecord = new Record("", "", 0, 0, Status.Ok); IEnumerable <Record> records = root.DescendantTrivia() // Beware: ToString() is an expensive operation on Syntax Nodes and // involves some complex logic and a string builder! // Hence we convert the trivia to string only at this single place. .Select((trivia) => (trivia, trivia.ToString())) .Select( ((SyntaxTrivia, string)t) => { var(trivia, triviaAsString) = t; var result = Text.Inspect(triviaAsString, rules); if (result == null) { return(irrelevantRecord); } var span = tree.GetLineSpan(trivia.Span); var position = span.StartLinePosition; var line = position.Line; var column = position.Character; return(new Record(result.Prefix, result.Suffix, line, column, result.Status)); })
public static string CreateUniqueVariableName(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, string baseName) { var contextNode = syntaxTree.GetRoot(); var symbols = contextNode.DescendantNodes().OfType <MethodDeclarationSyntax>().Select(n => n.Identifier.ValueText).ToList(); symbols.AddRange(contextNode.DescendantNodes().OfType <LocalDeclarationStatementSyntax>().Select(n => n.Declaration.Variables.FirstOrDefault().Identifier.ValueText).ToList()); symbols.AddRange(contextNode.DescendantNodes().OfType <FieldDeclarationSyntax>().Select(n => n.Declaration.Variables.FirstOrDefault().Identifier.ValueText).ToList()); symbols.AddRange(contextNode.DescendantNodes().OfType <ParameterSyntax>().Select(n => n.Identifier.ValueText).ToList()); return(GenerateUniqueName(baseName, string.Empty, n => symbols.Where(x => x.Equals(n)).ToArray().Length == 0)); }
public static string CreateUniqueVariableName(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, string baseName) { var contextNode = syntaxTree.GetRoot(); var symbols = contextNode.DescendantNodes().OfType <MethodDeclarationSyntax>().Select(n => n.Identifier.ValueText).ToList(); symbols.AddRange(contextNode.DescendantNodes().OfType <LocalDeclarationStatementSyntax>().Select(n => n.Declaration.Variables.FirstOrDefault().Identifier.ValueText).ToList()); symbols.AddRange(contextNode.DescendantNodes().OfType <FieldDeclarationSyntax>().Select(n => n.Declaration.Variables.FirstOrDefault().Identifier.ValueText).ToList()); symbols.AddRange(contextNode.DescendantNodes().OfType <ParameterSyntax>().Select(n => n.Identifier.ValueText).ToList()); var existingNames = new HashSet <string>(symbols); return(baseName.GetUniqueName(existingNames)); }
private static void UpdateCSFileCodes(Client client, SoftwareFile softwareFile, ref AppsClient.AppsResult result) { var softwareFileCodeDB = client.DB.GetCollection <SoftwareFileCode>("SoftwareFileCodes"); Microsoft.CodeAnalysis.SyntaxTree tree = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(softwareFile.Contents); var descendents = tree.GetRoot().DescendantNodes(); //.OfType<LiteralExpressionSyntax>(); foreach (var desc in descendents) { if (desc.GetType().Name == "MethodDeclarationSyntax") { var method = (MethodDeclarationSyntax)desc; var existingCodeList = softwareFile.SoftwareFileCodes.Where(sc => sc.Name == method.Identifier.Text); if (existingCodeList.Count() == 1) { var existingCode = existingCodeList.Single(); existingCode.CodeType = SoftwareFileCodeTypes.Method; existingCode.Contents = method.Body.ToFullString(); existingCode.Name = method.Identifier.Text; existingCode.SoftwareFileID = softwareFile.SoftwareFileID; softwareFileCodeDB.Upsert(existingCode); } else if (existingCodeList.Count() == 0) { var newCode = new SoftwareFileCode { CodeType = SoftwareFileCodeTypes.Method, Contents = method.Body != null?method.Body.ToFullString() : "", Name = method.Identifier.Text, SoftwareFileID = softwareFile.SoftwareFileID }; softwareFileCodeDB.Insert(newCode); softwareFile.SoftwareFileCodes.Add(newCode); } else { result.FailMessages.Add("More than one code found for " + method.Identifier.Text + " in file " + softwareFile.FullName); } } } }
private static IEnumerable <SuspectTrivia> InspectTrivias(SyntaxTree tree) { var root = (CompilationUnitSyntax)tree.GetRoot(); var tracker = new OnOffTracker(); var relevantTrivias = root.DescendantTrivia() // Beware: ToString() is an expensive operation on Syntax Nodes and // involves some complex logic and a string builder! // Hence we convert the trivia to string only at this single place. .Select((trivia) => (trivia, trivia.ToString())) .Where( (t) => { var(_, triviaAsString) = t; tracker.Feed(triviaAsString); return(tracker.IsOn && TriviaIsComment(triviaAsString) && !ShouldSkipTrivia(triviaAsString)); }); foreach (var(trivia, triviaAsString) in relevantTrivias) { var span = tree.GetLineSpan(trivia.Span); var position = span.StartLinePosition; List <Cue>?cues = InspectComment(position.Line, position.Character, triviaAsString); if (cues != null) { yield return(new SuspectTrivia(trivia, cues)); } } }
public void Apply(ref Microsoft.CodeAnalysis.SyntaxTree syntaxTree, CompilationOptions options) { syntaxTree = new InstrumentForInEditorDebugging().Visit(syntaxTree.GetRoot()).SyntaxTree; // TODO handle exceptions again: syntaxTree = new ExceptionHandlingInjection().Visit(syntaxTree.GetRoot()).SyntaxTree; }
public static DoctestsAndErrors Extract(SyntaxTree tree) { var doctests = new List <Doctest>(); var errors = new List <Error>(); // stack var stack = new Stack <NamespaceWip>(); // Push the Work-in-progress for the global namespace stack.Push(new NamespaceWip { Namespace = "", SpanEnd = tree.Length }); var root = (CompilationUnitSyntax)tree.GetRoot(); foreach (var node in NamespaceDeclsAndDocumentations(root)) { if (node.SpanStart >= stack.Peek().SpanEnd) { var wip = stack.Pop(); if (wip.Doctests.Count > 0) { doctests.AddRange(wip.Doctests); } } switch (node) { case Syntax.DocumentationCommentTriviaSyntax documentation: List <Pipeline.Code> codes = Pipeline.CodesFromDocumentation(documentation); List <Pipeline.DoctestWithoutNamespaceOrError> dtWoNsOrErrorList = codes.Select(Pipeline.SplitHeaderBody).ToList(); stack.Peek().Doctests.AddRange( dtWoNsOrErrorList .Where((dtOrErr) => dtOrErr.DoctestWithoutNamespace != null) .Select((dtOrErr) => new Doctest( stack.Peek().Namespace, dtOrErr.DoctestWithoutNamespace !.Usings, dtOrErr.DoctestWithoutNamespace !.Body, dtOrErr.DoctestWithoutNamespace !.Line, dtOrErr.DoctestWithoutNamespace !.Column))); errors.AddRange( dtWoNsOrErrorList .Where((dtOrErr) => dtOrErr.Error != null) .Select((dtOrErr) => dtOrErr.Error !)); break; case Syntax.NamespaceDeclarationSyntax namespaceDecl: string ns = (stack.Peek().Namespace == "") ? namespaceDecl.Name.ToString() : $"{stack.Peek().Namespace}.{namespaceDecl.Name.ToString()}"; stack.Push(new NamespaceWip { Namespace = ns, SpanEnd = namespaceDecl.Span.End }); break; default: continue; } } while (stack.Count != 0) { var wip = stack.Pop(); if (wip.Doctests.Count > 0) { doctests.AddRange(wip.Doctests); } } // Sort doctests by line and column doctests.Sort((doctest, otherDoctest) => { int ret = doctest.Line.CompareTo(otherDoctest.Line); if (ret == 0) { ret = doctest.Column.CompareTo(otherDoctest.Column); } return(ret); }); return(new DoctestsAndErrors(doctests, errors)); }
static List <CGFDocument> ProcessDocuments(CGFParserReporter reporter, List <Microsoft.CodeAnalysis.Document> documents, Microsoft.CodeAnalysis.Project project) { using (reporter.CreateContextScope(CGFParserReporterContext.Type.Project, project.FilePath)) { List <CGFDocument> documentsToProcess = new List <CGFDocument>(); foreach (Microsoft.CodeAnalysis.Document document in documents) { using (reporter.CreateContextScope(CGFParserReporterContext.Type.File, document.FilePath)) { List <CGFTypeSymbol> typesToProcess = new List <CGFTypeSymbol>(); Microsoft.CodeAnalysis.SemanticModel semanticModel = document.GetSemanticModelAsync().Result; Microsoft.CodeAnalysis.SyntaxTree syntaxTree = document.GetSyntaxTreeAsync().Result; IEnumerable <Microsoft.CodeAnalysis.SyntaxNode> syntaxNodes = syntaxTree.GetRoot().DescendantNodes().Where(n => (n as ClassDeclarationSyntax) != null || (n as EnumDeclarationSyntax) != null); foreach (Microsoft.CodeAnalysis.SyntaxNode node in syntaxNodes) { ClassDeclarationSyntax classSyntax = node as ClassDeclarationSyntax; if (classSyntax != null) { Microsoft.CodeAnalysis.INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(classSyntax); using (reporter.CreateContextScope(CGFParserReporterContext.Type.Type, typeSymbol.Name)) { CGFTypeSymbol cgfTypeSymbol = CGFTypeSymbol.Parse(reporter, typeSymbol); typesToProcess.Add(cgfTypeSymbol); } } else { EnumDeclarationSyntax enumSyntax = node as EnumDeclarationSyntax; Microsoft.CodeAnalysis.INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(enumSyntax); using (reporter.CreateContextScope(CGFParserReporterContext.Type.Type, typeSymbol.Name)) { CGFTypeSymbol cgfTypeSymbol = CGFTypeSymbol.Parse(reporter, typeSymbol); typesToProcess.Add(cgfTypeSymbol); } } } if (typesToProcess.Count > 0) { CGFDocument cgfDocument = CGFDocument.Parse(reporter, document, typesToProcess); documentsToProcess.Add(cgfDocument); } } } return(documentsToProcess); } }