public IndentationResult? GetDesiredIndentation(Document document, int lineNumber, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var sourceText = root.SyntaxTree.GetText(cancellationToken); var documentOptions = document.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken); var lineToBeIndented = sourceText.Lines[lineNumber]; var formattingRules = GetFormattingRules(document, lineToBeIndented.Start); // enter on a token case. if (ShouldUseSmartTokenFormatterInsteadOfIndenter(formattingRules, root, lineToBeIndented, documentOptions, cancellationToken)) { return null; } var indenter = GetIndenter( document.GetLanguageService<ISyntaxFactsService>(), root.SyntaxTree, lineToBeIndented, formattingRules, documentOptions, cancellationToken); return indenter.GetDesiredIndentation(); }
/// <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.GetOptionsAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken), 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()); }
internal static async Task<Document> FormatAsync(Document document, SyntaxAnnotation annotation, OptionSet options, IEnumerable<IFormattingRule> rules, CancellationToken cancellationToken) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (annotation == null) { throw new ArgumentNullException(nameof(annotation)); } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var documentOptions = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); return document.WithSyntaxRoot(await FormatAsync(root, annotation, document.Project.Solution.Workspace, documentOptions, rules, cancellationToken).ConfigureAwait(false)); }