提交 43d413f6 编写于 作者: J Jonathon Marolf 提交者: GitHub

Merge pull request #21027 from dotnet/merges/master-to-features/ioperation-20170721-070014

Merge master to features/ioperation
......@@ -1313,6 +1313,7 @@ private BoundExpression BindDefaultExpression(DefaultExpressionSyntax node, Diag
{
if (node.IsKind(SyntaxKind.IdentifierName) && FallBackOnDiscard((IdentifierNameSyntax)node, diagnostics))
{
lookupResult.Free();
return new BoundDiscardExpression(node, type: null);
}
......
......@@ -395,11 +395,6 @@ internal static bool IsStatementExpression(SyntaxNode syntax)
case IdentifierName:
return syntax.IsMissing;
// TODO: The native implementation also disallows delegate
// creation expressions with the ERR_IllegalStatement error,
// so that needs to go into the semantic analysis somewhere
// if we intend to carry it forward.
default:
return false;
}
......
......@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Metadata.PE
......@@ -733,7 +734,7 @@ public void GenericsClosedOverLocalTypes1()
Assert.IsType<NoPiaIllegalGenericInstantiationSymbol>(localTypes3.GetMembers("Test6").OfType<MethodSymbol>().Single().ReturnType);
}
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void GenericsClosedOverLocalTypes2()
{
var mscorlibRef = TestReferences.NetFx.v4_0_21006.mscorlib;
......
......@@ -171,7 +171,7 @@ struct Name5 {}
}
[WorkItem(527531, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527531")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/18985")]
[Fact]
public void InterfaceName()
{
var text = @"
......
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddAccessibilityModifiers
{
public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new CSharpAddAccessibilityModifiersDiagnosticAnalyzer(), new CSharpAddAccessibilityModifiersCodeFixProvider());
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestAllConstructs()
{
await TestInRegularAndScriptAsync(
@"
namespace Outer
{
namespace Inner1.Inner2
{
class {|FixAllInDocument:C|}
{
class NestedClass { }
struct NestedStruct { }
int f1;
int f2, f3;
public int f4;
event Action e1, e2;
public event Action e3;
event Action e4 { add { } remove { } }
public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } }
static C() { }
C() { }
public C(int i) { }
~C() { }
void M1() { }
public void M2() { }
void I.M3() { }
partial void M4() { }
int P1 { get; }
public int P2 { get; }
int I.P3 { get; }
int this[int i] { get; }
public int this[string s] { get; }
int I.this[bool b] { get; }
}
interface I
{
event Action e6;
void M3();
int P3 { get; }
int this[bool b] { get; }
}
delegate void D();
enum E
{
EMember
}
}
}",
@"
namespace Outer
{
namespace Inner1.Inner2
{
internal class {|FixAllInDocument:C|}
{
private class NestedClass { }
private struct NestedStruct { }
private int f1;
private int f2, f3;
public int f4;
private event Action e1, e2;
public event Action e3;
private event Action e4 { add { } remove { } }
public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } }
static C() { }
private C() { }
public C(int i) { }
~C() { }
private void M1() { }
public void M2() { }
void I.M3() { }
partial void M4() { }
private int P1 { get; }
public int P2 { get; }
int I.P3 { get; }
private int this[int i] { get; }
public int this[string s] { get; }
int I.this[bool b] { get; }
}
internal interface I
{
event Action e6;
void M3();
int P3 { get; }
int this[bool b] { get; }
}
internal delegate void D();
internal enum E
{
EMember
}
}
}");
}
}
}
......@@ -458,5 +458,137 @@ private void Foo()
}",
ignoreTrivia: false);
}
[WorkItem(20973, "https://github.com/dotnet/roslyn/issues/20973")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
public async Task TestNullArg1()
{
await TestInRegularAndScriptAsync(
@"
class C
{
public C(int i) { }
}
class D
{
void M()
{
new [|C|](null, 1);
}
}",
@"
class C
{
public C(object p, int i) { }
}
class D
{
void M()
{
new C(null, 1);
}
}");
}
[WorkItem(20973, "https://github.com/dotnet/roslyn/issues/20973")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
public async Task TestNullArg2()
{
await TestInRegularAndScriptAsync(
@"
class C
{
public C(string s) { }
}
class D
{
void M()
{
new [|C|](null, 1);
}
}",
@"
class C
{
public C(string s, int v) { }
}
class D
{
void M()
{
new C(null, 1);
}
}");
}
[WorkItem(20973, "https://github.com/dotnet/roslyn/issues/20973")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
public async Task TestDefaultArg1()
{
await TestInRegularAndScriptAsync(
@"
class C
{
public C(int i) { }
}
class D
{
void M()
{
new [|C|](default, 1);
}
}",
@"
class C
{
public C(int i, int v) { }
}
class D
{
void M()
{
new C(default, 1);
}
}");
}
[WorkItem(20973, "https://github.com/dotnet/roslyn/issues/20973")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
public async Task TestDefaultArg2()
{
await TestInRegularAndScriptAsync(
@"
class C
{
public C(string s) { }
}
class D
{
void M()
{
new [|C|](default, 1);
}
}",
@"
class C
{
public C(string s, int v) { }
}
class D
{
void M()
{
new C(default, 1);
}
}");
}
}
}
......@@ -761,6 +761,42 @@ class C {
await VerifyNotBuilderAsync(markup);
}
[WorkItem(20937, "https://github.com/dotnet/roslyn/issues/20937")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task AsyncLambda()
{
var markup = @"
using System;
using System.Threading.Tasks;
class Program
{
public void B(Func<int, int, Task<int>> f) { }
void A()
{
B(async($$";
await VerifyBuilderAsync(markup);
}
[WorkItem(20937, "https://github.com/dotnet/roslyn/issues/20937")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task AsyncLambdaAfterComma()
{
var markup = @"
using System;
using System.Threading.Tasks;
class Program
{
public void B(Func<int, int, Task<int>> f) { }
void A()
{
B(async(p1, $$";
await VerifyBuilderAsync(markup);
}
private async Task VerifyNotBuilderAsync(string markup)
{
await VerifyWorkerAsync(markup, isBuilder: false);
......
......@@ -155,6 +155,297 @@ static void Main2(string[] args)
Console.WriteLine(""Their section"");
}
}
}", index: 2, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestEmptyTop_TakeTop()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
=======
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
}", index: 0, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestEmptyTop_TakeBottom()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
=======
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
}", index: 1, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestEmptyBottom_TakeTop()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
=======
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
}", index: 0, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestEmptyBottom_TakeBottom()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
=======
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
}", index: 1, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestTakeTop_WhitespaceInSection()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
=======
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
}", index: 0, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestTakeBottom1_WhitespaceInSection()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
=======
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
}", index: 1, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsResolveConflictMarker)]
public async Task TestTakeBoth_WhitespaceInSection()
{
await TestInRegularAndScript1Async(
@"
using System;
namespace N
{
[|<<<<<<<|] This is mine!
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
=======
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
>>>>>>> This is theirs!
}",
@"
using System;
namespace N
{
class Program
{
static void Main(string[] args)
{
Program p;
Console.WriteLine(""My section"");
}
}
class Program2
{
static void Main2(string[] args)
{
Program2 p;
Console.WriteLine(""Their section"");
}
}
}", index: 2, ignoreTrivia: false);
}
}
......
......@@ -10,12 +10,12 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnusedLocalFunction
{
public partial class RemoveUnusedVariableTest : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public partial class RemoveUnusedLocalFunctionTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new CSharpRemoveUnusedLocalFunctionCodeFixProvider());
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)]
public async Task RemoveUnusedLocalFunction()
{
await TestInRegularAndScriptAsync(
......@@ -34,7 +34,7 @@ void Method()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)]
public async Task RemoveUnusedLocalFunctionFixAll1()
{
await TestInRegularAndScriptAsync(
......@@ -54,7 +54,7 @@ void Method()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)]
public async Task RemoveUnusedLocalFunctionFixAll2()
{
await TestInRegularAndScriptAsync(
......@@ -74,7 +74,7 @@ void Method()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)]
public async Task RemoveUnusedLocalFunctionFixAll3()
{
await TestInRegularAndScriptAsync(
......@@ -93,7 +93,7 @@ void Method()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)]
public async Task RemoveUnusedLocalFunctionFixAll4()
{
await TestInRegularAndScriptAsync(
......@@ -112,4 +112,4 @@ void Method()
}");
}
}
}
\ No newline at end of file
}
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnusedVariable
{
public partial class RemoveUnusedVariableTest : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public partial class RemoveUnusedVariableTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new CSharpRemoveUnusedVariableCodeFixProvider());
......@@ -205,5 +205,59 @@ void Method()
}
}");
}
[WorkItem(20987, "https://github.com/dotnet/roslyn/issues/20987")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)]
public async Task LeadingDirectives()
{
await TestInRegularAndScriptAsync(
@"
#define NET461
using System;
namespace ClassLibrary
{
public class Class1
{
public static string GetText()
{
#if NET461
return ""Hello from "" + Environment.OSVersion;
#elif NETSTANDARD1_4
return ""Hello from .NET Standard"";
#else
#error Unknown platform
#endif
int [|blah|] = 5;
}
}
}",
@"
#define NET461
using System;
namespace ClassLibrary
{
public class Class1
{
public static string GetText()
{
#if NET461
return ""Hello from "" + Environment.OSVersion;
#elif NETSTANDARD1_4
return ""Hello from .NET Standard"";
#else
#error Unknown platform
#endif
}
}
}", ignoreTrivia: false);
}
#if false
#endif
}
}
\ 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;
namespace Microsoft.VisualStudio.LanguageServices.Implementation
{
/// <summary>
/// Mock to make test project build
/// </summary>
internal class WatsonReporter
{
public static void Report(string description, Exception exception, Func<IFaultUtility, int> callback)
{
// do nothing
}
public interface IFaultUtility
{
void AddProcessDump(int pid);
void AddFile(string fullpathname);
}
}
}
......@@ -32,6 +32,7 @@ public static class Features
public const string CodeActionsAddDocCommentNodes = "CodeActions.AddDocCommentParamNodes";
public const string CodeActionsAddAwait = "CodeActions.AddAwait";
public const string CodeActionsUpgradeProject = "CodeActions.UpgradeProject";
public const string CodeActionsAddAccessibilityModifiers = "CodeActions.AddAccessibilityModifiers";
public const string CodeActionsAddBraces = "CodeActions.AddBraces";
public const string CodeActionsAddImport = "CodeActions.AddImport";
public const string CodeActionsAddMissingReference = "CodeActions.AddMissingReference";
......
' 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 Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.AddAccessibilityModifiers
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.AddAccessibilityModifiers
Public Class AddAccessibilityModifiersTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As (DiagnosticAnalyzer, CodeFixProvider)
Return (New VisualBasicAddAccessibilityModifiersDiagnosticAnalyzer(),
New VisualBasicAddAccessibilityModifiersCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)>
Public Async Function TestAllConstructs() As Task
Await TestInRegularAndScriptAsync(
"
namespace N
namespace Outer.Inner
class {|FixAllInDocument:C|}
class NestedClass
end class
structure NestedStruct
end structure
dim f1 as integer
dim f2, f3 as integer
dim f4, f5 as integer, f6, f7 as boolean
public f4 as integer
event e1 as Action
public event e2 as Action
custom event e4 as Action
end event
shared sub new()
end sub
sub new()
end sub
public sub new(i as integer)
end sub
sub M1()
end sub
public sub M2()
end sub
function M3() as integer
end function
function M4() as integer
public function M5() as integer
end function
partial sub M6()
end sub
property P1 as integer
property P2 as integer
get
end get
end property
public property P3 as integer
shared operator &(c1 as C, c2 as C) as integer
end operator
end class
interface I
event e6 as Action
sub M3()
function M4() as integer
property P3 as integer
end interface
delegate sub D1()
delegate function D2() as integer
enum E
EMember
end enum
structure S
dim f as integer
sub M()
end sub()
shared operator &(c1 as S, c2 as S) as integer
end operator
end structure
module M
dim f as integer
sub M()
end sub()
end module
end namespace
end namespace",
"
namespace N
namespace Outer.Inner
Friend class C
Public class NestedClass
end class
Public structure NestedStruct
end structure
Private f1 as integer
Private f2, f3 as integer
Private f4, f5 as integer, f6, f7 as boolean
public f4 as integer
Public event e1 as Action
public event e2 as Action
Public custom event e4 as Action
end event
shared sub new()
end sub
Public sub new()
end sub
public sub new(i as integer)
end sub
Public sub M1()
end sub
public sub M2()
end sub
Public function M3() as integer
end function
Public function M4() as integer
public function M5() as integer
end function
Public partial sub M6()
end sub
Public property P1 as integer
Public property P2 as integer
get
end get
end property
public property P3 as integer
Public shared operator &(c1 as C, c2 as C) as integer
end operator
end class
Friend interface I
event e6 as Action
sub M3()
function M4() as integer
property P3 as integer
end interface
Friend delegate sub D1()
Friend delegate function D2() as integer
Friend enum E
EMember
end enum
Friend structure S
Public f as integer
Public sub M()
end sub()
Public shared operator &(c1 as S, c2 as S) as integer
end operator
end structure
Friend module M
Private f as integer
Public sub M()
end sub()
end module
end namespace
end namespace")
End Function
End Class
End Namespace
......@@ -54,6 +54,34 @@ class D
end class")
End Function
<WorkItem(20973, "https://github.com/dotnet/roslyn/issues/20973")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)>
Public Async Function TestNothingArgument1() As Task
Await TestInRegularAndScriptAsync(
"
class C
public sub new(i as integer)
end sub
end class
class D
sub M()
dim a = new C(nothing, [|1|])
end sub
end class",
"
class C
public sub new(i as integer, v As Integer)
end sub
end class
class D
sub M()
dim a = new C(nothing, 1)
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)>
Public Async Function TestNamedArg() As Task
Await TestInRegularAndScriptAsync(
......
// 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.Composition;
using System.Diagnostics;
using Microsoft.CodeAnalysis.AddAccessibilityModifiers;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class CSharpAddAccessibilityModifiersCodeFixProvider : AbstractAddAccessibilityModifiersCodeFixProvider
{
protected override SyntaxNode MapToDeclarator(SyntaxNode node)
{
switch (node)
{
case FieldDeclarationSyntax field:
return field.Declaration.Variables[0];
case EventFieldDeclarationSyntax eventField:
return eventField.Declaration.Variables[0];
default:
return node;
}
}
}
}
// 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.Collections.Immutable;
using Microsoft.CodeAnalysis.AddAccessibilityModifiers;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
namespace Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class CSharpAddAccessibilityModifiersDiagnosticAnalyzer
: AbstractAddAccessibilityModifiersDiagnosticAnalyzer<CompilationUnitSyntax>
{
public CSharpAddAccessibilityModifiersDiagnosticAnalyzer()
{
}
protected override void ProcessCompilationUnit(
SyntaxTreeAnalysisContext context, SyntaxGenerator generator,
CodeStyleOption<AccessibilityModifiersRequired> option, CompilationUnitSyntax compilationUnit)
{
ProcessMembers(context, generator, option, compilationUnit.Members);
}
private void ProcessMembers(
SyntaxTreeAnalysisContext context, SyntaxGenerator generator,
CodeStyleOption<AccessibilityModifiersRequired> option,
SyntaxList<MemberDeclarationSyntax> members)
{
foreach (var memberDeclaration in members)
{
ProcessMemberDeclaration(context, generator, option, memberDeclaration);
}
}
private void ProcessMemberDeclaration(
SyntaxTreeAnalysisContext context, SyntaxGenerator generator,
CodeStyleOption<AccessibilityModifiersRequired> option, MemberDeclarationSyntax member)
{
if (member.IsKind(SyntaxKind.NamespaceDeclaration, out NamespaceDeclarationSyntax namespaceDeclaration))
{
ProcessMembers(context, generator, option, namespaceDeclaration.Members);
}
// If we have a class or struct, recurse inwards.
if (member.IsKind(SyntaxKind.ClassDeclaration, out TypeDeclarationSyntax typeDeclaration) ||
member.IsKind(SyntaxKind.StructDeclaration, out typeDeclaration))
{
ProcessMembers(context, generator, option, typeDeclaration.Members);
}
#if false
// Add this once we have the language version for C# that supports accessibility
// modifiers on interface methods.
if (option.Value == AccessibilityModifiersRequired.Always &&
member.IsKind(SyntaxKind.InterfaceDeclaration, out typeDeclaration))
{
// Only recurse into an interface if the user wants accessibility modifiers on
ProcessTypeDeclaration(context, generator, option, typeDeclaration);
}
#endif
// Have to have a name to report the issue on.
var name = member.GetNameToken();
if (name.Kind() == SyntaxKind.None)
{
return;
}
// Certain members never have accessibility. Don't bother reporting on them.
if (!generator.CanHaveAccessibility(member))
{
return;
}
// If they already have accessibility, no need to report anything.
var accessibility = generator.GetAccessibility(member);
if (accessibility != Accessibility.NotApplicable)
{
return;
}
// Missing accessibility. Report issue to user.
var additionalLocations = ImmutableArray.Create(member.GetLocation());
context.ReportDiagnostic(Diagnostic.Create(
CreateDescriptorWithSeverity(option.Notification.Value),
name.GetLocation(),
additionalLocations: additionalLocations));
}
}
}
using System;
// 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.Immutable;
using System.Composition;
using System.Linq;
......
......@@ -168,6 +168,19 @@ private bool IsLambdaExpression(SemanticModel semanticModel, int position, Synta
return false;
}
// async lambda:
// Foo(async($$
// Foo(async(p1, $$
if (token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.CommaToken) && token.Parent.IsKind(SyntaxKind.ArgumentList)
&& token.Parent.Parent is InvocationExpressionSyntax invocation
&& invocation.Expression is IdentifierNameSyntax identifier)
{
if (identifier.Identifier.IsKindOrHasMatchingText(SyntaxKind.AsyncKeyword))
{
return true;
}
}
// If we're an argument to a function with multiple overloads,
// open the builder if any overload takes a delegate at our argument position
var inferredTypeInfo = typeInferrer.GetTypeInferenceInfo(semanticModel, position, cancellationToken: cancellationToken);
......
......@@ -24,8 +24,5 @@ protected override bool IsDisabledText(SyntaxTrivia trivia)
protected override bool IsEndOfLine(SyntaxTrivia trivia)
=> trivia.Kind() == SyntaxKind.EndOfLineTrivia;
protected override bool IsNewLine(char ch)
=> SyntaxFacts.IsNewLine(ch);
}
}
// 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.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddAccessibilityModifiers
{
internal abstract class AbstractAddAccessibilityModifiersCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
protected abstract SyntaxNode MapToDeclarator(SyntaxNode declaration);
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.AddAccessibilityModifiersDiagnosticId);
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
var priority = diagnostic.Severity == DiagnosticSeverity.Hidden
? CodeActionPriority.Low
: CodeActionPriority.Medium;
context.RegisterCodeFix(
new MyCodeAction(priority, c => FixAsync(context.Document, context.Diagnostics.First(), c)),
context.Diagnostics);
return SpecializedTasks.EmptyTask;
}
protected sealed override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in diagnostics)
{
var declaration = diagnostic.AdditionalLocations[0].FindNode(cancellationToken);
var declarator = MapToDeclarator(declaration);
var symbol = semanticModel.GetDeclaredSymbol(declarator, cancellationToken);
editor.ReplaceNode(
declaration,
(currentDeclaration, generator) =>
{
return generator.WithAccessibility(currentDeclaration, symbol.DeclaredAccessibility);
});
}
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(CodeActionPriority priority, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(FeaturesResources.Add_accessibility_modifiers, createChangedDocument, FeaturesResources.Add_accessibility_modifiers)
{
this.Priority = priority;
}
internal override CodeActionPriority Priority { get; }
}
}
}
// 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.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
namespace Microsoft.CodeAnalysis.AddAccessibilityModifiers
{
internal abstract class AbstractAddAccessibilityModifiersDiagnosticAnalyzer<TCompilationUnitSyntax>
: AbstractCodeStyleDiagnosticAnalyzer
where TCompilationUnitSyntax : SyntaxNode
{
protected AbstractAddAccessibilityModifiersDiagnosticAnalyzer()
: base(IDEDiagnosticIds.AddAccessibilityModifiersDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Add_accessibility_modifiers), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Accessibility_modifiers_required), FeaturesResources.ResourceManager, typeof(FeaturesResources)))
{
}
public sealed override DiagnosticAnalyzerCategory GetAnalyzerCategory()
=> DiagnosticAnalyzerCategory.SyntaxAnalysis;
public sealed override bool OpenFileOnly(Workspace workspace)
=> false;
protected sealed override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree);
private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
{
var cancellationToken = context.CancellationToken;
var syntaxTree = context.Tree;
var workspaceAnalyzerOptions = context.Options as WorkspaceAnalyzerOptions;
if (workspaceAnalyzerOptions == null)
{
return;
}
var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();
if (optionSet == null)
{
return;
}
var language = syntaxTree.Options.Language;
var option = optionSet.GetOption(CodeStyleOptions.RequireAccessibilityModifiers, language);
if (option.Value == AccessibilityModifiersRequired.Never)
{
return;
}
var generator = SyntaxGenerator.GetGenerator(workspaceAnalyzerOptions.Services.Workspace, language);
ProcessCompilationUnit(context, generator, option, (TCompilationUnitSyntax)syntaxTree.GetRoot(cancellationToken));
}
protected abstract void ProcessCompilationUnit(SyntaxTreeAnalysisContext context, SyntaxGenerator generator, CodeStyleOption<AccessibilityModifiersRequired> option, TCompilationUnitSyntax compilationUnitSyntax);
}
}
......@@ -440,19 +440,27 @@ private int NonParamsParameterCount(IMethodSymbol method)
// Now check the type of the argument versus the type of the parameter. If they
// don't match, then this is the argument we should make the parameter for.
var argumentTypeInfo = semanticModel.GetTypeInfo(syntaxFacts.GetExpressionOfArgument(argument));
var expressionOfArgumment = syntaxFacts.GetExpressionOfArgument(argument);
var argumentTypeInfo = semanticModel.GetTypeInfo(expressionOfArgumment);
var isNullLiteral = syntaxFacts.IsNullLiteralExpression(expressionOfArgumment);
var isDefaultLiteral = syntaxFacts.IsDefaultLiteralExpression(expressionOfArgumment);
if (argumentTypeInfo.Type == null && argumentTypeInfo.ConvertedType == null)
{
// Didn't know the type of the argument. We shouldn't assume it doesn't
// match a parameter.
continue;
// match a parameter. However, if the user wrote 'null' and it didn't
// match anything, then this is the problem argument.
if (!isNullLiteral && !isDefaultLiteral)
{
continue;
}
}
var parameter = method.Parameters[i];
if (!TypeInfoMatchesType(argumentTypeInfo, parameter.Type))
if (!TypeInfoMatchesType(argumentTypeInfo, parameter.Type, isNullLiteral, isDefaultLiteral))
{
if (TypeInfoMatchesWithParamsExpansion(argumentTypeInfo, parameter))
if (TypeInfoMatchesWithParamsExpansion(argumentTypeInfo, parameter, isNullLiteral, isDefaultLiteral))
{
// The argument matched if we expanded out the params-parameter.
// As the params-parameter has to be last, there's nothing else to
......@@ -468,11 +476,13 @@ private int NonParamsParameterCount(IMethodSymbol method)
return null;
}
private bool TypeInfoMatchesWithParamsExpansion(TypeInfo argumentTypeInfo, IParameterSymbol parameter)
private bool TypeInfoMatchesWithParamsExpansion(
TypeInfo argumentTypeInfo, IParameterSymbol parameter,
bool isNullLiteral, bool isDefaultLiteral)
{
if (parameter.IsParams && parameter.Type is IArrayTypeSymbol arrayType)
{
if (TypeInfoMatchesType(argumentTypeInfo, arrayType.ElementType))
if (TypeInfoMatchesType(argumentTypeInfo, arrayType.ElementType, isNullLiteral, isDefaultLiteral))
{
return true;
}
......@@ -481,8 +491,27 @@ private bool TypeInfoMatchesWithParamsExpansion(TypeInfo argumentTypeInfo, IPara
return false;
}
private bool TypeInfoMatchesType(TypeInfo argumentTypeInfo, ITypeSymbol type)
=> type.Equals(argumentTypeInfo.Type) || type.Equals(argumentTypeInfo.ConvertedType);
private bool TypeInfoMatchesType(
TypeInfo argumentTypeInfo, ITypeSymbol type,
bool isNullLiteral, bool isDefaultLiteral)
{
if (type.Equals(argumentTypeInfo.Type) || type.Equals(argumentTypeInfo.ConvertedType))
{
return true;
}
if (isDefaultLiteral)
{
return true;
}
if (isNullLiteral)
{
return type.IsReferenceType || type.IsNullable();
}
return false;
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
......
......@@ -18,7 +18,6 @@ protected AbstractResolveConflictMarkerCodeFixProvider(string diagnosticId)
FixableDiagnosticIds = ImmutableArray.Create(diagnosticId);
}
protected abstract bool IsNewLine(char ch);
protected abstract bool IsEndOfLine(SyntaxTrivia trivia);
protected abstract bool IsDisabledText(SyntaxTrivia trivia);
protected abstract bool IsConflictMarker(SyntaxTrivia trivia);
......@@ -45,12 +44,6 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
while (true)
{
token = token.GetNextToken(includeZeroWidth: true);
if (token.RawKind == 0)
{
return;
}
var index = GetEqualsConflictMarkerIndex(text, token);
if (index >= 0)
{
......@@ -58,6 +51,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (index + 3 < token.LeadingTrivia.Count)
{
// normal case where there us =====, then dead code, then >>>>>>
var equalsTrivia = leadingTrivia[index];
var endOfLineTrivia = leadingTrivia[index + 1];
var disabledTrivia = leadingTrivia[index + 2];
......@@ -67,105 +62,119 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
IsDisabledText(disabledTrivia) &&
IsConflictMarker(text, endTrivia, '>'))
{
var topText = startTrivia.ToString().Substring(s_mergeConflictLength).Trim();
var takeTopText = string.IsNullOrWhiteSpace(topText)
? FeaturesResources.Take_top
: string.Format(FeaturesResources.Take_0, topText);
var bottomText = endTrivia.ToString().Substring(s_mergeConflictLength).Trim();
var takeBottomText = string.IsNullOrWhiteSpace(bottomText)
? FeaturesResources.Take_bottom
: string.Format(FeaturesResources.Take_0, bottomText);
var startSpan = startTrivia.Span;
var equalsSpan = equalsTrivia.Span;
var endSpan = endTrivia.Span;
context.RegisterCodeFix(
new MyCodeAction(takeTopText,
c => TakeTopAsync(document, startSpan, equalsSpan, endSpan, c)),
context.Diagnostics);
context.RegisterCodeFix(
new MyCodeAction(takeBottomText,
c => TakeBottomAsync(document, startSpan, equalsSpan, endSpan, c)),
context.Diagnostics);
context.RegisterCodeFix(
new MyCodeAction(FeaturesResources.Take_both,
c => TakeBothAsync(document, startSpan, equalsSpan, endSpan, c)),
context.Diagnostics);
RegisterCodeFixes(context, startTrivia, equalsTrivia, endTrivia);
return;
}
}
if (index + 2 < token.LeadingTrivia.Count)
{
// case where there is ===== followed by >>>>>> on the next line.
var equalsTrivia = leadingTrivia[index];
var endOfLineTrivia = leadingTrivia[index + 1];
var endTrivia = leadingTrivia[index + 2];
if (IsEndOfLine(endOfLineTrivia) &&
IsConflictMarker(text, endTrivia, '>'))
{
RegisterCodeFixes(context, startTrivia, equalsTrivia, endTrivia);
return;
}
}
}
token = token.GetNextToken(includeZeroWidth: true);
if (token.RawKind == 0)
{
return;
}
}
}
private void RegisterCodeFixes(
CodeFixContext context, SyntaxTrivia startTrivia, SyntaxTrivia equalsTrivia, SyntaxTrivia endTrivia)
{
var document = context.Document;
var topText = startTrivia.ToString().Substring(s_mergeConflictLength).Trim();
var takeTopText = string.IsNullOrWhiteSpace(topText)
? FeaturesResources.Take_top
: string.Format(FeaturesResources.Take_0, topText);
var bottomText = endTrivia.ToString().Substring(s_mergeConflictLength).Trim();
var takeBottomText = string.IsNullOrWhiteSpace(bottomText)
? FeaturesResources.Take_bottom
: string.Format(FeaturesResources.Take_0, bottomText);
var startPos = startTrivia.SpanStart;
var equalsPos = equalsTrivia.SpanStart;
var endPos = endTrivia.SpanStart;
context.RegisterCodeFix(
new MyCodeAction(takeTopText,
c => TakeTopAsync(document, startPos, equalsPos, endPos, c)),
context.Diagnostics);
context.RegisterCodeFix(
new MyCodeAction(takeBottomText,
c => TakeBottomAsync(document, startPos, equalsPos, endPos, c)),
context.Diagnostics);
context.RegisterCodeFix(
new MyCodeAction(FeaturesResources.Take_both,
c => TakeBothAsync(document, startPos, equalsPos, endPos, c)),
context.Diagnostics);
}
private async Task<Document> TakeTopAsync(
Document document, TextSpan startSpan, TextSpan equalsSpan, TextSpan endSpan,
Document document, int startPos, int equalsPos, int endPos,
CancellationToken cancellationToken)
{
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var bottomEnd = GetEndIncludingNewLines(text, endSpan.End);
var newText = text.Replace(TextSpan.FromBounds(equalsSpan.Start, bottomEnd), "");
var bottomEnd = GetEndIncludingLineBreak(text, endPos);
var newText = text.Replace(TextSpan.FromBounds(equalsPos, bottomEnd), "");
var startEnd = GetEndIncludingNewLines(text, startSpan.End);
var finaltext = newText.Replace(TextSpan.FromBounds(startSpan.Start, startEnd), "");
var startEnd = GetEndIncludingLineBreak(text, startPos);
var finaltext = newText.Replace(TextSpan.FromBounds(startPos, startEnd), "");
return document.WithText(finaltext);
}
private async Task<Document> TakeBottomAsync(
Document document, TextSpan startSpan, TextSpan equalsSpan, TextSpan endSpan,
Document document, int startPos, int equalsPos, int endPos,
CancellationToken cancellationToken)
{
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var bottomEnd = GetEndIncludingNewLines(text, endSpan.End);
var newText = text.Replace(TextSpan.FromBounds(endSpan.Start, bottomEnd), "");
var bottomEnd = GetEndIncludingLineBreak(text, endPos);
var newText = text.Replace(TextSpan.FromBounds(endPos, bottomEnd), "");
var equalsEnd = GetEndIncludingNewLines(text, equalsSpan.End);
var finaltext = newText.Replace(TextSpan.FromBounds(startSpan.Start, equalsEnd), "");
var equalsEnd = GetEndIncludingLineBreak(text, equalsPos);
var finaltext = newText.Replace(TextSpan.FromBounds(startPos, equalsEnd), "");
return document.WithText(finaltext);
}
private async Task<Document> TakeBothAsync(
Document document,
TextSpan startSpan, TextSpan equalsSpan, TextSpan endSpan,
Document document, int startPos, int equalsPos, int endPos,
CancellationToken cancellationToken)
{
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var bottomEnd = GetEndIncludingNewLines(text, endSpan.End);
var newText = text.Replace(TextSpan.FromBounds(endSpan.Start, bottomEnd), "");
var bottomEnd = GetEndIncludingLineBreak(text, endPos);
var newText = text.Replace(TextSpan.FromBounds(endPos, bottomEnd), "");
var equalsEnd = GetEndIncludingNewLines(text, equalsSpan.End);
newText = newText.Replace(TextSpan.FromBounds(equalsSpan.Start, equalsEnd), "");
var equalsEnd = GetEndIncludingLineBreak(text, equalsPos);
newText = newText.Replace(TextSpan.FromBounds(equalsPos, equalsEnd), "");
var startEnd = GetEndIncludingNewLines(text, startSpan.End);
var finaltext = newText.Replace(TextSpan.FromBounds(startSpan.Start, startEnd), "");
var startEnd = GetEndIncludingLineBreak(text, startPos);
var finaltext = newText.Replace(TextSpan.FromBounds(startPos, startEnd), "");
return document.WithText(finaltext);
}
private int GetEndIncludingNewLines(SourceText text, int position)
{
var endPosition = position;
// Skip the text until we get to the newlines.
while (endPosition < text.Length && !IsNewLine(text[endPosition]))
{
endPosition++;
}
// Skip the newlines.
while (endPosition < text.Length && IsNewLine(text[endPosition]))
{
endPosition++;
}
return endPosition;
}
private int GetEndIncludingLineBreak(SourceText text, int position)
=> text.Lines.GetLineFromPosition(position).SpanIncludingLineBreak.End;
private int GetEqualsConflictMarkerIndex(SourceText text, SyntaxToken token)
{
......
......@@ -57,6 +57,8 @@ internal static class IDEDiagnosticIds
public const string UseLocalFunctionDiagnosticId = "IDE0039";
public const string AddAccessibilityModifiersDiagnosticId = "IDE0040";
// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
......
......@@ -79,6 +79,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Accessibility modifiers required.
/// </summary>
internal static string Accessibility_modifiers_required {
get {
return ResourceManager.GetString("Accessibility_modifiers_required", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Accessing captured variable &apos;{0}&apos; that hasn&apos;t been accessed before in {1} will prevent the debug session from continuing..
/// </summary>
......@@ -98,6 +107,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Add accessibility modifiers.
/// </summary>
internal static string Add_accessibility_modifiers {
get {
return ResourceManager.GetString("Add_accessibility_modifiers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add argument name &apos;{0}&apos;.
/// </summary>
......
......@@ -1277,6 +1277,12 @@ This version used in: {2}</value>
<data name="in_0_project_1" xml:space="preserve">
<value>in {0} (project {1})</value>
</data>
<data name="Accessibility_modifiers_required" xml:space="preserve">
<value>Accessibility modifiers required</value>
</data>
<data name="Add_accessibility_modifiers" xml:space="preserve">
<value>Add accessibility modifiers</value>
</data>
<data name="Use_local_function" xml:space="preserve">
<value>Use local function</value>
</data>
......
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
......@@ -45,6 +46,7 @@ public async override Task RegisterCodeFixesAsync(CodeFixContext context)
protected override Task FixAllAsync(Document document, ImmutableArray<Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken)
{
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var root = editor.OriginalRoot;
foreach (var diagnostic in diagnostics)
{
......@@ -58,12 +60,19 @@ protected override Task FixAllAsync(Document document, ImmutableArray<Diagnostic
else
{
var variableDeclarator = token.GetAncestor<TVariableDeclarator>();
var variableDeclarators = token.GetAncestor<TVariableDeclaration>().ChildNodes().Where(x => x is TVariableDeclarator);
if (variableDeclarators.Count() == 1)
{
editor.RemoveNode(token.GetAncestor<TLocalDeclarationStatement>());
var localDeclaration = token.GetAncestor<TLocalDeclarationStatement>();
var removeOptions = SyntaxGenerator.DefaultRemoveOptions;
if (localDeclaration.GetLeadingTrivia().Contains(t => t.IsDirective))
{
removeOptions |= SyntaxRemoveOptions.KeepLeadingTrivia;
}
editor.RemoveNode(localDeclaration, removeOptions);
}
else if (variableDeclarators.Count() > 1)
{
......@@ -83,4 +92,4 @@ private class MyCodeAction : CodeAction.DocumentChangeAction
}
}
}
}
\ 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.
Imports System.Composition
Imports Microsoft.CodeAnalysis.AddAccessibilityModifiers
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.AddAccessibilityModifiers
<ExportCodeFixProvider(LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicAddAccessibilityModifiersCodeFixProvider
Inherits AbstractAddAccessibilityModifiersCodeFixProvider
Protected Overrides Function MapToDeclarator(declaration As SyntaxNode) As SyntaxNode
If TypeOf declaration Is FieldDeclarationSyntax Then
Return DirectCast(declaration, FieldDeclarationSyntax).Declarators(0).Names(0)
End If
Return declaration
End Function
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 Microsoft.CodeAnalysis.AddAccessibilityModifiers
Imports Microsoft.CodeAnalysis.CodeStyle
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.AddAccessibilityModifiers
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend Class VisualBasicAddAccessibilityModifiersDiagnosticAnalyzer
Inherits AbstractAddAccessibilityModifiersDiagnosticAnalyzer(Of CompilationUnitSyntax)
Protected Overrides Sub ProcessCompilationUnit(
context As SyntaxTreeAnalysisContext, generator As SyntaxGenerator,
[option] As CodeStyleOption(Of AccessibilityModifiersRequired), compilationUnit As CompilationUnitSyntax)
ProcessMembers(context, generator, [option], compilationUnit.Members)
End Sub
Private Sub ProcessMembers(context As SyntaxTreeAnalysisContext, generator As SyntaxGenerator,
[option] As CodeStyleOption(Of AccessibilityModifiersRequired), members As SyntaxList(Of StatementSyntax))
For Each member In members
ProcessMember(context, generator, [option], member)
Next
End Sub
Private Sub ProcessMember(context As SyntaxTreeAnalysisContext, generator As SyntaxGenerator,
[option] As CodeStyleOption(Of AccessibilityModifiersRequired), member As StatementSyntax)
If member.Kind() = SyntaxKind.NamespaceBlock Then
Dim namespaceBlock = DirectCast(member, NamespaceBlockSyntax)
ProcessMembers(context, generator, [option], namespaceBlock.Members)
End If
' If we have a class or struct or module, recurse inwards.
If member.IsKind(SyntaxKind.ClassBlock) OrElse
member.IsKind(SyntaxKind.StructureBlock) OrElse
member.IsKind(SyntaxKind.ModuleBlock) Then
Dim typeBlock = DirectCast(member, TypeBlockSyntax)
ProcessMembers(context, generator, [option], typeBlock.Members)
End If
' Have to have a name to report the issue on.
Dim name = member.GetNameToken()
If name.Kind() = SyntaxKind.None Then
Return
End If
' Certain members never have accessibility. Don't bother reporting on them.
If Not generator.CanHaveAccessibility(member) Then
Return
End If
' If they already have accessibility, no need to report anything.
Dim Accessibility = generator.GetAccessibility(member)
If Accessibility <> Accessibility.NotApplicable Then
Return
End If
' Missing accessibility. Report issue to user.
Dim additionalLocations = ImmutableArray.Create(member.GetLocation())
context.ReportDiagnostic(Diagnostic.Create(
CreateDescriptorWithSeverity([option].Notification.Value),
name.GetLocation(),
additionalLocations:=additionalLocations))
End Sub
End Class
End Namespace
......@@ -26,9 +26,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConflictMarkerResolution
Protected Overrides Function IsEndOfLine(trivia As SyntaxTrivia) As Boolean
Return trivia.Kind() = SyntaxKind.EndOfLineTrivia
End Function
Protected Overrides Function IsNewLine(ch As Char) As Boolean
Return SyntaxFacts.IsNewLine(ch)
End Function
End Class
End Namespace
......@@ -53,6 +53,19 @@ public virtual void Dispose()
#region Metadata References
/// <summary>
/// Helper for atomically acquiring and saving a metadata reference. Necessary
/// if the acquired reference will ever be used in object identity comparisons.
/// </summary>
private static MetadataReference GetOrCreateMetadataReference(ref MetadataReference field, Func<MetadataReference> getReference)
{
if (field == null)
{
Interlocked.CompareExchange(ref field, getReference(), null);
}
return field;
}
private static MetadataReference[] s_lazyDefaultVbReferences;
private static MetadataReference[] s_lazyLatestVbReferences;
......@@ -143,22 +156,10 @@ public static MetadataReference[] PortableRefsMinimal
private static MetadataReference s_systemCoreRef;
public static MetadataReference SystemCoreRef
{
get
{
if (s_systemCoreRef == null)
{
// We rely on reference equality in CreateSharedCompilation, so
// we must use a CompareExchange here.
Interlocked.CompareExchange(
ref s_systemCoreRef,
AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System_Core).GetReference(display: "System.Core.v4_0_30319.dll"),
null);
}
return s_systemCoreRef;
}
}
// We rely on reference equality in CreateSharedCompilation, so
// we must use a CompareExchange here.
=> GetOrCreateMetadataReference(ref s_systemCoreRef,
() => AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System_Core).GetReference(display: "System.Core.v4_0_30319.dll"));
private static MetadataReference s_systemCoreRef_v4_0_30319_17929;
public static MetadataReference SystemCoreRef_v4_0_30319_17929
......@@ -232,17 +233,10 @@ public static MetadataReference SystemDataRef
private static MetadataReference s_mscorlibRef;
public static MetadataReference MscorlibRef
{
get
{
if (s_mscorlibRef == null)
{
s_mscorlibRef = AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.mscorlib).GetReference(display: "mscorlib.v4_0_30319.dll");
}
return s_mscorlibRef;
}
}
// We rely on reference equality in CreateSharedCompilation, so
// we must use a CompareExchange here.
=> GetOrCreateMetadataReference(ref s_mscorlibRef,
() => AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.mscorlib).GetReference(display: "mscorlib.v4_0_30319.dll"));
private static MetadataReference s_mscorlibRefPortable;
public static MetadataReference MscorlibRefPortable
......@@ -415,22 +409,8 @@ public static MetadataReference SystemDynamicRuntimeRef
private static MetadataReference s_systemRef;
public static MetadataReference SystemRef
{
get
{
if (s_systemRef == null)
{
// We rely on reference equality in CreateSharedCompilation, so
// we must use a CompareExchange here.
Interlocked.CompareExchange(
ref s_systemRef,
AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System).GetReference(display: "System.v4_0_30319.dll"),
null);
}
return s_systemRef;
}
}
=> GetOrCreateMetadataReference(ref s_systemRef,
() => AssemblyMetadata.CreateFromImage(TestResources.NetFX.v4_0_30319.System).GetReference(display: "System.v4_0_30319.dll"));
private static MetadataReference s_systemRef_v46;
public static MetadataReference SystemRef_v46
......
......@@ -430,18 +430,64 @@ internal bool TryGetProjectByBinPath(string filePath, out AbstractProject projec
lock (_gate)
{
project = null;
if (_projectsByBinPath.TryGetValue(filePath, out var projects))
if (!_projectsByBinPath.TryGetValue(filePath, out var projects))
{
// If for some reason we have more than one referencing project, it's ambiguous so bail
if (projects.Length == 1)
// Workaround https://github.com/dotnet/roslyn/issues/20412 by checking to see if */ref/A.dll can be
// adjusted to */A.dll - only handles the default location for reference assemblies during a build.
if (!HACK_StripRefDirectoryFromPath(filePath, out string binFilePath)
|| !_projectsByBinPath.TryGetValue(binFilePath, out projects))
{
project = projects[0];
return true;
return false;
}
}
// If for some reason we have more than one referencing project, it's ambiguous so bail
if (projects.Length == 1)
{
project = projects[0];
return true;
}
return false;
}
}
private static readonly char[] s_directorySeparatorChars = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
private bool HACK_StripRefDirectoryFromPath(string filePath, out string binFilePath)
{
const string refDirectoryName = "ref";
// looking for "/ref/" where:
// 1. the first / is a directory separator
// 2. 'ref' matches in a case-insensitive comparison
// 3. the second / is the last directory separator
var lastSeparator = filePath.LastIndexOfAny(s_directorySeparatorChars);
var secondToLastSeparator = lastSeparator - refDirectoryName.Length - 1;
if (secondToLastSeparator < 0)
{
// Failed condition 3
binFilePath = null;
return false;
}
if (filePath[secondToLastSeparator] != Path.DirectorySeparatorChar
&& filePath[secondToLastSeparator] != Path.AltDirectorySeparatorChar)
{
// Failed condition 1
binFilePath = null;
return false;
}
if (string.Compare(refDirectoryName, 0, filePath, secondToLastSeparator + 1, lastSeparator - secondToLastSeparator - 1, StringComparison.OrdinalIgnoreCase) != 0)
{
// Failed condition 2
binFilePath = null;
return false;
}
binFilePath = filePath.Remove(secondToLastSeparator, lastSeparator - secondToLastSeparator);
return true;
}
/// <summary>
......
......@@ -2,12 +2,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamJsonRpc;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.VisualStudio.LanguageServices.Implementation;
using Roslyn.Utilities;
using StreamJsonRpc;
namespace Microsoft.VisualStudio.LanguageServices.Remote
{
......@@ -19,6 +22,9 @@ internal abstract class JsonRpcEx : IDisposable
{
private readonly JsonRpc _rpc;
private JsonRpcDisconnectedEventArgs _debuggingLastDisconnectReason;
private string _debuggingLastDisconnectCallstack;
public JsonRpcEx(Stream stream, object callbackTarget, bool useThisAsCallback)
{
Contract.Requires(stream != null);
......@@ -42,12 +48,9 @@ public async Task InvokeAsync(string targetName, IReadOnlyList<object> arguments
await _rpc.InvokeWithCancellationAsync(targetName, arguments, cancellationToken).ConfigureAwait(false);
}
catch
catch (Exception ex) when (ReportUnlessCanceled(ex, cancellationToken))
{
// any exception can be thrown from StreamJsonRpc if JsonRpc is disposed in the middle of read/write.
// until we move to newly added cancellation support in JsonRpc, we will catch exception and translate to
// cancellation exception here. if any exception is thrown unrelated to cancellation, then we will rethrow
// the exception
// if any exception is thrown unrelated to cancellation, then we will rethrow the exception
cancellationToken.ThrowIfCancellationRequested();
throw;
}
......@@ -61,12 +64,9 @@ public async Task<T> InvokeAsync<T>(string targetName, IReadOnlyList<object> arg
{
return await _rpc.InvokeWithCancellationAsync<T>(targetName, arguments, cancellationToken).ConfigureAwait(false);
}
catch
catch (Exception ex) when (ReportUnlessCanceled(ex, cancellationToken))
{
// any exception can be thrown from StreamJsonRpc if JsonRpc is disposed in the middle of read/write.
// until we move to newly added cancellation support in JsonRpc, we will catch exception and translate to
// cancellation exception here. if any exception is thrown unrelated to cancellation, then we will rethrow
// the exception
// if any exception is thrown unrelated to cancellation, then we will rethrow the exception
cancellationToken.ThrowIfCancellationRequested();
throw;
}
......@@ -84,6 +84,68 @@ public async Task<T> InvokeAsync<T>(string targetName, IReadOnlyList<object> arg
return Extensions.InvokeAsync(_rpc, targetName, arguments, funcWithDirectStreamAsync, cancellationToken);
}
private bool ReportUnlessCanceled(Exception ex, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return true;
}
// save extra info using NFW
ReportExtraInfoAsNFW(ex);
// make it to explicitly crash to get better info
FatalError.Report(ex);
GC.KeepAlive(_debuggingLastDisconnectReason);
GC.KeepAlive(_debuggingLastDisconnectCallstack);
return Contract.FailWithReturn<bool>("shouldn't be able to reach here");
}
private void ReportExtraInfoAsNFW(Exception ex)
{
WatsonReporter.Report("RemoteHost Failed", ex, u =>
{
try
{
// we will record dumps for all service hub processes
foreach (var p in Process.GetProcessesByName("ServiceHub.RoslynCodeAnalysisService32"))
{
// include all remote host processes
u.AddProcessDump(p.Id);
}
// include all service hub logs as well
var logPath = Path.Combine(Path.GetTempPath(), "servicehub", "logs");
if (Directory.Exists(logPath))
{
// attach all log files that are modified less than 1 day before.
var now = DateTime.UtcNow;
var oneDay = TimeSpan.FromDays(1);
foreach (var file in Directory.EnumerateFiles(logPath, "*.log"))
{
var lastWrite = File.GetLastWriteTimeUtc(file);
if (now - lastWrite > oneDay)
{
continue;
}
u.AddFile(file);
}
}
}
catch
{
// ignore issue
}
// 0 means send watson
return 0;
});
}
protected void Disconnect()
{
_rpc.Dispose();
......@@ -99,6 +161,8 @@ protected void StartListening()
protected virtual void OnDisconnected(object sender, JsonRpcDisconnectedEventArgs e)
{
// do nothing
_debuggingLastDisconnectReason = e;
_debuggingLastDisconnectCallstack = new StackTrace().ToString();
}
public void Dispose()
......
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.Shell.Interop;
using Moq;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Roslyn.VisualStudio.Next.UnitTests.Services
{
public class VisualStudioSnapshotSerializationTests : SnapshotSerializationTestBase
{
[Fact, WorkItem(466282, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/466282")]
public async Task TestUnresolvedAnalyzerReference()
{
var workspace = new AdhocWorkspace();
var project = workspace.CurrentSolution.AddProject("empty", "empty", LanguageNames.CSharp);
var mockFileChangeService = new Mock<IVsFileChangeEx>();
using (var analyzer = new VisualStudioAnalyzer(
@"PathToAnalyzer",
fileChangeService: mockFileChangeService.Object,
hostDiagnosticUpdateSource: null,
projectId: project.Id,
workspace: workspace,
loader: null,
language: project.Language))
{
var analyzerReference = analyzer.GetReference();
project = project.WithAnalyzerReferences(new AnalyzerReference[]
{
analyzerReference,
});
var checksum = await project.State.GetChecksumAsync(CancellationToken.None).ConfigureAwait(false);
Assert.NotNull(checksum);
var assetBuilder = new CustomAssetBuilder(workspace);
var serializer = new Serializer(workspace);
var asset = assetBuilder.Build(analyzerReference, CancellationToken.None);
using (var stream = SerializableBytes.CreateWritableStream())
using (var writer = new ObjectWriter(stream))
{
await asset.WriteObjectToAsync(writer, CancellationToken.None).ConfigureAwait(false);
stream.Position = 0;
using (var reader = ObjectReader.TryGetReader(stream))
{
var recovered = serializer.Deserialize<AnalyzerReference>(asset.Kind, reader, CancellationToken.None);
var assetFromStorage = assetBuilder.Build(recovered, CancellationToken.None);
Assert.Equal(asset.Checksum, assetFromStorage.Checksum);
// This won't round trip, but we should get an UnresolvedAnalyzerReference, with the same path
Assert.Equal(analyzerReference.FullPath, recovered.FullPath);
}
}
}
}
}
}
......@@ -475,6 +475,7 @@ public override SyntaxNode AsPublicInterfaceImplementation(SyntaxNode declaratio
// C# interface implementations are implicit/not-specified -- so they are just named the name as the interface member
return PreserveTrivia(declaration, d =>
{
d = WithInterfaceSpecifier(d, null);
d = this.AsImplementation(d, Accessibility.Public);
if (interfaceMemberName != null)
......@@ -482,7 +483,7 @@ public override SyntaxNode AsPublicInterfaceImplementation(SyntaxNode declaratio
d = this.WithName(d, interfaceMemberName);
}
return WithInterfaceSpecifier(d, null);
return d;
});
}
......@@ -1408,7 +1409,7 @@ private SyntaxNode AsMemberOf(SyntaxNode declaration, SyntaxNode member)
}
}
private bool CanHaveAccessibility(SyntaxNode declaration)
internal override bool CanHaveAccessibility(SyntaxNode declaration)
{
switch (declaration.Kind())
{
......@@ -1417,27 +1418,50 @@ private bool CanHaveAccessibility(SyntaxNode declaration)
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.DelegateDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.OperatorDeclaration:
case SyntaxKind.ConversionOperatorDeclaration:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.FieldDeclaration:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.IndexerDeclaration:
case SyntaxKind.EventFieldDeclaration:
case SyntaxKind.EventDeclaration:
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
return true;
case SyntaxKind.VariableDeclaration:
case SyntaxKind.VariableDeclarator:
return this.GetDeclarationKind(declaration) == DeclarationKind.Field;
case SyntaxKind.EnumMemberDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.LocalDeclarationStatement:
case SyntaxKind.DestructorDeclaration:
var declarationKind = this.GetDeclarationKind(declaration);
return declarationKind == DeclarationKind.Field || declarationKind == DeclarationKind.Event;
case SyntaxKind.ConstructorDeclaration:
// Static constructor can't have accessibility
return !((ConstructorDeclarationSyntax)declaration).Modifiers.Any(SyntaxKind.StaticKeyword);
case SyntaxKind.PropertyDeclaration:
return ((PropertyDeclarationSyntax)declaration).ExplicitInterfaceSpecifier == null;
case SyntaxKind.IndexerDeclaration:
return ((IndexerDeclarationSyntax)declaration).ExplicitInterfaceSpecifier == null;
case SyntaxKind.MethodDeclaration:
var method = (MethodDeclarationSyntax)declaration;
if (method.ExplicitInterfaceSpecifier != null)
{
// explicit interface methods can't have accessibility.
return false;
}
if (method.Modifiers.Any(SyntaxKind.PartialKeyword))
{
// partial methods can't have accessibility modifiers.
return false;
}
return true;
case SyntaxKind.EventDeclaration:
return ((EventDeclarationSyntax)declaration).ExplicitInterfaceSpecifier == null;
default:
return false;
}
......@@ -1457,7 +1481,8 @@ public override Accessibility GetAccessibility(SyntaxNode declaration)
public override SyntaxNode WithAccessibility(SyntaxNode declaration, Accessibility accessibility)
{
if (!this.CanHaveAccessibility(declaration))
if (!this.CanHaveAccessibility(declaration) &&
accessibility != Accessibility.NotApplicable)
{
return declaration;
}
......@@ -3122,9 +3147,9 @@ private static SyntaxNode WithBaseList(SyntaxNode declaration, BaseListSyntax ba
}
}
#endregion
#endregion
#region Remove, Replace, Insert
#region Remove, Replace, Insert
public override SyntaxNode ReplaceNode(SyntaxNode root, SyntaxNode declaration, SyntaxNode newDeclaration)
{
......@@ -3352,7 +3377,7 @@ private static IReadOnlyList<SyntaxNode> GetSubDeclarations(SyntaxNode declarati
case SyntaxKind.FieldDeclaration:
return ((FieldDeclarationSyntax)declaration).Declaration.Variables;
case SyntaxKind.EventFieldDeclaration:
return ((FieldDeclarationSyntax)declaration).Declaration.Variables;
return ((EventFieldDeclarationSyntax)declaration).Declaration.Variables;
case SyntaxKind.LocalDeclarationStatement:
return ((LocalDeclarationStatementSyntax)declaration).Declaration.Variables;
case SyntaxKind.VariableDeclaration:
......@@ -3461,9 +3486,9 @@ private static SyntaxNode ShiftTrivia(SyntaxNode root, SyntaxNode node)
internal override bool IsRegularOrDocComment(SyntaxTrivia trivia)
=> trivia.IsRegularOrDocComment();
#endregion
#endregion
#region Statements and Expressions
#region Statements and Expressions
public override SyntaxNode AddEventHandler(SyntaxNode @event, SyntaxNode handler)
{
......@@ -4152,6 +4177,6 @@ internal override SyntaxNode RefExpression(SyntaxNode expression)
public override SyntaxNode TupleExpression(IEnumerable<SyntaxNode> arguments)
=> SyntaxFactory.TupleExpression(SyntaxFactory.SeparatedList(arguments.Select(AsArgument)));
#endregion
#endregion
}
}
......@@ -17,6 +17,19 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
internal static partial class SyntaxNodeExtensions
{
public static bool IsKind<TNode>(this SyntaxNode node, SyntaxKind kind, out TNode result)
where TNode : SyntaxNode
{
if (node.IsKind(kind))
{
result = (TNode)node;
return true;
}
result = null;
return false;
}
public static bool IsParentKind(this SyntaxNode node, SyntaxKind kind)
{
return node != null && CodeAnalysis.CSharpExtensions.IsKind(node.Parent, kind);
......
......@@ -1541,6 +1541,9 @@ public SyntaxNode GetExpressionOfExpressionStatement(SyntaxNode node)
public bool IsNullLiteralExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.NullLiteralExpression;
public bool IsDefaultLiteralExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.DefaultLiteralExpression;
public bool IsBinaryExpression(SyntaxNode node)
=> node is BinaryExpressionSyntax;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal enum AccessibilityModifiersRequired
{
Never = 0,
Always = 1,
// Future proofing for when C# adds default interface methods. At that point
// accessibility modifiers will be allowed in interfaces, and some people may
// want to require them, while some may want to keep the traditional C# style
// that public interface members do not need accessibility modifiers.
ForNonInterfaceMembers = 2,
}
}
// 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 Microsoft.CodeAnalysis.Options;
using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers;
......@@ -132,5 +133,43 @@ public class CodeStyleOptions
storageLocations: new OptionStorageLocation[] {
EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_explicit_tuple_names"),
new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferExplicitTupleNames") });
private static readonly CodeStyleOption<AccessibilityModifiersRequired> s_requireAccessibilityModifiersDefault =
new CodeStyleOption<AccessibilityModifiersRequired>(AccessibilityModifiersRequired.ForNonInterfaceMembers, NotificationOption.None);
internal static readonly PerLanguageOption<CodeStyleOption<AccessibilityModifiersRequired>> RequireAccessibilityModifiers =
new PerLanguageOption<CodeStyleOption<AccessibilityModifiersRequired>>(
nameof(CodeStyleOptions), nameof(RequireAccessibilityModifiers), defaultValue: s_requireAccessibilityModifiersDefault,
storageLocations: new OptionStorageLocation[]{
new EditorConfigStorageLocation<CodeStyleOption<AccessibilityModifiersRequired>>("dotnet_style_require_accessibility_modifiers", s => ParseAccessibilityModifiersRequired(s)),
new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RequireAccessibilityModifiers")});
private static CodeStyleOption<AccessibilityModifiersRequired> ParseAccessibilityModifiersRequired(string optionString)
{
if (TryGetCodeStyleValueAndOptionalNotification(optionString,
out var value, out var notificationOpt))
{
if (value == "never")
{
// If they provide 'never', they don't need a notification level.
notificationOpt = notificationOpt ?? NotificationOption.None;
}
if (notificationOpt != null)
{
switch (value)
{
case "never":
return new CodeStyleOption<AccessibilityModifiersRequired>(AccessibilityModifiersRequired.Never, notificationOpt);
case "always":
return new CodeStyleOption<AccessibilityModifiersRequired>(AccessibilityModifiersRequired.Always, notificationOpt);
case "for_non_interface_members":
return new CodeStyleOption<AccessibilityModifiersRequired>(AccessibilityModifiersRequired.ForNonInterfaceMembers, notificationOpt);
}
}
}
return s_requireAccessibilityModifiersDefault;
}
}
}
......@@ -1023,6 +1023,8 @@ public SyntaxNode AddMembers(SyntaxNode declaration, params SyntaxNode[] members
/// </summary>
public abstract SyntaxNode WithAccessibility(SyntaxNode declaration, Accessibility accessibility);
internal abstract bool CanHaveAccessibility(SyntaxNode declaration);
/// <summary>
/// Gets the <see cref="DeclarationModifiers"/> for the declaration.
/// </summary>
......
......@@ -231,6 +231,7 @@ protected void WriteOptionSetTo(OptionSet options, string language, ObjectWriter
WriteOptionTo(options, language, CodeStyleOptions.PreferNullPropagation, writer, cancellationToken);
WriteOptionTo(options, language, CodeStyleOptions.PreferObjectInitializer, writer, cancellationToken);
WriteOptionTo(options, language, CodeStyleOptions.PreferThrowExpression, writer, cancellationToken);
WriteOptionTo(options, language, CodeStyleOptions.RequireAccessibilityModifiers, writer, cancellationToken);
WriteOptionTo(options, language, SimplificationOptions.NamingPreferences, writer, cancellationToken);
}
......@@ -251,6 +252,7 @@ protected OptionSet ReadOptionSetFrom(OptionSet options, string language, Object
options = ReadOptionFrom(options, language, CodeStyleOptions.PreferNullPropagation, reader, cancellationToken);
options = ReadOptionFrom(options, language, CodeStyleOptions.PreferObjectInitializer, reader, cancellationToken);
options = ReadOptionFrom(options, language, CodeStyleOptions.PreferThrowExpression, reader, cancellationToken);
options = ReadOptionFrom(options, language, CodeStyleOptions.RequireAccessibilityModifiers, reader, cancellationToken);
options = ReadOptionFrom(options, language, SimplificationOptions.NamingPreferences, reader, cancellationToken);
return options;
}
......
......@@ -21,6 +21,7 @@ namespace Microsoft.CodeAnalysis.Execution
internal abstract class AbstractReferenceSerializationService : IReferenceSerializationService
{
private const int MetadataFailed = int.MaxValue;
private const string VisualStudioUnresolvedAnalyzerReference = "Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioAnalyzer+VisualStudioUnresolvedAnalyzerReference";
protected const byte NoEncodingSerialization = 0;
protected const byte EncodingSerialization = 1;
......@@ -101,13 +102,17 @@ public Checksum CreateChecksum(AnalyzerReference reference, CancellationToken ca
WriteUnresolvedAnalyzerReferenceTo(unresolved, writer);
break;
case AnalyzerReference analyzerReference when analyzerReference.GetType().FullName == VisualStudioUnresolvedAnalyzerReference:
WriteUnresolvedAnalyzerReferenceTo(analyzerReference, writer);
break;
case AnalyzerImageReference _:
// TODO: think a way to support this or a way to deal with this kind of situation.
// https://github.com/dotnet/roslyn/issues/15783
throw new NotSupportedException(nameof(AnalyzerImageReference));
default:
throw ExceptionUtilities.UnexpectedValue(reference.GetType());
throw ExceptionUtilities.UnexpectedValue(reference);
}
stream.Position = 0;
......@@ -184,6 +189,12 @@ public void WriteTo(AnalyzerReference reference, ObjectWriter writer, bool usePa
return;
}
case AnalyzerReference analyzerReference when analyzerReference.GetType().FullName == VisualStudioUnresolvedAnalyzerReference:
{
WriteUnresolvedAnalyzerReferenceTo(analyzerReference, writer);
return;
}
case AnalyzerImageReference _:
{
// TODO: think a way to support this or a way to deal with this kind of situation.
......@@ -192,7 +203,7 @@ public void WriteTo(AnalyzerReference reference, ObjectWriter writer, bool usePa
}
default:
throw ExceptionUtilities.UnexpectedValue(reference.GetType());
throw ExceptionUtilities.UnexpectedValue(reference);
}
}
......
......@@ -55,6 +55,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsDocumentationComment(SyntaxNode node);
bool IsNumericLiteralExpression(SyntaxNode node);
bool IsNullLiteralExpression(SyntaxNode node);
bool IsDefaultLiteralExpression(SyntaxNode node);
bool IsLiteralExpression(SyntaxNode node);
string GetText(int kind);
......
......@@ -2669,6 +2669,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End Function
Public Overrides Function GetAccessibility(declaration As SyntaxNode) As Accessibility
If Not CanHaveAccessibility(declaration) Then
Return Accessibility.NotApplicable
End If
Dim tokens = GetModifierTokens(declaration)
Dim acc As Accessibility
Dim mods As DeclarationModifiers
......@@ -2678,6 +2682,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End Function
Public Overrides Function WithAccessibility(declaration As SyntaxNode, accessibility As Accessibility) As SyntaxNode
If Not CanHaveAccessibility(declaration) AndAlso
accessibility <> Accessibility.NotApplicable Then
Return declaration
End If
Return Isolate(declaration, Function(d) Me.WithAccessibilityInternal(d, accessibility))
End Function
......@@ -2700,7 +2709,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return WithModifierTokens(declaration, Merge(tokens, newTokens))
End Function
Private Function CanHaveAccessibility(declaration As SyntaxNode) As Boolean
Friend Overrides Function CanHaveAccessibility(declaration As SyntaxNode) As Boolean
Select Case declaration.Kind
Case SyntaxKind.ClassBlock,
SyntaxKind.ClassStatement,
......@@ -2717,10 +2726,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
SyntaxKind.FieldDeclaration,
SyntaxKind.FunctionBlock,
SyntaxKind.SubBlock,
SyntaxKind.ConstructorBlock,
SyntaxKind.FunctionStatement,
SyntaxKind.SubStatement,
SyntaxKind.SubNewStatement,
SyntaxKind.PropertyBlock,
SyntaxKind.PropertyStatement,
SyntaxKind.OperatorBlock,
......@@ -2738,6 +2745,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
SyntaxKind.RaiseEventAccessorBlock,
SyntaxKind.RaiseEventAccessorStatement
Return True
Case SyntaxKind.ConstructorBlock,
SyntaxKind.SubNewStatement
' Shared constructor cannot have modifiers in VB.
Return Not declaration.GetModifiers().Any(SyntaxKind.SharedKeyword)
Case SyntaxKind.ModifiedIdentifier
Return If(IsChildOf(declaration, SyntaxKind.VariableDeclarator),
CanHaveAccessibility(declaration.Parent),
False)
Case SyntaxKind.VariableDeclarator
Return If(IsChildOfVariableDeclaration(declaration),
CanHaveAccessibility(declaration.Parent),
False)
Case Else
Return False
End Select
......
......@@ -303,7 +303,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End Function
<Extension()>
Public Function GetNameToken(member As DeclarationStatementSyntax) As SyntaxToken
Public Function GetNameToken(member As StatementSyntax) As SyntaxToken
If member IsNot Nothing Then
Select Case member.Kind
Case SyntaxKind.ClassBlock,
......
......@@ -1433,6 +1433,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return node.Kind() = SyntaxKind.NothingLiteralExpression
End Function
Public Function IsDefaultLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDefaultLiteralExpression
Return IsNullLiteralExpression(node)
End Function
Public Function IsBinaryExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsBinaryExpression
Return TypeOf node Is BinaryExpressionSyntax
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册