提交 4e12c1c2 编写于 作者: C CyrusNajmabadi

Merge remote-tracking branch 'upstream/master' into renameInaccessibleSymbols

......@@ -450,8 +450,8 @@ Global
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|ARM.Build.0 = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x64.ActiveCfg = Debug|x64
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x64.Build.0 = Debug|x64
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x64.ActiveCfg = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x64.Build.0 = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x86.ActiveCfg = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Debug|x86.Build.0 = Debug|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
......@@ -460,8 +460,8 @@ Global
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|ARM.Build.0 = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x64.ActiveCfg = Release|x64
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x64.Build.0 = Release|x64
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x64.ActiveCfg = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x64.Build.0 = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x86.ActiveCfg = Release|Any CPU
{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}.Release|x86.Build.0 = Release|Any CPU
{9508F118-F62E-4C16-A6F4-7C3B56E166AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
......@@ -486,22 +486,22 @@ Global
{9508F118-F62E-4C16-A6F4-7C3B56E166AD}.Release|x86.Build.0 = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|ARM.ActiveCfg = Debug|ARM
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|ARM.Build.0 = Debug|ARM
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|ARM.Build.0 = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x64.ActiveCfg = Debug|x64
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x64.Build.0 = Debug|x64
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x64.ActiveCfg = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x64.Build.0 = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x86.ActiveCfg = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Debug|x86.Build.0 = Debug|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|Any CPU.Build.0 = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|ARM.ActiveCfg = Release|ARM
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|ARM.Build.0 = Release|ARM
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|ARM.ActiveCfg = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|ARM.Build.0 = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x64.ActiveCfg = Release|x64
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x64.Build.0 = Release|x64
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x64.ActiveCfg = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x64.Build.0 = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x86.ActiveCfg = Release|Any CPU
{F5CE416E-B906-41D2-80B9-0078E887A3F6}.Release|x86.Build.0 = Release|Any CPU
{4B45CA0C-03A0-400F-B454-3D4BCB16AF38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
......@@ -530,8 +530,8 @@ Global
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|ARM.Build.0 = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x64.ActiveCfg = Debug|x64
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x64.Build.0 = Debug|x64
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x64.ActiveCfg = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x64.Build.0 = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x86.ActiveCfg = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Debug|x86.Build.0 = Debug|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|Any CPU.ActiveCfg = Release|Any CPU
......@@ -540,8 +540,8 @@ Global
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|ARM.Build.0 = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x64.ActiveCfg = Release|x64
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x64.Build.0 = Release|x64
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x64.ActiveCfg = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x64.Build.0 = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x86.ActiveCfg = Release|Any CPU
{B501A547-C911-4A05-AC6E-274A50DFF30E}.Release|x86.Build.0 = Release|Any CPU
{50D26304-0961-4A51-ABF6-6CAD1A56D203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
......@@ -646,22 +646,22 @@ Global
{50D26304-0961-4A51-ABF6-6CAD1A56D202}.Release|x86.Build.0 = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|ARM.ActiveCfg = Debug|ARM
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|ARM.Build.0 = Debug|ARM
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|ARM.Build.0 = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x64.ActiveCfg = Debug|x64
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x64.Build.0 = Debug|x64
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x64.ActiveCfg = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x64.Build.0 = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x86.ActiveCfg = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Debug|x86.Build.0 = Debug|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|Any CPU.Build.0 = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|ARM.ActiveCfg = Release|ARM
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|ARM.Build.0 = Release|ARM
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|ARM.ActiveCfg = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|ARM.Build.0 = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x64.ActiveCfg = Release|x64
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x64.Build.0 = Release|x64
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x64.ActiveCfg = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x64.Build.0 = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x86.ActiveCfg = Release|Any CPU
{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}.Release|x86.Build.0 = Release|Any CPU
{F7712928-1175-47B3-8819-EE086753DEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
......@@ -2178,21 +2178,21 @@ Global
{FCFA8808-A1B6-48CC-A1EA-0B8CA8AEDA8E}.Release|x86.Build.0 = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|ARM.ActiveCfg = Debug|ARM
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|ARM.Build.0 = Debug|ARM
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|ARM.Build.0 = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|x64.ActiveCfg = Debug|x64
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|x64.Build.0 = Debug|x64
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|x64.ActiveCfg = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|x64.Build.0 = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Debug|x86.ActiveCfg = Debug|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|Any CPU.Build.0 = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|ARM.ActiveCfg = Release|ARM
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|ARM.Build.0 = Release|ARM
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|ARM.ActiveCfg = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|ARM.Build.0 = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|x64.ActiveCfg = Release|x64
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|x64.Build.0 = Release|x64
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|x64.ActiveCfg = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|x64.Build.0 = Release|Any CPU
{1DFEA9C5-973C-4179-9B1B-0F32288E1EF2}.Release|x86.ActiveCfg = Release|Any CPU
{76242A2D-2600-49DD-8C15-FEA07ECB1842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76242A2D-2600-49DD-8C15-FEA07ECB1842}.Debug|Any CPU.Build.0 = Debug|Any CPU
......
......@@ -59,4 +59,4 @@ public override Stream CreateStream(DiagnosticBag diagnostics)
}
}
}
}
}
\ No newline at end of file
......@@ -4373,6 +4373,43 @@ class C
compareTokens: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)]
public async Task TestPlaceUsingWithUsings_NotWithAliases()
{
await TestAsync(
@"
using System;
namespace N
{
using C = System.Collections;
class Class
{
[|List<int>|] Method()
{
Foo();
}
}
}",
@"
using System;
using System.Collections.Generic;
namespace N
{
using C = System.Collections;
class Class
{
List<int> Method()
{
Foo();
}
}
}");
}
public partial class AddUsingTestsWithAddImportDiagnosticProvider : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
......
......@@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.AddImport;
......@@ -395,6 +396,7 @@ protected override string GetDescription(IReadOnlyList<string> nameParts)
}
protected override string TryGetDescription(
Document document,
INamespaceOrTypeSymbol namespaceOrTypeSymbol,
SemanticModel semanticModel,
SyntaxNode contextNode,
......@@ -415,7 +417,7 @@ protected override string GetDescription(IReadOnlyList<string> nameParts)
}
var usingDirective = TryGetUsingDirective(
namespaceOrTypeSymbol, semanticModel, root, contextNode);
document, namespaceOrTypeSymbol, semanticModel, root, contextNode);
if (usingDirective != null)
{
......@@ -465,63 +467,33 @@ protected override string GetDescription(IReadOnlyList<string> nameParts)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var firstContainingNamespaceWithUsings = GetFirstContainingNamespaceWithUsings(contextNode);
var namespaceToUpdate = firstContainingNamespaceWithUsings;
var externAliasDirective = TryGetExternAliasDirective(
namespaceOrTypeSymbol, semanticModel, contextNode,
checkForExistingExternAlias: true);
var usingDirective = TryGetUsingDirective(
namespaceOrTypeSymbol, semanticModel, root, contextNode);
document, namespaceOrTypeSymbol, semanticModel, root, contextNode);
if (externAliasDirective != null)
var newImports = ArrayBuilder<SyntaxNode>.GetInstance();
try
{
AddExterns(ref root, ref namespaceToUpdate, externAliasDirective);
}
if (usingDirective != null)
{
AddUsingDirective(ref root, ref namespaceToUpdate,
placeSystemNamespaceFirst, usingDirective);
}
return firstContainingNamespaceWithUsings != null
? root.ReplaceNode(firstContainingNamespaceWithUsings, namespaceToUpdate)
: root;
}
if (externAliasDirective != null)
{
newImports.Add(externAliasDirective);
}
private void AddUsingDirective(
ref CompilationUnitSyntax root,
ref NamespaceDeclarationSyntax namespaceToUpdate,
bool placeSystemNamespaceFirst,
UsingDirectiveSyntax usingDirective)
{
IList<UsingDirectiveSyntax> directives = new[] { usingDirective };
if (namespaceToUpdate != null)
{
namespaceToUpdate = namespaceToUpdate.AddUsingDirectives(
directives, placeSystemNamespaceFirst);
}
else
{
root = root.AddUsingDirectives(
directives, placeSystemNamespaceFirst);
}
}
if (usingDirective != null)
{
newImports.Add(usingDirective);
}
private void AddExterns(
ref CompilationUnitSyntax root,
ref NamespaceDeclarationSyntax namespaceToUpdate,
ExternAliasDirectiveSyntax externAliasDirective)
{
if (namespaceToUpdate != null)
{
namespaceToUpdate = namespaceToUpdate.AddExterns(externAliasDirective);
var addImportService = document.GetLanguageService<IAddImportService>();
var newRoot = addImportService.AddImports(root, contextNode, newImports, placeSystemNamespaceFirst);
return (CompilationUnitSyntax)newRoot;
}
else
finally
{
root = root.AddExterns(externAliasDirective);
newImports.Free();
}
}
......@@ -581,15 +553,19 @@ private NameSyntax CreateNameSyntax(IReadOnlyList<string> namespaceParts, int in
}
private UsingDirectiveSyntax TryGetUsingDirective(
Document document,
INamespaceOrTypeSymbol namespaceOrTypeSymbol,
SemanticModel semanticModel,
CompilationUnitSyntax root,
SyntaxNode contextNode)
{
var namespaceToAddTo = GetFirstContainingNamespaceWithUsings(contextNode);
var usingDirectives = namespaceToAddTo?.Usings ?? root.Usings;
var addImportService = document.GetLanguageService<IAddImportService>();
var nameSyntax = namespaceOrTypeSymbol.GenerateNameSyntax();
var dummyUsing = SyntaxFactory.UsingDirective(nameSyntax);
var container = addImportService.GetImportContainer(root, contextNode, dummyUsing);
var namespaceToAddTo = container as NamespaceDeclarationSyntax;
// Replace the alias that GenerateTypeSyntax added if we want this to be looked
// up off of an extern alias.
......@@ -694,19 +670,6 @@ private NameSyntax CreateNameSyntax(IReadOnlyList<string> namespaceParts, int in
return aliasName.WithAlias(alias);
}
private NamespaceDeclarationSyntax GetFirstContainingNamespaceWithUsings(SyntaxNode contextNode)
{
var usingDirective = contextNode.GetAncestor<UsingDirectiveSyntax>();
if (usingDirective != null)
{
contextNode = usingDirective.Parent;
}
return contextNode.GetAncestors<NamespaceDeclarationSyntax>()
.Where(n => n.Usings.Count > 0)
.FirstOrDefault();
}
private static bool TryGetExternAliasString(
INamespaceOrTypeSymbol namespaceSymbol,
SemanticModel semanticModel,
......
......@@ -52,7 +52,7 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
internal abstract bool IsAddMethodContext(SyntaxNode node, SemanticModel semanticModel);
protected abstract string GetDescription(IReadOnlyList<string> nameParts);
protected abstract string TryGetDescription(INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, bool checkForExistingImport, CancellationToken cancellationToken);
protected abstract string TryGetDescription(Document document, INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, bool checkForExistingImport, CancellationToken cancellationToken);
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
......
......@@ -23,12 +23,12 @@ private partial class MetadataSymbolReference : SymbolReference
}
protected override string TryGetDescription(
Project project, SyntaxNode node,
Document document, SyntaxNode node,
SemanticModel semanticModel, CancellationToken cancellationToken)
{
// If 'TryGetDescription' returns 'null' then that means that we don't actually want to add a reference
// in this case. As such, just continue to return the 'null' outwards.
var description = base.TryGetDescription(project, node, semanticModel, cancellationToken);
var description = base.TryGetDescription(document, node, semanticModel, cancellationToken);
if (description == null)
{
return null;
......
......@@ -73,15 +73,16 @@ protected override Solution GetUpdatedSolution(Document newDocument)
}
protected override string TryGetDescription(
Project project, SyntaxNode node,
Document document, SyntaxNode node,
SemanticModel semanticModel, CancellationToken cancellationToken)
{
var description = base.TryGetDescription(project, node, semanticModel, cancellationToken);
var description = base.TryGetDescription(document, node, semanticModel, cancellationToken);
if (description == null)
{
return null;
}
var project = document.Project;
return project.Id == _project.Id
? description
: string.Format(FeaturesResources.Add_reference_to_0, _project.Name);
......
......@@ -73,7 +73,7 @@ protected virtual Solution GetUpdatedSolution(Document newDocument)
bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
string description = TryGetDescription(document.Project, node, semanticModel, cancellationToken);
string description = TryGetDescription(document, node, semanticModel, cancellationToken);
if (description == null)
{
return null;
......@@ -104,12 +104,12 @@ protected virtual Solution GetUpdatedSolution(Document newDocument)
}
protected virtual string TryGetDescription(
Project project, SyntaxNode node,
Document document, SyntaxNode node,
SemanticModel semanticModel, CancellationToken cancellationToken)
{
return provider.TryGetDescription(
SymbolResult.Symbol, semanticModel, node,
this.CheckForExistingImport(project), cancellationToken);
document, SymbolResult.Symbol, semanticModel, node,
this.CheckForExistingImport(document.Project), cancellationToken);
}
}
}
......
......@@ -248,6 +248,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport
End Function
Protected Overrides Function TryGetDescription(
document As Document,
namespaceSymbol As INamespaceOrTypeSymbol,
semanticModel As SemanticModel,
root As SyntaxNode,
......@@ -313,7 +314,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport
Return symbol IsNot Nothing AndAlso symbol.Locations.Length > 0
End Function
Protected Overloads Overrides Async Function AddImportAsync(
Protected Overloads Overrides Function AddImportAsync(
contextNode As SyntaxNode,
symbol As INamespaceOrTypeSymbol,
document As Document,
......@@ -322,9 +323,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport
Dim nameSyntax = DirectCast(symbol.GenerateTypeSyntax(addGlobal:=False), NameSyntax)
Return Await AddImportsAsync(
Return AddImportsAsync(
contextNode, document, placeSystemNamespaceFirst, nameSyntax,
additionalAnnotation:=Nothing, cancellationToken:=cancellationToken).ConfigureAwait(False)
additionalAnnotation:=Nothing, cancellationToken:=cancellationToken)
End Function
Private Shared Async Function AddImportsAsync(
......
......@@ -6,6 +6,7 @@
using System.Threading;
using System.Xml.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
......@@ -93,7 +94,10 @@ public override int GetExpansionFunction(IXMLDOMNode xmlFunctionNode, string bst
return document;
}
var newUsingDirectives = GetUsingDirectivesToAdd(document, snippetNode, importsNode, cancellationToken);
var root = document.GetSyntaxRootSynchronously(cancellationToken);
var contextLocation = root.FindToken(position).Parent;
var newUsingDirectives = GetUsingDirectivesToAdd(contextLocation, snippetNode, importsNode, cancellationToken);
if (!newUsingDirectives.Any())
{
return document;
......@@ -106,15 +110,9 @@ public override int GetExpansionFunction(IXMLDOMNode xmlFunctionNode, string bst
return document;
}
var root = document.GetSyntaxRootSynchronously(cancellationToken);
var node = root.FindToken(position).Parent;
var container = node.GetInnermostNamespaceDeclarationWithUsings() ?? (SyntaxNode)node.GetAncestorOrThis<CompilationUnitSyntax>();
var newContainer = container is NamespaceDeclarationSyntax n
? (SyntaxNode)n.AddUsingDirectives(newUsingDirectives, placeSystemNamespaceFirst, Formatter.Annotation)
: ((CompilationUnitSyntax)container).AddUsingDirectives(newUsingDirectives, placeSystemNamespaceFirst);
var addImportService = document.GetLanguageService<IAddImportService>();
var newRoot = addImportService.AddImports(root, contextLocation, newUsingDirectives, placeSystemNamespaceFirst);
var newRoot = root.ReplaceNode(container, newContainer);
var newDocument = document.WithSyntaxRoot(newRoot);
var formattedDocument = Formatter.FormatAsync(newDocument, Formatter.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
......@@ -123,11 +121,11 @@ public override int GetExpansionFunction(IXMLDOMNode xmlFunctionNode, string bst
return formattedDocument;
}
private static IList<UsingDirectiveSyntax> GetUsingDirectivesToAdd(Document document, XElement snippetNode, XElement importsNode, CancellationToken cancellationToken)
private static IList<UsingDirectiveSyntax> GetUsingDirectivesToAdd(
SyntaxNode contextLocation, XElement snippetNode, XElement importsNode, CancellationToken cancellationToken)
{
var namespaceXmlName = XName.Get("Namespace", snippetNode.Name.NamespaceName);
var root = document.GetSyntaxRootSynchronously(cancellationToken);
var existingUsings = ((CompilationUnitSyntax)root).Usings;
var existingUsings = contextLocation.GetEnclosingUsingDirectives();
var newUsings = new List<UsingDirectiveSyntax>();
foreach (var import in importsNode.Elements(XName.Get("Import", snippetNode.Name.NamespaceName)))
......@@ -150,7 +148,7 @@ private static IList<UsingDirectiveSyntax> GetUsingDirectivesToAdd(Document docu
continue;
}
if (!existingUsings.Any(u => UsingsMatch(u, candidateUsing)))
if (!existingUsings.Any(u => u.IsEquivalentTo(candidateUsing, topLevel: false)))
{
newUsings.Add(candidateUsing.WithAdditionalAnnotations(Formatter.Annotation).WithAppendedTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed));
}
......@@ -159,11 +157,6 @@ private static IList<UsingDirectiveSyntax> GetUsingDirectivesToAdd(Document docu
return newUsings;
}
private static bool UsingsMatch(UsingDirectiveSyntax usingDirective1, UsingDirectiveSyntax usingDirective2)
{
return usingDirective1.Name.ToString() == usingDirective2.Name.ToString() && GetAliasName(usingDirective1) == GetAliasName(usingDirective2);
}
private static string GetAliasName(UsingDirectiveSyntax usingDirective)
{
return (usingDirective.Alias == null || usingDirective.Alias.Name == null) ? null : usingDirective.Alias.Name.ToString();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.AddImport
{
[ExportLanguageService(typeof(IAddImportService), LanguageNames.CSharp), Shared]
internal class CSharpAddImportService : IAddImportService
{
private static readonly Func<UsingDirectiveSyntax, bool> s_isUsing = u => u.Alias == null;
private static readonly Func<UsingDirectiveSyntax, bool> s_isAlias = u => u.Alias != null;
private static readonly Func<SyntaxNode, bool> s_hasAliases = n => GetUsings(n).Any(s_isAlias);
private static readonly Func<SyntaxNode, bool> s_hasUsings = n => GetUsings(n).Any(s_isUsing);
private static readonly Func<SyntaxNode, bool> s_hasExterns = n => GetExterns(n).Any();
private static readonly Func<SyntaxNode, bool> s_hasAnyImports = n => GetUsings(n).Any() || GetExterns(n).Any();
public SyntaxNode GetImportContainer(SyntaxNode root, SyntaxNode contextLocation, SyntaxNode import)
{
contextLocation = contextLocation ?? root;
GetContainers(root, contextLocation,
out var externContainer, out var usingContainer, out var aliasContainer);
switch (import)
{
case ExternAliasDirectiveSyntax e: return externContainer;
case UsingDirectiveSyntax u: return s_isAlias(u) ? aliasContainer : usingContainer;
}
throw new InvalidOperationException();
}
public SyntaxNode AddImports(
SyntaxNode root,
SyntaxNode contextLocation,
IEnumerable<SyntaxNode> newImports,
bool placeSystemNamespaceFirst)
{
contextLocation = contextLocation ?? root;
GetContainers(root, contextLocation,
out var externContainer, out var usingContainer, out var aliasContainer);
var externAliases = newImports.OfType<ExternAliasDirectiveSyntax>().ToArray();
var usingDirectives = newImports.OfType<UsingDirectiveSyntax>().Where(u => u.Alias == null).ToArray();
var aliasDirectives = newImports.OfType<UsingDirectiveSyntax>().Where(u => u.Alias != null).ToArray();
var rewriter = new Rewriter(
externAliases, usingDirectives, aliasDirectives,
externContainer, usingContainer, aliasContainer,
placeSystemNamespaceFirst);
var newRoot = rewriter.Visit(root);
return newRoot;
}
private static void GetContainers(SyntaxNode root, SyntaxNode contextLocation, out SyntaxNode externContainer, out SyntaxNode usingContainer, out SyntaxNode aliasContainer)
{
var applicableContainer = GetFirstApplicableContainer(contextLocation);
var contextSpine = applicableContainer.GetAncestorsOrThis<SyntaxNode>().ToImmutableArray();
// The node we'll add to if we can't find a specific namespace with imports of
// the type we're trying to add. This will be the closest namespace with any
// imports in it, or the root if there are no such namespaces.
var fallbackNode = contextSpine.FirstOrDefault(s_hasAnyImports) ?? root;
// The specific container to add each type of import to. We look for a container
// that already has an import of the same type as the node we want to add to.
// If we can find one, we add to that container. If not, we call back to the
// innermost node with any imports.
externContainer = contextSpine.FirstOrDefault(s_hasExterns) ?? fallbackNode;
usingContainer = contextSpine.FirstOrDefault(s_hasUsings) ?? fallbackNode;
aliasContainer = contextSpine.FirstOrDefault(s_hasAliases) ?? fallbackNode;
}
private static SyntaxList<UsingDirectiveSyntax> GetUsings(SyntaxNode node)
{
switch (node)
{
case CompilationUnitSyntax c: return c.Usings;
case NamespaceDeclarationSyntax n: return n.Usings;
default: return default(SyntaxList<UsingDirectiveSyntax>);
}
}
private static SyntaxList<ExternAliasDirectiveSyntax> GetExterns(SyntaxNode node)
{
switch (node)
{
case CompilationUnitSyntax c: return c.Externs;
case NamespaceDeclarationSyntax n: return n.Externs;
default: return default(SyntaxList<ExternAliasDirectiveSyntax>);
}
}
private static SyntaxNode GetFirstApplicableContainer(SyntaxNode contextNode)
{
var usingDirective = contextNode.GetAncestor<UsingDirectiveSyntax>();
if (usingDirective != null)
{
contextNode = usingDirective.Parent;
}
return contextNode.GetAncestor<NamespaceDeclarationSyntax>() ??
(SyntaxNode)contextNode.GetAncestor<CompilationUnitSyntax>();
}
private class Rewriter : CSharpSyntaxRewriter
{
private readonly bool _placeSystemNamespaceFirst;
private readonly SyntaxNode _externContainer;
private readonly SyntaxNode _usingContainer;
private readonly SyntaxNode _aliasContainer;
private readonly UsingDirectiveSyntax[] _aliasDirectives;
private readonly ExternAliasDirectiveSyntax[] _externAliases;
private readonly UsingDirectiveSyntax[] _usingDirectives;
public Rewriter(
ExternAliasDirectiveSyntax[] externAliases,
UsingDirectiveSyntax[] usingDirectives,
UsingDirectiveSyntax[] aliasDirectives,
SyntaxNode externContainer,
SyntaxNode usingContainer,
SyntaxNode aliasContainer,
bool placeSystemNamespaceFirst)
{
_externAliases = externAliases;
_usingDirectives = usingDirectives;
_aliasDirectives = aliasDirectives;
_externContainer = externContainer;
_usingContainer = usingContainer;
_aliasContainer = aliasContainer;
_placeSystemNamespaceFirst = placeSystemNamespaceFirst;
}
public override SyntaxNode VisitNamespaceDeclaration(NamespaceDeclarationSyntax node)
{
// recurse downwards so we visit inner namespaces first.
var rewritten = (NamespaceDeclarationSyntax)base.VisitNamespaceDeclaration(node);
if (node == _aliasContainer)
{
rewritten = rewritten.AddUsingDirectives(_aliasDirectives, _placeSystemNamespaceFirst);
}
if (node == _usingContainer)
{
rewritten = rewritten.AddUsingDirectives(_usingDirectives, _placeSystemNamespaceFirst);
}
if (node == _externContainer)
{
rewritten = rewritten.AddExterns(_externAliases);
}
return rewritten;
}
public override SyntaxNode VisitCompilationUnit(CompilationUnitSyntax node)
{
// recurse downwards so we visit inner namespaces first.
var rewritten = (CompilationUnitSyntax)base.VisitCompilationUnit(node);
if (node == _aliasContainer)
{
rewritten = rewritten.AddUsingDirectives(_aliasDirectives, _placeSystemNamespaceFirst);
}
if (node == _usingContainer)
{
rewritten = rewritten.AddUsingDirectives(_usingDirectives, _placeSystemNamespaceFirst);
}
if (node == _externContainer)
{
rewritten = rewritten.AddExterns(_externAliases);
}
return rewritten;
}
}
}
}
\ No newline at end of file
......@@ -51,6 +51,7 @@
<InternalsVisibleToTest Include="Roslyn.Services.Test.Utilities2" />
</ItemGroup>
<ItemGroup>
<Compile Include="AddImport\CSharpAddImportService.cs" />
<Compile Include="CaseCorrection\CSharpCaseCorrectionService.cs" />
<Compile Include="Classification\ClassificationHelpers.cs" />
<Compile Include="Classification\Classifiers\AbstractSyntaxClassifier.cs" />
......@@ -246,4 +247,4 @@
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
</Project>
\ No newline at end of file
......@@ -22,7 +22,7 @@ internal static class NamespaceDeclarationSyntaxExtensions
bool placeSystemNamespaceFirst,
params SyntaxAnnotation[] annotations)
{
if (!usingDirectives.Any())
if (usingDirectives.Count == 0)
{
return namespaceDeclaration;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Host;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport
{
internal interface IAddImportService : ILanguageService
{
SyntaxNode AddImports(
SyntaxNode root, SyntaxNode contextLocation,
IEnumerable<SyntaxNode> newImports, bool placeSystemNamespaceFirst);
/// <summary>
/// Given a context location in a provided syntax tree, returns the appropriate container
/// that <paramref name="import"/> should should be added to.
/// </summary>
SyntaxNode GetImportContainer(SyntaxNode root, SyntaxNode contextLocation, SyntaxNode import);
}
internal static class IAddImportServiceExtensions
{
public static SyntaxNode AddImport(
this IAddImportService service, SyntaxNode root, SyntaxNode contextLocation,
SyntaxNode newImport, bool placeSystemNamespaceFirst)
{
return service.AddImports(root, contextLocation,
SpecializedCollections.SingletonEnumerable(newImport), placeSystemNamespaceFirst);
}
}
}
\ No newline at end of file
......@@ -294,6 +294,7 @@
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\UnicodeCharacterUtilities.cs">
<Link>InternalUtilities\UnicodeCharacterUtilities.cs</Link>
</Compile>
<Compile Include="AddImport\IAddImportService.cs" />
<Compile Include="CaseCorrection\AbstractCaseCorrectionService.cs" />
<Compile Include="CaseCorrection\CaseCorrector.cs" />
<Compile Include="CaseCorrection\ICaseCorrectionService.cs" />
......@@ -1090,7 +1091,8 @@
</ItemGroup>
<ItemGroup>
<None Include="project.json">
<SubType></SubType>
<SubType>
</SubType>
</None>
<Compile Include="Utilities\BKTree.Builder.cs" />
<Compile Include="SymbolKey\SymbolKey.SymbolKeyReader.cs" />
......@@ -1099,4 +1101,4 @@
</ItemGroup>
<Import Project="..\..\..\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册