Beispiel #1
0
 private static string GetLanguageName(CompilerInvocationInfo invocationInfo)
 {
     return(invocationInfo.Tool switch
     {
         "csc" => LanguageNames.CSharp,
         "vbc" => LanguageNames.VisualBasic,
         _ => throw new NotSupportedException($"Tool '{invocationInfo.Tool}' is not supported."),
     });
Beispiel #2
0
        public static async Task <CompilerInvocation> CreateFromInvocationInfoAsync(CompilerInvocationInfo invocationInfo)
        {
            // We will use a Workspace to simplify the creation of the compilation, but will be careful not to return the Workspace instance from this class.
            // We will still provide the language services which are used by the generator itself, but we don't tie it to a Workspace object so we can
            // run this as an in-proc source generator if one day desired.
            var workspace = new AdhocWorkspace();

            var languageName     = GetLanguageName(invocationInfo);
            var languageServices = workspace.Services.GetLanguageServices(languageName);

            var mapPath = GetPathMapper(invocationInfo);

            var splitCommandLine = CommandLineParser.SplitCommandLineIntoArguments(invocationInfo.Arguments, removeHashComments: false).ToList();

            // Unfortunately for us there are a few paths that get directly read by the command line parse which we need to remap,
            // such as /ruleset files. So let's go through and process them now.
            for (var i = 0; i < splitCommandLine.Count; i++)
            {
                const string RuleSetSwitch = "/ruleset:";

                if (splitCommandLine[i].StartsWith(RuleSetSwitch, StringComparison.Ordinal))
                {
                    var rulesetPath = splitCommandLine[i].Substring(RuleSetSwitch.Length);

                    var quoted = rulesetPath.Length > 2 &&
                                 rulesetPath.StartsWith("\"", StringComparison.Ordinal) &&
                                 rulesetPath.EndsWith("\"", StringComparison.Ordinal);

                    if (quoted)
                    {
                        rulesetPath = rulesetPath.Substring(1, rulesetPath.Length - 2);
                    }

                    rulesetPath = mapPath(rulesetPath);

                    if (quoted)
                    {
                        rulesetPath = "\"" + rulesetPath + "\"";
                    }

                    splitCommandLine[i] = RuleSetSwitch + rulesetPath;
                }
            }

            var commandLineParserService = languageServices.GetRequiredService <ICommandLineParserService>();
            var parsedCommandLine        = commandLineParserService.Parse(splitCommandLine, Path.GetDirectoryName(invocationInfo.ProjectFilePath), isInteractive: false, sdkDirectory: null);

            var analyzerLoader = new DefaultAnalyzerAssemblyLoader();

            var projectId = ProjectId.CreateNewId(invocationInfo.ProjectFilePath);

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Default,
                name: Path.GetFileNameWithoutExtension(invocationInfo.ProjectFilePath),
                assemblyName: parsedCommandLine.CompilationName !,
                language: languageName,
                filePath: invocationInfo.ProjectFilePath,
                outputFilePath: parsedCommandLine.OutputFileName,
                parsedCommandLine.CompilationOptions,
                parsedCommandLine.ParseOptions,
                parsedCommandLine.SourceFiles.Select(s => CreateDocumentInfo(unmappedPath: s.Path)),
                metadataReferences: parsedCommandLine.MetadataReferences.Select(r => MetadataReference.CreateFromFile(mapPath(r.Reference), r.Properties)),
                additionalDocuments: parsedCommandLine.AdditionalFiles.Select(f => CreateDocumentInfo(unmappedPath: f.Path)),
                analyzerReferences: parsedCommandLine.AnalyzerReferences.Select(r => new AnalyzerFileReference(r.FilePath, analyzerLoader)))
                              .WithAnalyzerConfigDocuments(parsedCommandLine.AnalyzerConfigPaths.Select(CreateDocumentInfo));

            var solution    = workspace.CurrentSolution.AddProject(projectInfo);
            var compilation = await solution.GetRequiredProject(projectId).GetRequiredCompilationAsync(CancellationToken.None);

            var options = GeneratorOptions.Default;

            return(new CompilerInvocation(compilation, languageServices, invocationInfo.ProjectFilePath, options));

            // Local methods:
            DocumentInfo CreateDocumentInfo(string unmappedPath)
            {
                var mappedPath = mapPath(unmappedPath);

                return(DocumentInfo.Create(
                           DocumentId.CreateNewId(projectId, mappedPath),
                           name: mappedPath,
                           filePath: mappedPath,
                           loader: new FileTextLoader(mappedPath, parsedCommandLine.Encoding)));
            }
        }