コード例 #1
0
        public static IEnumerable <IFieldSymbol> CreateFieldsForParameters(
            this SyntaxGenerator factory,
            IList <IParameterSymbol> parameters,
            IDictionary <string, string> parameterToNewFieldMap)
        {
            foreach (var parameter in parameters)
            {
                var refKind       = parameter.RefKind;
                var parameterType = parameter.Type;
                var parameterName = parameter.Name;

                if (refKind != RefKind.Out)
                {
                    // For non-out parameters, create a field and assign the parameter to it.
                    // TODO: I'm not sure that's what we really want for ref parameters.
                    string fieldName;
                    if (TryGetValue(parameterToNewFieldMap, parameterName, out fieldName))
                    {
                        yield return(CodeGenerationSymbolFactory.CreateFieldSymbol(
                                         attributes: null,
                                         accessibility: Accessibility.Private,
                                         modifiers: default(DeclarationModifiers),
                                         type: parameterType,
                                         name: parameterToNewFieldMap[parameterName]));
                    }
                }
            }
        }
        private static IFieldSymbol GetBackingField(IPropertySymbol property)
        {
            var field = property.GetBackingFieldIfAny();

            if (field == null)
            {
                return(null);
            }

            // If the field is something can be referenced with the name it has, then just use
            // it as the backing field we'll generate.  This is the case in VB where the backing
            // field can be referenced as is.
            if (field.CanBeReferencedByName)
            {
                return(field);
            }

            // Otherwise, generate a good name for the backing field we're generating.  This is
            // the case for C# where we have mangled names for the backing field and need something
            // actually usable in code.
            var uniqueName = NameGenerator.GenerateUniqueName(
                property.Name.ToCamelCase(),
                n => !property.ContainingType.GetMembers(n).Any());

            return(CodeGenerationSymbolFactory.CreateFieldSymbol(
                       attributes: default(ImmutableArray <AttributeData>),
                       accessibility: field.DeclaredAccessibility,
                       modifiers: DeclarationModifiers.From(field),
                       type: field.Type,
                       name: uniqueName));
        }
            protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                var languageServices = _document.Project.Solution.Workspace.Services.GetLanguageServices(_state.TypeToGenerateIn.Language);
                var codeGenerator    = languageServices.GetService <ICodeGenerationService>();
                var semanticFacts    = languageServices.GetService <ISemanticFactsService>();

                var value = semanticFacts.LastEnumValueHasInitializer(_state.TypeToGenerateIn)
                    ? EnumValueUtilities.GetNextEnumValue(_state.TypeToGenerateIn, cancellationToken)
                    : null;

                var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                var result = await codeGenerator.AddFieldAsync(
                    _document.Project.Solution,
                    _state.TypeToGenerateIn,
                    CodeGenerationSymbolFactory.CreateFieldSymbol(
                        attributes: default(ImmutableArray <AttributeData>),
                        accessibility: Accessibility.Public,
                        modifiers: default(DeclarationModifiers),
                        type: _state.TypeToGenerateIn,
                        name: _state.IdentifierToken.ValueText,
                        hasConstantValue: value != null,
                        constantValue: value),
                    new CodeGenerationOptions(contextLocation : _state.IdentifierToken.GetLocation()),
                    cancellationToken)
                             .ConfigureAwait(false);

                return(result);
            }
コード例 #4
0
ファイル: CodeGenerationTests.cs プロジェクト: tohfe/roslyn
 internal static async Task TestAddFieldAsync(
     string initial,
     string expected,
     Func<SemanticModel, ITypeSymbol> type = null,
     string name = "F",
     Accessibility accessibility = Accessibility.Public,
     Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
     CodeGenerationOptions codeGenerationOptions = null,
     bool hasConstantValue = false,
     object constantValue = null,
     bool addToCompilationUnit = false)
 {
     using (var context = await TestContext.CreateAsync(initial, expected))
     {
         var typeSymbol = type != null ? type(context.SemanticModel) : null;
         var field = CodeGenerationSymbolFactory.CreateFieldSymbol(
             default(ImmutableArray<AttributeData>),
             accessibility,
             modifiers,
             typeSymbol,
             name,
             hasConstantValue,
             constantValue);
         if (!addToCompilationUnit)
         {
             context.Result = await context.Service.AddFieldAsync(context.Solution, (INamedTypeSymbol)context.GetDestination(), field, codeGenerationOptions);
         }
         else
         {
             var newRoot = context.Service.AddField(await context.Document.GetSyntaxRootAsync(), field, codeGenerationOptions);
             context.Result = context.Document.WithSyntaxRoot(newRoot);
         }
     }
 }
コード例 #5
0
            protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                var generateUnsafe = _state.TypeMemberType.IsUnsafe() &&
                                     !_state.IsContainedInUnsafeType;

                if (_generateProperty)
                {
                    var getAccessor = CodeGenerationSymbolFactory.CreateAccessorSymbol(
                        attributes: null,
                        accessibility: DetermineMaximalAccessibility(_state),
                        statements: null);
                    var setAccessor = _isReadonly ? null : CodeGenerationSymbolFactory.CreateAccessorSymbol(
                        attributes: null,
                        accessibility: DetermineMinimalAccessibility(_state),
                        statements: null);

                    var result = await CodeGenerator.AddPropertyDeclarationAsync(
                        _document.Project.Solution,
                        _state.TypeToGenerateIn,
                        CodeGenerationSymbolFactory.CreatePropertySymbol(
                            attributes: null,
                            accessibility: DetermineMaximalAccessibility(_state),
                            modifiers: new DeclarationModifiers(isStatic: _state.IsStatic, isUnsafe: generateUnsafe),
                            type: _state.TypeMemberType,
                            explicitInterfaceSymbol: null,
                            name: _state.IdentifierToken.ValueText,
                            isIndexer: _state.IsIndexer,
                            parameters: _state.Parameters,
                            getMethod: getAccessor,
                            setMethod: setAccessor),
                        new CodeGenerationOptions(contextLocation : _state.IdentifierToken.GetLocation()),
                        cancellationToken : cancellationToken)
                                 .ConfigureAwait(false);

                    return(result);
                }
                else
                {
                    var result = await CodeGenerator.AddFieldDeclarationAsync(
                        _document.Project.Solution,
                        _state.TypeToGenerateIn,
                        CodeGenerationSymbolFactory.CreateFieldSymbol(
                            attributes: null,
                            accessibility: DetermineMinimalAccessibility(_state),
                            modifiers: _isConstant ?
                            new DeclarationModifiers(isConst: true, isUnsafe: generateUnsafe) :
                            new DeclarationModifiers(isStatic: _state.IsStatic, isReadOnly: _isReadonly, isUnsafe: generateUnsafe),
                            type: _state.TypeMemberType,
                            name: _state.IdentifierToken.ValueText),
                        new CodeGenerationOptions(contextLocation : _state.IdentifierToken.GetLocation()),
                        cancellationToken : cancellationToken)
                                 .ConfigureAwait(false);

                    return(result);
                }
            }
コード例 #6
0
            protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                var generateUnsafe = _state.TypeMemberType.IsUnsafe() &&
                                     !_state.IsContainedInUnsafeType;

                if (_generateProperty)
                {
                    var getAccessor = CodeGenerationSymbolFactory.CreateAccessorSymbol(
                        attributes: null,
                        accessibility: DetermineMaximalAccessibility(_state),
                        statements: null);
                    var setAccessor = _isReadonly ? null : CodeGenerationSymbolFactory.CreateAccessorSymbol(
                        attributes: null,
                        accessibility: DetermineMinimalAccessibility(_state),
                        statements: null);

                    var result = await ICSharpCode.NRefactory6.CSharp.CodeGenerator.AddPropertyDeclarationAsync(
                        _document.Project.Solution,
                        _state.TypeToGenerateIn,
                        CodeGenerationSymbolFactory.CreatePropertySymbol(
                            attributes: null,
                            accessibility: DetermineMaximalAccessibility(_state),
                            modifiers: DeclarationModifiers.None.WithIsStatic(_state.IsStatic).WithIsUnsafe(generateUnsafe),
                            type: _state.TypeMemberType,
                            explicitInterfaceSymbol: null,
                            name: _state.IdentifierToken.ValueText,
                            isIndexer: _state.IsIndexer,
                            parameters: _state.Parameters,
                            getMethod: getAccessor,
                            setMethod: setAccessor),
                        new CodeGenerationOptions(contextLocation : _state.IdentifierToken.GetLocation(), generateDefaultAccessibility : false),
                        cancellationToken : cancellationToken)
                                 .ConfigureAwait(false);

                    return(await AnnotateInsertionMode(_document.Project.Solution.GetDocument(result.Id), result));
                }
                else
                {
                    var result = await ICSharpCode.NRefactory6.CSharp.CodeGenerator.AddFieldDeclarationAsync(
                        _document.Project.Solution,
                        _state.TypeToGenerateIn,
                        CodeGenerationSymbolFactory.CreateFieldSymbol(
                            attributes: null,
                            accessibility: DetermineMinimalAccessibility(_state),
                            modifiers: _isConstant ?
                            DeclarationModifiers.None.WithIsConst(true).WithIsUnsafe(generateUnsafe) :
                            DeclarationModifiers.None.WithIsStatic(_state.IsStatic).WithIsReadOnly(_isReadonly).WithIsUnsafe(generateUnsafe),
                            type: _state.TypeMemberType,
                            name: _state.IdentifierToken.ValueText),
                        new CodeGenerationOptions(contextLocation : _state.IdentifierToken.GetLocation(), generateDefaultAccessibility : false),
                        cancellationToken : cancellationToken)
                                 .ConfigureAwait(false);

                    return(await AnnotateInsertionMode(_document.Project.Solution.GetDocument(result.Id), result));
                }
            }
コード例 #7
0
        private IList <ISymbol> GetNewFieldsForRuleNameMultipleZero(INamedTypeSymbol enumType, IEnumerable <IFieldSymbol> zeroValuedFields, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Remove all members that have the value zero from '{0}' except for one member that is named 'None'.
            // Fix: Remove all members that have the value zero except for one member that is named 'None'.

            bool needsNewZeroValuedNoneField = true;
            var  set = zeroValuedFields.ToSet();

            bool makeNextFieldExplicit = false;
            var  newFields             = new List <ISymbol>();

            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                var isZeroValued          = set.Contains(field);
                var isZeroValuedNamedNone = isZeroValued && CA1008DiagnosticAnalyzer.IsMemberNamedNone(field);

                if (!isZeroValued || isZeroValuedNamedNone)
                {
                    var newField = field;
                    if (makeNextFieldExplicit)
                    {
                        newField = GetExplicitlyAssignedField(field, syntaxFactoryService);
                        makeNextFieldExplicit = false;
                    }

                    newFields.Add(newField);

                    if (isZeroValuedNamedNone)
                    {
                        needsNewZeroValuedNoneField = false;
                    }
                }
                else
                {
                    makeNextFieldExplicit = true;
                }
            }

            if (needsNewZeroValuedNoneField)
            {
                var firstZeroValuedField    = zeroValuedFields.First();
                var constantValueExpression = syntaxFactoryService.LiteralExpression(firstZeroValuedField.ConstantValue);
                var newInitializer          = CreateConstantValueInitializer(constantValueExpression);
                var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(firstZeroValuedField.GetAttributes(), firstZeroValuedField.DeclaredAccessibility, firstZeroValuedField.GetSymbolModifiers(),
                                                                             firstZeroValuedField.Type, "None", firstZeroValuedField.HasConstantValue, firstZeroValuedField.ConstantValue, newInitializer);
                newFields.Insert(0, newField);
            }

            return(newFields);
        }
コード例 #8
0
            protected override Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                var solution       = _document.Project.Solution;
                var syntaxTree     = _document.SyntaxTree;
                var generateUnsafe = _state.TypeMemberType.IsUnsafe() &&
                                     !_state.IsContainedInUnsafeType;

                var otions = new CodeGenerationOptions(
                    afterThisLocation: _state.AfterThisLocation,
                    beforeThisLocation: _state.BeforeThisLocation,
                    contextLocation: _state.IdentifierToken.GetLocation());

                if (_generateProperty)
                {
                    var getAccessor = CreateAccessor(DetermineMaximalAccessibility(_state), cancellationToken);
                    var setAccessor = _isReadonly || _returnsByRef
                        ? null
                        : CreateAccessor(DetermineMinimalAccessibility(_state), cancellationToken);

                    var propertySymbol = CodeGenerationSymbolFactory.CreatePropertySymbol(
                        attributes: default(ImmutableArray <AttributeData>),
                        accessibility: DetermineMaximalAccessibility(_state),
                        modifiers: new DeclarationModifiers(isStatic: _state.IsStatic, isUnsafe: generateUnsafe),
                        type: _state.TypeMemberType,
                        returnsByRef: _returnsByRef,
                        explicitInterfaceSymbol: null,
                        name: _state.IdentifierToken.ValueText,
                        isIndexer: _state.IsIndexer,
                        parameters: _state.Parameters,
                        getMethod: getAccessor,
                        setMethod: setAccessor);

                    return(CodeGenerator.AddPropertyDeclarationAsync(
                               solution, _state.TypeToGenerateIn, propertySymbol, otions, cancellationToken));
                }
                else
                {
                    var fieldSymbol = CodeGenerationSymbolFactory.CreateFieldSymbol(
                        attributes: default(ImmutableArray <AttributeData>),
                        accessibility: DetermineMinimalAccessibility(_state),
                        modifiers: _isConstant
                            ? new DeclarationModifiers(isConst: true, isUnsafe: generateUnsafe)
                            : new DeclarationModifiers(isStatic: _state.IsStatic, isReadOnly: _isReadonly, isUnsafe: generateUnsafe),
                        type: _state.TypeMemberType,
                        name: _state.IdentifierToken.ValueText);

                    return(CodeGenerator.AddFieldDeclarationAsync(
                               solution, _state.TypeToGenerateIn, fieldSymbol, otions, cancellationToken));
                }
            }
コード例 #9
0
        protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type)
        {
            var destination = CodeModelService.GetDestination(containerNode);

            var newFieldSymbol = CodeGenerationSymbolFactory.CreateFieldSymbol(
                attributes: default(ImmutableArray <AttributeData>),
                accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Field, destination),
                modifiers: new DeclarationModifiers(isWithEvents: CodeModelService.GetWithEvents(access)),
                type: type,
                name: name);

            return(CodeGenerationService.CreateFieldDeclaration(
                       newFieldSymbol, destination,
                       options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options)));
        }
コード例 #10
0
        private IFieldSymbol GetExplicitlyAssignedField(IFieldSymbol originalField, SyntaxGenerator syntaxFactoryService)
        {
            var originalInitializer = GetFieldInitializer(originalField);

            if (originalInitializer != null || !originalField.HasConstantValue)
            {
                return(originalField);
            }

            var constantValueExpression = syntaxFactoryService.LiteralExpression(originalField.ConstantValue);
            var newInitializer          = CreateConstantValueInitializer(constantValueExpression);

            return(CodeGenerationSymbolFactory.CreateFieldSymbol(originalField.GetAttributes(), originalField.DeclaredAccessibility, originalField.GetSymbolModifiers(),
                                                                 originalField.Type, originalField.Name, originalField.HasConstantValue, originalField.ConstantValue, newInitializer));
        }
コード例 #11
0
        private static TypeDeclarationSyntax WithBackingFields(this TypeDeclarationSyntax node, IEnumerable <ExpandablePropertyInfo> properties, Workspace workspace)
        {
            foreach (var property in properties)
            {
                // When the getter doesn't have a body (i.e. an auto-prop), we'll need to generate a new field.
                var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(
                    attributes: null,
                    accessibility: Microsoft.CodeAnalysis.Accessibility.Private,
                    modifiers: new SymbolModifiers(),
                    type: property.Type,
                    name: property.BackingFieldName);

                node = CodeGenerator.AddFieldDeclaration(node, newField, workspace);
            }

            return(node);
        }
コード例 #12
0
        private IFieldSymbol CreateField(
            IParameterSymbol parameter, ImmutableArray <NamingRule> rules, List <string> parameterNameParts)
        {
            foreach (var rule in rules)
            {
                if (rule.SymbolSpecification.AppliesTo(SymbolKind.Field, Accessibility.Private))
                {
                    var uniqueName = GenerateUniqueName(parameter, parameterNameParts, rule);

                    return(CodeGenerationSymbolFactory.CreateFieldSymbol(
                               default(ImmutableArray <AttributeData>),
                               Accessibility.Private,
                               DeclarationModifiers.ReadOnly,
                               parameter.Type, uniqueName));
                }
            }

            // We place a special rule in s_builtInRules that matches all fields.  So we should
            // always find a matching rule.
            throw ExceptionUtilities.Unreachable;
        }
コード例 #13
0
        private IList <ISymbol> GetNewFieldsForRuleNameNoZeroValue(INamedTypeSymbol enumType, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Add a member to '{0}' that has a value of zero with a suggested name of 'None'.
            // Fix: Add a zero-valued member 'None' to enum.

            var newFields = new List <ISymbol>();
            var constantValueExpression = syntaxFactoryService.LiteralExpression(0);
            var newInitializer          = CreateConstantValueInitializer(constantValueExpression);
            var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(SpecializedCollections.EmptyList <AttributeData>(), Accessibility.Public,
                                                                         default(SymbolModifiers), enumType.EnumUnderlyingType, "None", true, 0, newInitializer);

            newFields.Add(newField);

            foreach (var member in enumType.GetMembers())
            {
                if (!CA1008DiagnosticAnalyzer.IsMemberNamedNone(member))
                {
                    newFields.Add(member);
                }
            }

            return(newFields);
        }
コード例 #14
0
            protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                var value = _state.TypeToGenerateIn.LastEnumValueHasInitializer()
                                        ? EnumValueUtilities.GetNextEnumValue(_state.TypeToGenerateIn, cancellationToken)
                                        : null;

                var result = await new CSharpCodeGenerationService(_document.Project.Solution.Workspace).AddFieldAsync(
                    _document.Project.Solution,
                    _state.TypeToGenerateIn,
                    CodeGenerationSymbolFactory.CreateFieldSymbol(
                        attributes: null,
                        accessibility: Accessibility.Public,
                        modifiers: default(DeclarationModifiers),
                        type: _state.TypeToGenerateIn,
                        name: _state.IdentifierToken.ValueText,
                        hasConstantValue: value != null,
                        constantValue: value),
                    new CodeGenerationOptions(contextLocation: _state.IdentifierToken.GetLocation(), generateDefaultAccessibility: false),
                    cancellationToken)
                             .ConfigureAwait(false);

                return(result);
            }
コード例 #15
0
        private IList <ISymbol> GetNewFieldsForRuleNameRename(INamedTypeSymbol enumType, IFieldSymbol zeroValuedField)
        {
            // Diagnostic: In enum '{0}', change the name of '{1}' to 'None'.
            // Fix: Rename zero-valued enum field to 'None'.

            var newFields = new List <ISymbol>();

            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                if (field != zeroValuedField)
                {
                    newFields.Add(field);
                }
                else
                {
                    var newInitializer = GetFieldInitializer(field);
                    var newField       = CodeGenerationSymbolFactory.CreateFieldSymbol(field.GetAttributes(), field.DeclaredAccessibility, field.GetSymbolModifiers(),
                                                                                       field.Type, "None", field.HasConstantValue, field.ConstantValue, newInitializer);
                    newFields.Add(newField);
                }
            }

            return(newFields);
        }
コード例 #16
0
        internal static void TestAddField(
            string initial,
            string expected,
            Func <SemanticModel, ITypeSymbol> type = null,
            string name = "F",
            Accessibility accessibility    = Accessibility.Public,
            DeclarationModifiers modifiers = default(DeclarationModifiers),
            CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions),
            bool compareTokens        = true,
            bool hasConstantValue     = false,
            object constantValue      = null,
            bool addToCompilationUnit = false)
        {
            using (var context = new TestContext(initial, expected, compareTokens))
            {
                var typeSymbol = type != null?type(context.SemanticModel) : null;

                var field = CodeGenerationSymbolFactory.CreateFieldSymbol(
                    null,
                    accessibility,
                    modifiers,
                    typeSymbol,
                    name,
                    hasConstantValue,
                    constantValue);
                if (!addToCompilationUnit)
                {
                    context.Result = context.Service.AddFieldAsync(context.Solution, (INamedTypeSymbol)context.GetDestination(), field, codeGenerationOptions).Result;
                }
                else
                {
                    var newRoot = context.Service.AddField(context.Document.GetSyntaxRootAsync().Result, field, codeGenerationOptions);
                    context.Result = context.Document.WithSyntaxRoot(newRoot);
                }
            }
        }
コード例 #17
0
 internal static Func <SemanticModel, ISymbol> CreateField(Accessibility accessibility, DeclarationModifiers modifiers, Type type, string name)
 {
     return(s => CodeGenerationSymbolFactory.CreateFieldSymbol(
                null, accessibility, modifiers, GetTypeSymbol(type)(s), name));
 }
コード例 #18
0
 internal static Func <SemanticModel, ISymbol> CreateField(Accessibility accessibility, DeclarationModifiers modifiers, Type type, string name)
 {
     return(s => CodeGenerationSymbolFactory.CreateFieldSymbol(
                default(ImmutableArray <AttributeData>), accessibility,
                modifiers, GetTypeSymbol(type)(s), name));
 }
コード例 #19
0
 private static Func <SemanticModel, ISymbol> CreateEnumField(string name, object value)
 {
     return(s => CodeGenerationSymbolFactory.CreateFieldSymbol(
                null, Accessibility.Public, new DeclarationModifiers(), GetTypeSymbol(typeof(int))(s), name, value != null, value));
 }
コード例 #20
0
        protected async override Task <SyntaxNode> RewriteFieldNameAndAccessibilityAsync(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(declarationAnnotation).FirstOrDefault();

            // There may be no field to rewrite if this document is part of a set of linked files
            // and the declaration is not conditionally compiled in this document's project.
            if (declarator == null)
            {
                return(root);
            }

            var tempAnnotation = new SyntaxAnnotation();
            var escapedName    = originalFieldName.EscapeIdentifier();
            var newIdentifier  = SyntaxFactory.Identifier(
                leading: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker),
                contextualKind: SyntaxKind.IdentifierName,
                text: escapedName,
                valueText: originalFieldName,
                trailing: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker))
                                 .WithTrailingTrivia(declarator.Identifier.TrailingTrivia)
                                 .WithLeadingTrivia(declarator.Identifier.LeadingTrivia);

            var updatedDeclarator = declarator.WithIdentifier(newIdentifier).WithAdditionalAnnotations(tempAnnotation);

            root     = root.ReplaceNode(declarator, updatedDeclarator);
            document = document.WithSyntaxRoot(root);

            var declaration = root.GetAnnotatedNodes <SyntaxNode>(tempAnnotation).First().Parent as VariableDeclarationSyntax;

            if (declaration.Variables.Count == 1)
            {
                var fieldSyntax = declaration.Parent as FieldDeclarationSyntax;

                var modifierKinds = new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, SyntaxKind.PublicKeyword };

                if (makePrivate)
                {
                    var modifiers = SpecializedCollections.SingletonEnumerable(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))
                                    .Concat(fieldSyntax.Modifiers.Where(m => !modifierKinds.Contains(m.Kind())));

                    root = root.ReplaceNode(fieldSyntax, fieldSyntax.WithModifiers(
                                                SyntaxFactory.TokenList(modifiers))
                                            .WithAdditionalAnnotations(Formatter.Annotation)
                                            .WithLeadingTrivia(fieldSyntax.GetLeadingTrivia())
                                            .WithTrailingTrivia(fieldSyntax.GetTrailingTrivia()));
                }
            }
            else if (declaration.Variables.Count > 1 && makePrivate)
            {
                document = document.WithSyntaxRoot(root);
                var codeGenService = document.GetLanguageService <ICodeGenerationService>();
                var semanticModel  = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                declarator  = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First();
                declaration = declarator.Parent as VariableDeclarationSyntax;

                var field = semanticModel.GetDeclaredSymbol(declarator, cancellationToken) as IFieldSymbol;

                var fieldToAdd = declarationAnnotation.AddAnnotationToSymbol(CodeGenerationSymbolFactory.CreateFieldSymbol(
                                                                                 field.GetAttributes(),
                                                                                 Accessibility.Private,
                                                                                 new DeclarationModifiers(isStatic: field.IsStatic, isReadOnly: field.IsReadOnly, isConst: field.IsConst),
                                                                                 field.Type,
                                                                                 field.Name,
                                                                                 field.HasConstantValue,
                                                                                 field.ConstantValue,
                                                                                 declarator.Initializer));

                var withField = await codeGenService.AddFieldAsync(document.Project.Solution, field.ContainingType, fieldToAdd, new CodeGenerationOptions(), cancellationToken).ConfigureAwait(false);

                root = await withField.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                declarator  = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First();
                declaration = declarator.Parent as VariableDeclarationSyntax;

                return(root.RemoveNode(declarator, SyntaxRemoveOptions.KeepNoTrivia));
            }

            return(root);
        }
コード例 #21
0
ファイル: SyntaxNodeTests.cs プロジェクト: CSRedRat/roslyn
        public void TestTrackNodesWithDocument()
        {
            var pid = ProjectId.CreateNewId();
            var did = DocumentId.CreateNewId(pid);

            var sourceText = @"public class C { void M() { } }";

            var sol = new CustomWorkspace().CurrentSolution
                      .AddProject(pid, "proj", "proj", LanguageNames.CSharp)
                      .AddDocument(did, "doc", sourceText);

            var doc = sol.GetDocument(did);

            // find initial nodes of interest
            var root       = doc.GetSyntaxRootAsync().Result;
            var classDecl  = root.DescendantNodes().OfType <ClassDeclarationSyntax>().First();
            var methodDecl = classDecl.DescendantNodes().OfType <MethodDeclarationSyntax>().First();

            // track these nodes
            var trackedRoot = root.TrackNodes(classDecl, methodDecl);

            // use some fancy document centric rewrites
            var comp = doc.Project.GetCompilationAsync().Result;

            var cgenField = CodeGenerationSymbolFactory.CreateFieldSymbol(
                attributes: null,
                accessibility: Accessibility.Private,
                modifiers: new SymbolModifiers(),
                type: comp.GetSpecialType(SpecialType.System_Int32),
                name: "X");

            var currentClassDecl   = trackedRoot.GetCurrentNodes(classDecl).First();
            var classDeclWithField = Formatter.Format(
                CodeGenerator.AddFieldDeclaration(currentClassDecl, cgenField, sol.Workspace),
                sol.Workspace);

            // we can find related bits even from sub-tree fragments
            var latestMethod = classDeclWithField.GetCurrentNodes(methodDecl).First();

            Assert.NotNull(latestMethod);
            Assert.NotEqual(latestMethod, methodDecl);

            trackedRoot = trackedRoot.ReplaceNode(currentClassDecl, classDeclWithField);

            // put back into document (branch solution, etc)
            doc = doc.WithSyntaxRoot(trackedRoot);

            // re-get root of new document
            var root2 = doc.GetSyntaxRootAsync().Result;

            Assert.NotEqual(trackedRoot, root2);

            // we can still find the tracked node in the new document
            var finalClassDecl = root2.GetCurrentNodes(classDecl).First();

            Assert.Equal(@"public class C { private int X; void M() { } }", finalClassDecl.ToString());

            // and other tracked nodes too
            var finalMethodDecl = root2.GetCurrentNodes(methodDecl).First();

            Assert.NotNull(finalMethodDecl);
            Assert.NotEqual(finalMethodDecl, methodDecl);
        }