提交 278304b9 编写于 作者: N Neal Gafter

Merge remote-tracking branch 'upstream/master' into merges/master-to-features/target-typing

......@@ -696,7 +696,8 @@ private bool IsCandidateSymbol(ISymbol memberSymbol)
}
private bool IsEntryPoint(IMethodSymbol methodSymbol)
=> (methodSymbol.Name == WellKnownMemberNames.EntryPointMethodName || methodSymbol.Name == "$Main") &&
=> (methodSymbol.Name == WellKnownMemberNames.EntryPointMethodName || methodSymbol.Name == "<Main>$") && // https://github.com/dotnet/roslyn/issues/45110 Switch to using WellKnownMemberNames.TopLevelStatementsEntryPointMethodName
// once src\CodeStyle\Core\Analyzers\Microsoft.CodeAnalysis.CodeStyle.csproj is able to use the latest version of the type.
methodSymbol.IsStatic &&
(methodSymbol.ReturnsVoid ||
methodSymbol.ReturnType.SpecialType == SpecialType.System_Int32 ||
......
......@@ -131,7 +131,7 @@ private static SingleNamespaceOrTypeDeclaration CreateSimpleProgram(GlobalStatem
{
return new SingleTypeDeclaration(
kind: DeclarationKind.SimpleProgram,
name: SimpleProgramNamedTypeSymbol.UnspeakableName,
name: WellKnownMemberNames.TopLevelStatementsEntryPointTypeName,
arity: 0,
modifiers: DeclarationModifiers.Internal | DeclarationModifiers.Partial | DeclarationModifiers.Static,
declFlags: (hasAwaitExpressions ? SingleTypeDeclaration.TypeDeclarationFlags.HasAwaitExpressions : SingleTypeDeclaration.TypeDeclarationFlags.None) |
......
......@@ -6867,13 +6867,9 @@ private TypeSyntax ParseUnderlyingType(ParseTypeMode mode, NameOptions options =
return ParseFunctionPointerTypeSyntax();
}
var name = this.CreateMissingIdentifierName();
if (mode != ParseTypeMode.NewExpression)
{
return this.AddError(name, ErrorCode.ERR_TypeExpected);
}
return name;
return this.AddError(
this.CreateMissingIdentifierName(),
mode == ParseTypeMode.NewExpression ? ErrorCode.ERR_BadNewExpr : ErrorCode.ERR_TypeExpected);
}
#nullable enable
......@@ -11505,11 +11501,11 @@ private ExpressionSyntax ParseArrayOrObjectCreationExpression()
initializer = this.ParseObjectOrCollectionInitializer();
}
// we need one or the other
// we need one or the other. also, don't bother reporting this if we already complained about the new type.
if (argumentList == null && initializer == null)
{
argumentList = _syntaxFactory.ArgumentList(
this.EatToken(SyntaxKind.OpenParenToken, ErrorCode.ERR_BadNewExpr),
this.EatToken(SyntaxKind.OpenParenToken, ErrorCode.ERR_BadNewExpr, reportError: type?.ContainsDiagnostics == false),
default(SeparatedSyntaxList<ArgumentSyntax>),
SyntaxFactory.MissingToken(SyntaxKind.CloseParenToken));
}
......
......@@ -23,14 +23,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
/// </summary>
internal sealed class SimpleProgramNamedTypeSymbol : SourceMemberContainerTypeSymbol
{
internal const string UnspeakableName = "$Program";
internal SimpleProgramNamedTypeSymbol(NamespaceSymbol globalNamespace, MergedTypeDeclaration declaration, DiagnosticBag diagnostics)
: base(globalNamespace, declaration, diagnostics)
{
Debug.Assert(globalNamespace.IsGlobalNamespace);
Debug.Assert(declaration.Kind == DeclarationKind.SimpleProgram);
Debug.Assert(declaration.Name == UnspeakableName);
Debug.Assert(declaration.Name == WellKnownMemberNames.TopLevelStatementsEntryPointTypeName);
state.NotePartComplete(CompletionPart.EnumUnderlyingType); // No work to do for this.
}
......@@ -42,7 +40,7 @@ internal SimpleProgramNamedTypeSymbol(NamespaceSymbol globalNamespace, MergedTyp
private static SimpleProgramNamedTypeSymbol? GetSimpleProgramNamedTypeSymbol(CSharpCompilation compilation)
{
return compilation.SourceModule.GlobalNamespace.GetTypeMembers(UnspeakableName).OfType<SimpleProgramNamedTypeSymbol>().SingleOrDefault();
return compilation.SourceModule.GlobalNamespace.GetTypeMembers(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName).OfType<SimpleProgramNamedTypeSymbol>().SingleOrDefault();
}
internal static SynthesizedSimpleProgramEntryPointSymbol? GetSimpleProgramEntryPoint(CSharpCompilation compilation, CompilationUnitSyntax compilationUnit, bool fallbackToMainEntryPoint)
......
......@@ -18,8 +18,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedSimpleProgramEntryPointSymbol : SourceMemberMethodSymbol
{
internal const string UnspeakableName = "$Main";
/// <summary>
/// The corresponding <see cref="SingleTypeDeclaration"/>.
/// </summary>
......@@ -73,7 +71,7 @@ public override string Name
{
get
{
return UnspeakableName;
return WellKnownMemberNames.TopLevelStatementsEntryPointMethodName;
}
}
......
......@@ -947,7 +947,7 @@ static void Main(string[] args)
Children(0)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1526: A new expression requires (), [], or {} after type
// file.cs(8,41): error CS1526: A new expression requires an argument list or (), [], or {} after type
// C1 /*<bind>*/c1 = new/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(8, 41)
};
......
......@@ -1241,7 +1241,7 @@ void local(Func<nint, nint> fn)
{
Console.WriteLine(fn(0));
}";
VerifyInPreview(source, expectedOutput: "1", metadataName: "$Program.<>c.<$Main>b__0_0", expectedIL: @"
VerifyInPreview(source, expectedOutput: "1", metadataName: WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + ".<>c.<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">b__0_0", expectedIL: @"
{
// Code size 5 (0x5)
.maxstack 2
......
......@@ -2173,7 +2173,7 @@ public record C(int i)
var cMembers = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMembers();
AssertEx.SetEqual(new[] {
"C C.<>Clone()",
"C C." + WellKnownMemberNames.CloneMethodName + "()",
"System.Type C.EqualityContract.get",
"System.Type C.EqualityContract { get; }",
"C..ctor(System.Int32 i)",
......
......@@ -39,6 +39,8 @@ public void Simple_01()
Assert.Same(entryPoint, comp.GetEntryPoint(default));
Assert.False(entryPoint.CanBeReferencedByName);
Assert.False(entryPoint.ContainingType.CanBeReferencedByName);
Assert.Equal("<Main>$", entryPoint.Name);
Assert.Equal("<Program>$", entryPoint.ContainingType.Name);
}
private static void AssertEntryPointParameter(SynthesizedSimpleProgramEntryPointSymbol entryPoint)
......@@ -6053,13 +6055,13 @@ void validateAssembly(PEAssembly assembly)
var methodName = peReader.GetString(methodDef.Name);
var expectedFlags = methodName switch
{
"<$Main>g__forwardRef|0_0" => MethodImplAttributes.ForwardRef,
"<$Main>g__noInlining|0_1" => MethodImplAttributes.NoInlining,
"<$Main>g__noOptimization|0_2" => MethodImplAttributes.NoOptimization,
"<$Main>g__synchronized|0_3" => MethodImplAttributes.Synchronized,
"<$Main>g__internalCallStatic|0_4" => MethodImplAttributes.InternalCall,
"<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__forwardRef|0_0" => MethodImplAttributes.ForwardRef,
"<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__noInlining|0_1" => MethodImplAttributes.NoInlining,
"<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__noOptimization|0_2" => MethodImplAttributes.NoOptimization,
"<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__synchronized|0_3" => MethodImplAttributes.Synchronized,
"<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__internalCallStatic|0_4" => MethodImplAttributes.InternalCall,
".ctor" => MethodImplAttributes.IL,
"$Main" => MethodImplAttributes.IL,
WellKnownMemberNames.TopLevelStatementsEntryPointMethodName => MethodImplAttributes.IL,
_ => throw TestExceptionUtilities.UnexpectedValue(methodName)
};
......@@ -6108,12 +6110,12 @@ public void Attributes_03()
void validate(ModuleSymbol module)
{
var cClass = module.GlobalNamespace.GetMember<NamedTypeSymbol>(SimpleProgramNamedTypeSymbol.UnspeakableName);
var cClass = module.GlobalNamespace.GetMember<NamedTypeSymbol>(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName);
Assert.Equal(new[] { "CompilerGeneratedAttribute" }, GetAttributeNames(cClass.GetAttributes().As<CSharpAttributeData>()));
Assert.Empty(cClass.GetMethod(SynthesizedSimpleProgramEntryPointSymbol.UnspeakableName).GetAttributes());
Assert.Empty(cClass.GetMethod(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName).GetAttributes());
var localFn1 = cClass.GetMethod("<$Main>g__local1|0_0");
var localFn1 = cClass.GetMethod("<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">g__local1|0_0");
Assert.Empty(localFn1.GetAttributes());
validateLocalFunction(localFn1);
......@@ -6572,7 +6574,7 @@ private void Handle1(SymbolStartAnalysisContext context)
private void Handle2(SymbolStartAnalysisContext context)
{
Assert.Equal(SimpleProgramNamedTypeSymbol.UnspeakableName, context.Symbol.ToTestDisplayString());
Assert.Equal(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName, context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount3);
context.RegisterSymbolEndAction(Handle5);
......@@ -6609,7 +6611,7 @@ private void Handle4(SymbolAnalysisContext context)
private void Handle5(SymbolAnalysisContext context)
{
Assert.Equal(SimpleProgramNamedTypeSymbol.UnspeakableName, context.Symbol.ToTestDisplayString());
Assert.Equal(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName, context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount8);
}
}
......@@ -7256,7 +7258,7 @@ private void Handle3(SymbolAnalysisContext context)
case "C1":
Interlocked.Increment(ref FireCount3);
break;
case SimpleProgramNamedTypeSymbol.UnspeakableName:
case WellKnownMemberNames.TopLevelStatementsEntryPointTypeName:
Interlocked.Increment(ref FireCount4);
break;
default:
......@@ -7593,14 +7595,14 @@ public void Return_01()
{
_ = ConditionalSkipReason.NativePdbRequiresDesktop;
comp.VerifyPdb("$Program.$Main",
@"<symbols>
comp.VerifyPdb(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "." + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName,
@$"<symbols>
<files>
<file id=""1"" name="""" language=""C#"" />
</files>
<entryPoint declaringType=""$Program"" methodName=""$Main"" parameterNames=""args"" />
<entryPoint declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"" />
<methods>
<method containingType=""$Program"" name=""$Main"" parameterNames=""args"">
<method containingType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" name=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"">
<customDebugInfo>
<using>
<namespace usingCount=""0"" />
......@@ -7616,6 +7618,11 @@ public void Return_01()
}
}
private static string EscapeForXML(string toEscape)
{
return toEscape.Replace("<", "&lt;").Replace(">", "&gt;");
}
[Fact]
public void Return_02()
{
......@@ -7635,14 +7642,14 @@ public void Return_02()
{
_ = ConditionalSkipReason.NativePdbRequiresDesktop;
comp.VerifyPdb("$Program.$Main",
@"<symbols>
comp.VerifyPdb(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "." + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName,
@$"<symbols>
<files>
<file id=""1"" name="""" language=""C#"" />
</files>
<entryPoint declaringType=""$Program"" methodName=""$Main"" parameterNames=""args"" />
<entryPoint declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"" />
<methods>
<method containingType=""$Program"" name=""$Main"" parameterNames=""args"">
<method containingType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" name=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"">
<customDebugInfo>
<using>
<namespace usingCount=""0"" />
......@@ -7682,16 +7689,16 @@ public void Return_03()
{
_ = ConditionalSkipReason.NativePdbRequiresDesktop;
comp.VerifyPdb("$Program+<$Main>d__0.MoveNext",
@"<symbols>
comp.VerifyPdb(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "+<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">d__0.MoveNext",
@$"<symbols>
<files>
<file id=""1"" name="""" language=""C#"" />
</files>
<entryPoint declaringType=""$Program"" methodName=""&lt;Main&gt;"" parameterNames=""args"" />
<entryPoint declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""&lt;Main&gt;"" parameterNames=""args"" />
<methods>
<method containingType=""$Program+&lt;$Main&gt;d__0"" name=""MoveNext"">
<method containingType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;d__0"" name=""MoveNext"">
<customDebugInfo>
<forward declaringType=""$Program+&lt;&gt;c"" methodName=""&lt;$Main&gt;b__0_0"" />
<forward declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;&gt;c"" methodName=""&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;b__0_0"" />
<encLocalSlotMap>
<slot kind=""27"" offset=""2"" />
<slot kind=""33"" offset=""76"" />
......@@ -7712,8 +7719,8 @@ public void Return_03()
</sequencePoints>
<asyncInfo>
<catchHandler offset=""0xa9"" />
<kickoffMethod declaringType=""$Program"" methodName=""$Main"" parameterNames=""args"" />
<await yield=""0x5a"" resume=""0x75"" declaringType=""$Program+&lt;$Main&gt;d__0"" methodName=""MoveNext"" />
<kickoffMethod declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"" />
<await yield=""0x5a"" resume=""0x75"" declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;d__0"" methodName=""MoveNext"" />
</asyncInfo>
</method>
</methods>
......@@ -7745,16 +7752,16 @@ public void Return_04()
{
_ = ConditionalSkipReason.NativePdbRequiresDesktop;
comp.VerifyPdb("$Program+<$Main>d__0.MoveNext",
@"<symbols>
comp.VerifyPdb(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "+<" + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName + ">d__0.MoveNext",
@$"<symbols>
<files>
<file id=""1"" name="""" language=""C#"" />
</files>
<entryPoint declaringType=""$Program"" methodName=""&lt;Main&gt;"" parameterNames=""args"" />
<entryPoint declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""&lt;Main&gt;"" parameterNames=""args"" />
<methods>
<method containingType=""$Program+&lt;$Main&gt;d__0"" name=""MoveNext"">
<method containingType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;d__0"" name=""MoveNext"">
<customDebugInfo>
<forward declaringType=""$Program+&lt;&gt;c"" methodName=""&lt;$Main&gt;b__0_0"" />
<forward declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;&gt;c"" methodName=""&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;b__0_0"" />
<encLocalSlotMap>
<slot kind=""27"" offset=""2"" />
<slot kind=""20"" offset=""2"" />
......@@ -7776,8 +7783,8 @@ public void Return_04()
</sequencePoints>
<asyncInfo>
<catchHandler offset=""0xac"" />
<kickoffMethod declaringType=""$Program"" methodName=""$Main"" parameterNames=""args"" />
<await yield=""0x5a"" resume=""0x75"" declaringType=""$Program+&lt;$Main&gt;d__0"" methodName=""MoveNext"" />
<kickoffMethod declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }"" methodName=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }"" parameterNames=""args"" />
<await yield=""0x5a"" resume=""0x75"" declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+&lt;{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }&gt;d__0"" methodName=""MoveNext"" />
</asyncInfo>
</method>
</methods>
......@@ -8214,7 +8221,7 @@ public void ThrowStatement_02()
var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions);
comp.VerifyEmitDiagnostics();
CompileAndVerify(comp).VerifyIL("<top-level-statements-entry-point>", sequencePoints: "$Program.$Main", source: text, expectedIL:
CompileAndVerify(comp).VerifyIL("<top-level-statements-entry-point>", sequencePoints: WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "." + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName, source: text, expectedIL:
@"
{
// Code size 2 (0x2)
......@@ -8292,7 +8299,7 @@ public void CheckedStatement_01()
";
var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions);
comp.VerifyEmitDiagnostics();
CompileAndVerify(comp, expectedOutput: "3").VerifyIL("<top-level-statements-entry-point>", sequencePoints: "$Program.$Main", source: text, expectedIL:
CompileAndVerify(comp, expectedOutput: "3").VerifyIL("<top-level-statements-entry-point>", sequencePoints: WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "." + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName, source: text, expectedIL:
@"
{
// Code size 20 (0x14)
......@@ -8339,7 +8346,7 @@ public void UncheckedStatement_01()
";
var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithOverflowChecks(true), parseOptions: DefaultParseOptions);
comp.VerifyEmitDiagnostics();
CompileAndVerify(comp, expectedOutput: "3").VerifyIL("<top-level-statements-entry-point>", sequencePoints: "$Program.$Main", source: text, expectedIL:
CompileAndVerify(comp, expectedOutput: "3").VerifyIL("<top-level-statements-entry-point>", sequencePoints: WellKnownMemberNames.TopLevelStatementsEntryPointTypeName + "." + WellKnownMemberNames.TopLevelStatementsEntryPointMethodName, source: text, expectedIL:
@"
{
// Code size 20 (0x14)
......
......@@ -813,7 +813,7 @@ public class A
var typeA = mems.Where(s => s.Name == "A").Select(s => s);
Assert.Equal(1, typeA.Count());
var invalid = mems.Where(s => s.Name == SimpleProgramNamedTypeSymbol.UnspeakableName).Select(s => s);
var invalid = mems.Where(s => s.Name == WellKnownMemberNames.TopLevelStatementsEntryPointTypeName).Select(s => s);
Assert.Equal(1, invalid.Count());
}
......
......@@ -1056,7 +1056,7 @@ record C
}");
var members = comp.GlobalNamespace.GetTypeMember("C").GetMembers();
AssertEx.Equal(new[] {
"C! C.<>Clone()",
"C! C." + WellKnownMemberNames.CloneMethodName + "()",
"System.Type! C.EqualityContract.get",
"System.Type! C.EqualityContract { get; }",
"System.Int32 C.<X>k__BackingField",
......@@ -1429,7 +1429,7 @@ public static void Main()
Assert.True(clone.IsAbstract);
Assert.Equal(0, clone.ParameterCount);
Assert.Equal(0, clone.Arity);
Assert.Equal("R R.<>Clone()", clone.ToTestDisplayString());
Assert.Equal("R R." + WellKnownMemberNames.CloneMethodName + "()", clone.ToTestDisplayString());
var r2 = comp.GlobalNamespace.GetTypeMember("R2");
var clone2 = (MethodSymbol)r2.GetMembers(WellKnownMemberNames.CloneMethodName).Single();
......@@ -1439,7 +1439,7 @@ public static void Main()
Assert.Equal(0, clone2.ParameterCount);
Assert.Equal(0, clone2.Arity);
Assert.True(clone2.OverriddenMethod.Equals(clone, TypeCompareKind.ConsiderEverything));
Assert.Equal("R R2.<>Clone()", clone2.ToTestDisplayString());
Assert.Equal("R R2." + WellKnownMemberNames.CloneMethodName + "()", clone2.ToTestDisplayString());
var r3 = comp.GlobalNamespace.GetTypeMember("R3");
var clone3 = (MethodSymbol)r3.GetMembers(WellKnownMemberNames.CloneMethodName).Single();
......@@ -1449,7 +1449,7 @@ public static void Main()
Assert.Equal(0, clone3.ParameterCount);
Assert.Equal(0, clone3.Arity);
Assert.True(clone3.OverriddenMethod.Equals(clone2, TypeCompareKind.ConsiderEverything));
Assert.Equal("R R3.<>Clone()", clone3.ToTestDisplayString());
Assert.Equal("R R3." + WellKnownMemberNames.CloneMethodName + "()", clone3.ToTestDisplayString());
var r4 = comp.GlobalNamespace.GetTypeMember("R4");
var clone4 = (MethodSymbol)r4.GetMembers(WellKnownMemberNames.CloneMethodName).Single();
......@@ -1459,7 +1459,7 @@ public static void Main()
Assert.Equal(0, clone4.ParameterCount);
Assert.Equal(0, clone4.Arity);
Assert.True(clone4.OverriddenMethod.Equals(clone3, TypeCompareKind.ConsiderEverything));
Assert.Equal("R R4.<>Clone()", clone4.ToTestDisplayString());
Assert.Equal("R R4." + WellKnownMemberNames.CloneMethodName + "()", clone4.ToTestDisplayString());
var r5 = comp.GlobalNamespace.GetTypeMember("R5");
var clone5 = (MethodSymbol)r5.GetMembers(WellKnownMemberNames.CloneMethodName).Single();
......@@ -1469,7 +1469,7 @@ public static void Main()
Assert.Equal(0, clone5.ParameterCount);
Assert.Equal(0, clone5.Arity);
Assert.True(clone5.OverriddenMethod.Equals(clone4, TypeCompareKind.ConsiderEverything));
Assert.Equal("R R5.<>Clone()", clone5.ToTestDisplayString());
Assert.Equal("R R5." + WellKnownMemberNames.CloneMethodName + "()", clone5.ToTestDisplayString());
var verifier = CompileAndVerify(comp, expectedOutput: "", verify: Verification.Passes);
verifier.VerifyIL("C.Main", @"
......@@ -1477,10 +1477,10 @@ public static void Main()
// Code size 28 (0x1c)
.maxstack 1
IL_0000: newobj ""R3..ctor()""
IL_0005: callvirt ""R R.<>Clone()""
IL_0005: callvirt ""R R." + WellKnownMemberNames.CloneMethodName + @"()""
IL_000a: pop
IL_000b: newobj ""R5..ctor()""
IL_0010: callvirt ""R R.<>Clone()""
IL_0010: callvirt ""R R." + WellKnownMemberNames.CloneMethodName + @"()""
IL_0015: castclass ""R4""
IL_001a: pop
IL_001b: ret
......
......@@ -1450,7 +1450,7 @@ public void ErrorTypeTest01()
var errSymbol = comp.SourceModule.GlobalNamespace.GetMembers().FirstOrDefault() as NamedTypeSymbol;
Assert.NotNull(errSymbol);
Assert.Equal(SimpleProgramNamedTypeSymbol.UnspeakableName, errSymbol.Name);
Assert.Equal(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName, errSymbol.Name);
Assert.False(errSymbol.IsErrorType(), "ErrorType");
Assert.False(errSymbol.IsImplicitClass, "ImplicitClass");
}
......
......@@ -500,11 +500,8 @@ public void TestNewRefArray()
UsingStatement("new ref[];",
// (1,8): error CS1031: Type expected
// new ref[];
Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(1, 8),
// (1,10): error CS1526: A new expression requires an argument list or (), [], or {} after type
// new ref[];
Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(1, 10)
);
Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(1, 8));
N(SyntaxKind.ExpressionStatement);
{
N(SyntaxKind.ObjectCreationExpression);
......
......@@ -19,10 +19,9 @@ public class TargetTypedObjectCreationParsingTests : ParsingTests
public void TestNoRegressionOnNew()
{
UsingExpression("new", DefaultParseOptions,
// (1,4): error CS1526: A new expression requires (), [], or {} after type
// (1,4): error CS1526: A new expression requires an argument list or (), [], or {} after type
// new
Diagnostic(ErrorCode.ERR_BadNewExpr, "").WithLocation(1, 4)
);
Diagnostic(ErrorCode.ERR_BadNewExpr, "").WithLocation(1, 4));
N(SyntaxKind.ObjectCreationExpression);
{
......
Microsoft.CodeAnalysis.Compilation.CreateFunctionPointerTypeSymbol(Microsoft.CodeAnalysis.ITypeSymbol returnType, Microsoft.CodeAnalysis.RefKind returnRefKind, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> parameterTypes, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.RefKind> parameterRefKinds) -> Microsoft.CodeAnalysis.IFunctionPointerTypeSymbol
Microsoft.CodeAnalysis.Compilation.CreateNativeIntegerTypeSymbol(bool signed) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AssemblyLoader.get -> Microsoft.CodeAnalysis.IAnalyzerAssemblyLoader
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference other) -> bool
Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsync(Microsoft.CodeAnalysis.SemanticModel model, Microsoft.CodeAnalysis.Text.TextSpan? filterSpan, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer> analyzers, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Diagnostics.AnalysisResult>
Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsync(Microsoft.CodeAnalysis.SemanticModel model, Microsoft.CodeAnalysis.Text.TextSpan? filterSpan, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Diagnostics.AnalysisResult>
Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsync(Microsoft.CodeAnalysis.SyntaxTree tree, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer> analyzers, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Diagnostics.AnalysisResult>
Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsync(Microsoft.CodeAnalysis.SyntaxTree tree, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Diagnostics.AnalysisResult>
Microsoft.CodeAnalysis.Emit.EmitOptions.DefaultSourceFileEncoding.get -> System.Text.Encoding
Microsoft.CodeAnalysis.Emit.EmitOptions.EmitOptions(bool metadataOnly = false, Microsoft.CodeAnalysis.Emit.DebugInformationFormat debugInformationFormat = (Microsoft.CodeAnalysis.Emit.DebugInformationFormat)0, string pdbFilePath = null, string outputNameOverride = null, int fileAlignment = 0, ulong baseAddress = 0, bool highEntropyVirtualAddressSpace = false, Microsoft.CodeAnalysis.SubsystemVersion subsystemVersion = default(Microsoft.CodeAnalysis.SubsystemVersion), string runtimeMetadataVersion = null, bool tolerateErrors = false, bool includePrivateMembers = true, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Emit.InstrumentationKind> instrumentationKinds = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Emit.InstrumentationKind>), System.Security.Cryptography.HashAlgorithmName? pdbChecksumAlgorithm = null, System.Text.Encoding defaultSourceFileEncoding = null, System.Text.Encoding fallbackSourceFileEncoding = null) -> void
Microsoft.CodeAnalysis.Emit.EmitOptions.EmitOptions(bool metadataOnly, Microsoft.CodeAnalysis.Emit.DebugInformationFormat debugInformationFormat, string pdbFilePath, string outputNameOverride, int fileAlignment, ulong baseAddress, bool highEntropyVirtualAddressSpace, Microsoft.CodeAnalysis.SubsystemVersion subsystemVersion, string runtimeMetadataVersion, bool tolerateErrors, bool includePrivateMembers, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Emit.InstrumentationKind> instrumentationKinds, System.Security.Cryptography.HashAlgorithmName? pdbChecksumAlgorithm) -> void
Microsoft.CodeAnalysis.Emit.EmitOptions.FallbackSourceFileEncoding.get -> System.Text.Encoding
Microsoft.CodeAnalysis.Emit.EmitOptions.WithDefaultSourceFileEncoding(System.Text.Encoding defaultSourceFileEncoding) -> Microsoft.CodeAnalysis.Emit.EmitOptions
Microsoft.CodeAnalysis.Emit.EmitOptions.WithFallbackSourceFileEncoding(System.Text.Encoding fallbackSourceFileEncoding) -> Microsoft.CodeAnalysis.Emit.EmitOptions
Microsoft.CodeAnalysis.IMethodSymbol.IsInitOnly.get -> bool
Microsoft.CodeAnalysis.IAssemblySymbol.GetForwardedTypes() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.INamedTypeSymbol>
Microsoft.CodeAnalysis.IFunctionPointerTypeSymbol
Microsoft.CodeAnalysis.IFunctionPointerTypeSymbol.Signature.get -> Microsoft.CodeAnalysis.IMethodSymbol
Microsoft.CodeAnalysis.INamedTypeSymbol.NativeIntegerUnderlyingType.get -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.ITypeSymbol.IsNativeIntegerType.get -> bool
Microsoft.CodeAnalysis.MethodKind.FunctionPointerSignature = 18 -> Microsoft.CodeAnalysis.MethodKind
Microsoft.CodeAnalysis.OperationKind.BinaryPattern = 110 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.NegatedPattern = 109 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.RelationalPattern = 112 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TypePattern = 111 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.With = 113 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.Operations.CommonConversion.IsNullable.get -> bool
Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation
Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation.LeftPattern.get -> Microsoft.CodeAnalysis.Operations.IPatternOperation
Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation.OperatorKind.get -> Microsoft.CodeAnalysis.Operations.BinaryOperatorKind
Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation.RightPattern.get -> Microsoft.CodeAnalysis.Operations.IPatternOperation
Microsoft.CodeAnalysis.Operations.INegatedPatternOperation
Microsoft.CodeAnalysis.Operations.INegatedPatternOperation.Pattern.get -> Microsoft.CodeAnalysis.Operations.IPatternOperation
Microsoft.CodeAnalysis.Operations.IPatternOperation.NarrowedType.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation
Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation.OperatorKind.get -> Microsoft.CodeAnalysis.Operations.BinaryOperatorKind
Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation.Value.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Operations.ITypePatternOperation
Microsoft.CodeAnalysis.Operations.ITypePatternOperation.MatchedType.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.SourceGeneratorContext.AnalyzerConfigOptions.get -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider
Microsoft.CodeAnalysis.Operations.IWithOperation
Microsoft.CodeAnalysis.Operations.IWithOperation.CloneMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol
Microsoft.CodeAnalysis.Operations.IWithOperation.Initializer.get -> Microsoft.CodeAnalysis.Operations.IObjectOrCollectionInitializerOperation
Microsoft.CodeAnalysis.Operations.IWithOperation.Operand.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.SymbolKind.FunctionPointerType = 20 -> Microsoft.CodeAnalysis.SymbolKind
Microsoft.CodeAnalysis.TypeKind.FunctionPointer = 13 -> Microsoft.CodeAnalysis.TypeKind
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider.GlobalOptions.get -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions
static Microsoft.CodeAnalysis.AnalyzerConfigSet.Create<TList>(TList analyzerConfigs, out System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostic> diagnostics) -> Microsoft.CodeAnalysis.AnalyzerConfigSet
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitBinaryPattern(Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitNegatedPattern(Microsoft.CodeAnalysis.Operations.INegatedPatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitRelationalPattern(Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitTypePattern(Microsoft.CodeAnalysis.Operations.ITypePatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitWith(Microsoft.CodeAnalysis.Operations.IWithOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitBinaryPattern(Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitNegatedPattern(Microsoft.CodeAnalysis.Operations.INegatedPatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitRelationalPattern(Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitTypePattern(Microsoft.CodeAnalysis.Operations.ITypePatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitWith(Microsoft.CodeAnalysis.Operations.IWithOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.SymbolVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.IFunctionPointerTypeSymbol symbol) -> void
virtual Microsoft.CodeAnalysis.SymbolVisitor<TResult>.VisitFunctionPointerType(Microsoft.CodeAnalysis.IFunctionPointerTypeSymbol symbol) -> TResult
const Microsoft.CodeAnalysis.WellKnownMemberNames.TopLevelStatementsEntryPointMethodName = "<Main>$" -> string
const Microsoft.CodeAnalysis.WellKnownMemberNames.TopLevelStatementsEntryPointTypeName = "<Program>$" -> string
Microsoft.CodeAnalysis.Operations.IPatternOperation.NarrowedType.get -> Microsoft.CodeAnalysis.ITypeSymbol
\ No newline at end of file
......@@ -344,6 +344,16 @@ public static class WellKnownMemberNames
public const string SliceMethodName = "Slice";
// internal until we settle on this long-term
internal const string CloneMethodName = "<>Clone";
internal const string CloneMethodName = "<Clone>$";
/// <summary>
/// The name of an entry point method synthesized for top-level statements.
/// </summary>
public const string TopLevelStatementsEntryPointMethodName = "<Main>$";
/// <summary>
/// The name of a type synthesized for a top-level statements entry point method.
/// </summary>
public const string TopLevelStatementsEntryPointTypeName = "<Program>$";
}
}
......@@ -5532,7 +5532,8 @@ Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseSyntaxTree(text As
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseToken(text As String, offset As Integer = 0, startStatement As Boolean = False) -> Microsoft.CodeAnalysis.SyntaxToken
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTokens(text As String, offset As Integer = 0, initialTokenPosition As Integer = 0, options As Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions = Nothing) -> System.Collections.Generic.IEnumerable(Of Microsoft.CodeAnalysis.SyntaxToken)
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTrailingTrivia(text As String, offset As Integer = 0) -> Microsoft.CodeAnalysis.SyntaxTriviaList
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, options As Microsoft.CodeAnalysis.ParseOptions = Nothing, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer, consumeFullText As Boolean) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.PartitionClause(kind As Microsoft.CodeAnalysis.VisualBasic.SyntaxKind, skipOrTakeKeyword As Microsoft.CodeAnalysis.SyntaxToken, count As Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.PartitionClauseSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.PartitionWhileClause(kind As Microsoft.CodeAnalysis.VisualBasic.SyntaxKind, skipOrTakeKeyword As Microsoft.CodeAnalysis.SyntaxToken, condition As Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.PartitionWhileClauseSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.PartitionWhileClause(kind As Microsoft.CodeAnalysis.VisualBasic.SyntaxKind, skipOrTakeKeyword As Microsoft.CodeAnalysis.SyntaxToken, whileKeyword As Microsoft.CodeAnalysis.SyntaxToken, condition As Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.PartitionWhileClauseSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, options As Microsoft.CodeAnalysis.ParseOptions = Nothing, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer, consumeFullText As Boolean) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
*REMOVED*Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
......@@ -25,6 +25,8 @@ public ExtensionMethodImportCompletionProviderTests(CSharpTestWorkspaceFixture w
{
}
private const string NonBreakingSpaceString = "\x00A0";
private bool? ShowImportCompletionItemsOptionValue { get; set; } = true;
private bool IsExpandedCompletion { get; set; } = true;
......@@ -1667,6 +1669,61 @@ public void M(int x)
expectedDescriptionOrNull: $"({CSharpFeaturesResources.extension}) bool int.ExtentionMethod<int>()");
}
[InlineData(ReferenceType.Project)]
[InlineData(ReferenceType.Metadata)]
[Theory, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestDescriptionOfOverloads(ReferenceType refType)
{
var refDoc = @"
using System;
namespace NS2
{
public static class Extensions
{
public static bool ExtentionMethod(this int t) => false;
public static bool ExtentionMethod(this int t, int a) => false;
public static bool ExtentionMethod(this int t, int a, int b) => false;
public static bool ExtentionMethod<T>(this int t, T a) => false;
public static bool ExtentionMethod<T>(this int t, T a, T b) => false;
public static bool ExtentionMethod<T1, T2>(this int t, T1 a, T2 b) => false;
}
}";
var srcDoc = @"
namespace NS1
{
public class C
{
public void M(int x)
{
x.$$
}
}
}";
var markup = refType switch
{
ReferenceType.Project => CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
ReferenceType.Metadata => CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
_ => null,
};
await VerifyImportItemExistsAsync(
markup,
"ExtentionMethod",
glyph: (int)Glyph.ExtensionMethodPublic,
inlineDescription: "NS2",
expectedDescriptionOrNull: $"({CSharpFeaturesResources.extension}) bool int.ExtentionMethod() (+{NonBreakingSpaceString}2{NonBreakingSpaceString}{FeaturesResources.overloads_})");
await VerifyImportItemExistsAsync(
markup,
"ExtentionMethod",
displayTextSuffix: "<>",
glyph: (int)Glyph.ExtensionMethodPublic,
inlineDescription: "NS2",
expectedDescriptionOrNull: $"({CSharpFeaturesResources.extension}) bool int.ExtentionMethod<T>(T a) (+{NonBreakingSpaceString}2{NonBreakingSpaceString}{FeaturesResources.generic_overloads})");
}
private Task VerifyImportItemExistsAsync(string markup, string expectedItem, int glyph, string inlineDescription, string displayTextSuffix = null, string expectedDescriptionOrNull = null)
=> VerifyItemExistsAsync(markup, expectedItem, displayTextSuffix: displayTextSuffix, glyph: glyph, inlineDescription: inlineDescription, expectedDescriptionOrNull: expectedDescriptionOrNull);
......
......@@ -528,7 +528,7 @@ class D
await VerifyNoItemsExistAsync(markup);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015")]
[Fact]
public async Task PropertiesInRecursivePattern_InPositional_Incomplete()
{
var markup =
......@@ -539,16 +539,16 @@ public class Program
void M()
{
_ = this is ({ $$ }) // no deconstruction into 1 element
_ = this is ({ $$ }) // Can deconstruct into a parenthesized property pattern
}
public void Deconstruct(out Program x, out Program y) => throw null;
}
";
await VerifyNoItemsExistAsync(markup);
await VerifyItemExistsAsync(markup, "P1", displayTextSuffix: ":");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015")]
[Fact]
public async Task PropertiesInRecursivePattern_InPositional_Incomplete_WithoutClosingBrace()
{
var markup =
......@@ -559,13 +559,13 @@ public class Program
void M()
{
_ = this is ({ $$ // no deconstruction into 1 element
_ = this is ({ $$ // Can deconstruct into a parenthesized property pattern
}
public void Deconstruct(out Program x, out Program y) => throw null;
}
";
await VerifyNoItemsExistAsync(markup);
await VerifyItemExistsAsync(markup, "P1", displayTextSuffix: ":");
}
[Fact]
......
......@@ -193,33 +193,33 @@ public async Task TestForCatchClause_NotAfterFilter3()
public async Task TestForSwitchCase_NotInEmptySwitchStatement() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (1) { $$ }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterPredefinedType() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case int $$ }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case int $$ }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterPredefinedType_BeforeBreak() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case int $$ break; }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case int $$ break; }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterPredefinedType_BeforeWhen() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case int $$ when }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case int $$ when }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterGenericType() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterGenericType_BeforeBreak() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ break; }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ break; }"));
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/40015"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterGenericType_BeforeWhen() =>
await VerifyAbsenceAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ when }"));
await VerifyKeywordAsync(AddInsideMethod(@"switch (new object()) { case Dictionary<string, int> $$ when }"));
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterCustomType() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class SyntaxNode { }
class C
{
......@@ -228,7 +228,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterCustomType_BeforeBreak() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class SyntaxNode { }
class C
{
......@@ -237,7 +237,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterCustomType_BeforeWhen() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class SyntaxNode { }
class C
{
......@@ -246,7 +246,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterTypeAlias() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
using Type = System.String;
class C
{
......@@ -255,7 +255,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterTypeAlias_BeforeBreak() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
using Type = System.String;
class C
{
......@@ -264,7 +264,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterTypeAlias_BeforeWhen() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
using Type = System.String;
class C
{
......@@ -273,7 +273,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterOverloadedTypeName() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class ValueTuple { }
class ValueTuple<T> { }
class C
......@@ -283,7 +283,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterOverloadedTypeName_BeforeBreak() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class ValueTuple { }
class ValueTuple<T> { }
class C
......@@ -293,7 +293,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_NotAfterOverloadedTypeName_BeforeWhen() =>
await VerifyAbsenceAsync(@"
await VerifyKeywordAsync(@"
class ValueTuple { }
class ValueTuple<T> { }
class C
......@@ -462,19 +462,19 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterLocalConstantVar() =>
await VerifyKeywordAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ }"));
await VerifyAbsenceAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ }"));
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterLocalConstantVar_BeforeBreak() =>
await VerifyKeywordAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ break; }"));
await VerifyAbsenceAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ break; }"));
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterLocalConstantVar_BeforeWhen() =>
await VerifyKeywordAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ when }"));
await VerifyAbsenceAsync(AddInsideMethod(@"const object var = null; switch (new object()) { case var $$ when }"));
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterClassAndLocalConstantVar() =>
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
class var { }
class C
{
......@@ -483,7 +483,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterClassAndLocalConstantVar_BeforeBreak() =>
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
class var { }
class C
{
......@@ -492,7 +492,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterClassAndLocalConstantVar_BeforeWhen() =>
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
class var { }
class C
{
......@@ -502,7 +502,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterTypeAliasAndFieldConstantVar()
{
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
using var = System.String;
class C
{
......@@ -514,7 +514,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterTypeAliasAndFieldConstantVar_BeforeBreak()
{
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
using var = System.String;
class C
{
......@@ -526,7 +526,7 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestForSwitchCase_SemanticCheck_AfterTypeAliasAndFieldConstantVar_BeforeWhen()
{
await VerifyKeywordAsync(@"
await VerifyAbsenceAsync(@"
using var = System.String;
class C
{
......
......@@ -5223,7 +5223,7 @@ class C
state.SendBackspace()
state.SendTypeChars("w")
Await state.AssertSelectedCompletionItem(displayText:="with", isHardSelected:=False)
Await state.AssertSelectedCompletionItem(displayText:="when", isHardSelected:=False)
End Using
End Function
......
......@@ -22,20 +22,14 @@ public WhenKeywordRecommender()
protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken)
{
return context.IsCatchFilterContext ||
(IsAfterCompleteExpressionOrPatternInCaseLabel(context, out var expressionOrPattern) &&
!IsTypeName(expressionOrPattern, context.SemanticModel, cancellationToken));
IsAfterCompleteExpressionOrPatternInCaseLabel(context);
}
private static bool IsAfterCompleteExpressionOrPatternInCaseLabel(CSharpSyntaxContext context,
out SyntaxNodeOrToken nodeOrToken)
private static bool IsAfterCompleteExpressionOrPatternInCaseLabel(CSharpSyntaxContext context)
{
nodeOrToken = null;
var switchLabel = context.TargetToken.GetAncestor<SwitchLabelSyntax>();
if (switchLabel == null)
{
return false;
}
var expressionOrPattern = switchLabel.ChildNodes().FirstOrDefault();
if (expressionOrPattern == null)
......@@ -44,6 +38,13 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context
return false;
}
// Never show `when` after `var` in a pattern. It's virtually always going to be unhelpful as the user is
// far more likely to be writing `case var someName...` rather than typing `cae var when...` (in the case
// that `var` is a constant). In other words, it's fine to make that rare case have to manually type out
// `when` rather than risk having `when` pop up when it's not desired.
if (context.TargetToken.Text == "var")
return false;
// If the last token is missing, the expression is incomplete - possibly because of missing parentheses,
// but not necessarily. We don't want to offer 'when' in those cases. Here are some examples that illustrate this:
// case |
......@@ -55,122 +56,27 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context
// case (1 + ) |
if (expressionOrPattern.GetLastToken(includeZeroWidth: true).IsMissing)
{
return false;
}
// There are zero width tokens that are not "missing" (inserted by the parser) because they are optional,
// such as the identifier in a recursive pattern. We want to ignore those now, so we exclude all zero width.
var lastToken = expressionOrPattern.GetLastToken(includeZeroWidth: false);
// We're writing past the end of a complete pattern. This is a place where 'when' could be added to add
// restrictions on the pattern.
if (lastToken == context.TargetToken)
{
nodeOrToken = expressionOrPattern;
return true;
}
// We're writing the last token of a pattern. In this case, we might either be writing a name for the pattern
// (like `case Wolf w:`) or we might be starting to write `when` (like `case Wolf when ...:`).
if (lastToken == context.LeftToken)
{
// The user is typing a new word (might be a partially written 'when' keyword),
// which is part of the pattern as opposed to appearing outside of it. In a few special cases,
// this word can actually be replaced with 'when' and the resulting pattern would still be valid.
if (expressionOrPattern is DeclarationPatternSyntax declarationPattern)
{
// The new token causes this to be parsed as a declaration pattern:
// case constant w| ('w' = LeftToken, 'constant' = TargetToken)
// However 'constant' itself might end up being a valid constant pattern.
// We will pretend as if 'w' didn't exist so that the later check
// for whether 'constant' is actually a type can still work properly.
nodeOrToken = declarationPattern.Type;
if (expressionOrPattern is DeclarationPatternSyntax)
return true;
}
if (expressionOrPattern is VarPatternSyntax varPattern)
{
// The new token causes this to be parsed as a var pattern:
// case var w| ('w' = LeftToken, 'var' = TargetToken)
// However 'var' itself might end up being a valid constant pattern.
nodeOrToken = varPattern.VarKeyword;
if (expressionOrPattern is RecursivePatternSyntax)
return true;
}
if (expressionOrPattern is RecursivePatternSyntax recursivePattern)
{
// The new token is consumed as the identifier in a recursive pattern:
// case { } w| ('w' = LeftToken, '}' = TargetToken)
// However the identifier is optional and can be replaced by 'when'.
nodeOrToken = recursivePattern.Type;
return true;
}
// In other cases, this would not be true because the pattern would be incomplete without this word:
// case 1 + w|
}
return false;
}
private static bool IsTypeName(
SyntaxNodeOrToken nodeOrToken,
SemanticModel semanticModel,
CancellationToken cancellationToken)
{
// Syntactically, everything works out. We're in a pretty good spot to show 'when' now.
// But let's not do it just yet... Consider these cases:
// case SyntaxNode |
// case SyntaxNode w|
// If what we have here is known to be a type, we don't want to clutter the variable name suggestion list
// with 'when' since we know that the resulting code would be semantically invalid.
bool isVar;
ImmutableArray<ISymbol> symbols;
if (nodeOrToken.IsNode)
{
var node = nodeOrToken.AsNode();
var expression = node as ExpressionSyntax
?? (node as ConstantPatternSyntax)?.Expression;
if (!(expression is TypeSyntax typeSyntax))
{
return false;
}
// We don't pass in the semantic model - let IsPotentialTypeName handle the cases where it's clear
// from the syntax, but other than that, we need to do our own logic here.
if (typeSyntax.IsPotentialTypeName(semanticModelOpt: null, cancellationToken))
{
return true;
}
isVar = typeSyntax.IsVar;
symbols = semanticModel.LookupName(typeSyntax, cancellationToken);
}
else
{
// In a var pattern, the 'var' keyword is not wrapped in a type syntax, so we might just have a naked token.
var token = nodeOrToken.AsToken();
isVar = token.Text == SyntaxFacts.GetText(SyntaxKind.VarKeyword);
symbols = semanticModel.LookupSymbols(nodeOrToken.AsToken().SpanStart, null, token.Text);
}
if (symbols.Length == 0)
{
// For all unknown identifiers except var, we return false (therefore 'when' will be offered),
// because the user could later create a type with this name OR a constant. We give them both options.
// But with var, when there is no type or constant with this name, we instead make the reasonable
// assumption that the user didn't just type 'var' to then create a constant named 'var', but really
// is about to declare a variable. Therefore we don't want to interfere with the declaration.
// However note that if such a constant already exists, we do the right thing and do offer 'when'.
return isVar;
}
return symbols.All(symbol => symbol is IAliasSymbol || symbol is ITypeSymbol);
}
}
}
......@@ -29,15 +29,12 @@ internal enum ActionInfo
TargetTypeCompletionTicks,
ExtensionMethodCompletionSuccessCount,
// following are only reported when successful (i.e. filter is available)
ExtensionMethodCompletionTicks,
ExtensionMethodCompletionMethodsProvided,
ExtensionMethodCompletionGetFilterTicks,
ExtensionMethodCompletionGetSymbolTicks,
ExtensionMethodCompletionTypesChecked,
ExtensionMethodCompletionMethodsChecked,
ExtensionMethodCompletionGetSymbolsTicks,
ExtensionMethodCompletionCreateItemsTicks,
CommitsOfExtensionMethodImportCompletionItem,
ExtensionMethodCompletionPartialResultCount,
}
internal static void LogTypeImportCompletionTicksDataPoint(int count)
......@@ -61,9 +58,6 @@ internal static void LogTypeImportCompletionTicksDataPoint(int count)
internal static void LogTargetTypeCompletionTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.TargetTypeCompletionTicks, count);
internal static void LogExtensionMethodCompletionSuccess() =>
s_logAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionSuccessCount);
internal static void LogExtensionMethodCompletionTicksDataPoint(int count)
{
s_histogramLogAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionTicks, count);
......@@ -73,21 +67,18 @@ internal static void LogExtensionMethodCompletionTicksDataPoint(int count)
internal static void LogExtensionMethodCompletionMethodsProvidedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsProvided, count);
internal static void LogExtensionMethodCompletionGetFilterTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetFilterTicks, count);
internal static void LogExtensionMethodCompletionGetSymbolTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolTicks, count);
internal static void LogExtensionMethodCompletionGetSymbolsTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolsTicks, count);
internal static void LogExtensionMethodCompletionTypesCheckedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTypesChecked, count);
internal static void LogExtensionMethodCompletionMethodsCheckedDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsChecked, count);
internal static void LogExtensionMethodCompletionCreateItemsTicksDataPoint(int count) =>
s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionCreateItemsTicks, count);
internal static void LogCommitOfExtensionMethodImportCompletionItem() =>
s_logAggregator.IncreaseCount((int)ActionInfo.CommitsOfExtensionMethodImportCompletionItem);
internal static void LogExtensionMethodCompletionPartialResultCount() =>
s_logAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionPartialResultCount);
internal static void ReportTelemetry()
{
Logger.Log(FunctionId.Intellisense_CompletionProviders_Data, KeyValueLogMessage.Create(m =>
......
......@@ -39,7 +39,7 @@ protected override void LogCommit()
var syntaxFacts = completionContext.Document.GetRequiredLanguageService<ISyntaxFactsService>();
if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, cancellationToken, out var receiverTypeSymbol))
{
var items = await ExtensionMethodImportCompletionHelper.GetUnimportedExtensionMethodsAsync(
var (items, counter) = await ExtensionMethodImportCompletionHelper.GetUnimportedExtensionMethodsAsync(
completionContext.Document,
completionContext.Position,
receiverTypeSymbol,
......@@ -113,6 +113,6 @@ private CompletionItem Convert(SerializableImportCompletionItem serializableItem
serializableItem.Glyph,
GenericSuffix,
CompletionItemFlags.Expanded,
(serializableItem.SymbolKeyData, receiverTypeSymbolKey));
(serializableItem.SymbolKeyData, receiverTypeSymbolKey, serializableItem.AdditionalOverloadCount));
}
}
......@@ -30,6 +30,8 @@ internal static partial class ExtensionMethodImportCompletionHelper
/// </summary>
public readonly MultiDictionary<string, DeclaredSymbolInfo> ReceiverTypeNameToExtensionMethodMap { get; }
public bool ContainsExtensionMethod => !ReceiverTypeNameToExtensionMethodMap.IsEmpty;
private CacheEntry(
Checksum checksum,
string language,
......
......@@ -22,11 +22,19 @@ internal static class ImportCompletionItem
private const string AttributeFullName = nameof(AttributeFullName);
private const string MethodKey = nameof(MethodKey);
private const string ReceiverKey = nameof(ReceiverKey);
private const string OverloadCountKey = nameof(OverloadCountKey);
public static CompletionItem Create(INamedTypeSymbol typeSymbol, string containingNamespace, string genericTypeSuffix)
=> Create(typeSymbol.Name, typeSymbol.Arity, containingNamespace, typeSymbol.GetGlyph(), genericTypeSuffix, CompletionItemFlags.CachedAndExpanded, extensionMethodData: null);
public static CompletionItem Create(string name, int arity, string containingNamespace, Glyph glyph, string genericTypeSuffix, CompletionItemFlags flags, (string methodSymbolKey, string receiverTypeSymbolKey)? extensionMethodData)
public static CompletionItem Create(
string name,
int arity,
string containingNamespace,
Glyph glyph,
string genericTypeSuffix,
CompletionItemFlags flags,
(string methodSymbolKey, string receiverTypeSymbolKey, int overloadCount)? extensionMethodData)
{
ImmutableDictionary<string, string>? properties = null;
......@@ -38,6 +46,11 @@ public static CompletionItem Create(string name, int arity, string containingNam
{
builder.Add(MethodKey, extensionMethodData.Value.methodSymbolKey);
builder.Add(ReceiverKey, extensionMethodData.Value.receiverTypeSymbolKey);
if (extensionMethodData.Value.overloadCount > 0)
{
builder.Add(OverloadCountKey, extensionMethodData.Value.overloadCount.ToString());
}
}
else
{
......@@ -102,21 +115,18 @@ public static string GetContainingNamespace(CompletionItem item)
public static async Task<CompletionDescription> GetCompletionDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
{
var compilation = (await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false));
var symbol = GetSymbol(item, compilation);
var (symbol, overloadCount) = GetSymbolAndOverloadCount(item, compilation);
if (symbol != null)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
// We choose not to display the number of "type overloads" for simplicity.
// Otherwise, we need additional logic to track internal and public visible
// types separately, and cache both completion items.
return await CommonCompletionUtilities.CreateDescriptionAsync(
document.Project.Solution.Workspace,
semanticModel,
position: 0,
symbol,
overloadCount: 0,
overloadCount,
supportedPlatforms: null,
cancellationToken).ConfigureAwait(false);
}
......@@ -127,7 +137,7 @@ public static async Task<CompletionDescription> GetCompletionDescriptionAsync(Do
private static string GetFullyQualifiedName(string namespaceName, string typeName)
=> namespaceName.Length == 0 ? typeName : namespaceName + "." + typeName;
private static ISymbol? GetSymbol(CompletionItem item, Compilation compilation)
private static (ISymbol? symbol, int overloadCount) GetSymbolAndOverloadCount(CompletionItem item, Compilation compilation)
{
// If we have SymbolKey data (i.e. this is an extension method item), use it to recover symbol
if (item.Properties.TryGetValue(MethodKey, out var methodSymbolKey))
......@@ -136,17 +146,21 @@ private static string GetFullyQualifiedName(string namespaceName, string typeNam
if (methodSymbol != null)
{
var overloadCount = item.Properties.TryGetValue(OverloadCountKey, out var overloadCountString) && int.TryParse(overloadCountString, out var count) ? count : 0;
// Get reduced extension method symbol for the given receiver type.
if (item.Properties.TryGetValue(ReceiverKey, out var receiverTypeKey))
{
if (SymbolKey.ResolveString(receiverTypeKey, compilation).GetAnySymbol() is ITypeSymbol receiverTypeSymbol)
{
return methodSymbol.ReduceExtensionMethod(receiverTypeSymbol) ?? methodSymbol;
return (methodSymbol.ReduceExtensionMethod(receiverTypeSymbol) ?? methodSymbol, overloadCount);
}
}
return (methodSymbol, overloadCount);
}
return methodSymbol;
return default;
}
// Otherwise, this is a type item, so we don't have SymbolKey data. But we should still have all
......@@ -154,12 +168,16 @@ private static string GetFullyQualifiedName(string namespaceName, string typeNam
var containingNamespace = GetContainingNamespace(item);
var typeName = item.Properties.TryGetValue(AttributeFullName, out var attributeFullName) ? attributeFullName : item.DisplayText;
var fullyQualifiedName = GetFullyQualifiedName(containingNamespace, typeName);
// We choose not to display the number of "type overloads" for simplicity.
// Otherwise, we need additional logic to track internal and public visible
// types separately, and cache both completion items.
if (item.Properties.TryGetValue(TypeAritySuffixName, out var aritySuffix))
{
return compilation.GetTypeByMetadataName(fullyQualifiedName + aritySuffix);
return (compilation.GetTypeByMetadataName(fullyQualifiedName + aritySuffix), 0);
}
return compilation.GetTypeByMetadataName(fullyQualifiedName);
return (compilation.GetTypeByMetadataName(fullyQualifiedName), 0);
}
}
}
......@@ -13,14 +13,16 @@ namespace Microsoft.CodeAnalysis.Completion.Providers
public readonly string Name;
public readonly Glyph Glyph;
public readonly string ContainingNamespace;
public readonly int AdditionalOverloadCount;
public SerializableImportCompletionItem(string symbolKeyData, string name, int arity, Glyph glyph, string containingNamespace)
public SerializableImportCompletionItem(string symbolKeyData, string name, int arity, Glyph glyph, string containingNamespace, int additionalOverloadCount)
{
SymbolKeyData = symbolKeyData;
Arity = arity;
Name = name;
Glyph = glyph;
ContainingNamespace = containingNamespace;
AdditionalOverloadCount = additionalOverloadCount;
}
}
}
*REMOVED*abstract Microsoft.CodeAnalysis.Options.OptionSet.GetOption(Microsoft.CodeAnalysis.Options.OptionKey optionKey) -> object
*REMOVED*override Microsoft.CodeAnalysis.Options.DocumentOptionSet.GetOption(Microsoft.CodeAnalysis.Options.OptionKey optionKey) -> object
*REMOVED*static Microsoft.CodeAnalysis.SolutionInfo.Create(Microsoft.CodeAnalysis.SolutionId id, Microsoft.CodeAnalysis.VersionStamp version, string filePath = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ProjectInfo> projects = null) -> Microsoft.CodeAnalysis.SolutionInfo
*REMOVED*static Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindDerivedClassesAsync(Microsoft.CodeAnalysis.INamedTypeSymbol type, Microsoft.CodeAnalysis.Solution solution, System.Collections.Immutable.IImmutableSet<Microsoft.CodeAnalysis.Project> projects = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.INamedTypeSymbol>>
abstract Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAction.GetDescription(System.Globalization.CultureInfo culture = null) -> string
Microsoft.CodeAnalysis.ApplyChangesKind.AddSolutionAnalyzerReference = 20 -> Microsoft.CodeAnalysis.ApplyChangesKind
Microsoft.CodeAnalysis.ApplyChangesKind.RemoveSolutionAnalyzerReference = 21 -> Microsoft.CodeAnalysis.ApplyChangesKind
Microsoft.CodeAnalysis.CompilationOutputInfo
Microsoft.CodeAnalysis.CompilationOutputInfo.AssemblyPath.get -> string
Microsoft.CodeAnalysis.CompilationOutputInfo.Equals(Microsoft.CodeAnalysis.CompilationOutputInfo other) -> bool
Microsoft.CodeAnalysis.CompilationOutputInfo.WithAssemblyPath(string path) -> Microsoft.CodeAnalysis.CompilationOutputInfo
Microsoft.CodeAnalysis.Project.CompilationOutputInfo.get -> Microsoft.CodeAnalysis.CompilationOutputInfo
Microsoft.CodeAnalysis.Project.RemoveAdditionalDocuments(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.DocumentId> documentIds) -> Microsoft.CodeAnalysis.Project
Microsoft.CodeAnalysis.Project.RemoveAnalyzerConfigDocuments(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.DocumentId> documentIds) -> Microsoft.CodeAnalysis.Project
Microsoft.CodeAnalysis.ProjectInfo.CompilationOutputInfo.get -> Microsoft.CodeAnalysis.CompilationOutputInfo
Microsoft.CodeAnalysis.ProjectInfo.WithCompilationOutputInfo(in Microsoft.CodeAnalysis.CompilationOutputInfo info) -> Microsoft.CodeAnalysis.ProjectInfo
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAction
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAction.GetErrors(System.Globalization.CultureInfo culture = null) -> System.Collections.Immutable.ImmutableArray<string>
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentActionSet
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentActionSet.ApplicableActions.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAction>
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentActionSet.UpdateSolutionAsync(Microsoft.CodeAnalysis.Solution solution, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAction> actions, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Solution>
Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentActionSet.UpdateSolutionAsync(Microsoft.CodeAnalysis.Solution solution, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Solution>
Microsoft.CodeAnalysis.Solution.AddAnalyzerReference(Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference analyzerReference) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.Solution.AddAnalyzerReferences(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference> analyzerReferences) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.Solution.AnalyzerReferences.get -> System.Collections.Generic.IReadOnlyList<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference>
Microsoft.CodeAnalysis.Solution.RemoveAnalyzerReference(Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference analyzerReference) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.Solution.WithAnalyzerReferences(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference> analyzerReferences) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.Solution.WithProjectCompilationOutputInfo(Microsoft.CodeAnalysis.ProjectId projectId, in Microsoft.CodeAnalysis.CompilationOutputInfo info) -> Microsoft.CodeAnalysis.Solution
Microsoft.CodeAnalysis.SolutionChanges.GetAddedAnalyzerReferences() -> System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference>
Microsoft.CodeAnalysis.SolutionChanges.GetRemovedAnalyzerReferences() -> System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference>
Microsoft.CodeAnalysis.SolutionInfo.AnalyzerReferences.get -> System.Collections.Generic.IReadOnlyList<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference>
override Microsoft.CodeAnalysis.CompilationOutputInfo.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.CompilationOutputInfo.GetHashCode() -> int
static Microsoft.CodeAnalysis.CompilationOutputInfo.operator !=(in Microsoft.CodeAnalysis.CompilationOutputInfo left, in Microsoft.CodeAnalysis.CompilationOutputInfo right) -> bool
static Microsoft.CodeAnalysis.CompilationOutputInfo.operator ==(in Microsoft.CodeAnalysis.CompilationOutputInfo left, in Microsoft.CodeAnalysis.CompilationOutputInfo right) -> bool
static Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindDerivedClassesAsync(Microsoft.CodeAnalysis.INamedTypeSymbol type, Microsoft.CodeAnalysis.Solution solution, System.Collections.Immutable.IImmutableSet<Microsoft.CodeAnalysis.Project> projects, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.INamedTypeSymbol>>
static Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindDerivedClassesAsync(Microsoft.CodeAnalysis.INamedTypeSymbol type, Microsoft.CodeAnalysis.Solution solution, bool transitive = true, System.Collections.Immutable.IImmutableSet<Microsoft.CodeAnalysis.Project> projects = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.INamedTypeSymbol>>
static Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindDerivedInterfacesAsync(Microsoft.CodeAnalysis.INamedTypeSymbol type, Microsoft.CodeAnalysis.Solution solution, bool transitive = true, System.Collections.Immutable.IImmutableSet<Microsoft.CodeAnalysis.Project> projects = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.INamedTypeSymbol>>
static Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindImplementationsAsync(Microsoft.CodeAnalysis.INamedTypeSymbol type, Microsoft.CodeAnalysis.Solution solution, bool transitive = true, System.Collections.Immutable.IImmutableSet<Microsoft.CodeAnalysis.Project> projects = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.INamedTypeSymbol>>
static Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAsync(Microsoft.CodeAnalysis.Document document, string newDocumentName, System.Collections.Generic.IReadOnlyList<string> newDocumentFolders = null, Microsoft.CodeAnalysis.Options.OptionSet optionSet = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentActionSet>
static Microsoft.CodeAnalysis.SolutionInfo.Create(Microsoft.CodeAnalysis.SolutionId id, Microsoft.CodeAnalysis.VersionStamp version, string filePath = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ProjectInfo> projects = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference> analyzerReferences = null) -> Microsoft.CodeAnalysis.SolutionInfo
static Microsoft.CodeAnalysis.SolutionInfo.Create(Microsoft.CodeAnalysis.SolutionId id, Microsoft.CodeAnalysis.VersionStamp version, string filePath, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ProjectInfo> projects) -> Microsoft.CodeAnalysis.SolutionInfo
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册