提交 3facb050 编写于 作者: C Cyrus Najmabadi

Infer base type better when generating a type

上级 4faf4ad5
......@@ -7,9 +7,7 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateType;
using Microsoft.CodeAnalysis.CSharp.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
......@@ -5355,32 +5353,50 @@ public Class(global::System.Object method)
}}",
index: 1);
}
}
public partial class GenerateTypeWithUnboundAnalyzerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new CSharpUnboundIdentifiersDiagnosticAnalyzer(), new GenerateTypeCodeFixProvider());
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> codeActions)
=> FlattenActions(codeActions);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateType)]
[WorkItem(13211, "https://github.com/dotnet/roslyn/issues/13211")]
public async Task TestGenerateOffOfIncompleteMember()
[WorkItem(270, "https://github.com/dotnet/roslyn/issues/270")]
public async Task TestGenerateInIsExpression()
{
await TestInRegularAndScriptAsync(
@"class Class
@"using System;
class Program
{
public [|Goo|]
static void Main(Exception p)
{
bool result = p is [|SampleType|];
}
}",
@"class Class
@"using System;
using System.Runtime.Serialization;
class Program
{
public Goo
static void Main(Exception p)
{
bool result = p is SampleType;
}
}
internal class Goo
[Serializable]
internal class SampleType : Exception
{
public SampleType()
{
}
public SampleType(string message) : base(message)
{
}
public SampleType(string message, Exception innerException) : base(message, innerException)
{
}
protected SampleType(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}",
index: 1);
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateType;
using Microsoft.CodeAnalysis.CSharp.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.GenerateTypeTests
{
public partial class GenerateTypeWithUnboundAnalyzerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new CSharpUnboundIdentifiersDiagnosticAnalyzer(), new GenerateTypeCodeFixProvider());
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> codeActions)
=> FlattenActions(codeActions);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateType)]
[WorkItem(13211, "https://github.com/dotnet/roslyn/issues/13211")]
public async Task TestGenerateOffOfIncompleteMember()
{
await TestInRegularAndScriptAsync(
@"class Class
{
public [|Goo|]
}",
@"class Class
{
public Goo
}
internal class Goo
{
}",
index: 1);
}
}
}
......@@ -210,42 +210,36 @@ private State(Compilation compilation)
var syntaxFacts = document.Document.GetLanguageService<ISyntaxFactsService>();
if (service.IsInCatchDeclaration(NameOrMemberAccessExpression))
{
BaseTypeOrInterfaceOpt = document.SemanticModel.Compilation.ExceptionType();
SetBaseType(document.SemanticModel.Compilation.ExceptionType());
}
else if (syntaxFacts.IsAttributeName(NameOrMemberAccessExpression))
{
BaseTypeOrInterfaceOpt = document.SemanticModel.Compilation.AttributeType();
SetBaseType(document.SemanticModel.Compilation.AttributeType());
}
else if (
service.IsArrayElementType(NameOrMemberAccessExpression) ||
service.IsInVariableTypeContext(NameOrMemberAccessExpression) ||
ObjectCreationExpressionOpt != null)
else
{
var expr = ObjectCreationExpressionOpt ?? NameOrMemberAccessExpression;
if (expr != null)
{
var typeInference = document.Document.GetLanguageService<ITypeInferenceService>();
var baseType = typeInference.InferType(document.SemanticModel, expr, objectAsDefault: true, cancellationToken: cancellationToken) as INamedTypeSymbol;
SetBaseType(baseType);
}
}
}
private void SetBaseType(INamedTypeSymbol baseType)
{
if (baseType == null)
{
return;
}
// A base type need to be non class or interface type. Also, being 'object' is
// redundant as the base type.
if (baseType.IsSealed || baseType.IsStatic || baseType.SpecialType == SpecialType.System_Object)
{
return;
}
if (baseType.TypeKind != TypeKind.Class && baseType.TypeKind != TypeKind.Interface)
{
return;
}
// Strip off top-level nullability since we can't put top-level nullability into the base list. We will still include nested nullability
// if you're deriving some interface like IEnumerable<string?>.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册