Browse Source

Fix #1882: Provide a setting to desugar X? into Nullable<X> for value types

pull/1939/head
Siegfried Pammer 6 years ago
parent
commit
df84ab8f6b
  1. 19
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 1
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 1
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  4. 55
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  5. 5
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs
  6. 5
      ICSharpCode.Decompiler/Output/IAmbience.cs
  7. 11
      ILSpy/Languages/CSharpLanguage.cs

19
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -401,12 +401,13 @@ namespace ICSharpCode.Decompiler.CSharp
return new DecompilerTypeSystem(file, resolver); return new DecompilerTypeSystem(file, resolver);
} }
static TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext) static TypeSystemAstBuilder CreateAstBuilder(DecompilerSettings settings)
{ {
var typeSystemAstBuilder = new TypeSystemAstBuilder(); var typeSystemAstBuilder = new TypeSystemAstBuilder();
typeSystemAstBuilder.ShowAttributes = true; typeSystemAstBuilder.ShowAttributes = true;
typeSystemAstBuilder.AlwaysUseShortTypeNames = true; typeSystemAstBuilder.AlwaysUseShortTypeNames = true;
typeSystemAstBuilder.AddResolveResultAnnotations = true; typeSystemAstBuilder.AddResolveResultAnnotations = true;
typeSystemAstBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables;
return typeSystemAstBuilder; return typeSystemAstBuilder;
} }
@ -421,7 +422,7 @@ namespace ICSharpCode.Decompiler.CSharp
void RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext) void RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var context = new TransformContext(typeSystem, decompileRun, decompilationContext, typeSystemAstBuilder); var context = new TransformContext(typeSystem, decompileRun, decompilationContext, typeSystemAstBuilder);
foreach (var transform in astTransforms) { foreach (var transform in astTransforms) {
CancellationToken.ThrowIfCancellationRequested(); CancellationToken.ThrowIfCancellationRequested();
@ -466,13 +467,13 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
try { try {
foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) { foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) {
var astBuilder = CreateAstBuilder(decompilationContext); var astBuilder = CreateAstBuilder(decompileRun.Settings);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "assembly"; attrSection.AttributeTarget = "assembly";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole); syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
} }
foreach (var a in typeSystem.MainModule.GetModuleAttributes()) { foreach (var a in typeSystem.MainModule.GetModuleAttributes()) {
var astBuilder = CreateAstBuilder(decompilationContext); var astBuilder = CreateAstBuilder(decompileRun.Settings);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "module"; attrSection.AttributeTarget = "module";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole); syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
@ -1076,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
try { try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef); var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef);
var typeDecl = entityDecl as TypeDeclaration; var typeDecl = entityDecl as TypeDeclaration;
if (typeDecl == null) { if (typeDecl == null) {
@ -1239,7 +1240,7 @@ namespace ICSharpCode.Decompiler.CSharp
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == method); Debug.Assert(decompilationContext.CurrentMember == method);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var methodDecl = typeSystemAstBuilder.ConvertEntity(method); var methodDecl = typeSystemAstBuilder.ConvertEntity(method);
int lastDot = method.Name.LastIndexOf('.'); int lastDot = method.Name.LastIndexOf('.');
if (method.IsExplicitInterfaceImplementation && lastDot >= 0) { if (method.IsExplicitInterfaceImplementation && lastDot >= 0) {
@ -1412,7 +1413,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentMember == field); Debug.Assert(decompilationContext.CurrentMember == field);
try { try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst) { if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst) {
var enumDec = new EnumMemberDeclaration { Name = field.Name }; var enumDec = new EnumMemberDeclaration { Name = field.Name };
object constantValue = field.GetConstantValue(); object constantValue = field.GetConstantValue();
@ -1483,7 +1484,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentMember == property); Debug.Assert(decompilationContext.CurrentMember == property);
try { try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property); EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property);
if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) { if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) {
int lastDot = property.Name.LastIndexOf('.'); int lastDot = property.Name.LastIndexOf('.');
@ -1518,7 +1519,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentMember == ev); Debug.Assert(decompilationContext.CurrentMember == ev);
try { try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition.Kind != TypeKind.Interface; typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition.Kind != TypeKind.Interface;
var eventDecl = typeSystemAstBuilder.ConvertEntity(ev); var eventDecl = typeSystemAstBuilder.ConvertEntity(ev);
int lastDot = ev.Name.LastIndexOf('.'); int lastDot = ev.Name.LastIndexOf('.');

1
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -92,6 +92,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.astBuilder = new TypeSystemAstBuilder(resolver); this.astBuilder = new TypeSystemAstBuilder(resolver);
this.astBuilder.AlwaysUseShortTypeNames = true; this.astBuilder.AlwaysUseShortTypeNames = true;
this.astBuilder.AddResolveResultAnnotations = true; this.astBuilder.AddResolveResultAnnotations = true;
this.astBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables;
this.typeInference = new TypeInference(compilation) { Algorithm = TypeInferenceAlgorithm.Improved }; this.typeInference = new TypeInference(compilation) { Algorithm = TypeInferenceAlgorithm.Improved };
} }

1
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -195,6 +195,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility; astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility;
astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames; astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames;
astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames; astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames;
astBuilder.UseNullableSpecifierForValueTypes = (ConversionFlags & ConversionFlags.UseNullableSpecifierForValueTypes) != 0;
return astBuilder; return astBuilder;
} }

55
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -64,7 +64,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
#region Properties #region Properties
void InitProperties() void InitProperties()
{ {
this.AlwaysUseBuiltinTypeNames = true; this.UseKeywordsForBuiltinTypes = true;
this.UseNullableSpecifierForValueTypes = true;
this.ShowAccessibility = true; this.ShowAccessibility = true;
this.ShowModifiers = true; this.ShowModifiers = true;
this.ShowBaseTypes = true; this.ShowBaseTypes = true;
@ -78,82 +79,88 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// <summary> /// <summary>
/// Specifies whether the ast builder should add annotations to type references. /// Specifies whether the ast builder should add annotations to type references.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool AddTypeReferenceAnnotations { get; set; } public bool AddTypeReferenceAnnotations { get; set; }
/// <summary> /// <summary>
/// Specifies whether the ast builder should add ResolveResult annotations to AST nodes. /// Specifies whether the ast builder should add ResolveResult annotations to AST nodes.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool AddResolveResultAnnotations { get; set; } public bool AddResolveResultAnnotations { get; set; }
/// <summary> /// <summary>
/// Controls the accessibility modifiers are shown. /// Controls the accessibility modifiers are shown.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowAccessibility { get; set; } public bool ShowAccessibility { get; set; }
/// <summary> /// <summary>
/// Controls the non-accessibility modifiers are shown. /// Controls the non-accessibility modifiers are shown.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowModifiers { get; set; } public bool ShowModifiers { get; set; }
/// <summary> /// <summary>
/// Controls whether base type references are shown. /// Controls whether base type references are shown.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowBaseTypes { get; set; } public bool ShowBaseTypes { get; set; }
/// <summary> /// <summary>
/// Controls whether type parameter declarations are shown. /// Controls whether type parameter declarations are shown.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowTypeParameters { get; set; } public bool ShowTypeParameters { get; set; }
/// <summary> /// <summary>
/// Controls whether type parameter names are shown for unbound types. /// Controls whether type parameter names are shown for unbound types.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool ShowTypeParametersForUnboundTypes { get; set; } public bool ShowTypeParametersForUnboundTypes { get; set; }
/// <summary> /// <summary>
/// Controls whether constraints on type parameter declarations are shown. /// Controls whether constraints on type parameter declarations are shown.
/// Has no effect if ShowTypeParameters is false. /// Has no effect if ShowTypeParameters is false.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowTypeParameterConstraints { get; set; } public bool ShowTypeParameterConstraints { get; set; }
/// <summary> /// <summary>
/// Controls whether the names of parameters are shown. /// Controls whether the names of parameters are shown.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowParameterNames { get; set; } public bool ShowParameterNames { get; set; }
/// <summary> /// <summary>
/// Controls whether to show default values of optional parameters, and the values of constant fields. /// Controls whether to show default values of optional parameters, and the values of constant fields.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool ShowConstantValues { get; set; } public bool ShowConstantValues { get; set; }
/// <summary> /// <summary>
/// Controls whether to show attributes. /// Controls whether to show attributes.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool ShowAttributes { get; set; } public bool ShowAttributes { get; set; }
/// <summary> /// <summary>
/// Controls whether to use fully-qualified type names or short type names. /// Controls whether to use fully-qualified type names or short type names.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool AlwaysUseShortTypeNames { get; set; } public bool AlwaysUseShortTypeNames { get; set; }
/// <summary> /// <summary>
/// Controls whether to use fully-qualified type names or short type names. /// Controls whether to use keywords for builtin types.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary>
public bool UseKeywordsForBuiltinTypes { get; set; }
/// <summary>
/// Controls whether to use <c>T?</c> or <c>Nullable&lt;T&gt;</c> for nullable value types.
/// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool AlwaysUseBuiltinTypeNames { get; set; } public bool UseNullableSpecifierForValueTypes { get; set; }
/// <summary> /// <summary>
/// Determines the name lookup mode for converting a type name. /// Determines the name lookup mode for converting a type name.
@ -165,37 +172,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// <summary> /// <summary>
/// Controls whether to generate a body that throws a <c>System.NotImplementedException</c>. /// Controls whether to generate a body that throws a <c>System.NotImplementedException</c>.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool GenerateBody { get; set; } public bool GenerateBody { get; set; }
/// <summary> /// <summary>
/// Controls whether to generate custom events. /// Controls whether to generate custom events.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool UseCustomEvents { get; set; } public bool UseCustomEvents { get; set; }
/// <summary> /// <summary>
/// Controls whether unbound type argument names are inserted in the ast or not. /// Controls whether unbound type argument names are inserted in the ast or not.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool ConvertUnboundTypeArguments { get; set;} public bool ConvertUnboundTypeArguments { get; set;}
/// <summary> /// <summary>
/// Controls whether aliases should be used inside the type name or not. /// Controls whether aliases should be used inside the type name or not.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool UseAliases { get; set; } public bool UseAliases { get; set; }
/// <summary> /// <summary>
/// Controls whether constants like <c>int.MaxValue</c> are converted to a <see cref="MemberReferenceExpression"/> or <see cref="PrimitiveExpression" />. /// Controls whether constants like <c>int.MaxValue</c> are converted to a <see cref="MemberReferenceExpression"/> or <see cref="PrimitiveExpression" />.
/// The default value is <c>true</c>. /// The default value is <see langword="true" />.
/// </summary> /// </summary>
public bool UseSpecialConstants { get; set; } public bool UseSpecialConstants { get; set; }
/// <summary> /// <summary>
/// Controls whether integral constants should be printed in hexadecimal format. /// Controls whether integral constants should be printed in hexadecimal format.
/// The default value is <c>false</c>. /// The default value is <see langword="false" />.
/// </summary> /// </summary>
public bool PrintIntegralValuesAsHex { get; set; } public bool PrintIntegralValuesAsHex { get; set; }
#endregion #endregion
@ -290,7 +297,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
break; break;
case ParameterizedType pt: case ParameterizedType pt:
if (AlwaysUseBuiltinTypeNames && pt.IsKnownType(KnownTypeCode.NullableOfT)) { if (UseNullableSpecifierForValueTypes && pt.IsKnownType(KnownTypeCode.NullableOfT)) {
return ConvertType(pt.TypeArguments[0]).MakeNullableType(); return ConvertType(pt.TypeArguments[0]).MakeNullableType();
} }
astType = ConvertTypeHelper(pt.GenericType, pt.TypeArguments); astType = ConvertTypeHelper(pt.GenericType, pt.TypeArguments);
@ -313,7 +320,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Debug.Assert(typeDef != null || genericType.Kind == TypeKind.Unknown); Debug.Assert(typeDef != null || genericType.Kind == TypeKind.Unknown);
Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount); Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount);
if (AlwaysUseBuiltinTypeNames && typeDef != null) { if (UseKeywordsForBuiltinTypes && typeDef != null) {
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode); string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null) { if (keyword != null) {
return new PrimitiveType(keyword); return new PrimitiveType(keyword);

5
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -116,12 +116,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
readonly Stack<CSharpTypeResolveContext> context; readonly Stack<CSharpTypeResolveContext> context;
readonly bool ignoreUsingScope; readonly bool ignoreUsingScope;
readonly DecompilerSettings settings;
TypeSystemAstBuilder astBuilder; TypeSystemAstBuilder astBuilder;
public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope) public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope)
{ {
this.ignoreUsingScope = !context.Settings.UsingDeclarations; this.ignoreUsingScope = !context.Settings.UsingDeclarations;
this.settings = context.Settings;
CSharpTypeResolveContext currentContext; CSharpTypeResolveContext currentContext;
if (ignoreUsingScope) { if (ignoreUsingScope) {
@ -139,7 +141,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
this.astBuilder = CreateAstBuilder(currentContext); this.astBuilder = CreateAstBuilder(currentContext);
} }
static TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null) TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null)
{ {
CSharpResolver resolver = new CSharpResolver(context); CSharpResolver resolver = new CSharpResolver(context);
if (function != null) { if (function != null) {
@ -150,6 +152,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
return new TypeSystemAstBuilder(resolver) { return new TypeSystemAstBuilder(resolver) {
UseNullableSpecifierForValueTypes = settings.LiftNullables,
AddResolveResultAnnotations = true, AddResolveResultAnnotations = true,
UseAliases = true UseAliases = true
}; };

5
ICSharpCode.Decompiler/Output/IAmbience.cs

@ -92,12 +92,17 @@ namespace ICSharpCode.Decompiler.Output
/// Show default values of parameters. /// Show default values of parameters.
/// </summary> /// </summary>
ShowParameterDefaultValues = 0x4000, ShowParameterDefaultValues = 0x4000,
/// <summary>
/// Use <c>T?</c> instead of <c>Nullable&lt;T&gt;</c>.
/// </summary>
UseNullableSpecifierForValueTypes = 0x8000,
StandardConversionFlags = ShowParameterNames | StandardConversionFlags = ShowParameterNames |
ShowAccessibility | ShowAccessibility |
ShowParameterList | ShowParameterList |
ShowParameterModifiers | ShowParameterModifiers |
ShowParameterDefaultValues | ShowParameterDefaultValues |
UseNullableSpecifierForValueTypes |
ShowReturnType | ShowReturnType |
ShowModifiers | ShowModifiers |
ShowTypeParameterList | ShowTypeParameterList |

11
ILSpy/Languages/CSharpLanguage.cs

@ -457,6 +457,9 @@ namespace ICSharpCode.ILSpy
CSharpAmbience ambience = new CSharpAmbience(); CSharpAmbience ambience = new CSharpAmbience();
// Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes. // Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes.
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList; ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList;
if (new DecompilationOptions().DecompilerSettings.LiftNullables) {
ambience.ConversionFlags |= ConversionFlags.UseNullableSpecifierForValueTypes;
}
return ambience; return ambience;
} }
@ -635,7 +638,13 @@ namespace ICSharpCode.ILSpy
var output = new StringWriter(); var output = new StringWriter();
var decoratedWriter = new TextWriterTokenWriter(output); var decoratedWriter = new TextWriterTokenWriter(output);
var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter); var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter);
new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(entity, writer, new DecompilerSettings().CSharpFormattingOptions); var settings = new DecompilationOptions().DecompilerSettings;
if (!settings.LiftNullables) {
flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes;
}
new CSharpAmbience() {
ConversionFlags = flags,
}.ConvertSymbol(entity, writer, settings.CSharpFormattingOptions);
return new RichText(output.ToString(), writer.HighlightingModel); return new RichText(output.ToString(), writer.HighlightingModel);
} }

Loading…
Cancel
Save