private static bool TryReduce(
            this NameSyntax name,
            SemanticModel semanticModel,
            out TypeSyntax replacementNode,
            out TextSpan issueSpan,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            replacementNode = null;
            issueSpan = default(TextSpan);

            if (name.IsVar)
            {
                return false;
            }

            // we should not simplify a name of a namespace declaration
            if (IsPartOfNamespaceDeclarationName(name))
            {
                return false;
            }

            // We can simplify Qualified names and AliasQualifiedNames. Generally, if we have 
            // something like "A.B.C.D", we only consider the full thing something we can simplify.
            // However, in the case of "A.B.C<>.D", then we'll only consider simplifying up to the 
            // first open name.  This is because if we remove the open name, we'll often change 
            // meaning as "D" will bind to C<T>.D which is different than C<>.D!
            if (name is QualifiedNameSyntax)
            {
                var left = ((QualifiedNameSyntax)name).Left;
                if (ContainsOpenName(left))
                {
                    // Don't simplify A.B<>.C
                    return false;
                }
            }

            // 1. see whether binding the name binds to a symbol/type. if not, it is ambiguous and
            //    nothing we can do here.
            var symbol = SimplificationHelpers.GetOriginalSymbolInfo(semanticModel, name);
            if (symbol == null)
            {
                return false;
            }

            // treat constructor names as types
            var method = symbol as IMethodSymbol;
            if (method.IsConstructor())
            {
                symbol = method.ContainingType;
            }

            if (symbol.Kind == SymbolKind.Method && name.Kind() == SyntaxKind.GenericName)
            {
                // The option wants the generic method invocation name to be explicit, then quit the reduction
                if (!optionSet.GetOption(SimplificationOptions.PreferImplicitTypeInference))
                {
                    return false;
                }

                var genericName = (GenericNameSyntax)name;
                replacementNode = SyntaxFactory.IdentifierName(genericName.Identifier)
                    .WithLeadingTrivia(genericName.GetLeadingTrivia())
                    .WithTrailingTrivia(genericName.GetTrailingTrivia());

                issueSpan = genericName.TypeArgumentList.Span;
                return name.CanReplaceWithReducedName(replacementNode, semanticModel, cancellationToken);
            }

            if (!(symbol is INamespaceOrTypeSymbol))
            {
                return false;
            }

            if (name.HasAnnotations(SpecialTypeAnnotation.Kind))
            {
                replacementNode = SyntaxFactory.PredefinedType(
                    SyntaxFactory.Token(
                        name.GetLeadingTrivia(),
                        GetPredefinedKeywordKind(SpecialTypeAnnotation.GetSpecialType(name.GetAnnotations(SpecialTypeAnnotation.Kind).First())),
                        name.GetTrailingTrivia()));

                issueSpan = name.Span;

                return name.CanReplaceWithReducedNameInContext(replacementNode, semanticModel, cancellationToken);
            }
            else
            {
                if (!name.IsRightSideOfDotOrColonColon())
                {
                    IAliasSymbol aliasReplacement;
                    if (name.TryReplaceWithAlias(semanticModel, optionSet.GetOption(SimplificationOptions.PreferAliasToQualification), cancellationToken, out aliasReplacement))
                    {
                        // get the token text as it appears in source code to preserve e.g. unicode character escaping
                        var text = aliasReplacement.Name;
                        var syntaxRef = aliasReplacement.DeclaringSyntaxReferences.FirstOrDefault();

                        if (syntaxRef != null)
                        {
                            var declIdentifier = ((UsingDirectiveSyntax)syntaxRef.GetSyntax(cancellationToken)).Alias.Name.Identifier;
                            text = declIdentifier.IsVerbatimIdentifier() ? declIdentifier.ToString().Substring(1) : declIdentifier.ToString();
                        }

                        var identifierToken = SyntaxFactory.Identifier(
                                name.GetLeadingTrivia(),
                                SyntaxKind.IdentifierToken,
                                text,
                                aliasReplacement.Name,
                                name.GetTrailingTrivia());

                        identifierToken = CSharpSimplificationService.TryEscapeIdentifierToken(identifierToken, name, semanticModel);
                        replacementNode = SyntaxFactory.IdentifierName(identifierToken);

                        // Merge annotation to new syntax node
                        var annotatedNodesOrTokens = name.GetAnnotatedNodesAndTokens(RenameAnnotation.Kind);
                        foreach (var annotatedNodeOrToken in annotatedNodesOrTokens)
                        {
                            if (annotatedNodeOrToken.IsToken)
                            {
                                identifierToken = annotatedNodeOrToken.AsToken().CopyAnnotationsTo(identifierToken);
                            }
                            else
                            {
                                replacementNode = annotatedNodeOrToken.AsNode().CopyAnnotationsTo(replacementNode);
                            }
                        }

                        annotatedNodesOrTokens = name.GetAnnotatedNodesAndTokens(AliasAnnotation.Kind);
                        foreach (var annotatedNodeOrToken in annotatedNodesOrTokens)
                        {
                            if (annotatedNodeOrToken.IsToken)
                            {
                                identifierToken = annotatedNodeOrToken.AsToken().CopyAnnotationsTo(identifierToken);
                            }
                            else
                            {
                                replacementNode = annotatedNodeOrToken.AsNode().CopyAnnotationsTo(replacementNode);
                            }
                        }

                        replacementNode = ((SimpleNameSyntax)replacementNode).WithIdentifier(identifierToken);
                        issueSpan = name.Span;

                        // In case the alias name is the same as the last name of the alias target, we only include 
                        // the left part of the name in the unnecessary span to Not confuse uses.
                        if (name.Kind() == SyntaxKind.QualifiedName)
                        {
                            QualifiedNameSyntax qualifiedName = (QualifiedNameSyntax)name;

                            if (qualifiedName.Right.Identifier.ValueText == identifierToken.ValueText)
                            {
                                issueSpan = qualifiedName.Left.Span;
                            }
                        }

                        // first check if this would be a valid reduction
                        if (name.CanReplaceWithReducedNameInContext(replacementNode, semanticModel, cancellationToken))
                        {
                            // in case this alias name ends with "Attribute", we're going to see if we can also 
                            // remove that suffix.
                            TypeSyntax replacementNodeWithoutAttributeSuffix;
                            TextSpan issueSpanWithoutAttributeSuffix;
                            if (TryReduceAttributeSuffix(
                                name,
                                identifierToken,
                                semanticModel,
                                out replacementNodeWithoutAttributeSuffix,
                                out issueSpanWithoutAttributeSuffix,
                                cancellationToken))
                            {
                                if (name.CanReplaceWithReducedName(replacementNodeWithoutAttributeSuffix, semanticModel, cancellationToken))
                                {
                                    replacementNode = replacementNode.CopyAnnotationsTo(replacementNodeWithoutAttributeSuffix);
                                    issueSpan = issueSpanWithoutAttributeSuffix;
                                }
                            }

                            return true;
                        }

                        return false;
                    }

                    var nameHasNoAlias = false;

                    if (name is SimpleNameSyntax)
                    {
                        var simpleName = (SimpleNameSyntax)name;
                        if (!simpleName.Identifier.HasAnnotations(AliasAnnotation.Kind))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    if (name is QualifiedNameSyntax)
                    {
                        var qualifiedName = (QualifiedNameSyntax)name;
                        if (!qualifiedName.Right.HasAnnotation(Simplifier.SpecialTypeAnnotation))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    if (name is AliasQualifiedNameSyntax)
                    {
                        var aliasQualifiedName = (AliasQualifiedNameSyntax)name;
                        if (aliasQualifiedName.Name is SimpleNameSyntax &&
                            !aliasQualifiedName.Name.Identifier.HasAnnotations(AliasAnnotation.Kind) &&
                            !aliasQualifiedName.Name.HasAnnotation(Simplifier.SpecialTypeAnnotation))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    var aliasInfo = semanticModel.GetAliasInfo(name, cancellationToken);
                    if (nameHasNoAlias && aliasInfo == null)
                    {
                        if (IsReplaceableByVar(name, semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken))
                        {
                            return true;
                        }

                        // Don't simplify to predefined type if name is part of a QualifiedName.
                        // QualifiedNames can't contain PredefinedTypeNames (although MemberAccessExpressions can).
                        // In other words, the left side of a QualifiedName can't be a PredefinedTypeName.
                        if (!name.Parent.IsKind(SyntaxKind.QualifiedName) &&
                            (PreferPredefinedTypeKeywordInDeclarations(name, optionSet, semanticModel) ||
                             PreferPredefinedTypeKeywordInMemberAccess(name, optionSet, semanticModel)))
                        {
                            var type = semanticModel.GetTypeInfo(name, cancellationToken).Type;
                            if (type != null)
                            {
                                var keywordKind = GetPredefinedKeywordKind(type.SpecialType);
                                if (keywordKind != SyntaxKind.None)
                                {
                                    return CanReplaceWithPredefinedTypeKeywordInContext(name, semanticModel, out replacementNode, ref issueSpan, keywordKind, cancellationToken);
                                }
                            }
                            else
                            {
                                var typeSymbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol;
                                if (typeSymbol.IsKind(SymbolKind.NamedType))
                                {
                                    var keywordKind = GetPredefinedKeywordKind(((INamedTypeSymbol)typeSymbol).SpecialType);
                                    if (keywordKind != SyntaxKind.None)
                                    {
                                        return CanReplaceWithPredefinedTypeKeywordInContext(name, semanticModel, out replacementNode, ref issueSpan, keywordKind, cancellationToken);
                                    }
                                }
                            }
                        }
                    }

                    // nullable rewrite: Nullable<int> -> int?
                    // Don't rewrite in the case where Nullable<int> is part of some qualified name like Nullable<int>.Something
                    if (!name.IsVar && (symbol.Kind == SymbolKind.NamedType) && !name.IsLeftSideOfQualifiedName())
                    {
                        var type = (INamedTypeSymbol)symbol;
                        if (aliasInfo == null && CanSimplifyNullable(type, name, semanticModel))
                        {
                            GenericNameSyntax genericName;
                            if (name.Kind() == SyntaxKind.QualifiedName)
                            {
                                genericName = (GenericNameSyntax)((QualifiedNameSyntax)name).Right;
                            }
                            else
                            {
                                genericName = (GenericNameSyntax)name;
                            }

                            var oldType = genericName.TypeArgumentList.Arguments.First();
                            if (oldType.Kind() == SyntaxKind.OmittedTypeArgument)
                            {
                                return false;
                            }

                            replacementNode = SyntaxFactory.NullableType(oldType)
                                .WithLeadingTrivia(name.GetLeadingTrivia())
                                    .WithTrailingTrivia(name.GetTrailingTrivia());
                            issueSpan = name.Span;

                            // we need to simplify the whole qualified name at once, because replacing the identifier on the left in
                            // System.Nullable<int> alone would be illegal.
                            // If this fails we want to continue to try at least to remove the System if possible.
                            if (name.CanReplaceWithReducedNameInContext(replacementNode, semanticModel, cancellationToken))
                            {
                                return true;
                            }
                        }
                    }
                }

                SyntaxToken identifier;
                switch (name.Kind())
                {
                    case SyntaxKind.AliasQualifiedName:
                        var simpleName = ((AliasQualifiedNameSyntax)name).Name
                            .WithLeadingTrivia(name.GetLeadingTrivia());

                        simpleName = simpleName.ReplaceToken(simpleName.Identifier,
                            ((AliasQualifiedNameSyntax)name).Name.Identifier.CopyAnnotationsTo(
                                simpleName.Identifier.WithLeadingTrivia(
                                    ((AliasQualifiedNameSyntax)name).Alias.Identifier.LeadingTrivia)));

                        replacementNode = simpleName;

                        issueSpan = ((AliasQualifiedNameSyntax)name).Alias.Span;

                        break;

                    case SyntaxKind.QualifiedName:
                        replacementNode = ((QualifiedNameSyntax)name).Right.WithLeadingTrivia(name.GetLeadingTrivia());
                        issueSpan = ((QualifiedNameSyntax)name).Left.Span;

                        break;

                    case SyntaxKind.IdentifierName:
                        identifier = ((IdentifierNameSyntax)name).Identifier;

                        // we can try to remove the Attribute suffix if this is the attribute name
                        TryReduceAttributeSuffix(name, identifier, semanticModel, out replacementNode, out issueSpan, cancellationToken);
                        break;
                }
            }

            if (replacementNode == null)
            {
                return false;
            }

            return name.CanReplaceWithReducedName(replacementNode, semanticModel, cancellationToken);
        }