提交 7fbd4542 编写于 作者: J John Doe

Merge remote-tracking branch 'upstream/master'

......@@ -31,3 +31,7 @@ How did we miss it? What tests are we adding to guard against it in the future?
**How was the bug found?**
(E.g. customer reported it vs. ad hoc testing)
**Test documentation updated?**
If this is a new non-compiler feature or a significant improvement to an existing feature, update https://github.com/dotnet/roslyn/wiki/Manual-Testing once you know which release it is targeting.
......@@ -6599,5 +6599,35 @@ private static Symbol[] GetCrefOriginalDefinitions(SemanticModel model, IEnumera
{
return crefs.Select(syntax => model.GetSymbolInfo(syntax).Symbol).Select(symbol => (object)symbol == null ? null : (Symbol)symbol.OriginalDefinition).ToArray();
}
[Fact]
[WorkItem(410932, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=410932")]
public void LookupOnCrefTypeParameter()
{
var source = @"
class Test
{
T F<T>()
{
}
/// <summary>
/// <see cref=""F{U}()""/>
/// </summary>
void S()
{ }
}
";
var compilation = CreateCompilationWithMscorlibAndDocumentationComments(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
var crefSyntax = (NameMemberCrefSyntax)GetCrefSyntaxes(compilation).Single();
var name = ((GenericNameSyntax)crefSyntax.Name).TypeArgumentList.Arguments.Single();
Assert.Equal("U", name.ToString());
var typeParameter = (TypeParameterSymbol)model.GetSymbolInfo(name).Symbol;
Assert.Empty(model.LookupSymbols(name.SpanStart, typeParameter, "GetAwaiter"));
}
}
}
......@@ -1995,6 +1995,10 @@ ExitForFor:
typeParameter As TypeParameterSymbol,
options As LookupOptions,
binder As Binder)
If typeParameter.TypeParameterKind = TypeParameterKind.Cref Then
Return
End If
AddLookupSymbolsInfoInTypeParameterNoExtensionMethods(nameSet, typeParameter, options, binder)
' Search for extension methods.
......
......@@ -12410,5 +12410,40 @@ DashDash
stringMapper:=Function(o) StringReplace(o, System.IO.Path.Combine(TestHelpers.AsXmlCommentText(path), "- - -.xml"), "**FILE**"), ensureEnglishUICulture:=True)
End Sub
<Fact>
<WorkItem(410932, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=410932")>
Public Sub LookupOnCrefTypeParameter()
Dim sources =
<compilation>
<file name="a.vb">
<![CDATA[
Public Class Test
Function F(Of T)() As T
End Function
''' <summary>
''' <see cref="F(Of U)()"/>
''' </summary>
Public Sub S()
End Sub
End Class
]]>
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(
sources,
options:=TestOptions.ReleaseDll)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim name = FindNodesOfTypeFromText(Of NameSyntax)(tree, "U").Single()
Dim typeParameter = DirectCast(model.GetSymbolInfo(name).Symbol, TypeParameterSymbol)
Assert.Empty(model.LookupSymbols(name.SpanStart, typeParameter, "GetAwaiter"))
End Sub
End Class
End Namespace
......@@ -2058,6 +2058,48 @@ class Program
await VerifyItemExistsAsync(markup, "CompareTo");
}
[WorkItem(21596, "https://github.com/dotnet/roslyn/issues/21596")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task AmbiguityBetweenExpressionAndLocalFunctionReturnType()
{
var markup = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
AwaitTest test = new AwaitTest();
test.Test1().Wait();
}
}
class AwaitTest
{
List<string> stringList = new List<string>();
public async Task<bool> Test1()
{
stringList.$$
await Test2();
return true;
}
public async Task<bool> Test2()
{
return true;
}
}";
await VerifyItemExistsAsync(markup, "Add");
}
[WorkItem(540750, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540750")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task CompletionAfterNewInScript()
......
......@@ -161,7 +161,7 @@ public void ErrorSpans_TopLevel()
}
";
TestSpans(source, kind => TopSyntaxComparer.HasLabel(kind, ignoreVariableDeclarations: false));
TestSpans(source, kind => TopSyntaxComparer.HasLabel(kind));
}
[Fact]
......@@ -227,7 +227,7 @@ void M()
public void ErrorSpansAllKinds()
{
TestErrorSpansAllKinds(StatementSyntaxComparer.IgnoreLabeledChild);
TestErrorSpansAllKinds(kind => TopSyntaxComparer.HasLabel(kind, ignoreVariableDeclarations: false));
TestErrorSpansAllKinds(kind => TopSyntaxComparer.HasLabel(kind));
}
[Fact]
......
......@@ -3210,6 +3210,28 @@ static void Main(string[] args)
edits.VerifyRudeDiagnostics();
}
[Fact]
public void MethodUpdate_LocalFunctionsParameterRefnessInBody()
{
var src1 = @"class C { public void M(int a) { void f(ref int b) => b = 1; } }";
var src2 = @"class C { public void M(int a) { void f(out int b) => b = 1; } } ";
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(
"Update [public void M(int a) { void f(ref int b) => b = 1; }]@10 -> [public void M(int a) { void f(out int b) => b = 1; }]@10");
}
[Fact]
public void MethodUpdate_LambdaParameterRefnessInBody()
{
var src1 = @"class C { public void M(int a) { f((ref int b) => b = 1); } }";
var src2 = @"class C { public void M(int a) { f((out int b) => b = 1); } } ";
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(
"Update [public void M(int a) { f((ref int b) => b = 1); }]@10 -> [public void M(int a) { f((out int b) => b = 1); }]@10");
}
#endregion
#region Operators
......
......@@ -4992,5 +4992,28 @@ static void Main(string[] args)
}",
MainDescription($"({FeaturesResources.local_variable}) ref int i"));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
[WorkItem(410932, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=410932")]
public async Task TestGenericMethodInDocComment()
{
await TestAsync(
@"
class Test
{
T F<T>()
{
F<T>();
}
/// <summary>
/// <see cref=""F$${T}()""/>
/// </summary>
void S()
{ }
}
",
MainDescription("T Test.F<T>()"));
}
}
}
......@@ -743,6 +743,26 @@ void M(object o)
{
}
}
}");
}
[WorkItem(21551, "https://github.com/dotnet/roslyn/issues/21551")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestOverloadedUserOperator()
{
await TestMissingAsync(
@"class C
{
public static void Main()
{
object o = new C();
[|var|] c = o as C;
if (c != null)
System.Console.WriteLine();
}
public static bool operator ==(C c1, C c2) => false;
public static bool operator !=(C c1, C c2) => false;
}");
}
}
......
......@@ -2089,5 +2089,25 @@ End Class
",
Documentation("String http://microsoft.com Nothing cat"))
End Function
<Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)>
<WorkItem(410932, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=410932")>
Public Async Function TestGenericMethodInDocComment() As Task
Await TestWithImportsAsync(<Text><![CDATA[
Public Class Test
Function F(Of T)() As T
F(Of T)()
End Function
''' <summary>
''' <see cref="F$$(Of T)()"/>
''' </summary>
Public Sub S()
End Sub
End Class
]]></Text>.NormalizedValue,
MainDescription("Function Test.F(Of T)() As T"))
End Function
End Class
End Namespace
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue
{
......@@ -60,7 +61,7 @@ private static bool HasChildren(SyntaxNode node)
{
// Leaves are labeled statements that don't have a labeled child.
// We also return true for non-labeled statements.
Label label = Classify(node.Kind(), out var isLeaf, ignoreVariableDeclarations: false);
Label label = Classify(node.Kind(), out var isLeaf);
// ignored should always be reported as leaves
Debug.Assert(label != Label.Ignored || isLeaf);
......@@ -160,7 +161,7 @@ private static int TiedToAncestor(Label label)
}
// internal for testing
internal static Label Classify(SyntaxKind kind, out bool isLeaf, bool ignoreVariableDeclarations)
internal static Label Classify(SyntaxKind kind, out bool isLeaf)
{
switch (kind)
{
......@@ -205,12 +206,12 @@ internal static Label Classify(SyntaxKind kind, out bool isLeaf, bool ignoreVari
return Label.FieldDeclaration;
case SyntaxKind.VariableDeclaration:
isLeaf = ignoreVariableDeclarations;
return ignoreVariableDeclarations ? Label.Ignored : Label.FieldVariableDeclaration;
isLeaf = false;
return Label.FieldVariableDeclaration;
case SyntaxKind.VariableDeclarator:
isLeaf = true;
return ignoreVariableDeclarations ? Label.Ignored : Label.FieldVariableDeclarator;
return Label.FieldVariableDeclarator;
case SyntaxKind.MethodDeclaration:
isLeaf = false;
......@@ -306,13 +307,13 @@ protected internal override int GetLabel(SyntaxNode node)
internal static Label GetLabel(SyntaxKind kind)
{
return Classify(kind, out var isLeaf, ignoreVariableDeclarations: false);
return Classify(kind, out var isLeaf);
}
// internal for testing
internal static bool HasLabel(SyntaxKind kind, bool ignoreVariableDeclarations)
internal static bool HasLabel(SyntaxKind kind)
{
return Classify(kind, out var isLeaf, ignoreVariableDeclarations) != Label.Ignored;
return Classify(kind, out var isLeaf) != Label.Ignored;
}
protected internal override int LabelCount
......@@ -346,13 +347,22 @@ public override bool ValuesEqual(SyntaxNode left, SyntaxNode right)
case SyntaxKind.RemoveAccessorDeclaration:
// When comparing method bodies we need to NOT ignore VariableDeclaration and VariableDeclarator children,
// but when comparing field definitions we should ignore VariableDeclarations children.
ignoreChildFunction = childKind => HasLabel(childKind, ignoreVariableDeclarations: true);
var leftBody = GetBody(left);
var rightBody = GetBody(right);
if (!SyntaxFactory.AreEquivalent(leftBody, rightBody, null))
{
return false;
}
ignoreChildFunction = childKind => childKind == SyntaxKind.Block || childKind == SyntaxKind.ArrowExpressionClause || HasLabel(childKind);
break;
default:
if (HasChildren(left))
{
ignoreChildFunction = childKind => HasLabel(childKind, ignoreVariableDeclarations: false);
ignoreChildFunction = childKind => HasLabel(childKind);
}
else
{
......@@ -365,6 +375,16 @@ public override bool ValuesEqual(SyntaxNode left, SyntaxNode right)
return SyntaxFactory.AreEquivalent(left, right, ignoreChildFunction);
}
private static SyntaxNode GetBody(SyntaxNode node)
{
switch (node)
{
case BaseMethodDeclarationSyntax baseMethodDeclarationSyntax: return baseMethodDeclarationSyntax.Body ?? (SyntaxNode)baseMethodDeclarationSyntax.ExpressionBody?.Expression;
case AccessorDeclarationSyntax accessorDeclarationSyntax: return accessorDeclarationSyntax.Body ?? (SyntaxNode)accessorDeclarationSyntax.ExpressionBody?.Expression;
default: throw ExceptionUtilities.UnexpectedValue(node);
}
}
protected override bool TryComputeWeightedDistance(SyntaxNode leftNode, SyntaxNode rightNode, out double distance)
{
SyntaxNodeOrToken? leftName = TryGetName(leftNode);
......
......@@ -95,6 +95,11 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
}
var semanticModel = syntaxContext.SemanticModel;
if (semanticModel.GetSymbolInfo(comparison).GetAnySymbol().IsUserDefinedOperator())
{
return;
}
var typeNode = ((BinaryExpressionSyntax)asExpression).Right;
var asType = semanticModel.GetTypeInfo(typeNode, cancellationToken).Type;
if (asType.IsNullable())
......
......@@ -296,13 +296,21 @@ private static ImmutableArray<ISymbol> GetSymbolsForNamespaceDeclarationNameCont
// int i = 5;
// i. // <-- here
// List<string> ml = new List<string>();
//
// The problem is that "i.List<string>" gets parsed as a type. In this case we need
// to try binding again as if "i" is an expression and not a type. In order to do
// that, we need to speculate as to what 'i' meant if it wasn't part of a local
// declaration's type.
//
// Another interesting case is something like:
//
// stringList.
// await Test2();
//
// Here "stringList.await" is thought of as the return type of a local function.
// The problem is that "i.List<string>" gets parsed as a type. In this case we need to
// try binding again as if "i" is an expression and not a type. In order to do that, we
// need to speculate as to what 'i' meant if it wasn't part of a local declaration's
// type.
if (name.IsFoundUnder<LocalDeclarationStatementSyntax>(d => d.Declaration.Type) ||
if (name.IsFoundUnder<LocalFunctionStatementSyntax>(d => d.ReturnType) ||
name.IsFoundUnder<LocalDeclarationStatementSyntax>(d => d.Declaration.Type) ||
name.IsFoundUnder<FieldDeclarationSyntax>(d => d.Declaration.Type))
{
var speculativeBinding = context.SemanticModel.GetSpeculativeSymbolInfo(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册