public void Execute(GeneratorExecutionContext context) { Debug.WriteLine("Execute code generator"); // add the attribute text context.AddSource("ImplementEquatableAttribute", SourceText.From(attributeText, Encoding.UTF8)); if (!(context.SyntaxReceiver is SyntaxReceiver syntaxReceiver)) { return; } CSharpParseOptions?options = (context.Compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions; Compilation compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options)); INamedTypeSymbol?attributeSymbol = compilation.GetTypeByMetadataName("CodeGenerationSample.ImplementEquatableAttribute"); List <ITypeSymbol> typeSymbols = new(); foreach (ClassDeclarationSyntax @class in syntaxReceiver.CandidateClasses) { SemanticModel model = compilation.GetSemanticModel(@class.SyntaxTree); INamedTypeSymbol?typeSymbol = model.GetDeclaredSymbol(@class); if (typeSymbol !.GetAttributes().Any(attr => attr.AttributeClass !.Equals(attributeSymbol, SymbolEqualityComparer.Default))) { typeSymbols.Add(typeSymbol); } } foreach (INamedTypeSymbol typeSymbol in typeSymbols) { string classSource = GetClassSource(typeSymbol); context.AddSource(typeSymbol.Name, SourceText.From(classSource, Encoding.UTF8)); } }
public ScriptRunner(string?code, ImmutableList <SyntaxTree>?syntaxTrees = null, CSharpParseOptions?parseOptions = null, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, Platform platform = Platform.AnyCpu, IEnumerable <MetadataReference>?references = null, IEnumerable <string>?usings = null, string?filePath = null, string?workingDirectory = null, MetadataReferenceResolver?metadataResolver = null, SourceReferenceResolver?sourceResolver = null, InteractiveAssemblyLoader?assemblyLoader = null, OptimizationLevel optimizationLevel = OptimizationLevel.Debug, bool checkOverflow = false, bool allowUnsafe = true, bool registerDependencies = false) { _optimizationLevel = optimizationLevel; _checkOverflow = checkOverflow; _allowUnsafe = allowUnsafe; _registerDependencies = registerDependencies; Code = code; SyntaxTrees = syntaxTrees; OutputKind = outputKind; Platform = platform; _assemblyLoader = assemblyLoader ?? new InteractiveAssemblyLoader(); ParseOptions = (parseOptions ?? new CSharpParseOptions()) .WithKind(SourceCodeKind.Script) .WithPreprocessorSymbols(PreprocessorSymbols); References = references?.AsImmutable() ?? ImmutableArray <MetadataReference> .Empty; Usings = usings?.AsImmutable() ?? ImmutableArray <string> .Empty; FilePath = filePath ?? string.Empty; MetadataResolver = metadataResolver ?? ScriptMetadataResolver.Default.WithBaseDirectory(workingDirectory); SourceResolver = sourceResolver ?? (workingDirectory != null ? new SourceFileResolver(ImmutableArray <string> .Empty, workingDirectory) : SourceFileResolver.Default); }
public static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions?options = null, Encoding?encoding = null) { options ??= TestOptions.Regular; var stringText = SourceText.From(text, encoding ?? Encoding.UTF8); return(CheckSerializable(SyntaxFactory.ParseSyntaxTree(stringText, options, filename))); }
public SyntaxTree[] GetSyntaxTrees(CSharpParseOptions?parseOptions, string sourceFileName = "") { switch (Value) { case string source: return(new[] { Parse(source, filename: sourceFileName, parseOptions) }); case string[] sources: Debug.Assert(string.IsNullOrEmpty(sourceFileName)); return(Parse(parseOptions, sources)); case SyntaxTree tree: Debug.Assert(parseOptions == null); Debug.Assert(string.IsNullOrEmpty(sourceFileName)); return(new[] { tree }); case SyntaxTree[] trees: Debug.Assert(parseOptions == null); Debug.Assert(string.IsNullOrEmpty(sourceFileName)); return(trees); case CSharpTestSource[] testSources: return(testSources.SelectMany(s => s.GetSyntaxTrees(parseOptions, sourceFileName)).ToArray()); case null: return(Array.Empty <SyntaxTree>()); default: throw new Exception($"Unexpected value: {Value}"); } }
public static SyntaxTree[] Parse(CSharpParseOptions?options = null, params string[] sources) { if (sources == null || (sources.Length == 1 && null == sources[0])) { return(new SyntaxTree[] { }); } return(sources.Select(src => Parse(src, options: options)).ToArray()); }
/// <summary> /// 直接加载树,并缓存 /// </summary> /// <param name="tree"></param> /// <returns></returns> internal static SyntaxTree FormartTree(SyntaxTree tree, CSharpParseOptions?options) { if (options == null) { options = _options; } //Console.ReadKey(); //Mark : 16M Memory return(CSharpSyntaxTree.ParseText(tree.GetRoot().NormalizeWhitespace().SyntaxTree.ToString(), options)); }
/// <summary> /// Creates a new instance of <see cref="CSharpGeneratorDriver"/> with the specified <see cref="ISourceGenerator"/>s and the provided options or default. /// </summary> /// <param name="generators">The generators to create this driver with</param> /// <param name="additionalTexts">A list of <see cref="AdditionalText"/>s available to generators in this driver, or <c>null</c> if there are none.</param> /// <param name="parseOptions">The <see cref="CSharpParseOptions"/> that should be used when parsing generated files, or <c>null</c> to use <see cref="CSharpParseOptions.Default"/></param> /// <param name="optionsProvider">An <see cref="AnalyzerConfigOptionsProvider"/> that can be used to retrieve analyzer config values by the generators in this driver, or <c>null</c> if there are none.</param> /// <returns>A new <see cref="CSharpGeneratorDriver"/> instance.</returns> public static CSharpGeneratorDriver Create( IEnumerable <ISourceGenerator> generators, IEnumerable <AdditionalText>?additionalTexts = null, CSharpParseOptions?parseOptions = null, AnalyzerConfigOptionsProvider?optionsProvider = null ) => new CSharpGeneratorDriver( parseOptions ?? CSharpParseOptions.Default, generators.ToImmutableArray(), optionsProvider ?? CompilerAnalyzerConfigOptionsProvider.Empty, additionalTexts.AsImmutableOrEmpty() );
/// <summary> /// Parses given string and initializes a depth-first preorder enumerator. /// </summary> protected SyntaxTree UsingTree(string text, CSharpParseOptions?options = null) { VerifyEnumeratorConsumed(); var tree = ParseTree(text, options); _node = tree.GetCompilationUnitRoot(); var nodes = EnumerateNodes(_node, dump: false); _treeEnumerator = nodes.GetEnumerator(); return(tree); }
internal static SyntaxTree ParseTree(string script, CSharpParseOptions?options) { if (options == null) { options = _options; } //Mark1 : 647ms //Mark2 : 128ms //Mark : 7M Memory var tree = CSharpSyntaxTree.ParseText(script.Trim(), _options); return(FormartTree(tree, options)); }
public CSharpParseOptions GetParseOptions() { if (parseOptions is null) { List <string> preprocessorSymbols = new(); if (Debug) { preprocessorSymbols.Add("DEBUG"); } parseOptions = new CSharpParseOptions(preprocessorSymbols: preprocessorSymbols); } return(parseOptions); }
public bool Equals(CSharpParseOptions?other) { if (object.ReferenceEquals(this, other)) { return(true); } if (!base.EqualsHelper(other)) { return(false); } return(this.SpecifiedLanguageVersion == other.SpecifiedLanguageVersion); }
protected SyntaxTree UsingTree(string text, CSharpParseOptions?options, params DiagnosticDescription[] expectedErrors) { VerifyEnumeratorConsumed(); var tree = ParseTree(text, options); _node = tree.GetCompilationUnitRoot(); var actualErrors = _node.GetDiagnostics(); actualErrors.Verify(expectedErrors); var nodes = EnumerateNodes(_node, dump: false); _treeEnumerator = nodes.GetEnumerator(); return(tree); }
private void EnsureOptions() { if (!_optionsInitialized) { var dependencyContextOptions = GetDependencyContextCompilationOptions(); _parseOptions = GetParseOptions(_hostingEnvironment, dependencyContextOptions); _compilationOptions = GetCompilationOptions(_hostingEnvironment, dependencyContextOptions); _emitOptions = GetEmitOptions(dependencyContextOptions); _optionsInitialized = true; } Debug.Assert(_parseOptions is not null); Debug.Assert(_compilationOptions is not null); Debug.Assert(_emitOptions is not null); }
private static void TestNavigator( string code, Func <ITextStructureNavigator, SnapshotSpan, SnapshotSpan> func, int startPosition, int startLength, int endPosition, int endLength, CSharpParseOptions?options) { using var workspace = TestWorkspace.CreateCSharp(code, options); var buffer = workspace.Documents.First().GetTextBuffer(); var provider = Assert.IsType <CSharpTextStructureNavigatorProvider>( workspace.GetService <ITextStructureNavigatorProvider>(ContentTypeNames.CSharpContentType)); var navigator = provider.CreateTextStructureNavigator(buffer); var actualSpan = func(navigator, new SnapshotSpan(buffer.CurrentSnapshot, startPosition, startLength)); var expectedSpan = new SnapshotSpan(buffer.CurrentSnapshot, endPosition, endLength); Assert.Equal(expectedSpan, actualSpan.Span); }
/// <summary> /// Combines code workspaces and modules into a <see cref="GeneratorInput"/>. /// </summary> /// <param name="workspaceFactory">Factory for <see cref="ICodeWorkspace"/> implementations. Must not be null.</param> /// <param name="code">Original code. Can be null or empty.</param> /// <param name="modules">Code modules. Can be null or empty.</param> /// <param name="addRuntimeAssembly">True to automatically add the typeof(object)'s assembly.</param> /// <param name="options">The optional parse options to use.</param> /// <returns>A generator input.</returns> internal static GeneratorInput Create( Func <ICodeWorkspace> workspaceFactory, ICodeWorkspace code, IEnumerable <ICodeGeneratorModule> modules, bool addRuntimeAssembly, CSharpParseOptions?options) { Debug.Assert(workspaceFactory != null); var assemblies = new HashSet <Assembly>(); if (addRuntimeAssembly) { assemblies.Add(typeof(object).Assembly); } var trees = new List <SyntaxTree>(); if (code != null) { CombineWorkspace(assemblies, trees, code, options); } if (modules != null) { foreach (var m in modules) { var transformed = m.Rewrite(trees); if (transformed != null && transformed != trees) { trees.Clear(); trees.AddRange(transformed); } var wM = workspaceFactory(); m.Inject(wM); CombineWorkspace(assemblies, trees, wM, options); } } return(new GeneratorInput(assemblies, trees)); }
/// <summary> /// Compiles or parses only a single code source. /// </summary> /// <param name="code"></param> /// <param name="assemblyPath">The output path or null if only parsing is required.</param> /// <param name="references">Optional list of dependent assemblies. Used only if compilation is required. This list will be transitively closed.</param> /// <param name="parseOptions">By default, all default applies, the language version is <see cref="LanguageVersion.Default"/>.</param> /// <param name="compileOptions">The compilation options. Used only if compilation is required. Defaults to <see cref="DefaultCompilationOptions"/>.</param> /// <param name="loader">Optional loader function to load the final emitted assembly. Used only if compilation is required.</param> /// <returns>Encapsulation of the result.</returns> static public GenerateResult Generate( string code, string?assemblyPath = null, IEnumerable <Assembly>?references = null, CSharpParseOptions?parseOptions = null, CSharpCompilationOptions?compileOptions = null, Func <string, Assembly>?loader = null) { SyntaxTree[] trees = new[] { SyntaxFactory.ParseSyntaxTree(code, parseOptions) }; if (String.IsNullOrEmpty(assemblyPath)) { // Parsing is enough. return(new GenerateResult(trees)); } using (var weakLoader = WeakAssemblyNameResolver.TemporaryInstall()) { var collector = new HashSet <Assembly>(); collector.Add(typeof(object).Assembly); if (references != null) { foreach (var a in references) { if (collector.Add(a)) { Discover(a, collector); } } } return(Generate(compileOptions, trees, assemblyPath, collector.Select(a => MetadataReference.CreateFromFile(new Uri(a.Location).LocalPath)), loader) .WithLoadFailures(weakLoader.Conflicts)); } }
/// <summary> /// Construct tasks for reading source code files (possibly in parallel). /// /// The constructed syntax trees will be added (thread-safely) to the supplied /// list <paramref name="ret"/>. /// </summary> private static IEnumerable <Action> ReadSyntaxTrees(IEnumerable <string> sources, Analyser analyser, CSharpParseOptions?parseOptions, Encoding?encoding, IList <SyntaxTree> ret) { return(sources.Select <string, Action>(path => () => { try { using var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); var st = CSharpSyntaxTree.ParseText(SourceText.From(file, encoding), parseOptions, path); lock (ret) ret.Add(st); } catch (IOException ex) { lock (analyser) { analyser.Logger.Log(Severity.Error, " Unable to open source file {0}: {1}", path, ex.Message); ++analyser.CompilationErrors; } } })); }
protected virtual SyntaxTree ParseTree(string text, CSharpParseOptions?options) => SyntaxFactory.ParseSyntaxTree(text, options);
public CompilationUnitSyntax ParseFile( string text, CSharpParseOptions?parseOptions = null ) => SyntaxFactory.ParseCompilationUnit(text, options: parseOptions);
protected virtual CSharpSyntaxNode ParseNode(string text, CSharpParseOptions?options) => ParseTree(text, options).GetCompilationUnitRoot();
internal static CSharpCompilation AddAttributesToSyntax(CSharpCompilation compilation, CSharpParseOptions?options = null) { return(compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(_observableObjectAttributeString, options, encoding: Encoding.UTF8))); }
private static void TestConditional( string conditionalExpression, string targetType, string?naturalType, CSharpParseOptions?parseOptions, params DiagnosticDescription[] expectedDiagnostics) { string source = $@" class Program {{ unsafe void Test<T, U, V>(bool b) where T : class where U : class, T where V : class, T {{ {targetType} t = {conditionalExpression}; Use(t); }} A GetA() {{ return null; }} B GetB() {{ return null; }} C GetC() {{ return null; }} D GetD() {{ return null; }} int GetInt() {{ return 1; }} uint GetUInt() {{ return 1; }} T Get<T>() where T : class {{ return null; }} void Use(object t) {{ }} unsafe void Use(void* t) {{ }} unsafe int* GetIntp() {{ return null; }} unsafe long* GetLongp() {{ return null; }} static int M1(int x) => x; static int M2(int x) => x; static int M3(int x, int y) => x; }} public enum color {{ Red, Blue, Green }}; class A {{ }} class B : A {{ public static implicit operator X(B self) => new X(); }} class C : A {{ public static implicit operator X(C self) => new X(); }} class D : A {{ [System.Obsolete(""D"", true)] public static implicit operator X(D self) => new X(); }} class X {{ }} interface IOut<out T> {{ }} interface IIn<in T> {{ }} delegate int Del(int x); "; parseOptions ??= TestOptions.Regular; parseOptions = parseOptions.WithLanguageVersion(MessageID.IDS_FeatureTargetTypedConditional.RequiredVersion()); var tree = Parse(source, options: parseOptions); var comp = CreateCompilation(tree, options: TestOptions.DebugDll.WithAllowUnsafe(true)); comp.VerifyDiagnostics(expectedDiagnostics); var compUnit = tree.GetCompilationUnitRoot(); var classC = (TypeDeclarationSyntax)compUnit.Members.First(); var methodTest = (MethodDeclarationSyntax)classC.Members.First(); var stmt = (LocalDeclarationStatementSyntax)methodTest.Body !.Statements.First(); var conditionalExpr = (ConditionalExpressionSyntax)stmt.Declaration.Variables[0].Initializer !.Value; var model = comp.GetSemanticModel(tree); if (naturalType is null) { var actualType = model.GetTypeInfo(conditionalExpr).Type; if (actualType is { })
public static CSharpGeneratorDriver Create(IEnumerable <ISourceGenerator> generators, IEnumerable <AdditionalText>?additionalTexts = null, CSharpParseOptions?parseOptions = null, AnalyzerConfigOptionsProvider?optionsProvider = null) // https://github.com/dotnet/roslyn/issues/46623 - can remove suppression when me make it internal #pragma warning disable CS0618 // Type or member is obsolete => new CSharpGeneratorDriver(parseOptions ?? CSharpParseOptions.Default, generators.ToImmutableArray(), optionsProvider ?? CompilerAnalyzerConfigOptionsProvider.Empty, additionalTexts.AsImmutableOrEmpty());
public static CSharpGeneratorDriver Create(IEnumerable <ISourceGenerator> generators, IEnumerable <AdditionalText>?additionalTexts, CSharpParseOptions?parseOptions, AnalyzerConfigOptionsProvider?optionsProvider) => Create(generators, additionalTexts, parseOptions, optionsProvider, driverOptions: default);
protected static Assembly?RunGeneratorAndGenerateAssembly( ISourceGenerator generator, string source, out ImmutableArray <Diagnostic> diagnostics, CSharpParseOptions?parseOptions = null, AnalyzerConfigOptions?configOptions = null, IEnumerable <MetadataReference>?additionalReferences = null, CSharpCompilationOptions?compilationOptions = null, EmitOptions?emitOptions = null, bool printDiagnostics = true, bool makeTestFailIfError = true) { if (generator is null) { throw new ArgumentNullException(nameof(generator)); } if (source is null) { throw new ArgumentNullException(nameof(source)); } parseOptions ??= CSharpParseOptions.Default .WithLanguageVersion(LanguageVersion.CSharp9); configOptions ??= TestAnalyzerConfigOptions.Empty; compilationOptions ??= new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable); emitOptions ??= new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb); var optionsProvider = new TestAnalyzerConfigOptionsProvider(configOptions); var driver = CSharpGeneratorDriver.Create( new[] { generator }, parseOptions: parseOptions, optionsProvider: optionsProvider); string assemblyName = Guid.NewGuid().ToString("D"); var syntaxTree = CSharpSyntaxTree.ParseText( source, parseOptions, "Main.cs", Encoding.UTF8); var references = new List <MetadataReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(ITestHooks).Assembly.Location) }; if (additionalReferences is not null) { references.AddRange(additionalReferences); } var compilation = CSharpCompilation.Create( assemblyName, new[] { syntaxTree }, references, compilationOptions); var driver2 = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out _); var runResult = driver2.GetRunResult(); var exceptions = runResult.Results .Select(x => x.Exception) .Where(x => x is not null) .Select(x => x !) .ToArray(); var exception = exceptions.Length switch { 0 => null, 1 => exceptions[0], > 1 => new AggregateException(exceptions) }; if (exception is not null) { ExceptionDispatchInfo.Capture(exception).Throw(); } var embeddedTexts = outputCompilation.SyntaxTrees .Select(x => EmbeddedText.FromSource(x.FilePath, x.GetText())).ToArray(); using var peStream = new MemoryStream(); using var pdbStream = new MemoryStream(); var emitResult = outputCompilation.Emit( peStream, pdbStream, options: emitOptions, embeddedTexts: embeddedTexts); diagnostics = emitResult.Diagnostics; if (printDiagnostics) { foreach (var d in diagnostics .OrderByDescending(x => x.Severity)) { TestContext.WriteLine(d.ToString()); } } if (!emitResult.Success) { if (makeTestFailIfError) { Assert.Fail(); } return(null); } if (makeTestFailIfError) { if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { Assert.Fail(); return(null); } } peStream.Seek(0, SeekOrigin.Begin); pdbStream.Seek(0, SeekOrigin.Begin); var assembly = AssemblyLoadContext.Default.LoadFromStream( peStream, pdbStream); return(assembly); }
static void CombineWorkspace(HashSet <Assembly> assemblies, List <SyntaxTree> trees, ICodeWorkspace c, CSharpParseOptions?options) { foreach (var a in c.AssemblyReferences) { assemblies.Add(a); } var s = c.GetGlobalSource(); if (!String.IsNullOrWhiteSpace(s)) { trees.Add(SyntaxFactory.ParseSyntaxTree(s, options)); } }
/// <summary> /// 配置语法树选项 /// </summary> /// <param name="cSharpParseOptionsAction"></param> /// <returns></returns> public AssemblyCSharpBuilder ConfigSyntaxOptions(Func <CSharpParseOptions, CSharpParseOptions> cSharpParseOptionsAction) { _options = cSharpParseOptionsAction(new CSharpParseOptions()); return(this); }
/// <summary> /// 配置语法树选项 /// </summary> /// <param name="cSharpParseOptions"></param> /// <returns></returns> public AssemblyCSharpBuilder ConfigSyntaxOptions(CSharpParseOptions cSharpParseOptions) { _options = cSharpParseOptions; return(this); }
private static async Task AssertTagsOnBracesOrSemicolonsTokensAsync(string contents, int[] tokenIndices, CSharpParseOptions?options = null) { using var workspace = TestWorkspace.CreateCSharp(contents, options); var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id); var root = await document.GetRequiredSyntaxRootAsync(default);
protected override SyntaxTree ParseSyntaxTree(string content, string fileName, SourceHashAlgorithm hashAlgorithm, CSharpParseOptions?parseOptions) => CSharpTestBase.Parse( content, filename: fileName, checksumAlgorithm: hashAlgorithm, encoding: Encoding.UTF8, options: parseOptions);