static void FieldNameAnalyzerTest() { // // Construct a syntax tree and a compilation. // var tree = CSharpSyntaxTree.ParseText(@" class Person { private int _age; }"); var mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); var comp = CSharpCompilation.Create("Demo") .AddSyntaxTrees(tree) .AddReferences(mscorlib) .WithOptions(options); // // Get diagnostics. // var diags = AnalyzerDriver.GetDiagnostics(comp, new[] { new FieldNameAnalyzer() }, null, CancellationToken.None); foreach (var diag in diags) { Console.WriteLine(diag); } }
static void ConfigureAwaitAnalyzerTest() { // // Construct a syntax tree and a compilation. // var tree = CSharpSyntaxTree.ParseText(@" using System.Threading.Tasks; class Foo { async Task Bar(Task t) { await t; } async Task<int> Baz(Task<int> t) { return await t; } async Task Qux(Task t) { await t.ConfigureAwait(false); } }"); var mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); var comp = CSharpCompilation.Create("Demo") .AddSyntaxTrees(tree) .AddReferences(mscorlib) .WithOptions(options); // // Get diagnostics. // var diags = AnalyzerDriver.GetDiagnostics(comp, new[] { new ConfigureAwaitAnalyzer() }, null, CancellationToken.None); foreach (var diag in diags) { Console.WriteLine(diag); } }
/// <summary> /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it. /// The returned diagnostics are then ordered by location in the source document. /// </summary> /// <param name="analyzer">The analyzer to run on the documents</param> /// <param name="documents">The Documents that the analyzer will be run on</param> /// <param name="spans">Optional TextSpan indicating where a Diagnostic will be found</param> /// <returns>An IEnumerable of Diagnostics that surfaced in teh source code, sorted by Location</returns> protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(IDiagnosticAnalyzer analyzer, Document[] documents) { var projects = new HashSet <Project>(); foreach (var document in documents) { projects.Add(document.Project); } var diagnostics = new List <Diagnostic>(); foreach (var project in projects) { var compilation = project.GetCompilationAsync().Result; var diags = AnalyzerDriver.GetDiagnostics(compilation, new[] { analyzer }, null, CancellationToken.None); foreach (var diag in diags) { if (diag.Location == Location.None || diag.Location.IsInMetadata) { diagnostics.Add(diag); } else { for (int i = 0; i < documents.Length; i++) { var document = documents[i]; var tree = document.GetSyntaxTreeAsync().Result; if (tree == diag.Location.SourceTree) { diagnostics.Add(diag); } } } } } var results = SortDiagnostics(diagnostics); diagnostics.Clear(); return(results); }
/// <summary> /// csc.exe and vbc.exe entry point. /// </summary> public virtual int Run(TextWriter consoleOutput, CancellationToken cancellationToken) { Debug.Assert(!Arguments.IsInteractive); cancellationToken.ThrowIfCancellationRequested(); if (Arguments.DisplayLogo) { PrintLogo(consoleOutput); } if (Arguments.DisplayHelp) { PrintHelp(consoleOutput); return(Succeeded); } if (PrintErrors(Arguments.Errors, consoleOutput)) { return(Failed); } var touchedFilesLogger = (Arguments.TouchedFilesPath != null) ? new TouchedFileLogger() : null; Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger); if (compilation == null) { return(Failed); } var diagnostics = new List <DiagnosticInfo>(); var analyzers = Arguments.ResolveAnalyzersFromArguments(diagnostics, MessageProvider, touchedFilesLogger); if (PrintErrors(diagnostics, consoleOutput)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); EmitResult emitResult; // EDMAURER: Don't yet know if there are method body errors. don't overwrite // any existing output files until the compilation is known to be successful. string tempExeFilename = null; string tempPdbFilename = null; // NOTE: as native compiler does, we generate the documentation file // NOTE: 'in place', replacing the contents of the file if it exists try { tempExeFilename = CreateTempFile(consoleOutput); // Can happen when temp directory is "full" if (tempExeFilename == null) { return(Failed); } FileStream output = OpenFile(tempExeFilename, consoleOutput); if (output == null) { return(Failed); } string finalOutputPath; string finalPdbFilePath; string finalXmlFilePath; using (output) { FileStream pdb = null; FileStream xml = null; cancellationToken.ThrowIfCancellationRequested(); if (Arguments.CompilationOptions.DebugInformationKind != DebugInformationKind.None) { tempPdbFilename = CreateTempFile(consoleOutput); if (tempPdbFilename == null) { return(Failed); } pdb = OpenFile(tempPdbFilename, consoleOutput); if (pdb == null) { return(Failed); } } cancellationToken.ThrowIfCancellationRequested(); finalXmlFilePath = Arguments.DocumentationPath; if (finalXmlFilePath != null) { xml = OpenFile(finalXmlFilePath, consoleOutput, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete); if (xml == null) { return(Failed); } xml.SetLength(0); } cancellationToken.ThrowIfCancellationRequested(); IEnumerable <DiagnosticInfo> errors; using (var win32Res = GetWin32Resources(Arguments, compilation, out errors)) using (pdb) using (xml) { if (PrintErrors(errors, consoleOutput)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); string outputName = GetOutputFileName(compilation, cancellationToken); finalOutputPath = Path.Combine(Arguments.OutputDirectory, outputName); finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalOutputPath, ".pdb"); // NOTE: Unlike the PDB path, the XML doc path is not embedded in the assembly, so we don't need to pass it to emit. emitResult = compilation.Emit(output, outputName, finalPdbFilePath, pdb, xml, cancellationToken, win32Res, Arguments.ManifestResources); } } GenerateSqmData(Arguments.CompilationOptions, emitResult.Diagnostics); if (PrintErrors(emitResult.Diagnostics, consoleOutput)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); var analyzerDiagnostics = AnalyzerDriver.GetDiagnostics(compilation, analyzers, default(CancellationToken)); if (PrintErrors(analyzerDiagnostics, consoleOutput)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); if (!TryDeleteFile(finalOutputPath, consoleOutput) || !TryMoveFile(tempExeFilename, finalOutputPath, consoleOutput)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); if (tempPdbFilename != null) { if (!TryDeleteFile(finalPdbFilePath, consoleOutput) || !TryMoveFile(tempPdbFilename, finalPdbFilePath, consoleOutput)) { return(Failed); } } cancellationToken.ThrowIfCancellationRequested(); if (Arguments.TouchedFilesPath != null) { Debug.Assert(touchedFilesLogger != null); touchedFilesLogger.AddWritten(tempExeFilename); touchedFilesLogger.AddWritten(finalOutputPath); if (tempPdbFilename != null) { touchedFilesLogger.AddWritten(tempPdbFilename); touchedFilesLogger.AddWritten(finalPdbFilePath); } if (finalXmlFilePath != null) { touchedFilesLogger.AddWritten(finalXmlFilePath); } var readStream = OpenFile(Arguments.TouchedFilesPath + ".read", consoleOutput, FileMode.OpenOrCreate); if (readStream == null) { return(Failed); } using (var writer = new StreamWriter(readStream)) { touchedFilesLogger.WriteReadPaths(writer); } var writtenStream = OpenFile(Arguments.TouchedFilesPath + ".write", consoleOutput, FileMode.OpenOrCreate); if (writtenStream == null) { return(Failed); } using (var writer = new StreamWriter(writtenStream)) { touchedFilesLogger.WriteWrittenPaths(writer); } } return(Succeeded); } finally { if (tempExeFilename != null) { TryDeleteFile(tempExeFilename, consoleOutput: null); } if (tempPdbFilename != null) { TryDeleteFile(tempPdbFilename, consoleOutput: null); } } }
static void SingleStatementBodyAnalyzerTest() { // // Construct a syntax tree and a compilation. // var tree = CSharpSyntaxTree.ParseText(@" using System; class Foo { void If(int x) { if (x > 0) Console.WriteLine(x); else if (x == 0) Console.WriteLine(0); else if (x < 0) Console.WriteLine(-x); } void For() { for (int i = 0; i < 10; i++) Console.WriteLine(i); } void ForEach() { foreach (var x in new[] { 1, 2, 3 }) Console.WriteLine(x); } void While() { while (true) Console.Write('.'); } }"); var mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); var comp = CSharpCompilation.Create("Demo") .AddSyntaxTrees(tree) .AddReferences(mscorlib) .WithOptions(options); // // Get diagnostics. // var diags = AnalyzerDriver.GetDiagnostics(comp, new[] { new SingleStatementBodyAnalyzer() }, null, CancellationToken.None); foreach (var diag in diags) { Console.WriteLine(diag); } }
public void AnalyzerDriverIsSafeAgainstAnalyzerExceptions() { var compilation = CreateCompilationWithMscorlib45(TestResource.AllInOneCSharpCode); ThrowingDiagnosticAnalyzer <SyntaxKind> .VerifyAnalyzerEngineIsSafeAgainstExceptions(analyzer => AnalyzerDriver.GetDiagnostics(compilation, new[] { analyzer }, CancellationToken.None), typeof(AnalyzerDriver).Name); }
public static TCompilation VerifyAnalyzerDiagnostics <TCompilation>(this TCompilation c, IDiagnosticAnalyzer[] analyzers, params DiagnosticDescription[] expected) where TCompilation : Compilation { AnalyzerDriver.GetDiagnostics(c, analyzers, default(CancellationToken)).Verify(expected); return(c); }