protected override int GetAdjustedContextPoint(int contextPoint, Document document)
        {
            // Determine the position in the buffer at which to end the tracking span representing
            // the part of the imaginary buffer before the text in the view. 
            var tree = document.GetSyntaxTreeSynchronously(CancellationToken.None);
            var token = tree.FindTokenOnLeftOfPosition(contextPoint, CancellationToken.None);

            // Special case to handle class designer because it asks for debugger IntelliSense using
            // spans between members.
            if (contextPoint > token.Span.End &&
                token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) &&
                token.Parent.IsKind(SyntaxKind.Block) &&
                token.Parent.Parent is MemberDeclarationSyntax)
            {
                return contextPoint;
            }

            if (token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) &&
                token.Parent.IsKind(SyntaxKind.Block))
            {
                return token.SpanStart;
            }

            return token.FullSpan.End;
        }
        public static string CreateUniqueEventName(
            Document document, string className, string objectName, string nameOfEvent, CancellationToken cancellationToken)
        {
            var type = document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetTypeByMetadataName(className);
            var name = objectName + "_" + nameOfEvent;

            var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken);

            var tree = document.GetSyntaxTreeSynchronously(cancellationToken);
            var typeNode = type.DeclaringSyntaxReferences.Where(r => r.SyntaxTree == tree).Select(r => r.GetSyntax(cancellationToken)).First();
            var codeModel = document.Project.LanguageServices.GetService<ICodeModelNavigationPointService>();
            var point = codeModel.GetStartPoint(typeNode, EnvDTE.vsCMPart.vsCMPartBody);
            var reservedNames = semanticModel.LookupSymbols(point.Value.Position, type).Select(m => m.Name);

            return NameGenerator.EnsureUniqueness(name, reservedNames, document.Project.LanguageServices.GetService<ISyntaxFactsService>().IsCaseSensitive);
        }
        protected override int GetContainingClassName(Document document, SnapshotSpan fieldSpan, CancellationToken cancellationToken, ref string value, ref int hasDefaultValue)
        {
            // Find the nearest enclosing type declaration and use its name
            var syntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken);
            var type = syntaxTree.FindTokenOnLeftOfPosition(fieldSpan.Start.Position, cancellationToken).GetAncestor<TypeDeclarationSyntax>();

            if (type != null)
            {
                value = type.Identifier.ToString();

                if (!string.IsNullOrWhiteSpace(value))
                {
                    hasDefaultValue = 1;
                }
            }

            return VSConstants.S_OK;
        }
        private static ISymbol GetEventSymbol(
            Document document, string objectTypeName, string nameOfEvent, INamedTypeSymbol type, CancellationToken cancellationToken)
        {
            var compilation = document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken);
            var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken);

            var objectType = compilation.GetTypeByMetadataName(objectTypeName);
            if (objectType == null)
            {
                throw new InvalidOperationException();
            }

            var containingTree = document.GetSyntaxTreeSynchronously(cancellationToken);
            var typeLocation = type.Locations.FirstOrDefault(d => d.SourceTree == containingTree);
            if (typeLocation == null)
            {
                throw new InvalidOperationException();
            }

            return semanticModel.LookupSymbols(typeLocation.SourceSpan.Start, objectType, nameOfEvent).SingleOrDefault(m => m.Kind == SymbolKind.Event);
        }
        /// <summary>
        /// Ensure that an event handler exists for a given event.
        /// </summary>
        /// <param name="thisDocument">The document corresponding to this operation.</param>
        /// <param name="targetDocument">The document to generate the event handler in if it doesn't
        /// exist.</param>
        /// <param name="className">The name of the type to generate the event handler in.</param>
        /// <param name="objectName">The name of the event member (if <paramref
        /// name="useHandlesClause"/> is true)</param>
        /// <param name="objectTypeName">The name of the type containing the event.</param>
        /// <param name="nameOfEvent">The name of the event member in <paramref
        /// name="objectTypeName"/></param>
        /// <param name="eventHandlerName">The name of the method to be hooked up to the
        /// event.</param>
        /// <param name="itemidInsertionPoint">The VS itemid of the file to generate the event
        /// handler in.</param>
        /// <param name="useHandlesClause">If true, a vb "Handles" clause will be generated for the
        /// handler.</param>
        /// <param name="additionalFormattingRule">An additional formatting rule that can be used to
        /// format the newly inserted method</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>Either the unique id of the method if it already exists, or the unique id of
        /// the to be generated method, the text of the to be generated method, and the position in
        /// <paramref name="itemidInsertionPoint"/> where the text should be inserted.</returns>
        public static Tuple<string, string, VsTextSpan> EnsureEventHandler(
            Document thisDocument,
            Document targetDocument,
            string className,
            string objectName,
            string objectTypeName,
            string nameOfEvent,
            string eventHandlerName,
            uint itemidInsertionPoint,
            bool useHandlesClause,
            IFormattingRule additionalFormattingRule,
            CancellationToken cancellationToken)
        {
            var thisCompilation = thisDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken);
            var type = thisCompilation.GetTypeByMetadataName(className);

            var existingEventHandlers = GetCompatibleEventHandlers(targetDocument, className, objectTypeName, nameOfEvent, cancellationToken);
            var existingHandler = existingEventHandlers.SingleOrDefault(e => e.Item1 == eventHandlerName);
            if (existingHandler != null)
            {
                return Tuple.Create(existingHandler.Item2, (string)null, default(VsTextSpan));
            }

            // Okay, it doesn't exist yet.  Let's create it.
            var codeGenerationService = targetDocument.GetLanguageService<ICodeGenerationService>();
            var syntaxFactory = targetDocument.GetLanguageService<SyntaxGenerator>();
            var eventMember = GetEventSymbol(thisDocument, objectTypeName, nameOfEvent, type, cancellationToken);
            if (eventMember == null)
            {
                throw new InvalidOperationException();
            }

            var eventType = ((IEventSymbol)eventMember).Type;
            if (eventType.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)eventType).DelegateInvokeMethod == null)
            {
                throw new InvalidOperationException(ServicesVSResources.Event_type_is_invalid);
            }

            var handlesExpressions = useHandlesClause ?
                new[]
                {
                    syntaxFactory.MemberAccessExpression(
                        objectName != null ? syntaxFactory.IdentifierName(objectName) : syntaxFactory.ThisExpression(),
                        syntaxFactory.IdentifierName(nameOfEvent))
                }
            : null;

            var invokeMethod = ((INamedTypeSymbol)eventType).DelegateInvokeMethod;
            var newMethod = CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes: null,
                accessibility: Accessibility.Protected,
                modifiers: new DeclarationModifiers(),
                returnType: targetDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetSpecialType(SpecialType.System_Void),
                explicitInterfaceSymbol: null,
                name: eventHandlerName,
                typeParameters: null,
                parameters: invokeMethod.Parameters.ToArray(),
                statements: null,
                handlesExpressions: handlesExpressions);

            var annotation = new SyntaxAnnotation();
            newMethod = annotation.AddAnnotationToSymbol(newMethod);
            var codeModel = targetDocument.Project.LanguageServices.GetService<ICodeModelNavigationPointService>();
            var syntaxFacts = targetDocument.Project.LanguageServices.GetService<ISyntaxFactsService>();

            var targetSyntaxTree = targetDocument.GetSyntaxTreeSynchronously(cancellationToken);

            var position = type.Locations.First(loc => loc.SourceTree == targetSyntaxTree).SourceSpan.Start;
            var destinationType = syntaxFacts.GetContainingTypeDeclaration(targetSyntaxTree.GetRoot(cancellationToken), position);
            var insertionPoint = codeModel.GetEndPoint(destinationType, EnvDTE.vsCMPart.vsCMPartBody);

            if (insertionPoint == null)
            {
                throw new InvalidOperationException(ServicesVSResources.Can_t_find_where_to_insert_member);
            }

            var newType = codeGenerationService.AddMethod(destinationType, newMethod, new CodeGenerationOptions(autoInsertionLocation: false), cancellationToken);
            var newRoot = targetSyntaxTree.GetRoot(cancellationToken).ReplaceNode(destinationType, newType);

            newRoot = Simplifier.ReduceAsync(
                targetDocument.WithSyntaxRoot(newRoot), Simplifier.Annotation, null, cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetSyntaxRootSynchronously(cancellationToken);

            var formattingRules = additionalFormattingRule.Concat(Formatter.GetDefaultFormattingRules(targetDocument));

            newRoot = Formatter.FormatAsync(
                newRoot,
                Formatter.Annotation,
                targetDocument.Project.Solution.Workspace,
                targetDocument.Options,
                formattingRules,
                cancellationToken).WaitAndGetResult_Venus(cancellationToken);

            var newMember = newRoot.GetAnnotatedNodesAndTokens(annotation).Single();
            var newMemberText = newMember.ToFullString();

            // In VB, the final newline is likely a statement terminator in the parent - just add
            // one on so that things don't get messed.
            if (!newMemberText.EndsWith(Environment.NewLine, StringComparison.Ordinal))
            {
                newMemberText += Environment.NewLine;
            }

            return Tuple.Create(ConstructMemberId(newMethod), newMemberText, insertionPoint.Value.ToVsTextSpan());
        }