public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

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

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // if length is 0 then no particular range is selected, so pick the first enclosing member
            if (textSpan.Length == 0)
            {
                var decl = root.FindToken(textSpan.Start).Parent.AncestorsAndSelf().OfType <MemberDeclarationSyntax>().FirstOrDefault();
                if (decl != null)
                {
                    textSpan = decl.FullSpan;
                }
            }

            var properties = ExpansionChecker.GetExpandableProperties(textSpan, root, model);

            if (properties.Any())
            {
#pragma warning disable RS0005
                context.RegisterRefactoring(
                    CodeAction.Create("Implement INotifyPropertyChanged interface", (c) =>
                                      ImplementNotifyPropertyChangedAsync(document, root, model, properties, c)));
#pragma warning restore RS0005
            }
        }
        private static PropertyDeclarationSyntax ExpandProperty(PropertyDeclarationSyntax property, string backingFieldName)
        {
            AccessorDeclarationSyntax getter, setter;

            if (!ExpansionChecker.TryGetAccessors(property, out getter, out setter))
            {
                throw new ArgumentException();
            }

            if (getter.Body == null)
            {
                var returnFieldStatement = SyntaxFactory.ParseStatement(string.Format("return {0};", backingFieldName));
                getter = getter
                         .WithBody(SyntaxFactory.Block(SyntaxFactory.SingletonList(returnFieldStatement)));
            }

            getter = getter
                     .WithSemicolonToken(default(SyntaxToken));

            var setPropertyStatement = SyntaxFactory.ParseStatement($"{backingFieldName} = value;");    //string.Format("SetProperty(ref {0}, value, \"{1}\");", backingFieldName, property.Identifier.ValueText));
            var changeInvocation     = SyntaxFactory.ParseStatement("OnPropertyChanged();");

            setter = setter
                     .WithBody(SyntaxFactory.Block(new List <StatementSyntax>()
            {
                setPropertyStatement, changeInvocation
            }.ToArray()))
                     .WithSemicolonToken(default(SyntaxToken));

            var newProperty = property
                              .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { getter, setter })))
                              .WithAdditionalAnnotations(Formatter.Annotation);

            return(newProperty);
        }