private static ParameterListSyntax TransformParameterList(ParameterListSyntax list) { var resultingList = list.ReplaceNodes( WhereIsPointerParameter(list.Parameters), (n1, n2) => TransformParameterDefaultValue(n2.WithType(IntPtrTypeSyntax))); return(resultingList); }
private static ParameterListSyntax TransformParameterList(ParameterListSyntax list, GeneratorFlags generatorFlags, IReadOnlyDictionary <ParameterSyntax, FriendlyFlags> parametersToFriendlyTransform) { var resultingList = list.ReplaceNodes( WhereIsPointerParameter(list.Parameters), (n1, n2) => { // Remove all attributes n2 = n2.WithAttributeLists(SyntaxFactory.List <AttributeListSyntax>()); FriendlyFlags friendlyFlags; if (generatorFlags.HasFlag(GeneratorFlags.NativePointerToFriendly) && parametersToFriendlyTransform.TryGetValue(n1, out friendlyFlags)) { var pointerType = (PointerTypeSyntax)n2.Type; var alteredParameter = n2.WithDefault(null); if (friendlyFlags.HasFlag(FriendlyFlags.Array)) { alteredParameter = alteredParameter .WithType(SyntaxFactory.ArrayType(pointerType.ElementType, OneDimensionalUnspecifiedLengthArray)); } else { if (friendlyFlags.HasFlag(FriendlyFlags.Optional)) { alteredParameter = alteredParameter .WithType(SyntaxFactory.NullableType(pointerType.ElementType)); } if (friendlyFlags.HasFlag(FriendlyFlags.Out)) { SyntaxKind modifier = friendlyFlags.HasFlag(FriendlyFlags.Optional) || friendlyFlags.HasFlag(FriendlyFlags.In) ? SyntaxKind.RefKeyword : SyntaxKind.OutKeyword; if (!friendlyFlags.HasFlag(FriendlyFlags.Optional)) { alteredParameter = alteredParameter .WithType(pointerType.ElementType); } alteredParameter = alteredParameter .AddModifiers(SyntaxFactory.Token(modifier)); } else if (!friendlyFlags.HasFlag(FriendlyFlags.Optional)) { alteredParameter = alteredParameter .WithType(pointerType.ElementType); } } return(alteredParameter); } else if (generatorFlags.HasFlag(GeneratorFlags.NativePointerToIntPtr)) { return(n2 .WithType(IntPtrTypeSyntax) .WithDefault(null)); } else { return(n2); } }); return(resultingList); }
private static Task <Document> RefactorAsync( Document document, RecordDeclarationSyntax recordDeclaration, CancellationToken cancellationToken = default) { ParameterListSyntax parameterList = recordDeclaration.ParameterList; BaseListSyntax baseList = recordDeclaration.BaseList; SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters; var identifiersMap = new Dictionary <string, SyntaxToken>(); var statements = new List <StatementSyntax>(); var properties = new List <PropertyDeclarationSyntax>(); var allAttributeLists = new List <AttributeListSyntax>(); var baseType = baseList? .Types .FirstOrDefault(f => f.IsKind(SyntaxKind.PrimaryConstructorBaseType)) as PrimaryConstructorBaseTypeSyntax; ImmutableHashSet <string> basePropertyNames = ImmutableHashSet <string> .Empty; if (baseType != null) { basePropertyNames = baseType .ArgumentList? .Arguments .Select(f => f.ToString()) .ToImmutableHashSet(); } bool isWritable = !recordDeclaration.Modifiers.Contains(SyntaxKind.ReadOnlyKeyword) && recordDeclaration.ClassOrStructKeyword.IsKind(SyntaxKind.StructKeyword); foreach (ParameterSyntax parameter in parameters) { SyntaxToken identifier = parameter.Identifier; string identifierText = identifier.ValueText; SyntaxToken parameterIdentifier = Identifier(StringUtility.FirstCharToLower(identifierText)); SyntaxToken propertyIdentifier = Identifier(StringUtility.FirstCharToUpper(identifierText)); identifiersMap.Add(identifier.ValueText, parameterIdentifier); IEnumerable <AttributeListSyntax> attributeLists = parameter.AttributeLists.Where(f => f.Target?.Identifier.IsKind(SyntaxKind.PropertyKeyword) == true); allAttributeLists.AddRange(attributeLists); statements.Add(SimpleAssignmentStatement( IdentifierName(propertyIdentifier).QualifyWithThis(), IdentifierName(parameterIdentifier.WithTriviaFrom(identifier)))); if (!basePropertyNames.Contains(identifierText)) { properties.Add(PropertyDeclaration( attributeLists.Select(f => f.WithTarget(null)).ToSyntaxList(), Modifiers.Public(), parameter.Type, default(ExplicitInterfaceSpecifierSyntax), propertyIdentifier, AccessorList( AutoGetAccessorDeclaration(), (isWritable) ? AutoSetAccessorDeclaration() : AutoInitAccessorDeclaration() ))); } } ParameterListSyntax newParameterList = parameterList.RemoveNodes( allAttributeLists, SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.KeepUnbalancedDirectives); newParameterList = newParameterList.ReplaceTokens( newParameterList.Parameters.Select(parameter => parameter.Identifier), (identifier, _) => identifiersMap[identifier.ValueText]); ParameterSyntax firstParameter = parameterList.Parameters[0]; if (firstParameter.GetLeadingTrivia().SingleOrDefault(shouldThrow: false).IsKind(SyntaxKind.WhitespaceTrivia)) { SyntaxTriviaList newIndentation = SyntaxTriviaAnalysis.GetIncreasedIndentationTriviaList(firstParameter, cancellationToken); newParameterList = newParameterList.ReplaceNodes( newParameterList.Parameters, (parameter, _) => { return((parameter.GetLeadingTrivia().SingleOrDefault().IsKind(SyntaxKind.WhitespaceTrivia)) ? parameter.WithLeadingTrivia(newIndentation) : parameter); }); } ConstructorDeclarationSyntax constructor = ConstructorDeclaration( Modifiers.Public(), recordDeclaration.Identifier.WithoutTrivia(), newParameterList, Block(statements)); RecordDeclarationSyntax newRecord = recordDeclaration .WithIdentifier(recordDeclaration.Identifier.WithTrailingTrivia(recordDeclaration.ParameterList.GetTrailingTrivia())) .WithParameterList(null) .WithSemicolonToken(default);