private async Task <Tuple <CodeAction, string> > GetCodeActionAsync(
            Document document,
            TextSpan textSpan,
            CancellationToken cancellationToken)
        {
            var options = document.Project.Solution.Workspace.Options;

            try {
                var result = await service.ExtractMethodAsync(
                    document,
                    textSpan,
                    options,
                    cancellationToken).ConfigureAwait(false);

                if (result.Succeeded || result.SucceededWithSuggestion)
                {
                    var description = options.GetOption(ExtractMethodOptions.AllowMovingDeclaration, document.Project.Language) ?
                                      GettextCatalog.GetString("Extract Method + Local") : GettextCatalog.GetString("Extract Method");

                    var codeAction  = new DocumentChangeAction(textSpan, DiagnosticSeverity.Info, description, (c) => AddRenameAnnotationAsync(result.Document, result.InvocationNameToken, c));
                    var methodBlock = result.MethodDeclarationNode;

                    return(Tuple.Create <CodeAction, string>(codeAction, methodBlock.ToString()));
                }
            } catch (Exception) {
                // currently the extract method refactoring crashes often. Ignore the roslyn issues for now.
            }
            return(null);
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

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

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

            var    optionSet = document.Project.Solution.Workspace.Options;
            string diagnosticId;
            var    node = GetNodeToSimplify(root, model, span, optionSet, out diagnosticId, cancellationToken);

            if (node == null)
            {
                return;
            }

            var id         = GetCodeActionId(diagnosticId, node.ToString());
            var title      = id;
            var codeAction = new DocumentChangeAction(node.Span, DiagnosticSeverity.Warning, title,
                                                      (c) => SimplifyTypeNameAsync(document, node, c));

            context.RegisterCodeFix(codeAction, context.Diagnostics);
        }
		private async Task<Tuple<CodeAction, string>> GetCodeActionAsync(
			Document document,
			TextSpan textSpan,
			CancellationToken cancellationToken)
		{
			var options = document.Project.Solution.Workspace.Options;
			try {
				var result = await service.ExtractMethodAsync(
					document,
					textSpan,
					options,
					cancellationToken).ConfigureAwait(false);

				if (result.Succeeded || result.SucceededWithSuggestion)
				{
					var description = options.GetOption(ExtractMethodOptions.AllowMovingDeclaration, document.Project.Language) ?
						GettextCatalog.GetString ("Extract Method + Local") : GettextCatalog.GetString ("Extract Method");

					var codeAction = new DocumentChangeAction(textSpan, DiagnosticSeverity.Info, description, (c) => AddRenameAnnotationAsync(result.Document, result.InvocationNameToken, c));
					var methodBlock = result.MethodDeclarationNode;

					return Tuple.Create<CodeAction, string>(codeAction, methodBlock.ToString());
				}
			} catch (Exception) {
				// currently the extract method refactoring crashes often. Ignore the roslyn issues for now.
			}
			return null;
		}
		public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
		{
			var document = context.Document;
			var span = context.Span;
			var cancellationToken = context.CancellationToken;

			var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
			var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
			var optionSet = document.Project.Solution.Workspace.Options;
			string diagnosticId;
			var node = GetNodeToSimplify(root, model, span, optionSet, out diagnosticId, cancellationToken);
			if (node == null)
			{
				return;
			}

			var id = GetCodeActionId(diagnosticId, node.ToString());
			var title = id;
			var codeAction = new DocumentChangeAction(node.Span, DiagnosticSeverity.Warning, title,
				(c) => SimplifyTypeNameAsync(document, node, c));

			context.RegisterCodeFix(codeAction, context.Diagnostics);
		}
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var diagnostics       = context.Diagnostics;
            var cancellationToken = context.CancellationToken;

            var project    = document.Project;
            var diagnostic = diagnostics.First();
            var model      = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(context.CancellationToken))
            {
                return;
            }
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var ancestors = root.FindToken(span.Start, findInsideTrivia: true).GetAncestors <SyntaxNode>();

            if (!ancestors.Any())
            {
                return;
            }

            var node = ancestors.FirstOrDefault(n => n.Span.Contains(span) && n != root);

            if (node == null)
            {
                return;
            }

            var placeSystemNamespaceFirst = true;             //document.Project.Solution.Workspace.Options.GetOption(Microsoft.CodeAnalysis.Shared.Options.OrganizerOptions.PlaceSystemNamespaceFirst, document.Project.Language);

            if (!cancellationToken.IsCancellationRequested)
            {
                if (this.CanAddImport(node, cancellationToken))
                {
                    var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    //var containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
                    //var containingTypeOrAssembly = containingType ?? (ISymbol)semanticModel.Compilation.Assembly;
                    var namespacesInScope = this.GetNamespacesInScope(semanticModel, node, cancellationToken);

                    var matchingTypesNamespaces = await this.GetNamespacesForMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var matchingTypes = await this.GetMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var matchingNamespaces = await this.GetNamespacesForMatchingNamespacesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var matchingExtensionMethodsNamespaces = await this.GetNamespacesForMatchingExtensionMethodsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var matchingFieldsAndPropertiesAsync = await this.GetNamespacesForMatchingFieldsAndPropertiesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var queryPatternsNamespaces = await this.GetNamespacesForQueryPatternsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    if (matchingTypesNamespaces != null || matchingNamespaces != null || matchingExtensionMethodsNamespaces != null || matchingFieldsAndPropertiesAsync != null || queryPatternsNamespaces != null || matchingTypes != null)
                    {
                        matchingTypesNamespaces            = matchingTypesNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingNamespaces                 = matchingNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingExtensionMethodsNamespaces = matchingExtensionMethodsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingFieldsAndPropertiesAsync   = matchingFieldsAndPropertiesAsync ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        queryPatternsNamespaces            = queryPatternsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingTypes = matchingTypes ?? SpecializedCollections.EmptyList <ITypeSymbol>();

                        var proposedImports =
                            matchingTypesNamespaces.Cast <INamespaceOrTypeSymbol> ()
                            .Concat(matchingNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingExtensionMethodsNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingFieldsAndPropertiesAsync.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(queryPatternsNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingTypes.Cast <INamespaceOrTypeSymbol> ())
                            .Distinct()
                            .Where(NotNull)
                            .Where(NotGlobalNamespace)
                            .ToList();
                        proposedImports.Sort(INamespaceOrTypeSymbolExtensions.CompareNamespaceOrTypeSymbols);
                        proposedImports = proposedImports.Take(8).ToList();

                        if (proposedImports.Count > 0)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            foreach (var import in proposedImports)
                            {
                                var action = new DocumentChangeAction(
                                    node.Span,
                                    DiagnosticSeverity.Error,
                                    this.GetDescription(import, semanticModel, node),
                                    (c) => this.AddImportAsync(node, import, document, placeSystemNamespaceFirst, cancellationToken)
                                    );

                                context.RegisterCodeFix(action, diagnostic);
                            }
                        }
                    }
                }
            }
        }
		public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
		{
			var document = context.Document;
			var span = context.Span;
			var diagnostics = context.Diagnostics;
			var cancellationToken = context.CancellationToken;

			var project = document.Project;
			var diagnostic = diagnostics.First();
			var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait (false);
			if (model.IsFromGeneratedCode (context.CancellationToken))
				return;
			
			var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
			var node = root.FindToken(span.Start).GetAncestors<SyntaxNode>().First(n => n.Span.Contains(span));

			// Has to be a simple identifier or generic name.
			if (node != null && CanFullyQualify(diagnostic, ref node))
			{
				var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

				var matchingTypes = await this.GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);
				var matchingNamespaces = await this.GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

				if (matchingTypes != null || matchingNamespaces != null)
				{
					matchingTypes = matchingTypes ?? SpecializedCollections.EmptyEnumerable<ISymbol>();
					matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable<ISymbol>();

					var matchingTypeContainers = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation));
					var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation));

					var proposedContainers =
						matchingTypeContainers.Concat(matchingNamespaceContainers)
							.Distinct()
							.Take(8);

					foreach (var container in proposedContainers)
					{
						var containerName = RoslynCompletionData.SafeMinimalDisplayString (container, semanticModel, node.SpanStart);

						string name;
						int arity;
						node.GetNameAndArityOfSimpleName(out name, out arity);

						// Actual member name might differ by case.
						string memberName;
						if (this.IgnoreCase)
						{
							var member = container.GetMembers(name).FirstOrDefault();
							memberName = member != null ? member.Name : name;
						}
						else
						{
							memberName = name;
						}

						var codeAction = new DocumentChangeAction(
							node.Span,
							DiagnosticSeverity.Info,
							string.Format(GettextCatalog.GetString ("Change '{0}' to '{1}.{2}'"), name, containerName, memberName),
							(c) =>
							{
								var newRoot = this.ReplaceNode(node, containerName, c);
								return Task.FromResult(document.WithSyntaxRoot(newRoot));
							});

						context.RegisterCodeFix(codeAction, diagnostic);
					}
				}
			}
		}
		public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
		{
			var document = context.Document;
			var span = context.Span;
			var diagnostics = context.Diagnostics;
			var cancellationToken = context.CancellationToken;

			var project = document.Project;
			var diagnostic = diagnostics.First();
			var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait (false);
			if (model.IsFromGeneratedCode (context.CancellationToken))
				return;
			var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
			if (root.FullSpan.Length < span.Start)
				return;
			var ancestors = root.FindToken(span.Start, findInsideTrivia: true).GetAncestors<SyntaxNode>();
			if (!ancestors.Any())
			{
				return;
			}

			var node = ancestors.FirstOrDefault(n => n.Span.Contains(span) && n != root);
			if (node == null)
			{
				return;
			}

			var placeSystemNamespaceFirst = true; //document.Project.Solution.Workspace.Options.GetOption(Microsoft.CodeAnalysis.Shared.Options.OrganizerOptions.PlaceSystemNamespaceFirst, document.Project.Language);

			if (!cancellationToken.IsCancellationRequested)
			{
				if (this.CanAddImport(node, cancellationToken))
				{
					var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
					//var containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
					//var containingTypeOrAssembly = containingType ?? (ISymbol)semanticModel.Compilation.Assembly;
					var namespacesInScope = this.GetNamespacesInScope(semanticModel, node, cancellationToken);

					var matchingTypesNamespaces = await this.GetNamespacesForMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope,  cancellationToken).ConfigureAwait(false);
					var matchingTypes = await this.GetMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope,  cancellationToken).ConfigureAwait(false);
					var matchingNamespaces = await this.GetNamespacesForMatchingNamespacesAsync(project, diagnostic, node, semanticModel, namespacesInScope,  cancellationToken).ConfigureAwait(false);
					var matchingExtensionMethodsNamespaces = await this.GetNamespacesForMatchingExtensionMethodsAsync(project, diagnostic, node, semanticModel, namespacesInScope,  cancellationToken).ConfigureAwait(false);
					var matchingFieldsAndPropertiesAsync = await this.GetNamespacesForMatchingFieldsAndPropertiesAsync(project, diagnostic, node, semanticModel, namespacesInScope,  cancellationToken).ConfigureAwait(false);
					var queryPatternsNamespaces = await this.GetNamespacesForQueryPatternsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

					if (matchingTypesNamespaces != null || matchingNamespaces != null || matchingExtensionMethodsNamespaces != null || matchingFieldsAndPropertiesAsync != null || queryPatternsNamespaces != null || matchingTypes != null)
					{
						matchingTypesNamespaces = matchingTypesNamespaces ?? SpecializedCollections.EmptyList<INamespaceSymbol>();
						matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyList<INamespaceSymbol>();
						matchingExtensionMethodsNamespaces = matchingExtensionMethodsNamespaces ?? SpecializedCollections.EmptyList<INamespaceSymbol>();
						matchingFieldsAndPropertiesAsync = matchingFieldsAndPropertiesAsync ?? SpecializedCollections.EmptyList<INamespaceSymbol>();
						queryPatternsNamespaces = queryPatternsNamespaces ?? SpecializedCollections.EmptyList<INamespaceSymbol>();
						matchingTypes = matchingTypes ?? SpecializedCollections.EmptyList<ITypeSymbol>();

						var proposedImports =
							matchingTypesNamespaces.Cast<INamespaceOrTypeSymbol> ()
								.Concat (matchingNamespaces.Cast<INamespaceOrTypeSymbol> ())
								.Concat (matchingExtensionMethodsNamespaces.Cast<INamespaceOrTypeSymbol> ())
								.Concat (matchingFieldsAndPropertiesAsync.Cast<INamespaceOrTypeSymbol> ())
								.Concat (queryPatternsNamespaces.Cast<INamespaceOrTypeSymbol> ())
								.Concat (matchingTypes.Cast<INamespaceOrTypeSymbol> ())
								.Distinct ()
								.Where (NotNull)
								.Where (NotGlobalNamespace)
								.ToList ();
						proposedImports.Sort (INamespaceOrTypeSymbolExtensions.CompareNamespaceOrTypeSymbols);
						proposedImports = proposedImports.Take (8).ToList ();
							
						if (proposedImports.Count > 0)
						{
							cancellationToken.ThrowIfCancellationRequested();

							foreach (var import in proposedImports)
							{
								var action = new DocumentChangeAction(
									node.Span, 
									DiagnosticSeverity.Error, 
									this.GetDescription(import, semanticModel, node), 
									(c) => this.AddImportAsync(node, import, document, placeSystemNamespaceFirst, cancellationToken)
								);

								context.RegisterCodeFix(action, diagnostic);
							}
						}
					}
				}
			}
		}
Example #8
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var diagnostics       = context.Diagnostics;
            var cancellationToken = context.CancellationToken;

            var project    = document.Project;
            var diagnostic = diagnostics.First();
            var model      = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(context.CancellationToken))
            {
                return;
            }

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

            var node = root.FindToken(span.Start).GetAncestors <SyntaxNode>().First(n => n.Span.Contains(span));

            // Has to be a simple identifier or generic name.
            if (node != null && CanFullyQualify(diagnostic, ref node))
            {
                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var matchingTypes = await this.GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

                var matchingNamespaces = await this.GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

                if (matchingTypes != null || matchingNamespaces != null)
                {
                    matchingTypes      = matchingTypes ?? SpecializedCollections.EmptyEnumerable <ISymbol>();
                    matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable <ISymbol>();

                    var matchingTypeContainers      = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation));
                    var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation));

                    var proposedContainers =
                        matchingTypeContainers.Concat(matchingNamespaceContainers)
                        .Distinct()
                        .Take(8);

                    foreach (var container in proposedContainers)
                    {
                        var containerName = RoslynCompletionData.SafeMinimalDisplayString(container, semanticModel, node.SpanStart);

                        string name;
                        int    arity;
                        node.GetNameAndArityOfSimpleName(out name, out arity);

                        // Actual member name might differ by case.
                        string memberName;
                        if (this.IgnoreCase)
                        {
                            var member = container.GetMembers(name).FirstOrDefault();
                            memberName = member != null ? member.Name : name;
                        }
                        else
                        {
                            memberName = name;
                        }

                        var codeAction = new DocumentChangeAction(
                            node.Span,
                            DiagnosticSeverity.Info,
                            string.Format(GettextCatalog.GetString("Change '{0}' to '{1}.{2}'"), name, containerName, memberName),
                            (c) =>
                        {
                            var newRoot = this.ReplaceNode(node, containerName, c);
                            return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
                        });

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                }
            }
        }