提交 4b733b8b 编写于 作者: J Jonathon Marolf

Report semantic errors in lambdas

The compiler does not generate semantic errors inside lambdas in the
presence of syntactic errors causing several features to not work in
lambdas with syntax errors.  The bug for this
([1867](https://github.com/dotnet/roslyn/issues/1867)) was moved to
milestone 1.1 so we are going to use an analyzer in the interim for 1.0.

1. We now check for IncompleteMemberSyntax nodes and
LambdaExpressionSyntax nodes which contain syntax diagnostics on any of
their descendant nodes.
2. We report both unbound identifier names and constructors that the
compiler reports as binding, but which fail overload resolution
(actually don't exist).

Performance considerations should be mitigated by only doing these
checks only lambdas with syntax errors.

Other notes:

- Renamed analyzer to UnboundIdentifier instead of AddImport since it is
being used in more places than just the AddImport fixer
- Updated the DiagnosticDescriptor for this analyzer to take
localizeable strings.

Fixes #1744
Fixes #1241
Fixes #1239
上级 6e7ddc3f
......@@ -5,7 +5,7 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.AddImport;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.AddImport;
using Microsoft.CodeAnalysis.CSharp.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
......@@ -1975,7 +1975,7 @@ public partial class AddUsingTestsWithAddImportDiagnosticProvider : AbstractCSha
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return Tuple.Create<DiagnosticAnalyzer, CodeFixProvider>(
new CSharpAddImportDiagnosticAnalyzer(),
new CSharpUnboundIdentifiersDiagnosticAnalyzer(),
new CSharpAddImportCodeFixProvider());
}
......@@ -2060,6 +2060,33 @@ public void TestOutsideOfMethodWithMalformedGenericParameters()
@"using System ; class Program { Func < [|FlowControl|] x } ",
@"using System ; using System . Reflection . Emit ; class Program { Func < FlowControl x } ");
}
[WorkItem(1744, @"https://github.com/dotnet/roslyn/issues/1744")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)]
public void TestIncompleteCatchBlockInLambda()
{
Test(
@"class A { System . Action a = ( ) => { try { } catch ( [|Exception|] ",
@"using System ; class A { System . Action a = ( ) => { try { } catch ( Exception ");
}
[WorkItem(1239, @"https://github.com/dotnet/roslyn/issues/1239")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)]
public void TestIncompleteLambda1()
{
Test(
@"using System . Linq ; class C { C ( ) { """" . Select ( ( ) => { new [|Byte|] ",
@"using System ; using System . Linq ; class C { C ( ) { """" . Select ( ( ) => { new Byte ");
}
[WorkItem(1239, @"https://github.com/dotnet/roslyn/issues/1239")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)]
public void TestIncompleteLambda2()
{
Test(
@"using System . Linq ; class C { C ( ) { """" . Select ( ( ) => { new [|Byte|] ( ) } ",
@"using System ; using System . Linq ; class C { C ( ) { """" . Select ( ( ) => { new Byte ( ) } ");
}
}
}
}
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateConstructor;
using Microsoft.CodeAnalysis.CSharp.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Simplification;
......@@ -617,5 +618,23 @@ public void TestGenerateInInaccessibleType()
@"class Foo { class Bar { } } class A { static void Main(string[] args) { var s = new [|Foo.Bar(5)|]; } }",
@"class Foo { class Bar { private int v; public Bar(int v) { this.v = v; } } } class A { static void Main(string[] args) { var s = new Foo.Bar(5); } }");
}
public partial class GenerateConstructorTestsWithFindMissingIdentifiersAnalyzer : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new CSharpUnboundIdentifiersDiagnosticAnalyzer(), new GenerateConstructorCodeFixProvider());
}
[WorkItem(1241, @"https://github.com/dotnet/roslyn/issues/1241")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public void TestGenerateConstructorInIncompleteLambda()
{
Test(
@"using System . Threading . Tasks ; class C { C ( ) { Task . Run ( ( ) => { new [|C|] ( 0 ) } ) ; } } ",
@"using System . Threading . Tasks ; class C { private int v ; public C ( int v ) { this . v = v ; } C ( ) { Task . Run ( ( ) => { new C ( 0 ) } ) ; } } ");
}
}
}
}
......@@ -5,7 +5,7 @@ Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.AddImport
Public Class AddImportTests
......@@ -1065,7 +1065,7 @@ Nothing, 1, True, True, Nothing, False, Nothing)
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, CodeFixProvider)(
New VisualBasicAddImportDiagnosticAnalyzer(),
New VisualBasicUnboundIdentifiersDiagnosticAnalyzer(),
New VisualBasicAddImportCodeFixProvider())
End Function
......@@ -1119,6 +1119,22 @@ Class MultiDictionary(Of K, V)
End Sub
End Class")
End Sub
<WorkItem(1744, "https://github.com/dotnet/roslyn/issues/1744")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)>
Public Sub TestImportIncompleteSub()
Test(
NewLines("Class A \n Dim a As Action = Sub() \n Try \n Catch ex As [|TestException|] \n End Sub \n End Class \n Namespace T \n Class TestException \n Inherits Exception \n End Class \n End Namespace"),
NewLines("Imports T \n Class A \n Dim a As Action = Sub() \n Try \n Catch ex As TestException \n End Sub \n End Class \n Namespace T \n Class TestException \n Inherits Exception \n End Class \n End Namespace"))
End Sub
<WorkItem(1239, "https://github.com/dotnet/roslyn/issues/1239")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)>
Public Sub TestImportIncompleteSub2()
Test(
NewLines("Imports System.Linq \n Namespace X \n Class Test \n End Class \n End Namespace \n Class C \n Sub New() \n Dim s As Action = Sub() \n Dim a = New [|Test|]()"),
NewLines("Imports System.Linq \n Imports X \n Namespace X \n Class Test \n End Class \n End Namespace \n Class C \n Sub New() \n Dim s As Action = Sub() \n Dim a = New Test()"))
End Sub
End Class
End Class
End Namespace
......@@ -4,7 +4,7 @@ Option Strict Off
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.FullyQualify
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.FullyQualify
Public Class FullyQualifyTests
......@@ -378,7 +378,7 @@ compareTokens:=False)
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, CodeFixProvider)(
New VisualBasicAddImportDiagnosticAnalyzer(),
New VisualBasicUnboundIdentifiersDiagnosticAnalyzer(),
New VisualBasicFullyQualifyCodeFixProvider())
End Function
......
......@@ -4,6 +4,7 @@ Option Strict Off
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateConstructor
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.GenerateConstructor
Public Class GenerateConstructorTests
......@@ -476,5 +477,21 @@ NewLines("Class Foo \n Private Class Bar \n End Class \n End Class \n Class A \n
NewLines("Class Foo \n Private Class Bar \n Private v As Integer \n Public Sub New(v As Integer) \n Me.v = v \n End Sub \n End Class \n End Class \n Class A \n Sub Main() \n Dim s = New Foo.Bar(5) \n End Sub \n End Class"))
End Sub
Public Class GenerateConstructorTestsWithFindMissingIdentifiersAnalyzer
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, CodeFixProvider)(New VisualBasicUnboundIdentifiersDiagnosticAnalyzer(), New GenerateConstructorCodeFixProvider())
End Function
<WorkItem(1241, "https://github.com/dotnet/roslyn/issues/1241")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)>
Public Sub TestGenerateConstructorInIncompleteLambda()
Test(
NewLines("Imports System.Linq \n Class C \n Sub New() \n Dim s As Action = Sub() \n Dim a = New [|C|](0)"),
NewLines("Imports System.Linq \n Class C \n Private v As Integer \n Sub New() \n Dim s As Action = Sub() \n Dim a = New C(0)Public Sub New(v As Integer) \n Me.v = v \n End Sub \n End Class"))
End Sub
End Class
End Class
End Namespace
......@@ -7,7 +7,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateType
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.GenerateType
Public Class GenerateTypeTests
......@@ -752,7 +752,7 @@ index:=0)
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, CodeFixProvider)(
New VisualBasicAddImportDiagnosticAnalyzer(),
New VisualBasicUnboundIdentifiersDiagnosticAnalyzer(),
New GenerateTypeCodeFixProvider())
End Function
......
......@@ -4,7 +4,7 @@ Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.Spellcheck
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Spellcheck
Public Class SpellcheckTests
......@@ -467,7 +467,7 @@ index:=0)
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, CodeFixProvider)(
New VisualBasicAddImportDiagnosticAnalyzer(),
New VisualBasicUnboundIdentifiersDiagnosticAnalyzer(),
New SpellcheckCodeFixProvider())
End Function
......
......@@ -285,7 +285,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>CSharpFeaturesResources.resx</DependentUpon>
</Compile>
<Compile Include="Diagnostics\Analyzers\CSharpAddImportDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUnboundIdentifiersDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs" />
......
......@@ -258,6 +258,24 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; does not contain a constructor that takes that many arguments..
/// </summary>
internal static string ERR_BadCtorArgCount {
get {
return ResourceManager.GetString("ERR_BadCtorArgCount", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The name &apos;{0}&apos; does not exist in the current context..
/// </summary>
internal static string ERR_NameNotInContext {
get {
return ResourceManager.GetString("ERR_NameNotInContext", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to event field.
/// </summary>
......
......@@ -383,7 +383,7 @@
</data>
<data name="Struct" xml:space="preserve">
<value>struct</value>
<comment>{Locked}</comment>
<comment>{Locked}</comment>
</data>
<data name="EventField" xml:space="preserve">
<value>event field</value>
......@@ -412,4 +412,10 @@
<data name="AttributeTarget" xml:space="preserve">
<value>attribute target</value>
</data>
<data name="ERR_BadCtorArgCount" xml:space="preserve">
<value>'{0}' does not contain a constructor that takes that many arguments.</value>
</data>
<data name="ERR_NameNotInContext" xml:space="preserve">
<value>The name '{0}' does not exist in the current context.</value>
</data>
</root>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.AddImport;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.AddImport
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpAddImportDiagnosticAnalyzer : AddImportDiagnosticAnalyzerBase<SyntaxKind, SimpleNameSyntax, QualifiedNameSyntax, IncompleteMemberSyntax>
{
private const string NameNotInContext = "CS0103";
private const string MessageFormat = "The name '{0}' does not exist in the current context";
private static readonly ImmutableArray<SyntaxKind> s_kindsOfInterest = ImmutableArray.Create(SyntaxKind.IncompleteMember);
protected override ImmutableArray<SyntaxKind> SyntaxKindsOfInterest
{
get
{
return s_kindsOfInterest;
}
}
protected override DiagnosticDescriptor DiagnosticDescriptor
{
get
{
return GetDiagnosticDescriptor(NameNotInContext, MessageFormat);
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.AddImport;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpUnboundIdentifiersDiagnosticAnalyzer : UnboundIdentifiersDiagnosticAnalyzerBase<SyntaxKind, SimpleNameSyntax, QualifiedNameSyntax, IncompleteMemberSyntax, LambdaExpressionSyntax>
{
private const string NameNotInContext = "CS0103";
private readonly LocalizableString NameNotInContextMessageFormat = new LocalizableResourceString(nameof(CSharpFeaturesResources.ERR_NameNotInContext), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
private const string ConstructorOverloadResolutionFailure = "CS1729";
private readonly LocalizableString ConstructorOverloadResolutionFailureMessageFormat = new LocalizableResourceString(nameof(CSharpFeaturesResources.ERR_BadCtorArgCount), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
private static readonly ImmutableArray<SyntaxKind> s_kindsOfInterest = ImmutableArray.Create(SyntaxKind.IncompleteMember, SyntaxKind.ParenthesizedLambdaExpression, SyntaxKind.SimpleLambdaExpression);
protected override ImmutableArray<SyntaxKind> SyntaxKindsOfInterest
{
get
{
return s_kindsOfInterest;
}
}
protected override DiagnosticDescriptor DiagnosticDescriptor => GetDiagnosticDescriptor(NameNotInContext, NameNotInContextMessageFormat);
protected override DiagnosticDescriptor DiagnosticDescriptor2 => GetDiagnosticDescriptor(ConstructorOverloadResolutionFailure, ConstructorOverloadResolutionFailureMessageFormat);
protected override bool ConstructorDoesNotExist(SyntaxNode node, SymbolInfo info, SemanticModel model)
{
var argList = (node.Parent as ObjectCreationExpressionSyntax)?.ArgumentList.Arguments;
if (!argList.HasValue)
{
return false;
}
var args = argList.Value;
var constructors = (info.Symbol?.OriginalDefinition as INamedTypeSymbol)?.Constructors;
if (!constructors.HasValue)
{
return false;
}
var count = constructors.Value
.WhereAsArray(constructor => constructor.Parameters.Length == args.Count)
.WhereAsArray(constructor =>
{
for (int i = 0; i < constructor.Parameters.Length; i++)
{
var typeInfo = model.GetTypeInfo(args[i].Expression);
if (!constructor.Parameters[i].Type.Equals(typeInfo.ConvertedType))
{
return false;
}
}
return true;
}).Length;
if (count == 0)
{
return true;
}
return false;
}
}
}
......@@ -7,20 +7,23 @@
namespace Microsoft.CodeAnalysis.Diagnostics.AddImport
{
internal abstract class AddImportDiagnosticAnalyzerBase<TLanguageKindEnum, TSimpleNameSyntax, TQualifiedNameSyntax, TIncompleteMemberSyntax> : DiagnosticAnalyzer, IBuiltInAnalyzer
internal abstract class UnboundIdentifiersDiagnosticAnalyzerBase<TLanguageKindEnum, TSimpleNameSyntax, TQualifiedNameSyntax, TIncompleteMemberSyntax, TLambdaExpressionSyntax> : DiagnosticAnalyzer, IBuiltInAnalyzer
where TLanguageKindEnum : struct
where TSimpleNameSyntax : SyntaxNode
where TQualifiedNameSyntax : SyntaxNode
where TIncompleteMemberSyntax : SyntaxNode
where TLambdaExpressionSyntax : SyntaxNode
{
protected abstract DiagnosticDescriptor DiagnosticDescriptor { get; }
protected abstract DiagnosticDescriptor DiagnosticDescriptor2 { get; }
protected abstract ImmutableArray<TLanguageKindEnum> SyntaxKindsOfInterest { get; }
protected abstract bool ConstructorDoesNotExist(SyntaxNode node, SymbolInfo info, SemanticModel semanticModel);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get
{
return ImmutableArray.Create(DiagnosticDescriptor);
return ImmutableArray.Create(DiagnosticDescriptor, DiagnosticDescriptor2);
}
}
......@@ -29,7 +32,7 @@ public override void Initialize(AnalysisContext context)
context.RegisterSyntaxNodeAction(AnalyzeNode, this.SyntaxKindsOfInterest.ToArray());
}
protected DiagnosticDescriptor GetDiagnosticDescriptor(string id, string messageFormat)
protected DiagnosticDescriptor GetDiagnosticDescriptor(string id, LocalizableString messageFormat)
{
// it is not configurable diagnostic, title doesn't matter
return new DiagnosticDescriptor(
......@@ -42,19 +45,27 @@ protected DiagnosticDescriptor GetDiagnosticDescriptor(string id, string message
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var member = (TIncompleteMemberSyntax)context.Node;
if ((context.Node is TLambdaExpressionSyntax && context.Node.ContainsDiagnostics) || context.Node is TIncompleteMemberSyntax)
{
ReportUnboundIdentifierNames(context, context.Node);
}
}
private void ReportUnboundIdentifierNames(SyntaxNodeAnalysisContext context, SyntaxNode member)
{
Func<SyntaxNode, bool> isQualifiedOrSimpleName = (SyntaxNode n) => n is TQualifiedNameSyntax || n is TSimpleNameSyntax;
var typeNames = member.DescendantNodes().Where(n => isQualifiedOrSimpleName(n) && !n.Span.IsEmpty);
foreach (var typeName in typeNames)
{
var info = context.SemanticModel.GetSymbolInfo(typeName);
if (info.Symbol != null || info.CandidateSymbols.Length > 0)
if (info.Symbol == null && info.CandidateSymbols.Length == 0)
{
continue;
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptor, typeName.GetLocation(), typeName.ToString()));
}
else if (ConstructorDoesNotExist(typeName, info, context.SemanticModel))
{
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptor2, typeName.GetLocation(), typeName.ToString()));
}
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptor, typeName.GetLocation(), typeName.ToString()));
}
}
}
......
......@@ -253,7 +253,7 @@
<Compile Include="Completion\Rules\ICompletionRules.cs" />
<Compile Include="Diagnostics\EngineV1\AbstractSyntaxNodeAnalyzerService.cs" />
<Compile Include="Diagnostics\Analyzers\RudeEditUserDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\AddImportDiagnosticAnalyzerBase.cs" />
<Compile Include="Diagnostics\Analyzers\UnboundIdentifiersDiagnosticAnalyzerBase.cs" />
<Compile Include="Diagnostics\Analyzers\IDocumentDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\IProjectDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs" />
......
......@@ -335,7 +335,7 @@
<Compile Include="Completion\KeywordRecommenders\Types\BuiltInTypesKeywordRecommender.vb" />
<Compile Include="Completion\VisualBasicCompletionRules.vb" />
<Compile Include="Completion\VisualBasicCompletionService.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicAddImportDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicUnboundIdentifiersDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicRemoveUnnecessaryCastDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb" />
......
......@@ -8,7 +8,7 @@ Imports Microsoft.CodeAnalysis.CaseCorrection
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.FullyQualify
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.FullyQualify
......
......@@ -7,7 +7,7 @@ Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.GenerateMember
Imports Microsoft.CodeAnalysis.GenerateType
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateType
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.AddImport
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend NotInheritable Class VisualBasicAddImportDiagnosticAnalyzer
Inherits AddImportDiagnosticAnalyzerBase(Of SyntaxKind, SimpleNameSyntax, QualifiedNameSyntax, IncompleteMemberSyntax)
Private Const s_undefinedType1 As String = "BC30002"
Private Const s_messageFormat As String = "Type '{0}' is not defined."
Private Shared ReadOnly s_kindsOfInterest As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.IncompleteMember)
Protected Overrides ReadOnly Property SyntaxKindsOfInterest As ImmutableArray(Of SyntaxKind)
Get
Return s_kindsOfInterest
End Get
End Property
Protected Overrides ReadOnly Property DiagnosticDescriptor As DiagnosticDescriptor
Get
Return GetDiagnosticDescriptor(s_undefinedType1, s_messageFormat)
End Get
End Property
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.AddImport
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend NotInheritable Class VisualBasicUnboundIdentifiersDiagnosticAnalyzer
Inherits UnboundIdentifiersDiagnosticAnalyzerBase(Of SyntaxKind, SimpleNameSyntax, QualifiedNameSyntax, IncompleteMemberSyntax, LambdaExpressionSyntax)
Private Const s_undefinedType1 As String = "BC30002"
Private ReadOnly s_messageFormat As LocalizableString = New LocalizableResourceString(NameOf(VBFeaturesResources.ERR_UndefinedType1), VBFeaturesResources.ResourceManager, GetType(VBFeaturesResources.VBFeaturesResources))
Private Const s_undefinedType2 As String = "BC30057"
Private ReadOnly s_messageFormat2 As LocalizableString = New LocalizableResourceString(NameOf(VBFeaturesResources.ERR_TooManyArgs1), VBFeaturesResources.ResourceManager, GetType(VBFeaturesResources.VBFeaturesResources))
Private Shared ReadOnly s_kindsOfInterest As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(
SyntaxKind.IncompleteMember,
SyntaxKind.MultiLineFunctionLambdaExpression,
SyntaxKind.MultiLineSubLambdaExpression,
SyntaxKind.SingleLineFunctionLambdaExpression,
SyntaxKind.SingleLineSubLambdaExpression)
Protected Overrides ReadOnly Property SyntaxKindsOfInterest As ImmutableArray(Of SyntaxKind)
Get
Return s_kindsOfInterest
End Get
End Property
Protected Overrides ReadOnly Property DiagnosticDescriptor As DiagnosticDescriptor
Get
Return GetDiagnosticDescriptor(s_undefinedType1, s_messageFormat)
End Get
End Property
Protected Overrides ReadOnly Property DiagnosticDescriptor2 As DiagnosticDescriptor
Get
Return GetDiagnosticDescriptor(s_undefinedType2, s_messageFormat2)
End Get
End Property
Protected Overrides Function ConstructorDoesNotExist(node As SyntaxNode, info As SymbolInfo, semanticModel As SemanticModel) As Boolean
Dim arguments = (TryCast(node.Parent, ObjectCreationExpressionSyntax)?.ArgumentList.Arguments)
If Not arguments.HasValue Then
Return False
End If
Dim args = arguments.Value
Dim constructors = TryCast(info.Symbol?.OriginalDefinition, INamedTypeSymbol)?.Constructors
If constructors Is Nothing Then
Return False
End If
Dim count = constructors.Value _
.WhereAsArray(Function(constructor) constructor.Parameters.Length = args.Count) _
.WhereAsArray(Function(constructor)
For index = 0 To constructor.Parameters.Length
Dim typeInfo = semanticModel.GetTypeInfo(args(index).GetExpression)
If Not constructor.Parameters(index).Type.Equals(typeInfo.ConvertedType) Then
Return False
End If
Next
Return True
End Function) _
.Length
If count = 0 Then
Return True
End If
Return False
End Function
End Class
End Namespace
......@@ -836,6 +836,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Too many arguments to &apos;{0}&apos;..
'''</summary>
Friend ReadOnly Property ERR_TooManyArgs1() As String
Get
Return ResourceManager.GetString("ERR_TooManyArgs1", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Type &apos;{0}&apos; is not defined..
'''</summary>
Friend ReadOnly Property ERR_UndefinedType1() As String
Get
Return ResourceManager.GetString("ERR_UndefinedType1", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Simulates the occurrence of an error..
'''</summary>
......
......@@ -1140,19 +1140,19 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value>
</data>
<data name="OptionStatement" xml:space="preserve">
<value>option</value>
<comment>{Locked}</comment>
<comment>{Locked}</comment>
</data>
<data name="ImportStatement" xml:space="preserve">
<value>import</value>
<comment>{Locked}</comment>
<comment>{Locked}</comment>
</data>
<data name="StructureStatement" xml:space="preserve">
<value>structure</value>
<comment>{Locked}</comment>
<comment>{Locked}</comment>
</data>
<data name="ModuleStatement" xml:space="preserve">
<value>module</value>
<comment>{Locked}</comment>
<comment>{Locked}</comment>
</data>
<data name="WithEventsFieldStatement" xml:space="preserve">
<value>WithEvents field</value>
......@@ -1172,4 +1172,10 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value>
<data name="AttributeList" xml:space="preserve">
<value>attributes</value>
</data>
<data name="ERR_TooManyArgs1" xml:space="preserve">
<value>Too many arguments to '{0}'.</value>
</data>
<data name="ERR_UndefinedType1" xml:space="preserve">
<value>Type '{0}' is not defined.</value>
</data>
</root>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册