public async Task<bool> IsValidAsync(
            Document document,
            int position,
            string expressionValue,
            CancellationToken cancellationToken)
        {
            var expression = SyntaxFactory.ParseExpression(expressionValue);
            var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var token = root.FindToken(position);
            if (token.Kind() == SyntaxKind.CloseBraceToken && token.GetPreviousToken().Kind() != SyntaxKind.None)
            {
                token = token.GetPreviousToken();
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var info = semanticModel.GetSpeculativeSymbolInfo(token.SpanStart, expression, SpeculativeBindingOption.BindAsExpression);
            if (info.Symbol == null)
            {
                return false;
            }

            // We seem to have bound successfully.  However, if it bound to a local, then make
            // sure that that local isn't after the statement that we're currently looking at.  
            if (info.Symbol.Kind == SymbolKind.Local)
            {
                var statement = info.Symbol.Locations.First().FindToken(cancellationToken).GetAncestor<StatementSyntax>();
                if (statement != null && position < statement.SpanStart)
                {
                    return false;
                }
            }

            return true;
        }
        protected override bool TryGetSimplifiedTypeName(Document documentWithFullyQualifiedTypeName, TextSpan updatedTextSpan, CancellationToken cancellationToken, out string simplifiedTypeName)
        {
            simplifiedTypeName = string.Empty;

            var typeAnnotation = new SyntaxAnnotation();
            var syntaxRoot = documentWithFullyQualifiedTypeName.GetCSharpSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken);
            var nodeToReplace = syntaxRoot.DescendantNodes().FirstOrDefault(n => n.Span == updatedTextSpan);

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

            var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation));
            var documentWithAnnotations = documentWithFullyQualifiedTypeName.WithSyntaxRoot(updatedRoot);

            var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
            simplifiedTypeName = simplifiedDocument.GetCSharpSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString();
            return true;
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax expression;
            SyntaxToken openBrace;
            if (!TryGetElementAccessExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out expression, out openBrace))
            {
                return null;
            }

            var semanticModel = await document.GetCSharpSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var expressionSymbol = semanticModel.GetSymbolInfo(expression, cancellationToken).GetAnySymbol();
            if (expressionSymbol is INamedTypeSymbol)
            {
                // foo?[$$]
                var namedType = (INamedTypeSymbol)expressionSymbol;
                if (namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T &&
                    expression.IsKind(SyntaxKind.NullableType) &&
                    expression.IsChildNode<ArrayTypeSyntax>(a => a.ElementType))
                {
                    // Speculatively bind the type part of the nullable as an expression
                    var nullableTypeSyntax = (NullableTypeSyntax)expression;
                    var speculativeBinding = semanticModel.GetSpeculativeSymbolInfo(position, nullableTypeSyntax.ElementType, SpeculativeBindingOption.BindAsExpression);
                    expressionSymbol = speculativeBinding.GetAnySymbol();
                    expression = nullableTypeSyntax.ElementType;
                }
            }

            if (expressionSymbol != null && expressionSymbol is INamedTypeSymbol)
            {
                return null;
            }

            IEnumerable<IPropertySymbol> indexers;
            ITypeSymbol expressionType;

            if (!TryGetIndexers(position, semanticModel, expression, cancellationToken, out indexers, out expressionType) &&
                !TryGetComIndexers(semanticModel, expression, cancellationToken, out indexers, out expressionType))
            {
                return null;
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            var accessibleIndexers = indexers.Where(m => m.IsAccessibleWithin(within, throughTypeOpt: expressionType));
            if (!accessibleIndexers.Any())
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            accessibleIndexers = accessibleIndexers.FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                                                   .Sort(symbolDisplayService, semanticModel, expression.SpanStart);

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = GetTextSpan(expression, openBrace);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            return CreateSignatureHelpItems(accessibleIndexers.Select(p =>
                Convert(p, openBrace, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
		private async Task<bool?> IsTriggerOnDotAsync(Document document, int characterPosition, CancellationToken cancellationToken)
		{
			var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
			if (text[characterPosition] != '.')
			{
				return null;
			}

			// don't want to trigger after a number.  All other cases after dot are ok.
			var tree = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
			var token = tree.FindToken(characterPosition);
			if (token.Kind() == SyntaxKind.DotToken)
			{
				token = token.GetPreviousToken();
			}

			return token.Kind() != SyntaxKind.NumericLiteralToken;
		}
        internal static async Task<DebugDataTipInfo> GetInfoAsync(Document document, int position, CancellationToken cancellationToken)
        {
            var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var token = root.FindToken(position);

            var expression = token.Parent as ExpressionSyntax;
            if (expression == null)
            {
                return token.IsKind(SyntaxKind.IdentifierToken)
                    ? new DebugDataTipInfo(token.Span, text: null)
                    : default(DebugDataTipInfo);
            }

            if (expression.IsAnyLiteralExpression())
            {
                // If the user hovers over a literal, give them a DataTip for the type of the
                // literal they're hovering over.
                // Partial semantics should always be sufficient because the (unconverted) type
                // of a literal can always easily be determined.
                var partialDocument = await document.WithFrozenPartialSemanticsAsync(cancellationToken).ConfigureAwait(false);
                var semanticModel = await partialDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                var type = semanticModel.GetTypeInfo(expression, cancellationToken).Type;
                return type == null
                    ? default(DebugDataTipInfo)
                    : new DebugDataTipInfo(expression.Span, type.ToNameDisplayString());
            }

            if (expression.IsRightSideOfDotOrArrow())
            {
                var curr = expression;
                while (true)
                {
                    var conditionalAccess = curr.GetParentConditionalAccessExpression();
                    if (conditionalAccess == null)
                    {
                        break;
                    }

                    curr = conditionalAccess;
                }

                if (curr == expression)
                {
                    // NB: Parent.Span, not Span as below.
                    return new DebugDataTipInfo(expression.Parent.Span, text: null);
                }

                // NOTE: There may not be an ExpressionSyntax corresponding to the range we want.
                // For example, for input a?.$$B?.C, we want span [|a?.B|]?.C.
                return new DebugDataTipInfo(TextSpan.FromBounds(curr.SpanStart, expression.Span.End), text: null);
            }

            // NOTE(cyrusn): This behavior is to mimic what we did in Dev10, i'm not sure if it's
            // necessary or not.
            if (expression.IsKind(SyntaxKind.InvocationExpression))
            {
                expression = ((InvocationExpressionSyntax)expression).Expression;
            }

            string textOpt = null;
            var typeSyntax = expression as TypeSyntax;
            if (typeSyntax != null && typeSyntax.IsVar)
            {
                // If the user is hovering over 'var', then pass back the full type name that 'var'
                // binds to.
                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                var type = semanticModel.GetTypeInfo(typeSyntax, cancellationToken).Type;
                if (type != null)
                {
                    textOpt = type.ToNameDisplayString();
                }
            }

            return new DebugDataTipInfo(expression.Span, textOpt);
        }
        internal override Document AddImports(Document document, XElement snippetNode, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
        {
            var importsNode = snippetNode.Element(XName.Get("Imports", snippetNode.Name.NamespaceName));
            if (importsNode == null ||
                !importsNode.HasElements)
            {
                return document;
            }

            var newUsingDirectives = GetUsingDirectivesToAdd(document, snippetNode, importsNode, cancellationToken);
            if (!newUsingDirectives.Any())
            {
                return document;
            }

            // In Venus/Razor, inserting imports statements into the subject buffer does not work.
            // Instead, we add the imports through the contained language host.
            if (TryAddImportsToContainedDocument(document, newUsingDirectives.Where(u => u.Alias == null).Select(u => u.Name.ToString())))
            {
                return document;
            }

            var root = document.GetCSharpSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken);

            var newRoot = root.AddUsingDirectives(newUsingDirectives, placeSystemNamespaceFirst);
            var newDocument = document.WithSyntaxRoot(newRoot);

            var formattedDocument = Formatter.FormatAsync(newDocument, Formatter.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
            document.Project.Solution.Workspace.ApplyDocumentChanges(formattedDocument, cancellationToken);

            return formattedDocument;
        }
        private static IList<UsingDirectiveSyntax> GetUsingDirectivesToAdd(Document document, XElement snippetNode, XElement importsNode, CancellationToken cancellationToken)
        {
            var namespaceXmlName = XName.Get("Namespace", snippetNode.Name.NamespaceName);
            var existingUsings = document.GetCSharpSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken).Usings;
            var newUsings = new List<UsingDirectiveSyntax>();

            foreach (var import in importsNode.Elements(XName.Get("Import", snippetNode.Name.NamespaceName)))
            {
                var namespaceElement = import.Element(namespaceXmlName);
                if (namespaceElement == null)
                {
                    continue;
                }

                var namespaceToImport = namespaceElement.Value.Trim();
                if (string.IsNullOrEmpty(namespaceToImport))
                {
                    continue;
                }

                var candidateUsing = SyntaxFactory.ParseCompilationUnit("using " + namespaceToImport + ";").DescendantNodes().OfType<UsingDirectiveSyntax>().FirstOrDefault();
                if (candidateUsing == null)
                {
                    continue;
                }

                if (!existingUsings.Any(u => UsingsMatch(u, candidateUsing)))
                {
                    newUsings.Add(candidateUsing.WithAdditionalAnnotations(Formatter.Annotation).WithAppendedTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed));
                }
            }

            return newUsings;
        }