提交 234e66aa 编写于 作者: P Paul Vick

Merge pull request #11331 from vslsnap/merge-master-into-future20160516-150017

Merge master into future
......@@ -153,7 +153,7 @@ public class CheckTermsAnalyzer : DiagnosticAnalyzer
Converting a File to a Stream
-----------------------------
In cases where an additional file contains structured data (e.g., XML or JSON) the line-by-line access provided by the `SourceText` may not be desirable. This sample demonstrates how to convert a `SourceText` to a `Stream` for consumption by other libraries. The terms file is assumed to have the following format:
In cases where an additional file contains structured data (e.g., XML or JSON) the line-by-line access provided by the `SourceText` may not be desirable. One alternative is to convert a `SourceText` to a `string`, by calling `ToString()` on it. This sample demonstrates another alternative: converting a `SourceText` to a `Stream` for consumption by other libraries. The terms file is assumed to have the following format:
``` XML
<Terms>
......@@ -207,10 +207,12 @@ public class CheckTermsXMLAnalyzer : DiagnosticAnalyzer
SourceText fileText = termsFile.GetText(compilationStartContext.CancellationToken);
MemoryStream stream = new MemoryStream();
using (StreamWriter writer = new StreamWriter(stream))
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
{
fileText.Write(writer);
}
stream.Position = 0;
// Read all the <Term> elements to get the terms.
XDocument document = XDocument.Load(stream);
......
......@@ -64,7 +64,7 @@ public abstract class AnalysisContext
public abstract void RegisterSemanticModelAction(Action<SemanticModelAnalysisContext> action);
/// <summary>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.
/// A symbol action reports <see cref="Diagnostic"/>s about <see cref="ISymbol"/>s.
/// </summary>
/// <param name="action">Action to be executed for an <see cref="ISymbol"/>.</param>
......@@ -75,7 +75,7 @@ public void RegisterSymbolAction(Action<SymbolAnalysisContext> action, params Sy
}
/// <summary>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.
/// A symbol action reports <see cref="Diagnostic"/>s about <see cref="ISymbol"/>s.
/// </summary>
/// <param name="action">Action to be executed for an <see cref="ISymbol"/>.</param>
......@@ -318,7 +318,7 @@ protected CompilationStartAnalysisContext(Compilation compilation, AnalyzerOptio
public abstract void RegisterSemanticModelAction(Action<SemanticModelAnalysisContext> action);
/// <summary>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.
/// A symbol action reports <see cref="Diagnostic"/>s about <see cref="ISymbol"/>s.
/// </summary>
/// <param name="action">Action to be executed for an <see cref="ISymbol"/>.</param>
......@@ -329,7 +329,7 @@ public void RegisterSymbolAction(Action<SymbolAnalysisContext> action, params Sy
}
/// <summary>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.>
/// Register an action to be executed at completion of semantic analysis of an <see cref="ISymbol"/> with an appropriate Kind.
/// A symbol action reports <see cref="Diagnostic"/>s about <see cref="ISymbol"/>s.
/// </summary>
/// <param name="action">Action to be executed for an <see cref="ISymbol"/>.</param>
......
......@@ -915,6 +915,16 @@ public string GetNameForArgument(SyntaxNode argument)
{
throw new NotImplementedException();
}
public bool IsLeftSideOfDot(SyntaxNode node)
{
throw new NotImplementedException();
}
public SyntaxNode GetRightSideOfDot(SyntaxNode node)
{
throw new NotImplementedException();
}
}
}
}
......
......@@ -461,6 +461,29 @@ namespace System.Xaml { public class A { } }
public class Program { static void M() { MS.Internal.Xaml } }");
}
[WorkItem(11071, "https://github.com/dotnet/roslyn/issues/11071")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsFullyQualify)]
public async Task AmbiguousFixOrdering()
{
await TestAsync(
@"using n1;
using n2;
[[|Inner|].C]
class B { }
namespace n1 { namespace Inner { } }
namespace n2 { namespace Inner { class CAttribute { } } }",
@"using n1;
using n2;
[n2.Inner.C]
class B { }
namespace n1 { namespace Inner { } }
namespace n2 { namespace Inner { class CAttribute { } } }");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsFullyQualify)]
public async Task TupleTest()
{
......
......@@ -868,8 +868,25 @@ public async Task TestUnmentionableTypeParameter6()
public async Task TestUnmentionableTypeParameter7()
{
await TestAsync(
@"class H < T > { void A ( T t1 ) { t1 = [|Foo < T >|] ( t1 ) ; } } ",
@"using System; class H < T > { void A ( T t1 ) { t1 = Foo < T > ( t1 ) ; } private T Foo < T1 > ( T t1 ) { throw new NotImplementedException ( ) ; } } ");
@"class H < T >
{
void A ( T t1 )
{
t1 = [|Foo < T >|] ( t1 ) ;
}
} ",
@"using System;
class H < T >
{
void A ( T t1 )
{
t1 = Foo < T > ( t1 ) ;
}
private T1 Foo < T1 > ( T1 t1 )
{
throw new NotImplementedException ( ) ;
}
} ");
}
[WorkItem(539593, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539593")]
......@@ -1007,8 +1024,19 @@ public async Task TestInTopLevelMethod()
public async Task TestLambdaReturnType()
{
await TestAsync(
@"using System ; class C < T , R > { private static Func < T , R > g = null ; private static Func < T , R > f = ( T ) => { return [|Foo < T , R >|] ( g ) ; } ; } ",
@"using System ; class C < T , R > { private static Func < T , R > g = null ; private static Func < T , R > f = ( T ) => { return Foo < T , R > ( g ) ; } ; private static R Foo < T1 , T2 > ( Func < T , R > g ) { throw new NotImplementedException ( ) ; } } ");
@"using System ;
class C < T , R >
{
private static Func < T , R > g = null ;
private static Func < T , R > f = ( T ) => { return [|Foo < T , R >|] ( g ) ; } ;
} ",
@"using System ;
class C < T , R >
{
private static Func < T , R > g = null ;
private static Func < T , R > f = ( T ) => { return Foo < T , R > ( g ) ; } ;
private static T2 Foo < T1 , T2 > ( Func < T1 , T2 > g ) { throw new NotImplementedException ( ) ; }
} ");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
......@@ -2918,6 +2946,38 @@ public static class Ex
}
}
");
}
[WorkItem(11141, "https://github.com/dotnet/roslyn/issues/11141")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task InferTypeParameters1()
{
await TestAsync(
@"using System;
class C
{
void M()
{
List<int> list = null;
int i = [|First<int>(list)|];
}
}",
@"using System;
class C
{
void M()
{
List<int> list = null;
int i = First<int>(list);
}
private T First<T>(List<T> list)
{
throw new NotImplementedException();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
......
......@@ -820,6 +820,14 @@ End Class]]></a>.Value.NormalizeLineEndings()
Public Function GetNameForArgument(argument As SyntaxNode) As String Implements ISyntaxFactsService.GetNameForArgument
Throw New NotImplementedException()
End Function
Public Function IsLeftSideOfDot(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLeftSideOfDot
Throw New NotImplementedException()
End Function
Public Function GetRightSideOfDot(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetRightSideOfDot
Throw New NotImplementedException()
End Function
End Class
End Class
End Namespace
......@@ -1337,7 +1337,7 @@ Class M1
sub1(Of Integer, String)(New Integer() {1, 2, 3}, New String() {"a", "b"})
End Sub
Private Sub sub1(Of T1, T2)(v1() As Integer, v2() As String)
Private Sub sub1(Of T1, T2)(v1() As T1, v2() As T2)
Throw New NotImplementedException()
End Sub
End Class
......
......@@ -169,6 +169,22 @@ protected override bool IsImplicitReferenceConversion(Compilation compilation, I
var conversion = compilation.ClassifyConversion(sourceType, targetType);
return conversion.IsImplicit && conversion.IsReference;
}
protected override IList<ITypeSymbol> DetermineTypeArguments(CancellationToken cancellationToken)
{
var result = new List<ITypeSymbol>();
if (State.SimpleNameOpt is GenericNameSyntax)
{
foreach (var typeArgument in ((GenericNameSyntax)State.SimpleNameOpt).TypeArgumentList.Arguments)
{
var type = this.Document.SemanticModel.GetTypeInfo(typeArgument, cancellationToken).Type;
result.Add(type);
}
}
return result;
}
}
}
}
......@@ -51,8 +51,8 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (matchingTypes != null || matchingNamespaces != null)
{
matchingTypes = matchingTypes ?? SpecializedCollections.EmptyEnumerable<ISymbol>();
matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable<ISymbol>();
matchingTypes = matchingTypes ?? SpecializedCollections.EmptyEnumerable<SymbolResult<ISymbol>>();
matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable<SymbolResult<ISymbol>>();
var matchingTypeContainers = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation));
var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation));
......@@ -102,7 +102,7 @@ private async Task<Document> ProcessNode(Document document, SyntaxNode node, str
return document.WithSyntaxRoot(newRoot);
}
internal async Task<IEnumerable<ISymbol>> GetMatchingTypesAsync(
private async Task<IEnumerable<SymbolResult<ISymbol>>> GetMatchingTypesAsync(
Project project, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
{
// Can't be on the right hand side of binary expression (like 'dot').
......@@ -130,7 +130,8 @@ private async Task<Document> ProcessNode(Document document, SyntaxNode node, str
&& HasValidContainer(s))
.ToList();
return accessibleTypeSymbols;
return accessibleTypeSymbols.Select(s => new SymbolResult<ISymbol>(s, weight: TypeWeight))
.ToList();
}
private static bool HasValidContainer(ISymbol symbol)
......@@ -140,7 +141,7 @@ private static bool HasValidContainer(ISymbol symbol)
(container is INamedTypeSymbol && !((INamedTypeSymbol)container).IsGenericType);
}
internal async Task<IEnumerable<ISymbol>> GetMatchingNamespacesAsync(
private async Task<IEnumerable<SymbolResult<ISymbol>>> GetMatchingNamespacesAsync(
Project project,
SemanticModel semanticModel,
SyntaxNode simpleName,
......@@ -153,21 +154,62 @@ private static bool HasValidContainer(ISymbol symbol)
}
string name;
int arity;
syntaxFacts.GetNameAndArityOfSimpleName(simpleName, out name, out arity);
int arityUnused;
syntaxFacts.GetNameAndArityOfSimpleName(simpleName, out name, out arityUnused);
if (cancellationToken.IsCancellationRequested)
{
return null;
}
var symbols = await SymbolFinder.FindDeclarationsAsync(project, name, this.IgnoreCase, SymbolFilter.Namespace, cancellationToken).ConfigureAwait(false);
var symbols = await SymbolFinder.FindDeclarationsAsync(
project, name, this.IgnoreCase, SymbolFilter.Namespace, cancellationToken).ConfigureAwait(false);
// There might be multiple namespaces that this name will resolve successfully in.
// Some of them may be 'better' results than others. For example, say you have
// Y.Z and Y exists in both X1 and X2
// We'll want to order them such that we prefer the namespace that will correctly
// bind Z off of Y as well.
string rightName = null;
bool isAttributeName = false;
if (syntaxFacts.IsLeftSideOfDot(simpleName))
{
var rightSide = syntaxFacts.GetRightSideOfDot(simpleName.Parent);
syntaxFacts.GetNameAndArityOfSimpleName(rightSide, out rightName, out arityUnused);
isAttributeName = syntaxFacts.IsAttributeName(rightSide);
}
var namespaces = symbols
.OfType<INamespaceSymbol>()
.Where(n => !n.IsGlobalNamespace &&
HasAccessibleTypes(n, semanticModel, cancellationToken));
.Where(n => !n.IsGlobalNamespace && HasAccessibleTypes(n, semanticModel, cancellationToken))
.Select(n => new SymbolResult<ISymbol>(n,
BindsWithoutErrors(n, rightName, isAttributeName) ? NamespaceWithNoErrorsWeight : NamespaceWithErrorsWeight));
return namespaces;
return namespaces.ToList();
}
private bool BindsWithoutErrors(INamespaceSymbol ns, string rightName, bool isAttributeName)
{
// If there was no name on the right, then this binds without any problems.
if (rightName == null)
{
return true;
}
// Otherwise, see if the namespace we will bind this contains a member with the same
// name as the name on the right.
var types = ns.GetMembers(rightName);
if (types.Any())
{
return true;
}
if (!isAttributeName)
{
return false;
}
return BindsWithoutErrors(ns, rightName + "Attribute", isAttributeName: false);
}
private bool HasAccessibleTypes(INamespaceSymbol @namespace, SemanticModel model, CancellationToken cancellationToken)
......@@ -175,11 +217,12 @@ private bool HasAccessibleTypes(INamespaceSymbol @namespace, SemanticModel model
return Enumerable.Any(@namespace.GetAllTypes(cancellationToken), t => t.IsAccessibleWithin(model.Compilation.Assembly));
}
private static IEnumerable<INamespaceOrTypeSymbol> GetContainers(IEnumerable<ISymbol> symbols, Compilation compilation)
private static IEnumerable<SymbolResult<INamespaceOrTypeSymbol>> GetContainers(
IEnumerable<SymbolResult<ISymbol>> symbols, Compilation compilation)
{
foreach (var symbol in symbols)
foreach (var symbolResult in symbols)
{
var containingSymbol = symbol.ContainingSymbol as INamespaceOrTypeSymbol;
var containingSymbol = symbolResult.Symbol.ContainingSymbol as INamespaceOrTypeSymbol;
if (containingSymbol is INamespaceSymbol)
{
containingSymbol = compilation.GetCompilationNamespace((INamespaceSymbol)containingSymbol);
......@@ -187,18 +230,19 @@ private static IEnumerable<INamespaceOrTypeSymbol> GetContainers(IEnumerable<ISy
if (containingSymbol != null)
{
yield return containingSymbol;
yield return symbolResult.WithSymbol(containingSymbol);
}
}
}
private IEnumerable<INamespaceOrTypeSymbol> FilterAndSort(IEnumerable<INamespaceOrTypeSymbol> symbols)
private IEnumerable<INamespaceOrTypeSymbol> FilterAndSort(
IEnumerable<SymbolResult<INamespaceOrTypeSymbol>> symbols)
{
symbols = symbols ?? SpecializedCollections.EmptyList<INamespaceOrTypeSymbol>();
symbols = symbols ?? SpecializedCollections.EmptyList<SymbolResult<INamespaceOrTypeSymbol>>();
symbols = symbols.Distinct()
.Where(n => n is INamedTypeSymbol || !((INamespaceSymbol)n).IsGlobalNamespace)
.OrderBy(this.Compare);
return symbols;
.Where(n => n.Symbol is INamedTypeSymbol || !((INamespaceSymbol)n.Symbol).IsGlobalNamespace)
.OrderBy(Compare);
return symbols.Select(n => n.Symbol).ToList();
}
private static readonly ConditionalWeakTable<INamespaceOrTypeSymbol, IList<string>> s_symbolToNameMap =
......@@ -210,22 +254,21 @@ private static IList<string> GetNameParts(INamespaceOrTypeSymbol symbol)
return symbol.ToNameDisplayString().Split('.');
}
private int Compare(INamespaceOrTypeSymbol n1, INamespaceOrTypeSymbol n2)
private static int Compare(
SymbolResult<INamespaceOrTypeSymbol> n1,
SymbolResult<INamespaceOrTypeSymbol> n2)
{
Contract.Requires(n1 is INamespaceSymbol || !((INamedTypeSymbol)n1).IsGenericType);
Contract.Requires(n2 is INamespaceSymbol || !((INamedTypeSymbol)n2).IsGenericType);
Contract.Requires(n1.Symbol is INamespaceSymbol || !((INamedTypeSymbol)n1.Symbol).IsGenericType);
Contract.Requires(n2.Symbol is INamespaceSymbol || !((INamedTypeSymbol)n2.Symbol).IsGenericType);
if (n1 is INamedTypeSymbol && n2 is INamespaceSymbol)
{
return -1;
}
else if (n1 is INamespaceSymbol && n2 is INamedTypeSymbol)
var diff = n1.Weight - n2.Weight;
if (diff != 0)
{
return 1;
return diff;
}
var names1 = s_symbolToNameMap.GetValue(n1, GetNameParts);
var names2 = s_symbolToNameMap.GetValue(n2, GetNameParts);
var names1 = s_symbolToNameMap.GetValue(n1.Symbol, GetNameParts);
var names2 = s_symbolToNameMap.GetValue(n2.Symbol, GetNameParts);
for (var i = 0; i < Math.Min(names1.Count, names2.Count); i++)
{
......@@ -246,5 +289,42 @@ private class MyCodeAction : CodeAction.DocumentChangeAction
{
}
}
private const int NamespaceWithNoErrorsWeight = 0;
private const int TypeWeight = 1;
private const int NamespaceWithErrorsWeight = 2;
private struct SymbolResult<TSymbol> : IEquatable<SymbolResult<TSymbol>>
where TSymbol : ISymbol
{
public readonly TSymbol Symbol;
public readonly int Weight;
public SymbolResult(TSymbol symbol, int weight)
{
Symbol = symbol;
Weight = weight;
}
public override bool Equals(object obj)
{
return Equals((SymbolResult<TSymbol>)obj);
}
public bool Equals(SymbolResult<TSymbol> other)
{
return Equals(Symbol, other.Symbol);
}
public override int GetHashCode()
{
return Symbol.GetHashCode();
}
public SymbolResult<TOther> WithSymbol<TOther>(TOther other) where TOther : ISymbol
{
return new SymbolResult<TOther>(other, Weight);
}
}
}
}
......@@ -24,14 +24,14 @@ protected AbstractInvocationInfo(SemanticDocument document, State state)
{
}
public override IList<ITypeParameterSymbol> DetermineTypeParameters(
protected override IList<ITypeParameterSymbol> DetermineTypeParametersWorker(
CancellationToken cancellationToken)
{
var typeParameters = DetermineTypeParametersWorker(cancellationToken);
var typeParameters = ComputeTypeParameters(cancellationToken);
return typeParameters.Select(tp => MassageTypeParameter(tp, cancellationToken)).ToList();
}
private IList<ITypeParameterSymbol> DetermineTypeParametersWorker(
private IList<ITypeParameterSymbol> ComputeTypeParameters(
CancellationToken cancellationToken)
{
if (IsIdentifierName())
......
// 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.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.GenerateMember.GenerateParameterizedMember
{
......@@ -32,7 +34,7 @@ protected override ITypeSymbol DetermineReturnTypeWorker(CancellationToken cance
return _methodSymbol.ReturnType;
}
public override IList<ITypeParameterSymbol> DetermineTypeParameters(CancellationToken cancellationToken)
protected override IList<ITypeParameterSymbol> DetermineTypeParametersWorker(CancellationToken cancellationToken)
{
return _methodSymbol.TypeParameters;
}
......@@ -56,6 +58,11 @@ protected override IList<string> DetermineParameterNames(CancellationToken cance
{
return _methodSymbol.Parameters.Select(p => p.Name).ToList();
}
protected override IList<ITypeSymbol> DetermineTypeArguments(CancellationToken cancellationToken)
{
return SpecializedCollections.EmptyList<ITypeSymbol>();
}
}
}
}
......@@ -21,6 +21,8 @@ internal abstract class SignatureInfo
{
protected readonly SemanticDocument Document;
protected readonly State State;
private IList<ITypeParameterSymbol> _typeParameters;
private IDictionary<ITypeSymbol, ITypeParameterSymbol> _typeArgumentToTypeParameterMap;
public SignatureInfo(
SemanticDocument document,
......@@ -30,12 +32,19 @@ internal abstract class SignatureInfo
this.State = state;
}
public abstract IList<ITypeParameterSymbol> DetermineTypeParameters(CancellationToken cancellationToken);
public IList<ITypeParameterSymbol> DetermineTypeParameters(CancellationToken cancellationToken)
{
return _typeParameters ?? (_typeParameters = DetermineTypeParametersWorker(cancellationToken));
}
protected abstract IList<ITypeParameterSymbol> DetermineTypeParametersWorker(CancellationToken cancellationToken);
public ITypeSymbol DetermineReturnType(CancellationToken cancellationToken)
{
return FixType(DetermineReturnTypeWorker(cancellationToken), cancellationToken);
}
protected abstract IList<ITypeSymbol> DetermineTypeArguments(CancellationToken cancellationToken);
protected abstract ITypeSymbol DetermineReturnTypeWorker(CancellationToken cancellationToken);
protected abstract IList<RefKind> DetermineParameterModifiers(CancellationToken cancellationToken);
protected abstract IList<ITypeSymbol> DetermineParameterTypes(CancellationToken cancellationToken);
......@@ -115,10 +124,38 @@ public ITypeSymbol DetermineReturnType(CancellationToken cancellationToken)
var compilation = this.Document.SemanticModel.Compilation;
var allTypeParameters = availableMethodTypeParameters.Concat(availableTypeParameters);
var typeArgumentToTypeParameterMap = this.GetTypeArgumentToTypeParameterMap(cancellationToken);
return typeSymbol.RemoveAnonymousTypes(compilation)
.ReplaceTypeParametersBasedOnTypeConstraints(compilation, allTypeParameters, this.Document.Document.Project.Solution, cancellationToken)
.RemoveUnavailableTypeParameters(compilation, allTypeParameters)
.RemoveUnnamedErrorTypes(compilation);
.RemoveUnnamedErrorTypes(compilation)
.SubstituteTypes(typeArgumentToTypeParameterMap, new TypeGenerator());
}
private IDictionary<ITypeSymbol, ITypeParameterSymbol> GetTypeArgumentToTypeParameterMap(
CancellationToken cancellationToken)
{
return _typeArgumentToTypeParameterMap ?? (_typeArgumentToTypeParameterMap = CreateTypeArgumentToTypeParameterMap(cancellationToken));
}
private IDictionary<ITypeSymbol, ITypeParameterSymbol> CreateTypeArgumentToTypeParameterMap(
CancellationToken cancellationToken)
{
var typeArguments = this.DetermineTypeArguments(cancellationToken);
var typeParameters = this.DetermineTypeParameters(cancellationToken);
var result = new Dictionary<ITypeSymbol, ITypeParameterSymbol>();
for(var i = 0; i < typeArguments.Count; i++)
{
if (typeArguments[i] != null)
{
result[typeArguments[i]] = typeParameters[i];
}
}
return result;
}
private IList<SyntaxNode> GenerateStatements(
......
......@@ -157,6 +157,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateMember.GenerateMethod
Dim conversion = compilation.ClassifyConversion(sourceType, targetType)
Return conversion.IsWidening AndAlso conversion.IsReference
End Function
Protected Overrides Function DetermineTypeArguments(cancellationToken As CancellationToken) As IList(Of ITypeSymbol)
Dim Result = New List(Of ITypeSymbol)()
If TypeOf State.SimpleNameOpt Is GenericNameSyntax Then
For Each typeArgument In DirectCast(State.SimpleNameOpt, GenericNameSyntax).TypeArgumentList.Arguments
Dim Type = Me.Document.SemanticModel.GetTypeInfo(typeArgument, cancellationToken).Type
Result.Add(Type)
Next
End If
Return Result
End Function
End Class
End Class
End Namespace
......@@ -18,13 +18,6 @@ internal CSharpObjectFormatterImpl()
Filter = new CSharpMemberFilter();
}
protected override string FormatRefKind(ParameterInfo parameter)
{
return parameter.IsOut
? parameter.IsIn
? "ref"
: "out"
: "";
}
protected override string FormatRefKind(ParameterInfo parameter) => parameter.IsOut ? "out" : "ref";
}
}
......@@ -938,6 +938,67 @@ public void StackTrace_Dynamic()
+ System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1<T0>(System.Runtime.CompilerServices.CallSite, T0)
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.Fixture2.MethodDynamic(){string.Format(ScriptingResources.AtFileLine, filePath, 10123)}
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.StackTrace_Dynamic(){string.Format(ScriptingResources.AtFileLine, filePath, 10132)}
";
var actual = s_formatter.FormatException(e);
Assert.Equal(expected, actual);
}
}
private static class ParametersFixture
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Method(ref char c, out DateTime d)
{
throw new Exception();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Method<U>(ref U u)
{
throw new Exception();
}
}
[Fact]
public void StackTrace_RefOutParameters()
{
try
{
char c = ' ';
DateTime date;
ParametersFixture.Method(ref c, out date);
}
catch (Exception e)
{
const string filePath = @"z:\Fixture.cs";
var expected =
$@"Exception of type 'System.Exception' was thrown.
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.ParametersFixture.Method(ref char, out System.DateTime){string.Format(ScriptingResources.AtFileLine, filePath, 10155)}
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.StackTrace_RefOutParameters(){string.Format(ScriptingResources.AtFileLine, filePath, 10172)}
";
var actual = s_formatter.FormatException(e);
Assert.Equal(expected, actual);
}
}
[Fact]
public void StackTrace_GenericRefParameter()
{
try
{
char c = ' ';
ParametersFixture.Method<char>(ref c);
}
catch (Exception e)
{
const string filePath = @"z:\Fixture.cs";
// TODO (DevDiv #173210): Should show ParametersFixture.Method<char>(ref char)
var expected =
$@"Exception of type 'System.Exception' was thrown.
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.ParametersFixture.Method<U>(ref U){string.Format(ScriptingResources.AtFileLine, filePath, 10161)}
+ Microsoft.CodeAnalysis.CSharp.Scripting.Hosting.UnitTests.ObjectFormatterTests.StackTrace_GenericRefParameter(){string.Format(ScriptingResources.AtFileLine, filePath, 10194)}
";
var actual = s_formatter.FormatException(e);
Assert.Equal(expected, actual);
......
......@@ -131,8 +131,16 @@ protected internal virtual string FormatMethodSignature(MethodBase method)
builder.Append(", ");
}
builder.Append(FormatRefKind(parameter));
builder.Append(TypeNameFormatter.FormatTypeName(parameter.ParameterType, options));
if (parameter.ParameterType.IsByRef)
{
builder.Append(FormatRefKind(parameter));
builder.Append(' ');
builder.Append(TypeNameFormatter.FormatTypeName(parameter.ParameterType.GetElementType(), options));
}
else
{
builder.Append(TypeNameFormatter.FormatTypeName(parameter.ParameterType, options));
}
}
builder.Append(')');
......
......@@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Scripting.Hosting
End Sub
Protected Overrides Function FormatRefKind(parameter As ParameterInfo) As String
Return If(parameter.IsOut, "ByRef", "")
Return If(parameter.IsOut, "<Out> ByRef", "ByRef")
End Function
End Class
......
......@@ -1202,16 +1202,21 @@ public override IReadOnlyList<SyntaxNode> GetNamespaceImports(SyntaxNode declara
public override SyntaxNode InsertNamespaceImports(SyntaxNode declaration, int index, IEnumerable<SyntaxNode> imports)
{
var usings = AsUsingDirectives(imports);
return PreserveTrivia(declaration, d => InsertNamespaceImportsInternal(d, index, imports));
}
private SyntaxNode InsertNamespaceImportsInternal(SyntaxNode declaration, int index, IEnumerable<SyntaxNode> imports)
{
SyntaxList<UsingDirectiveSyntax> usingsToInsert = AsUsingDirectives(imports);
switch (declaration.Kind())
{
case SyntaxKind.CompilationUnit:
var cu = ((CompilationUnitSyntax)declaration);
return cu.WithUsings(cu.Usings.InsertRange(index, usings));
var cu = (CompilationUnitSyntax)declaration;
return cu.WithUsings(cu.Usings.InsertRange(index, usingsToInsert));
case SyntaxKind.NamespaceDeclaration:
var nd = ((NamespaceDeclarationSyntax)declaration);
return nd.WithUsings(nd.Usings.InsertRange(index, usings));
var nd = (NamespaceDeclarationSyntax)declaration;
return nd.WithUsings(nd.Usings.InsertRange(index, usingsToInsert));
default:
return declaration;
}
......
......@@ -189,7 +189,12 @@ public static bool IsRightOfCloseParen(this ExpressionSyntax expression)
public static bool IsLeftSideOfDot(this ExpressionSyntax expression)
{
return
if (expression == null)
{
return false;
}
return
IsLeftSideOfQualifiedName(expression) ||
(expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)expression.Parent).Expression == expression);
}
......
......@@ -1446,5 +1446,16 @@ public string GetNameForArgument(SyntaxNode argument)
return string.Empty;
}
public bool IsLeftSideOfDot(SyntaxNode node)
{
return (node as ExpressionSyntax).IsLeftSideOfDot();
}
public SyntaxNode GetRightSideOfDot(SyntaxNode node)
{
return (node as QualifiedNameSyntax)?.Right ??
(node as MemberAccessExpressionSyntax)?.Name;
}
}
}
......@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Editing
......@@ -337,15 +338,14 @@ public async Task TestImportRemovedIfItMakesReferenceAmbiguous()
// to Simplifier not reducing the namespace reference because it would
// become ambiguous, thus leaving an unused using directive
await TestAsync(
@"
namespace N { class C { } }
@"namespace N { class C { } }
class C
{
public N.C F;
}",
@"using N;
@"using N;
namespace N { class C { } }
......@@ -354,14 +354,127 @@ class C
public N.C F;
}",
@"
namespace N { class C { } }
@"namespace N { class C { } }
class C
{
public N.C F;
}");
}
[Fact]
[WorkItem(8797, "https://github.com/dotnet/roslyn/issues/8797")]
public async Task TestBannerTextRemainsAtTopOfDocumentWithoutExistingImports()
{
await TestAsync(
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
class C
{
public System.Collections.Generic.List<int> F;
}",
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
class C
{
public System.Collections.Generic.List<int> F;
}",
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
class C
{
public List<int> F;
}");
}
[Fact]
[WorkItem(8797, "https://github.com/dotnet/roslyn/issues/8797")]
public async Task TestBannerTextRemainsAtTopOfDocumentWithExistingImports()
{
await TestAsync(
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using ZZZ;
class C
{
public System.Collections.Generic.List<int> F;
}",
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using ZZZ;
class C
{
public System.Collections.Generic.List<int> F;
}",
@"// --------------------------------------------------------------------------------------------------------------------
// <copyright file=""File.cs"" company=""MyOrgnaization"">
// Copyright (C) MyOrgnaization 2016
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using ZZZ;
class C
{
public List<int> F;
}");
}
[Fact]
[WorkItem(8797, "https://github.com/dotnet/roslyn/issues/8797")]
public async Task TestLeadingWhitespaceLinesArePreserved()
{
await TestAsync(
@"
class C
{
public System.Collections.Generic.List<int> F;
}",
@"
using System.Collections.Generic;
class C
{
public System.Collections.Generic.List<int> F;
}",
@"
using System.Collections.Generic;
class C
{
public List<int> F;
}");
}
}
}
......@@ -45,6 +45,9 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsObjectCreationExpression(SyntaxNode node);
bool IsInvocationExpression(SyntaxNode node);
bool IsLeftSideOfDot(SyntaxNode node);
SyntaxNode GetRightSideOfDot(SyntaxNode node);
bool IsRightSideOfQualifiedName(SyntaxNode node);
bool IsMemberAccessExpressionName(SyntaxNode node);
......
......@@ -45,7 +45,7 @@ private ITypeSymbol VisitType(ITypeSymbol symbol)
public override ITypeSymbol VisitDynamicType(IDynamicTypeSymbol symbol)
{
return symbol;
return VisitType(symbol);
}
public override ITypeSymbol VisitTypeParameter(ITypeParameterSymbol symbol)
......@@ -55,6 +55,12 @@ public override ITypeSymbol VisitTypeParameter(ITypeParameterSymbol symbol)
public override ITypeSymbol VisitNamedType(INamedTypeSymbol symbol)
{
var mapped = VisitType(symbol);
if (mapped != symbol)
{
return mapped;
}
if (symbol.IsAnonymousType)
{
return symbol;
......@@ -89,6 +95,12 @@ public override ITypeSymbol VisitNamedType(INamedTypeSymbol symbol)
public override ITypeSymbol VisitArrayType(IArrayTypeSymbol symbol)
{
var mapped = VisitType(symbol);
if (mapped != symbol)
{
return mapped;
}
var elementType = symbol.ElementType.Accept(this);
if (elementType != null && elementType.Equals(symbol.ElementType))
{
......@@ -100,6 +112,12 @@ public override ITypeSymbol VisitArrayType(IArrayTypeSymbol symbol)
public override ITypeSymbol VisitPointerType(IPointerTypeSymbol symbol)
{
var mapped = VisitType(symbol);
if (mapped != symbol)
{
return mapped;
}
var pointedAtType = symbol.PointedAtType.Accept(this);
if (pointedAtType != null && pointedAtType.Equals(symbol.PointedAtType))
{
......
......@@ -203,6 +203,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
<Extension()>
Public Function IsLeftSideOfDot(expression As ExpressionSyntax) As Boolean
If expression Is Nothing Then
Return False
End If
Return _
(expression.IsParentKind(SyntaxKind.QualifiedName) AndAlso DirectCast(expression.Parent, QualifiedNameSyntax).Left Is expression) OrElse
(expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) AndAlso DirectCast(expression.Parent, MemberAccessExpressionSyntax).Expression Is expression)
......
......@@ -1185,5 +1185,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return String.Empty
End Function
Public Function IsLeftSideOfDot(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLeftSideOfDot
Return TryCast(node, ExpressionSyntax).IsLeftSideOfDot()
End Function
Public Function GetRightSideOfDot(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetRightSideOfDot
Return If(TryCast(node, QualifiedNameSyntax)?.Right,
TryCast(node, MemberAccessExpressionSyntax)?.Name)
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册