private static RecordDeclarationSyntax GenerateRecordMembers( ICodeGenerationService service, CSharpCodeGenerationContextInfo info, RecordDeclarationSyntax recordDeclaration, ImmutableArray <ISymbol> members, CancellationToken cancellationToken) { if (!info.Context.GenerateMembers) { members = ImmutableArray <ISymbol> .Empty; } // For a record, add record parameters if we have a primary constructor. var primaryConstructor = members.OfType <IMethodSymbol>().FirstOrDefault(m => CodeGenerationConstructorInfo.GetIsPrimaryConstructor(m)); if (primaryConstructor != null) { var parameterList = ParameterGenerator.GenerateParameterList(primaryConstructor.Parameters, isExplicit: false, info); recordDeclaration = recordDeclaration.WithParameterList(parameterList); // remove the primary constructor from the list of members to generate. members = members.Remove(primaryConstructor); // remove any fields/properties that were created by the primary constructor members = members.WhereAsArray(m => m is not IPropertySymbol and not IFieldSymbol || !primaryConstructor.Parameters.Any(static (p, m) => p.Name == m.Name, m));
public static Task <Document> RefactorAsync( Document document, RecordDeclarationSyntax recordDeclaration, IMethodSymbol[] constructorSymbols, SemanticModel semanticModel, CancellationToken cancellationToken = default) { SyntaxList <MemberDeclarationSyntax> members = recordDeclaration.Members; string recordName = recordDeclaration.Identifier.ValueText; bool isSealedClass = recordDeclaration.Modifiers.Contains(SyntaxKind.SealedKeyword); int insertIndex = MemberDeclarationInserter.Default.GetInsertIndex(members, SyntaxKind.ConstructorDeclaration); int position = (insertIndex == 0) ? recordDeclaration.OpenBraceToken.FullSpan.End : members[insertIndex - 1].FullSpan.End; IEnumerable <ConstructorDeclarationSyntax> constructors = constructorSymbols .Select(symbol => CreateConstructor(symbol, recordName, isSealedClass, semanticModel, position)); RecordDeclarationSyntax newRecordDeclaration = recordDeclaration .WithMembers(members.InsertRange(insertIndex, constructors)); return(document.ReplaceNodeAsync(recordDeclaration, newRecordDeclaration, cancellationToken)); }
public SynthesizedRecordConstructor( SourceMemberContainerTypeSymbol containingType, RecordDeclarationSyntax syntax) : base(containingType, syntax.Identifier.GetLocation(), syntax, isIterator: false) { this.MakeFlags(MethodKind.Constructor, containingType.IsAbstract ? DeclarationModifiers.Protected : DeclarationModifiers.Public, returnsVoid: true, isExtensionMethod: false); }
private BaseTypeDeclarationSyntax GenerateRecord( InputObjectTypeDescriptor descriptor, string infoInterfaceType) { RecordDeclarationSyntax recordDeclaration = RecordDeclaration(Token(SyntaxKind.RecordKeyword), descriptor.Name.Value) .AddImplements(new [] { infoInterfaceType }) .AddModifiers( Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword)) .AddGeneratedAttribute() .AddSummary(descriptor.Documentation) .WithOpenBraceToken(Token(SyntaxKind.OpenBraceToken)); recordDeclaration = GenerateProperties( recordDeclaration, SyntaxKind.InitAccessorDeclaration, infoInterfaceType, descriptor); recordDeclaration = recordDeclaration.WithCloseBraceToken( Token(SyntaxKind.CloseBraceToken)); return(recordDeclaration); }
public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { //TODO - RecordDeclarationSyntax TypeDeclarationSyntax?declaration = syntaxNode switch { ClassDeclarationSyntax @class => @class, RecordDeclarationSyntax record => record, _ => null, }; if (declaration is null) { return; } bool include = declaration.Members .OfType <BaseMethodDeclarationSyntax>() .SelectMany(m => m.ParameterList.Parameters) .Concat((declaration as RecordDeclarationSyntax)?.ParameterList?.Parameters ?? Enumerable.Empty <ParameterSyntax>()) .Any(p => p.HasInjectAttribute()); if (include) { _types.Add(declaration); } }
public static void ComputeRefactoring(RefactoringContext context, RecordDeclarationSyntax recordDeclaration) { if (MemberDeclarationListSelection.TryCreate(recordDeclaration, context.Span, out MemberDeclarationListSelection selectedMembers)) { ComputeRefactoring(context, selectedMembers); } }
public static SourceText GeneratePrintMembersText( RecordDeclarationSyntax recordDeclaration, INamedTypeSymbol recordSymbol, Dictionary <SymbolClassification, List <ISymbol> > groups) { MemberDeclarationSyntax printMembersMethod = SyntaxFactory.MethodDeclaration( attributeLists: s_emptyAttributeList, modifiers: GetPrintMembersModifiers(recordSymbol), returnType: SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BoolKeyword)), explicitInterfaceSpecifier: null, identifier: s_printMembersIdentifier, typeParameterList: null, parameterList: SyntaxFactory.ParameterList( SyntaxFactory.SeparatedList <ParameterSyntax>( new[] { SyntaxFactory.Parameter(s_emptyAttributeList, s_emptyTokenList, s_stringBuilderType, s_builderIdentifier, null) } ) ), constraintClauses: s_emptyConstraintList, body: GenerateBody(recordDeclaration, recordSymbol, groups), expressionBody: null ); string namespaceFullyQualifiedName = GetFullyQualifiedNameOfNamespace(recordSymbol.ContainingNamespace); recordDeclaration = recordDeclaration.WithMembers(new SyntaxList <MemberDeclarationSyntax>(printMembersMethod)); if (namespaceFullyQualifiedName.Length == 0) { return(recordDeclaration.NormalizeWhitespace().GetText(Encoding.UTF8)); } NamespaceDeclarationSyntax namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName(namespaceFullyQualifiedName)); return(namespaceDeclaration.WithMembers(new SyntaxList <MemberDeclarationSyntax>(recordDeclaration)).NormalizeWhitespace().GetText(Encoding.UTF8)); }
/// <summary> /// Creates the partial record declaration where the Update(TRecord) method is placed. /// </summary> /// <param name="context">The execution context.</param> /// <param name="updateableRecord">The updateable record.</param> /// <returns>The record declaration.</returns> private static RecordDeclarationSyntax CreatePartialRecordDeclaration ( GeneratorExecutionContext context, RecordDeclarationSyntax updateableRecord ) { return(RecordDeclaration ( Token(RecordKeyword), updateableRecord.Identifier ) .AddModifiers(updateableRecord.Modifiers.ToArray()) .WithOpenBraceToken(Token(OpenBraceToken)) .WithCloseBraceToken(Token(CloseBraceToken)) .AddMembers ( CreateUpdateMethodDeclaration(context, updateableRecord) ) .AddBaseListTypes ( SimpleBaseType ( GenericName ( "IUpdateable" ) .AddTypeArgumentListArguments ( IdentifierName(updateableRecord.Identifier) ) ) )); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf( root, context.Span, out RecordDeclarationSyntax recordDeclaration)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; CodeAction codeAction = CodeAction.Create( "Remove unnecessary braces", ct => { RecordDeclarationSyntax newRecordDeclaration = recordDeclaration.Update( recordDeclaration.AttributeLists, recordDeclaration.Modifiers, recordDeclaration.Keyword, recordDeclaration.Identifier, recordDeclaration.TypeParameterList, recordDeclaration.ParameterList.WithoutTrailingTrivia(), recordDeclaration.BaseList, recordDeclaration.ConstraintClauses,
/// <summary> /// Creates a set of expressions that update each individual member of the record. /// </summary> /// <param name="context">The execution context.</param> /// <param name="updateableRecord">The updateable record.</param> /// <returns>The expressions.</returns> private static List <ExpressionSyntax> CreateMemberUpdateExpressions ( GeneratorExecutionContext context, RecordDeclarationSyntax updateableRecord ) { var withAssignments = new List <ExpressionSyntax>(); if (updateableRecord.ParameterList is null) { return(withAssignments); } foreach (var recordMember in GetRecordMembers(context, updateableRecord)) { ExpressionSyntax expressionSyntax; if (recordMember.Type.IsOptional()) { expressionSyntax = CreateOptionalUpdateExpression(recordMember.Identifier); } else if (recordMember.Type.IsNullableOptional()) { expressionSyntax = CreateNullableOptionalUpdateExpression(recordMember.Identifier); } else { expressionSyntax = CreateSimpleUpdateExpression(recordMember.Identifier); } withAssignments.Add(expressionSyntax); } return(withAssignments); }
public static TypeDeclarationSyntax?Rewrite(this ITypeSymbol symbol) { var @ref = symbol.DeclaringSyntaxReferences.First(); if (@ref is null || @ref.GetSyntax() is not TypeDeclarationSyntax declaration) { return(null); } var memberList = List(members().OfType <MemberDeclarationSyntax>()); if (!memberList.Any()) { return(null); } declaration = declaration .WithMembers(memberList); declaration = declaration switch { RecordDeclarationSyntax record => record .WithParameterList(null) .WithOpenBraceToken(Token(SyntaxKind.OpenBraceToken)) .WithCloseBraceToken(Token(SyntaxKind.CloseBraceToken)) .WithSemicolonToken(default),
protected override CSharpSyntaxGeneratorResult Generate( InputObjectTypeDescriptor descriptor, CSharpSyntaxGeneratorSettings settings) { if (settings.InputRecords) { RecordDeclarationSyntax recordDeclarationSyntax = RecordDeclaration(Token(SyntaxKind.RecordKeyword), descriptor.Name.Value) .AddModifiers( Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword)) .AddGeneratedAttribute() .AddSummary(descriptor.Documentation) .WithOpenBraceToken(Token(SyntaxKind.OpenBraceToken)); foreach (var prop in descriptor.Properties) { recordDeclarationSyntax = recordDeclarationSyntax.AddMembers( PropertyDeclaration(prop.Type.ToTypeSyntax(), prop.Name) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddSummary(prop.Description) .WithGetterAndInit() .WithSuppressNullableWarningExpression()); } recordDeclarationSyntax = recordDeclarationSyntax.WithCloseBraceToken( Token(SyntaxKind.CloseBraceToken)); return(new( descriptor.Name, null, descriptor.RuntimeType.NamespaceWithoutGlobal, recordDeclarationSyntax)); } ClassDeclarationSyntax classDeclaration = ClassDeclaration(descriptor.Name.Value) .AddModifiers( Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword)) .AddGeneratedAttribute() .AddSummary(descriptor.Documentation); foreach (var prop in descriptor.Properties) { classDeclaration = classDeclaration.AddMembers( PropertyDeclaration(prop.Type.ToTypeSyntax(), prop.Name) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddSummary(prop.Description) .WithGetterAndSetter() .WithSuppressNullableWarningExpression()); } return(new( descriptor.Name, null, descriptor.RuntimeType.NamespaceWithoutGlobal, classDeclaration)); }
public void Execute(GeneratorExecutionContext context) { if (!(context.SyntaxReceiver is SyntaxReceiver s)) { return; } var attributesMetadata = new AttributesMetadata( context.Compilation.GetTypeByMetadataName("Generator.Equals.EquatableAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.DefaultEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.OrderedEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.IgnoreEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.UnorderedEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.ReferenceEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.SetEqualityAttribute") !, context.Compilation.GetTypeByMetadataName("Generator.Equals.CustomEqualityAttribute") ! ); var handledSymbols = new HashSet <string>(); foreach (var node in s.CandidateSyntaxes) { var model = context.Compilation.GetSemanticModel(node.SyntaxTree); var symbol = model.GetDeclaredSymbol(node, context.CancellationToken) as ITypeSymbol; var equatableAttributeData = symbol?.GetAttributes().FirstOrDefault(x => x.AttributeClass?.Equals(attributesMetadata.Equatable, SymbolEqualityComparer.Default) == true); if (equatableAttributeData == null) { continue; } var symbolDisplayString = symbol !.ToDisplayString(); if (handledSymbols.Contains(symbolDisplayString)) { continue; } handledSymbols.Add(symbolDisplayString); var explicitMode = equatableAttributeData.NamedArguments .FirstOrDefault(pair => pair.Key == "Explicit") .Value.Value is true; var source = node switch { RecordDeclarationSyntax _ => RecordEqualityGenerator.Generate(symbol !, attributesMetadata, explicitMode), ClassDeclarationSyntax _ => ClassEqualityGenerator.Generate(symbol !, attributesMetadata, explicitMode), _ => throw new Exception("should not have gotten here.") }; var fileName = $"{EscapeFileName(symbolDisplayString)}.Generator.Equals.g.cs" !; context.AddSource(fileName, source); }
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { Debug.Assert(node.ParameterList is object); Binder enclosing = new ExpressionVariableBinder(node, _enclosing); AddToMap(node, enclosing); Visit(node.PrimaryConstructorBaseType, enclosing); }
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { Debug.Assert(node.ParameterList is object); if (node.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments) { VisitNodeToBind(baseWithArguments); } }
public override SyntaxNode VisitRecordDeclaration(RecordDeclarationSyntax node) { if (node != ContainerOfStatementsOrFieldToReplace) { return(base.VisitRecordDeclaration(node)); } return(GetUpdatedTypeDeclaration(node)); }
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { if (_semantics.GetDeclaredSymbol(node) is ITypeSymbol typeSymbol && typeSymbol.GetAttributes().Any(x => x.AttributeClass?.ToDisplayString() == PatchableAttributeFullName)) { _typeNames?.Add(typeSymbol); } base.VisitRecordDeclaration(node); }
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { Debug.Assert(node.ParameterList is object); if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments) { VisitNodeToBind(baseWithArguments); } }
private static string GetTypeName(MemberDeclarationSyntax memberDeclarationSyntax) { return(memberDeclarationSyntax switch { ClassDeclarationSyntax classDeclarationSyntax => NormaliseClass(classDeclarationSyntax), RecordDeclarationSyntax recordDeclarationSyntax => NormaliseStruct(recordDeclarationSyntax), StructDeclarationSyntax structDeclarationSyntax => NormaliseRecord(structDeclarationSyntax), InterfaceDeclarationSyntax interfaceDeclarationSyntax => NormaliseInterface(interfaceDeclarationSyntax), EnumDeclarationSyntax enumDeclarationSyntax => NormaliseEnum(enumDeclarationSyntax), _ => string.Empty });
public override SingleNamespaceOrTypeDeclaration VisitRecordDeclaration(RecordDeclarationSyntax node) { var declarationKind = node.Kind() switch { SyntaxKind.RecordDeclaration => DeclarationKind.Record, SyntaxKind.RecordStructDeclaration => DeclarationKind.RecordStruct, _ => throw ExceptionUtilities.UnexpectedValue(node.Kind()) }; return(VisitTypeDeclaration(node, declarationKind)); }
private static IEnumerable <(TypeSyntax Type, IdentifierNameSyntax Identifier)> GetRecordMembers ( GeneratorExecutionContext context, RecordDeclarationSyntax updateableRecord ) { var members = new List <(TypeSyntax Type, IdentifierNameSyntax Identifier)>(); if (updateableRecord.ParameterList is not null) { foreach (var recordParameter in updateableRecord.ParameterList.Parameters) { if (members.Any(n => n.Identifier.Identifier.Text == recordParameter.Identifier.Text)) { continue; } if (recordParameter.Type is null) { continue; } members.Add((recordParameter.Type, IdentifierName(recordParameter.Identifier))); } } foreach (var recordMember in updateableRecord.Members) { if (recordMember is not PropertyDeclarationSyntax recordProperty) { continue; } if (recordProperty.AccessorList is null) { continue; } var accessors = recordProperty.AccessorList.Accessors; if (!accessors.Any(a => a.IsKind(InitAccessorDeclaration) || a.IsKind(SetAccessorDeclaration))) { continue; } if (members.Any(n => n.Identifier.Identifier.Text == recordProperty.Identifier.Text)) { continue; } members.Add((recordProperty.Type, IdentifierName(recordProperty.Identifier))); } return(members); }
internal Binder GetInRecordBodyBinder(RecordDeclarationSyntax typeDecl) { BinderFactoryVisitor visitor = _binderFactoryVisitorPool.Allocate(); visitor.Initialize(position: typeDecl.SpanStart, memberDeclarationOpt: null, memberOpt: null); Binder resultBinder = visitor.VisitTypeDeclarationCore(typeDecl, NodeUsage.NamedTypeBodyOrTypeParameters); _binderFactoryVisitorPool.Free(visitor); return(resultBinder); }
public static void ComputeRefactoring(RefactoringContext context, RecordDeclarationSyntax recordDeclaration) { SeparatedSyntaxList <ParameterSyntax> parameters = recordDeclaration.ParameterList.Parameters; if (recordDeclaration.ParameterList?.Parameters.Count > 0) { context.RegisterRefactoring( "Use explicit constructor", ct => RefactorAsync(context.Document, recordDeclaration, ct), RefactoringDescriptors.ExpandPositionalConstructor); } }
public async Task <Document> ConvertToClass(Document document, RecordDeclarationSyntax record, bool initFromConstructor, CancellationToken cancellationToken) { var oldRoot = await document.GetSyntaxRootAsync(cancellationToken); var creator = new RecordToClassCreator(); var newRoot = oldRoot !.ReplaceNode(record, creator.GenerateClassDeclaration(record, initFromConstructor) .WithAdditionalAnnotations(Formatter.Annotation)); return(document.WithSyntaxRoot(newRoot)); }
/// <summary> /// Creates the Update(TRecord) method. /// </summary> /// <param name="context">The execution context.</param> /// <param name="updateableRecord">The updateable record.</param> /// <returns>The method.</returns> private static MethodDeclarationSyntax CreateUpdateMethodDeclaration ( GeneratorExecutionContext context, RecordDeclarationSyntax updateableRecord ) { var memberUpdateExpressions = CreateMemberUpdateExpressions(context, updateableRecord); return(MethodDeclaration ( ParseTypeName(updateableRecord.Identifier.Text), "Update" ) .AddModifiers(Token(PublicKeyword)) .AddParameterListParameters ( Parameter(Identifier("other")) .WithType(ParseTypeName(updateableRecord.Identifier.Text)) ) .WithBody ( Block() .AddStatements ( ReturnStatement ( WithExpression ( ThisExpression(), InitializerExpression ( WithInitializerExpression, SeparatedList <ExpressionSyntax>() ) ) .AddInitializerExpressions(memberUpdateExpressions.ToArray()) ) ) ) .WithLeadingTrivia ( Trivia ( DocumentationComment ( XmlText(" "), XmlEmptyElement("inheritdoc"), XmlText(XmlTextNewLine("\n", false)) ) ) )); }
public static SyntaxTriviaList Generate(RecordDeclarationSyntax recordDeclaration, DocumentationCommentGeneratorSettings settings = null) { if (recordDeclaration == null) { throw new ArgumentNullException(nameof(recordDeclaration)); } return(Generate( recordDeclaration.TypeParameterList, recordDeclaration.ParameterList, canGenerateReturns: false, settings: settings)); }
private RecordDeclarationSyntax SortRecordNode(RecordDeclarationSyntax recordDeclaration) { var membersOfRecord = recordDeclaration.Members.ToList(); var nodeData = membersOfRecord.ToDictionary(x => x, x => new CSharpSyntaxNodeData(x)); IComparer <MemberDeclarationSyntax> comparer = new NodeSorter(nodeData, sortingConfiguration); membersOfRecord.Sort(comparer); RecordDeclarationSyntax recordDeclarationNodeWithoutNodes = recordDeclaration.RemoveNodes(membersOfRecord, SyntaxRemoveOptions.KeepNoTrivia); RecordDeclarationSyntax finalRecordDeclarationNode = recordDeclarationNodeWithoutNodes.WithMembers(new SyntaxList <MemberDeclarationSyntax>(membersOfRecord)); return(finalRecordDeclarationNode); }
/// <summary> /// Creates a new <see cref="RecordDeclarationSyntax"/> with the specified member inserted. /// </summary> /// <param name="recordDeclaration"></param> /// <param name="member"></param> public RecordDeclarationSyntax Insert(RecordDeclarationSyntax recordDeclaration, MemberDeclarationSyntax member) { if (recordDeclaration == null) { throw new ArgumentNullException(nameof(recordDeclaration)); } if (member == null) { throw new ArgumentNullException(nameof(member)); } return(recordDeclaration.WithMembers(Insert(recordDeclaration.Members, member))); }
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { Debug.Assert(node.ParameterList is object); Binder enclosing = new ExpressionVariableBinder(node, _enclosing); AddToMap(node, enclosing); if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments) { enclosing = enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer); AddToMap(baseWithArguments, enclosing); Visit(baseWithArguments.ArgumentList, enclosing); } }
public override SyntaxNode?VisitRecordDeclaration(RecordDeclarationSyntax node) { if (!_declarationsToFix.Any(d => d.IsEquivalentTo(node))) { return(base.VisitRecordDeclaration(node)); } var publicKeyword = FindPublicKeyword(node); if (publicKeyword.IsMissing) { return(base.VisitRecordDeclaration(node)); } return(ReplaceWithInternalKeyword(node, publicKeyword)); }