private static Docs?ParseDocs(GeneratorExecutionContext context) { Docs?docs = null; if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWin32InputDocPaths", out string?delimitedApiDocsPaths) && !string.IsNullOrWhiteSpace(delimitedApiDocsPaths)) { string[] apiDocsPaths = delimitedApiDocsPaths !.Split('|'); if (apiDocsPaths.Length > 0) { List <Docs> docsList = new(apiDocsPaths.Length); foreach (string path in apiDocsPaths) { try { docsList.Add(Docs.Get(path)); } catch (Exception e) { context.ReportDiagnostic(Diagnostic.Create(DocParsingError, null, path, e.Message)); } } docs = Docs.Merge(docsList); } } return(docs); }
public InterfaceType ( // Type properties string fullyQualifiedName, string assembly, string name, string? @namespace = null, // Type properties Docs?docs = null, // InterfaceType properties string[]?interfaces = null, Method[]?methods = null, Property[]?properties = null, bool isDataType = false ) : base ( fullyQualifiedName, assembly, name, @namespace, TypeKind.Interface, docs ) { Interfaces = interfaces; Methods = methods; Properties = properties; IsDataType = isDataType; }
public EnumType ( // Type properties string fullyQualifiedName, string assembly, string name, // EnumType properties EnumMember[] members, string? @namespace = null, // Type properties Docs?docs = null ) : base ( fullyQualifiedName, assembly, name, @namespace, TypeKind.Enum, docs ) { Members = members ?? throw new ArgumentNullException(nameof(members)); }
public Method ( string name, OptionalValue?returns = null, Parameter[]?parameters = null, bool isAbstract = false, bool isAsync = false, bool isProtected = false, bool isVariadic = false, bool isStatic = false, string?overrides = null, Docs?docs = null ) : base ( parameters: parameters, isProtected: isProtected, isVariadic: isVariadic, overrides: overrides, docs: docs ) { Name = name; Returns = returns; IsAbstract = isAbstract; IsAsync = isAsync; IsStatic = isStatic; }
public Assembly ( string name, string description, string homepage, AssemblyRepository repository, Person author, string fingerprint, string version, string license, AssemblyTargets?targets = null, IDictionary <string, PackageVersion>?dependencies = null, Person[]?contributors = null, IDictionary <string, string>?bundled = null, IDictionary <string, Type>?types = null, Docs?docs = null, Readme?readme = null ) : base(targets, dependencies) { Name = name ?? throw new ArgumentNullException(nameof(name)); Description = description ?? throw new ArgumentNullException(nameof(description)); Homepage = homepage ?? throw new ArgumentNullException(nameof(homepage)); Repository = repository ?? throw new ArgumentNullException(nameof(repository)); Author = author ?? throw new ArgumentNullException(nameof(author)); Fingerprint = fingerprint ?? throw new ArgumentNullException(nameof(fingerprint)); Version = version ?? throw new ArgumentNullException(nameof(version)); License = license ?? throw new ArgumentNullException(nameof(license)); Contributors = contributors; Bundled = bundled; Types = types; Docs = docs; Readme = readme; }
public Parameter ( string name, TypeReference type, bool isOptional = false, bool isVariadic = false, Docs?docs = null ) : base(type: type, isOptional: isOptional) { Name = name ?? throw new ArgumentNullException(nameof(name)); Docs = docs; IsVariadic = isVariadic; }
protected Callable ( Parameter[]?parameters = null, bool isProtected = false, bool isVariadic = false, string?overrides = null, Docs?docs = null ) { Parameters = parameters; IsProtected = isProtected; IsVariadic = isVariadic; Overrides = overrides; Docs = docs; }
public Initializer ( Parameter[]?parameters = null, bool isProtected = false, bool isVariadic = false, string?overrides = null, Docs?docs = null ) : base( parameters: parameters, isProtected: isProtected, isVariadic: isVariadic, overrides: overrides, docs: docs ) { }
protected Type ( string fullyQualifiedName, string assembly, string name, string? @namespace, TypeKind kind, Docs?docs = null ) { FullyQualifiedName = fullyQualifiedName ?? throw new ArgumentNullException(nameof(fullyQualifiedName)); Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly)); Name = name ?? throw new ArgumentNullException(nameof(name)); Namespace = @namespace; Kind = kind; Docs = docs; }
public ClassType ( // Type properties string fullyQualifiedName, string assembly, string name, // ClassType properties bool isAbstract = false, string? @namespace = null, // Type properties Docs?docs = null, // ClassType properties string? @base = null, Initializer?initializer = null, Property[]?properties = null, Method[]?methods = null, string[]?interfaces = null ) : base ( fullyQualifiedName, assembly, name, @namespace, TypeKind.Class, docs ) { IsAbstract = isAbstract; Base = @base; Initializer = initializer; Properties = properties; Methods = methods; Interfaces = interfaces; }
public Property ( string name, TypeReference type, bool isImmutable = false, bool isOptional = false, bool isProtected = false, bool isAbstract = false, bool isStatic = false, bool isConstant = false, string?overrides = null, Docs?docs = null ) : base(type: type, isOptional: isOptional) { Name = name ?? throw new ArgumentNullException(nameof(name)); IsImmutable = isImmutable; IsProtected = isProtected; IsAbstract = isAbstract; Docs = docs; IsStatic = isStatic; IsConstant = isConstant; Overrides = overrides; }
/// <inheritdoc/> public void Execute(GeneratorExecutionContext context) { if (context.Compilation is not CSharpCompilation compilation) { return; } GeneratorOptions options; AdditionalText? nativeMethodsJsonFile = context.AdditionalFiles .FirstOrDefault(af => string.Equals(Path.GetFileName(af.Path), NativeMethodsJsonAdditionalFileName, StringComparison.OrdinalIgnoreCase)); if (nativeMethodsJsonFile is object) { string optionsJson = nativeMethodsJsonFile.GetText(context.CancellationToken) !.ToString(); try { options = JsonSerializer.Deserialize <GeneratorOptions>(optionsJson, new JsonSerializerOptions { AllowTrailingCommas = true, ReadCommentHandling = JsonCommentHandling.Skip, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }); } catch (JsonException ex) { context.ReportDiagnostic(Diagnostic.Create(OptionsParsingError, location: null, nativeMethodsJsonFile.Path, ex.Message)); return; } } else { options = new GeneratorOptions(); } AdditionalText?nativeMethodsTxtFile = context.AdditionalFiles .FirstOrDefault(af => string.Equals(Path.GetFileName(af.Path), NativeMethodsTxtAdditionalFileName, StringComparison.OrdinalIgnoreCase)); if (nativeMethodsTxtFile is null) { return; } var parseOptions = (CSharpParseOptions)context.ParseOptions; if (!compilation.Options.AllowUnsafe) { context.ReportDiagnostic(Diagnostic.Create(UnsafeCodeRequired, location: null)); } Docs?docs = ParseDocs(context); IReadOnlyList <Generator> generators = CollectMetadataPaths(context).Select(path => new Generator(path, docs, options, compilation, parseOptions)).ToList(); try { SuperGenerator.Combine(generators); SourceText?nativeMethodsTxt = nativeMethodsTxtFile.GetText(context.CancellationToken); if (nativeMethodsTxt is null) { return; } foreach (TextLine line in nativeMethodsTxt.Lines) { context.CancellationToken.ThrowIfCancellationRequested(); string name = line.ToString(); if (string.IsNullOrWhiteSpace(name) || name.StartsWith("//", StringComparison.InvariantCulture)) { continue; } name = name.Trim(); var location = Location.Create(nativeMethodsTxtFile.Path, line.Span, nativeMethodsTxt.Lines.GetLinePositionSpan(line.Span)); try { if (Generator.GetBannedAPIs(options).TryGetValue(name, out string?reason)) { context.ReportDiagnostic(Diagnostic.Create(BannedApi, location, reason)); continue; } if (name.EndsWith(".*", StringComparison.Ordinal)) { var moduleName = name.Substring(0, name.Length - 2); int matches = 0; foreach (Generator generator in generators) { if (generator.TryGenerateAllExternMethods(moduleName, context.CancellationToken)) { matches++; } } switch (matches) { case 0: context.ReportDiagnostic(Diagnostic.Create(NoMethodsForModule, location, moduleName)); break; case > 1: context.ReportDiagnostic(Diagnostic.Create(AmbiguousMatchError, location, moduleName)); break; } continue; } List <string> matchingApis = new(); foreach (Generator generator in generators) { if (generator.TryGenerate(name, out IReadOnlyList <string> preciseApi, context.CancellationToken)) { matchingApis.AddRange(preciseApi); continue; } matchingApis.AddRange(preciseApi); if (generator.TryGetEnumName(name, out string?declaringEnum)) { context.ReportDiagnostic(Diagnostic.Create(UseEnumValueDeclaringType, location, declaringEnum)); generator.TryGenerate(declaringEnum, out preciseApi, context.CancellationToken); matchingApis.AddRange(preciseApi); } } switch (matchingApis.Count) { case 0: ReportNoMatch(location, name); break; case > 1: context.ReportDiagnostic(Diagnostic.Create(AmbiguousMatchErrorWithSuggestions, location, name, ConcatSuggestions(matchingApis))); break; } } catch (GenerationFailedException ex) { if (Generator.IsPlatformCompatibleException(ex)) { context.ReportDiagnostic(Diagnostic.Create(CpuArchitectureIncompatibility, location)); } else { // Build up a complete error message. context.ReportDiagnostic(Diagnostic.Create(InternalError, location, AssembleFullExceptionMessage(ex))); } } } foreach (Generator generator in generators) { var compilationUnits = generator.GetCompilationUnits(context.CancellationToken) .OrderBy(pair => pair.Key, StringComparer.OrdinalIgnoreCase) .ThenBy(pair => pair.Key, StringComparer.Ordinal); foreach (var unit in compilationUnits) { context.AddSource($"{generator.InputAssemblyName}.{unit.Key}", unit.Value.ToFullString()); } } string ConcatSuggestions(IReadOnlyList <string> suggestions) { var suggestionBuilder = new StringBuilder(); for (int i = 0; i < suggestions.Count; i++) { if (i > 0) { suggestionBuilder.Append(i < suggestions.Count - 1 ? ", " : " or "); } suggestionBuilder.Append('"'); suggestionBuilder.Append(suggestions[i]); suggestionBuilder.Append('"'); } return(suggestionBuilder.ToString()); } void ReportNoMatch(Location?location, string failedAttempt) { List <string> suggestions = new(); foreach (Generator generator in generators) { suggestions.AddRange(generator.GetSuggestions(failedAttempt).Take(4)); } if (suggestions.Count > 0) { context.ReportDiagnostic(Diagnostic.Create(NoMatchingMethodOrTypeWithSuggestions, location, failedAttempt, ConcatSuggestions(suggestions))); } else { context.ReportDiagnostic(Diagnostic.Create(NoMatchingMethodOrType, location, failedAttempt)); } } } finally { foreach (Generator generator in generators) { generator.Dispose(); } } }
public EnumMember(string name, Docs?docs = null) { Name = name ?? throw new ArgumentNullException(nameof(name)); Docs = docs; }