예제 #1
0
        /// <summary>
        /// Determine the path of the output dll/exe.
        /// </summary>
        /// <param name="compilation">Information about the compilation.</param>
        /// <param name="cancel">Cancellation token required.</param>
        /// <returns>The filename.</returns>
        private static string GetOutputName(CSharpCompilation compilation,
                                            CSharpCommandLineArguments commandLineArguments)
        {
            // There's no apparent way to access the output filename from the compilation,
            // so we need to re-parse the command line arguments.

            if (commandLineArguments.OutputFileName == null)
            {
                // No output specified: Use name based on first filename
                var entry = compilation.GetEntryPoint(System.Threading.CancellationToken.None);
                if (entry == null)
                {
                    if (compilation.SyntaxTrees.Length == 0)
                    {
                        throw new InvalidOperationException("No source files seen");
                    }

                    // Probably invalid, but have a go anyway.
                    var entryPointFile = compilation.SyntaxTrees.First().FilePath;
                    return(Path.ChangeExtension(entryPointFile, ".exe"));
                }

                var entryPointFilename = entry.Locations.First().SourceTree.FilePath;
                return(Path.ChangeExtension(entryPointFilename, ".exe"));
            }

            return(Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName));
        }
예제 #2
0
        private static ImmutableDictionary <string, ReportDiagnostic> GetNullableWarningsFromCompiler()
        {
            string[] args = { "/warnaserror:nullable" };
            CSharpCommandLineArguments commandLineArguments = CSharpCommandLineParser.Default.Parse(args, Environment.CurrentDirectory, Environment.CurrentDirectory);
            ImmutableDictionary <string, ReportDiagnostic> nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions;

            return(nullableWarnings);
        }
예제 #3
0
        private static ImmutableDictionary <string, ReportDiagnostic> GetNullableWarningsFromCompiler()
        {
            string[] args = { "/warnaserror:nullable" };
            CSharpCommandLineArguments commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory);
            ImmutableDictionary <string, ReportDiagnostic> nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions;

            // Workaround for https://github.com/dotnet/roslyn/issues/41610
            nullableWarnings = nullableWarnings
                               .SetItem("CS8632", ReportDiagnostic.Error)
                               .SetItem("CS8669", ReportDiagnostic.Error);

            return(nullableWarnings);
        }
예제 #4
0
        /// <summary>
        /// Initialize the analyser.
        /// </summary>
        /// <param name="commandLineArguments">Arguments passed to csc.</param>
        /// <param name="compilationIn">The Roslyn compilation.</param>
        /// <param name="options">Extractor options.</param>
        /// <param name="roslynArgs">The arguments passed to Roslyn.</param>
        public void Initialize(
            CSharpCommandLineArguments commandLineArguments,
            CSharpCompilation compilationIn,
            Options options,
            string[] roslynArgs)
        {
            compilation = compilationIn;

            layout       = new Layout();
            this.options = options;

            extractor = new Extraction.Extractor(false, GetOutputName(compilation, commandLineArguments), Logger);

            LogDiagnostics(roslynArgs);
            SetReferencePaths();

            CompilationErrors += FilteredDiagnostics.Count();
        }
예제 #5
0
        /// <summary>
        /// End initialization of the analyser.
        /// </summary>
        /// <param name="commandLineArguments">Arguments passed to csc.</param>
        /// <param name="options">Extractor options.</param>
        /// <param name="compilation">The Roslyn compilation.</param>
        /// <returns>A Boolean indicating whether to proceed with extraction.</returns>
        public void EndInitialize(
            CSharpCommandLineArguments commandLineArguments,
            CommonOptions options,
            CSharpCompilation compilation)
        {
            if (!init)
            {
                throw new InternalError("EndInitialize called without BeginInitialize returning true");
            }
            this.options     = options;
            this.compilation = compilation;
            this.extractor   = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer, options);
            LogDiagnostics();

            SetReferencePaths();

            CompilationErrors += FilteredDiagnostics.Count();
        }
예제 #6
0
        /// <summary>
        /// End initialization of the analyser.
        /// </summary>
        /// <param name="commandLineArguments">Arguments passed to csc.</param>
        /// <param name="options">Extractor options.</param>
        /// <param name="compilation">The Roslyn compilation.</param>
        /// <returns>A Boolean indicating whether to proceed with extraction.</returns>
        public void EndInitialize(
            CSharpCommandLineArguments commandLineArguments,
            Options options,
            CSharpCompilation compilation)
        {
            if (!init)
            {
                throw new InternalError("EndInitialize called without BeginInitialize returning true");
            }
            layout           = new Layout();
            this.options     = options;
            this.compilation = compilation;
            extractor        = new Extraction.Extractor(false, GetOutputName(compilation, commandLineArguments), Logger);
            LogDiagnostics();

            SetReferencePaths();

            CompilationErrors += FilteredDiagnostics.Count();
        }
예제 #7
0
 private static ExitCode AnalyseTracing(
     TracingAnalyser analyser,
     CSharpCommandLineArguments compilerArguments,
     Options options,
     CanonicalPathCache canonicalPathCache,
     Stopwatch stopwatch)
 {
     return(Analyse(stopwatch, analyser, options,
                    references => ResolveReferences(compilerArguments, analyser, canonicalPathCache, references),
                    (analyser, syntaxTrees) =>
     {
         return ReadSyntaxTrees(
             compilerArguments.SourceFiles.Select(src => canonicalPathCache.GetCanonicalPath(src.Path)),
             analyser,
             compilerArguments.ParseOptions,
             compilerArguments.Encoding,
             syntaxTrees);
     },
                    (syntaxTrees, references) =>
     {
         // csc.exe (CSharpCompiler.cs) also provides CompilationOptions
         // .WithMetadataReferenceResolver(),
         // .WithXmlReferenceResolver() and
         // .WithSourceReferenceResolver().
         // These would be needed if we hadn't explicitly provided the source/references
         // already.
         return CSharpCompilation.Create(
             compilerArguments.CompilationName,
             syntaxTrees,
             references,
             compilerArguments.CompilationOptions
             .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
             .WithStrongNameProvider(new DesktopStrongNameProvider(compilerArguments.KeyFileSearchPaths))
             .WithMetadataImportOptions(MetadataImportOptions.All)
             );
     },
                    (compilation, options) => analyser.EndInitialize(compilerArguments, options, compilation),
                    () => analyser.AnalyseCompilation(),
                    performance => analyser.LogPerformance(performance),
                    () => { }));
 }
        private static void AssertSpecificDiagnostics(int[] expectedCodes, ReportDiagnostic[] expectedOptions, CSharpCommandLineArguments args)
        {
            var actualOrdered = args.CompilationOptions.SpecificDiagnosticOptions.OrderBy(entry => entry.Key);

            AssertEx.Equal(
                expectedCodes.Select(i => MessageProvider.Instance.GetIdForErrorCode(i)),
                actualOrdered.Select(entry => entry.Key));

            AssertEx.Equal(expectedOptions, actualOrdered.Select(entry => entry.Value));
        }
예제 #9
0
        CodeCompilerResult CompileFileInternal(
            CodeCompilerArguments arguments,
            TextWriter log,
            CancellationToken token)
        {
            CSharpCommandLineArguments args = null;

            if (arguments.AdditionalArguments != null)
            {
                var splitArgs = CommandLineParser.SplitCommandLineIntoArguments(arguments.AdditionalArguments, false);
                if (splitArgs.Any())
                {
                    args = CSharpCommandLineParser.Default.Parse(splitArgs, arguments.TempDirectory, null, null);
                }
            }

            var references = new List <MetadataReference> ();

            foreach (var assemblyReference in AssemblyResolver.GetResolvedReferences(runtime, arguments.AssemblyReferences))
            {
                references.Add(MetadataReference.CreateFromFile(assemblyReference));
            }

            var parseOptions = args?.ParseOptions ?? new CSharpParseOptions();

            if (arguments.LangVersion != null)
            {
                if (LanguageVersionFacts.TryParse(arguments.LangVersion, out var langVersion))
                {
                    parseOptions = parseOptions.WithLanguageVersion(langVersion);
                }
                else
                {
                    throw new System.Exception($"Unknown value '{arguments.LangVersion}' for langversion");
                }
            }
            else
            {
                // need to update this when updating referenced roslyn binaries
                CSharpLangVersionHelper.GetBestSupportedLangVersion(runtime, CSharpLangVersion.v9_0);
            }

            var syntaxTrees = new List <SyntaxTree> ();

            foreach (var sourceFile in arguments.SourceFiles)
            {
                using var stream = File.OpenRead(sourceFile);
                var        sourceText = SourceText.From(stream, Encoding.UTF8, canBeEmbedded: true);
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceText, parseOptions, cancellationToken: token, path: sourceFile);
                syntaxTrees.Add(syntaxTree);
            }

            var compilationOptions = (args?.CompilationOptions ?? new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                                     .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(
                "GeneratedTextTransformation",
                syntaxTrees,
                references,
                compilationOptions
                );


            EmitOptions emitOptions = args?.EmitOptions ?? new EmitOptions();

            if (arguments.Debug)
            {
                var embeddedTexts = syntaxTrees.Select(st => EmbeddedText.FromSource(st.FilePath, st.GetText())).ToList();
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded);
            }

            using var fs = File.OpenWrite(arguments.OutputPath);
            EmitResult result = compilation.Emit(fs, options: emitOptions, cancellationToken: token);

            if (result.Success)
            {
                return(new CodeCompilerResult {
                    Output = new List <string> (),
                    Success = true,
                    Errors = new List <CodeCompilerError> ()
                });
            }

            var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error);
            var errors   = failures.Select(x => {
                var location          = x.Location.GetMappedLineSpan();
                var startLinePosition = location.StartLinePosition;
                var endLinePosition   = location.EndLinePosition;
                return(new CodeCompilerError {
                    Message = x.GetMessage(),
                    Column = startLinePosition.Character,
                    Line = startLinePosition.Line,
                    EndLine = endLinePosition.Line,
                    EndColumn = endLinePosition.Character,
                    IsError = x.Severity == DiagnosticSeverity.Error,
                    Origin = location.Path
                });
            }).ToList();

            return(new CodeCompilerResult {
                Success = false,
                Output = new List <string> (),
                Errors = errors
            });
        }
 /// <summary>
 /// Tries to get the associated <see cref="CSharpCommandLineArguments"/> to the specified project.
 /// </summary>
 /// <param name="project">The project</param>
 /// <param name="commandLineArguments">The output arguments if it was found.</param>
 /// <returns><c>true</c> if the project id has associated command line arguments.</returns>
 public bool TryGetCommandLineArguments(Project project, out CSharpCommandLineArguments commandLineArguments)
 {
     return(TryGetCommandLineArguments(project.Id, out commandLineArguments));
 }
 /// <summary>
 /// Tries to get the associated <see cref="CSharpCommandLineArguments"/> to the specified project id.
 /// </summary>
 /// <param name="projectId">The project id.</param>
 /// <param name="commandLineArguments">The output arguments if it was found.</param>
 /// <returns><c>true</c> if the project id has associated command line arguments.</returns>
 public bool TryGetCommandLineArguments(ProjectId projectId, out CSharpCommandLineArguments commandLineArguments)
 {
     return(_commandLineArguments.TryGetValue(projectId, out commandLineArguments));
 }
예제 #12
0
        /// <summary>
        /// Creates a Project and collect CSharp arguments from a compiler invocation.
        /// </summary>
        private Project GetCompilationOptionsAndFiles(Project project, Microsoft.Build.Logging.StructuredLogger.CompilerInvocation invocation, List <string> args, out CSharpCommandLineArguments arguments)
        {
            arguments = CSharpCommandLineParser.Default.Parse(args, invocation.ProjectDirectory, sdkDirectory: null);

            project = project.WithCompilationOptions(arguments.CompilationOptions);
            project = project.WithParseOptions(arguments.ParseOptions);
            project = project.WithMetadataReferences(arguments.MetadataReferences.Select(x => x.Reference).Select(GetOrCreateMetaDataReference));

            foreach (var sourceFile in arguments.SourceFiles)
            {
                var filePath = sourceFile.Path;
                var name     = filePath;
                if (name.StartsWith(invocation.ProjectDirectory))
                {
                    name = name.Substring(invocation.ProjectDirectory.Length);
                }
                var document = project.AddDocument(name, File.ReadAllText(filePath), filePath: filePath);
                project = document.Project;
            }

            return(project);
        }