private static LanguageVersion RequiredVersion(ImmutableArray <Diagnostic> diagnostics) { LanguageVersion max = 0; foreach (var diagnostic in diagnostics) { if ( diagnostic.Properties.TryGetValue( DiagnosticPropertyConstants.RequiredLanguageVersion, out var requiredVersion ) && LanguageVersionFacts.TryParse(requiredVersion, out var required) ) { max = max > required ? max : required; } else if (diagnostic.Id == "CS8652") { max = LanguageVersion.Preview; break; } } return(max); }
public static CSharpParseOptions GetCSharpParseOptions(this IAnalyzerResult analyzerResult) { var parseOptions = new CSharpParseOptions(); // Add any constants var constants = analyzerResult.GetProperty("DefineConstants"); if (!string.IsNullOrWhiteSpace(constants)) { parseOptions = parseOptions .WithPreprocessorSymbols(constants.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())); } // Get language version var langVersion = analyzerResult.GetProperty("LangVersion"); if (!string.IsNullOrWhiteSpace(langVersion) && LanguageVersionFacts.TryParse(langVersion, out var languageVersion)) { parseOptions = parseOptions.WithLanguageVersion(languageVersion); } return(parseOptions); }
/// <summary> /// An error/warning directive tells the compiler to indicate a syntactic error/warning /// at the current location. /// /// Format: #error Error message string /// Resulting message: from the first non-whitespace character after the directive /// keyword until the end of the directive (aka EOD) at the line break or EOF. /// Resulting span: [first non-whitespace char, EOD) /// /// Examples (pipes indicate span): /// #error |goo| /// #error |goo| /// #error |goo | /// #error |goo baz| /// #error |//goo| /// #error |/*goo*/| /// #error |/*goo| /// </summary> /// <param name="hash">The '#' token.</param> /// <param name="keyword">The 'error' or 'warning' token.</param> /// <param name="isActive">True if the error/warning should be recorded.</param> /// <returns>An ErrorDirective or WarningDirective node.</returns> private DirectiveTriviaSyntax ParseErrorOrWarningDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive) { var eod = this.ParseEndOfDirectiveWithOptionalPreprocessingMessage(); bool isError = keyword.Kind == SyntaxKind.ErrorKeyword; if (isActive) { var triviaBuilder = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); int triviaWidth = 0; // whitespace and single line comments are trailing trivia on the keyword, the rest // of the error message is leading trivia on the eod. // bool skipping = true; foreach (var t in keyword.TrailingTrivia) { if (skipping) { if (t.Kind == SyntaxKind.WhitespaceTrivia) { continue; } skipping = false; } t.WriteTo(triviaBuilder, leading: true, trailing: true); triviaWidth += t.FullWidth; } foreach (var node in eod.LeadingTrivia) { node.WriteTo(triviaBuilder, leading: true, trailing: true); triviaWidth += node.FullWidth; } //relative to leading trivia of eod //could be negative if part of the error text comes from the trailing trivia of the keyword token int triviaOffset = eod.GetLeadingTriviaWidth() - triviaWidth; string errorText = triviaBuilder.ToString(); eod = this.AddError(eod, triviaOffset, triviaWidth, isError ? ErrorCode.ERR_ErrorDirective : ErrorCode.WRN_WarningDirective, errorText); if (isError) { if (errorText.Equals("version", StringComparison.Ordinal)) { Assembly assembly = typeof(CSharpCompiler).GetTypeInfo().Assembly; string version = CommonCompiler.GetAssemblyFileVersion(assembly); eod = this.AddError(eod, triviaOffset, triviaWidth, ErrorCode.ERR_CompilerAndLanguageVersion, version, this.Options.SpecifiedLanguageVersion.ToDisplayString()); } else { const string versionMarker = "version:"; if (errorText.StartsWith(versionMarker, StringComparison.Ordinal) && LanguageVersionFacts.TryParse(errorText.Substring(versionMarker.Length), out var languageVersion)) { ErrorCode error = this.Options.LanguageVersion.GetErrorCode(); eod = this.AddError(eod, triviaOffset, triviaWidth, error, "version", new CSharpRequiredLanguageVersion(languageVersion)); } } } } if (isError) { return(SyntaxFactory.ErrorDirectiveTrivia(hash, keyword, eod, isActive)); } else { return(SyntaxFactory.WarningDirectiveTrivia(hash, keyword, eod, isActive)); } }
private int ExecuteCore( RazorConfiguration configuration, string projectDirectory, string tagHelperManifest, SourceItem[] sourceItems) { tagHelperManifest = Path.Combine(projectDirectory, tagHelperManifest); var tagHelpers = GetTagHelpers(tagHelperManifest); var compositeFileSystem = new CompositeRazorProjectFileSystem(new[] { GetVirtualRazorProjectSystem(sourceItems), RazorProjectFileSystem.Create(projectDirectory), }); var success = true; var engine = RazorProjectEngine.Create(configuration, compositeFileSystem, b => { b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, }); b.Features.Add(new DefaultTypeNameFeature()); if (GenerateDeclaration.HasValue()) { b.Features.Add(new SetSuppressPrimaryMethodBodyOptionFeature()); } if (RootNamespace.HasValue()) { b.SetRootNamespace(RootNamespace.Value()); } if (CSharpLanguageVersion.HasValue()) { // Only set the C# language version if one was specified, otherwise it defaults to whatever // value was set in the corresponding RazorConfiguration's extensions. var rawLanguageVersion = CSharpLanguageVersion.Value(); if (LanguageVersionFacts.TryParse(rawLanguageVersion, out var csharpLanguageVersion)) { b.SetCSharpLanguageVersion(csharpLanguageVersion); } else { success = false; Error.WriteLine($"Unknown C# language version {rawLanguageVersion}."); } } }); var results = GenerateCode(engine, sourceItems); foreach (var result in results) { var errorCount = result.CSharpDocument.Diagnostics.Count; for (var i = 0; i < errorCount; i++) { var error = result.CSharpDocument.Diagnostics[i]; if (error.Severity == RazorDiagnosticSeverity.Error) { success = false; } if (i < 100) { Error.WriteLine(error.ToString()); // Only show the first 100 errors to prevent massive string allocations. if (i == 99) { Error.WriteLine($"And {errorCount - i + 1} more warnings/errors."); } } } if (success) { // Only output the file if we generated it without errors. var outputFilePath = result.InputItem.OutputPath; File.WriteAllText(outputFilePath, result.CSharpDocument.GeneratedCode); } } return(success ? ExitCodeSuccess : ExitCodeFailureRazorError); }
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 }); }