diff --git a/README.md b/README.md index b3afc01c65b7fe0cd7821bdd566c54eb397f54c9..51456fda1fce60b081427cc23262e670f71d72b5 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,15 @@ Roslyn provides open-source C# and Visual Basic compilers with rich code analysis APIs. It enables building code analysis tools with the same APIs that are used by Visual Studio. +### Language Design Discussion + +We are now taking language feature discussion in other repositories: +- https://github.com/dotnet/csharplang for C# specific issues +- https://github.com/dotnet/vblang for VB-specific features +- https://github.com/dotnet/csharplang for features that affect both languages + +Discussion about the transition of language design to the new repos is at https://github.com/dotnet/roslyn/issues/18002. + ### Download C# and Visual Basic Want to start developing in C# and Visual Basic? Download [Visual Studio 2015](https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx), diff --git a/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs b/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs index 1ed0149d70a6ae73de0d0a5d472d1774a0edee68..62a339b514e877dcbe585ed8c34ec172c04b2565 100644 --- a/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs +++ b/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs @@ -1610,5 +1610,25 @@ void Foo() } }", ignoreTrivia: false); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)] + public async Task TestMissingOnUnderscore() + { + await TestMissingInRegularAndScriptAsync( +@" +using System; + +class C +{ + void M() + { + [|int|] _; + if (N(out _) + { + Console.WriteLine(_); + } + } +}"); + } } } \ No newline at end of file diff --git a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs index 6c51423edf7c257ecc72640566a54a2fb59e4f76..187045b59a8fd011b7ab0f33a7ec361be04d8daf 100644 --- a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; using Microsoft.CodeAnalysis.Editor.Tagging; @@ -61,25 +63,98 @@ internal async Task ProduceTagsAsync(TaggerContext context, D { using (Logger.LogBlock(FunctionId.Tagger_BraceHighlighting_TagProducer_ProduceTags, context.CancellationToken)) { - await ProduceTagsForBracesAsync(context, document, snapshot, position, rightBrace: false).ConfigureAwait(false); - await ProduceTagsForBracesAsync(context, document, snapshot, position - 1, rightBrace: true).ConfigureAwait(false); + if (position >= 0 && position <= snapshot.Length) + { + var (bracesLeftOfPosition, bracesRightOfPosition) = await GetAllMatchingBracesAsync( + _braceMatcherService, document, position, context.CancellationToken).ConfigureAwait(false); + + AddBraces(context, snapshot, bracesLeftOfPosition); + AddBraces(context, snapshot, bracesRightOfPosition); + } } } - private async Task ProduceTagsForBracesAsync(TaggerContext context, Document document, ITextSnapshot snapshot, int position, bool rightBrace) + /// + /// Given code like ()^() (where ^ is the caret position), returns the two pairs of + /// matching braces on the left and the right of the position. Note: a brace matching + /// pair is only returned if the position is on the left-side of hte start brace, or the + /// right side of end brace. So, for example, if you have (^()), then only the inner + /// braces are returned as the position is not on the right-side of the outer braces. + /// + /// This function also works for multi-character braces i.e. ([ ]) In this case, + /// the rule is that the position has to be on the left side of the start brace, or + /// inside the start brace (but not at the end). So, ^([ ]) will return this + /// as a brace match, as will (^[ ]). But ([^ ]) will not. + /// + /// The same goes for the braces on the the left of the caret. i.e.: ([ ])^ + /// will return the braces on the left, as will ([ ]^). But ([ ^]) will not. + /// + private static async Task<(BraceMatchingResult? leftOfPosition, BraceMatchingResult? rightOfPosition)> GetAllMatchingBracesAsync( + IBraceMatchingService service, + Document document, + int position, + CancellationToken cancellationToken) { - if (position >= 0 && position <= snapshot.Length) + // These are the matching spans when checking the token to the right of the position. + var rightOfPosition = await service.GetMatchingBracesAsync(document, position, cancellationToken).ConfigureAwait(false); + + // The braces to the right of the position should only be added if the position is + // actually within the span of the start brace. Note that this is what we want for + // single character braces as well as multi char braces. i.e. if the user has: + // + // ^{ } // then { and } are matching braces. + // {^ } // then { and } are not matching braces. + // + // ^<@ @> // then <@ and @> are matching braces. + // <^@ @> // then <@ and @> are matching braces. + // <@^ @> // then <@ and @> are not matching braces. + if (rightOfPosition.HasValue && + !rightOfPosition.Value.LeftSpan.Contains(position)) { - var braces = await _braceMatcherService.GetMatchingBracesAsync(document, position, context.CancellationToken).ConfigureAwait(false); - if (braces.HasValue) - { - if ((!rightBrace && braces.Value.LeftSpan.Start == position) || - (rightBrace && braces.Value.RightSpan.Start == position)) - { - context.AddTag(snapshot.GetTagSpan(braces.Value.LeftSpan.ToSpan(), BraceHighlightTag.StartTag)); - context.AddTag(snapshot.GetTagSpan(braces.Value.RightSpan.ToSpan(), BraceHighlightTag.EndTag)); - } - } + // Not a valid match. + rightOfPosition = null; + } + + if (position == 0) + { + // We're at the start of the document, can't find braces to the left of the position. + return (leftOfPosition: null, rightOfPosition); + } + + // See if we're touching the end of some construct. i.e.: + // + // { }^ + // <@ @>^ + // <@ @^> + // + // But not + // + // { ^} + // <@ ^@> + + var leftOfPosition = await service.GetMatchingBracesAsync(document, position - 1, cancellationToken).ConfigureAwait(false); + + if (leftOfPosition.HasValue && + position <= leftOfPosition.Value.RightSpan.End && + position > leftOfPosition.Value.RightSpan.Start) + { + // Found a valid pair on the left of us. + return (leftOfPosition, rightOfPosition); + } + + // No valid pair of braces on the left of us. + return (leftOfPosition: null, rightOfPosition); + } + + private void AddBraces( + TaggerContext context, + ITextSnapshot snapshot, + BraceMatchingResult? braces) + { + if (braces.HasValue) + { + context.AddTag(snapshot.GetTagSpan(braces.Value.LeftSpan.ToSpan(), BraceHighlightTag.StartTag)); + context.AddTag(snapshot.GetTagSpan(braces.Value.RightSpan.ToSpan(), BraceHighlightTag.EndTag)); } } } diff --git a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceMatchingService.cs b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceMatchingService.cs index fb80f044f50e627e30cfcb0f321b4a9dce027ec8..6f5c73d76390a9406cfd9c4ed1177f82724fc067 100644 --- a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceMatchingService.cs +++ b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceMatchingService.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.Composition; using System.Linq; using System.Threading; @@ -13,14 +14,13 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching [Export(typeof(IBraceMatchingService))] internal class BraceMatchingService : IBraceMatchingService { - private readonly List> _braceMatchers; + private readonly ImmutableArray> _braceMatchers; [ImportingConstructor] public BraceMatchingService( [ImportMany] IEnumerable> braceMatchers) { - ////braceMatchers.RealizeImports(); - _braceMatchers = braceMatchers.ToList(); + _braceMatchers = braceMatchers.ToImmutableArray(); } public async Task GetMatchingBracesAsync(Document document, int position, CancellationToken cancellationToken) diff --git a/src/EditorFeatures/Core/Shared/Extensions/IBraceMatchingServiceExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/IBraceMatchingServiceExtensions.cs index ade2957c33cacfaac44a9cd73dc484b5f30590da..d5ec0ca22eb006cd886ec2ca4c09754d963aa596 100644 --- a/src/EditorFeatures/Core/Shared/Extensions/IBraceMatchingServiceExtensions.cs +++ b/src/EditorFeatures/Core/Shared/Extensions/IBraceMatchingServiceExtensions.cs @@ -47,11 +47,11 @@ internal static class IBraceMatchingServiceExtensions } else if (braces1.HasValue && position >= braces1.Value.RightSpan.Start && position < braces1.Value.RightSpan.End) { - // { ^} -- return left span + // { ^} - return left span return braces1.Value.LeftSpan; } return null; } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/TestUtilities/BraceHighlighting/AbstractBraceHighlightingTests.cs b/src/EditorFeatures/TestUtilities/BraceHighlighting/AbstractBraceHighlightingTests.cs index 7871d3f105494911c04a7377dd5881a5f01aba97..dfbefd8496816c0170ad65a33e1ff79b95edf9b2 100644 --- a/src/EditorFeatures/TestUtilities/BraceHighlighting/AbstractBraceHighlightingTests.cs +++ b/src/EditorFeatures/TestUtilities/BraceHighlighting/AbstractBraceHighlightingTests.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching; using Microsoft.CodeAnalysis.Editor.Tagging; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -24,7 +23,7 @@ protected async Task TestBraceHighlightingAsync(string markup, ParseOptions opti WpfTestCase.RequireWpfFact($"{nameof(AbstractBraceHighlightingTests)}.{nameof(TestBraceHighlightingAsync)} creates asynchronous taggers"); var provider = new BraceHighlightingViewTaggerProvider( - workspace.GetService(), + GetBraceMatchingService(workspace), workspace.GetService(), AggregateAsynchronousOperationListener.EmptyListeners); @@ -43,6 +42,9 @@ protected async Task TestBraceHighlightingAsync(string markup, ParseOptions opti } } + internal virtual IBraceMatchingService GetBraceMatchingService(TestWorkspace workspace) + => workspace.GetService(); + protected abstract TestWorkspace CreateWorkspace(string markup, ParseOptions options); } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs b/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..c6b9bbd053ac6032f37fee4a2807532a0c3935ac --- /dev/null +++ b/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs @@ -0,0 +1,260 @@ +// 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 System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.BraceHighlighting +{ + public class MultiCharacterBraceHighlightingTests : AbstractBraceHighlightingTests + { + protected override TestWorkspace CreateWorkspace(string markup, ParseOptions options) + => TestWorkspace.Create( + NoCompilationConstants.LanguageName, compilationOptions: null, parseOptions: options, content: markup); + + internal override IBraceMatchingService GetBraceMatchingService(TestWorkspace workspace) + => new TestBraceMatchingService(); + + private ImmutableArray GetSpans(BraceMatchingResult? result) + => result.HasValue + ? ImmutableArray.Create(result.Value.LeftSpan, result.Value.RightSpan) + : ImmutableArray.Empty; + + private class TestBraceMatchingService : IBraceMatchingService + { + public async Task GetMatchingBracesAsync( + Document document, int position, CancellationToken cancellationToken = default(CancellationToken)) + { + var text = (await document.GetTextAsync(cancellationToken)).ToString(); + var braces = GetMatchingBraces(text, position); + if (braces.HasValue) + { + Debug.Assert(text.Substring(braces.Value.LeftSpan.Start, braces.Value.LeftSpan.Length) == "<@"); + Debug.Assert(text.Substring(braces.Value.RightSpan.Start, braces.Value.RightSpan.Length) == "@>"); + } + + return braces; + } + + public BraceMatchingResult? GetMatchingBraces( + string text, int position) + { + if (position < text.Length) + { + var ch = text[position]; + + // Look for <@ @> depending on where the caret is. + + // ^<@ @> + if (ch == '<') + { + Debug.Assert(text[position + 1] == '@'); + var secondAt = text.IndexOf('@', position + 2); + return new BraceMatchingResult(new TextSpan(position, 2), new TextSpan(secondAt, 2)); + } + + // <^@ @> or <@ ^@> + if (ch == '@') + { + if (text[position - 1] == '<') + { + var secondAt = text.IndexOf('@', position + 1); + return new BraceMatchingResult(new TextSpan(position - 1, 2), new TextSpan(secondAt, 2)); + } + else + { + Debug.Assert(text[position + 1] == '>'); + var lessThan = text.LastIndexOf('<', position); + return new BraceMatchingResult(new TextSpan(lessThan, 2), new TextSpan(position, 2)); + } + } + + // <@ @^> + if (ch == '>') + { + Debug.Assert(text[position - 1] == '@'); + var lessThan = text.LastIndexOf('<', position); + return new BraceMatchingResult(new TextSpan(lessThan, 2), new TextSpan(position - 1, 2)); + } + } + + return null; + } + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnBrace() + { + await TestBraceHighlightingAsync( +"$$ <@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestOnLeftOfStartBrace() + { + await TestBraceHighlightingAsync( +"$$[|<@|] [|@>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInsideStartBrace() + { + await TestBraceHighlightingAsync( +"[|<$$@|] [|@>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnRightOfStartBrace() + { + await TestBraceHighlightingAsync( +"<@$$ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnLeftOfCloseBrace() + { + await TestBraceHighlightingAsync( +"<@ $$@>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInsideCloseBrace() + { + await TestBraceHighlightingAsync( +"[|<@|] [|@$$>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestOnRightOfCloseBrace() + { + await TestBraceHighlightingAsync( +"[|<@|] [|@>$$|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotAfterBrace() + { + await TestBraceHighlightingAsync( +"<@ @> $$"); + } + + + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnBrace2() + { + await TestBraceHighlightingAsync( +"$$ <@ @><@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestOnLeftOfStartBrace2() + { + await TestBraceHighlightingAsync( +"$$[|<@|] [|@>|]<@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInsideStartBrace2() + { + await TestBraceHighlightingAsync( +"[|<$$@|] [|@>|]<@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnRightOfStartBrace2() + { + await TestBraceHighlightingAsync( +"<@$$ @><@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotOnLeftOfCloseBrace2() + { + await TestBraceHighlightingAsync( +"<@ $$@><@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInsideCloseBrace3() + { + await TestBraceHighlightingAsync( +"[|<@|] [|@$$>|]<@ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestOnRightOfCloseBrace2() + { + await TestBraceHighlightingAsync( +"[|<@|] [|@>|]$$[|<@|] [|@>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInSecondBracePair() + { + await TestBraceHighlightingAsync( +"<@ @>[|<$$@|] [|@>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotAfterSecondBracePairStart() + { + await TestBraceHighlightingAsync( +"<@ @><@$$ @>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotBeforeSecondBracePairEnd() + { + await TestBraceHighlightingAsync( +"<@ @><@ $$@>"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestInSecondBracePairEnd() + { + await TestBraceHighlightingAsync( +"<@ @>[|<@|] [|@$$>|]"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestAtSecondBracePairEnd() + { + await TestBraceHighlightingAsync( +"<@ @>[|<@|] [|@>|]$$"); + } + + [WorkItem(18050, "https://github.com/dotnet/roslyn/issues/18050")] + [WpfFact, Trait(Traits.Feature, Traits.Features.BraceHighlighting)] + public async Task TestNotAfterSecondBracePairEnd() + { + await TestBraceHighlightingAsync( +"<@ @><@ @> $$"); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/TestUtilities/BraceMatching/AbstractBraceMatcherTests.cs b/src/EditorFeatures/TestUtilities/BraceMatching/AbstractBraceMatcherTests.cs index 1270d5beb2b561243b4737f30330f8b3bd7d3eba..dcec8ef4ec94bc0a8558fced7d662900e8bf0713 100644 --- a/src/EditorFeatures/TestUtilities/BraceMatching/AbstractBraceMatcherTests.cs +++ b/src/EditorFeatures/TestUtilities/BraceMatching/AbstractBraceMatcherTests.cs @@ -1,5 +1,6 @@ // 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.Linq; using System.Threading; @@ -15,11 +16,6 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.BraceMatching { public abstract class AbstractBraceMatcherTests { - private Document GetDocument(TestWorkspace workspace) - { - return workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); - } - protected abstract TestWorkspace CreateWorkspaceFromCode(string code, ParseOptions options); protected async Task TestAsync(string markup, string expectedCode, ParseOptions options = null) @@ -27,7 +23,7 @@ protected async Task TestAsync(string markup, string expectedCode, ParseOptions using (var workspace = CreateWorkspaceFromCode(markup, options)) { var position = workspace.Documents.Single().CursorPosition.Value; - var document = GetDocument(workspace); + var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); var braceMatcher = workspace.GetService(); var foundSpan = await braceMatcher.FindMatchingSpanAsync(document, position, CancellationToken.None); diff --git a/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj b/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj index b6900fac05498d5cb0bb655807f62510a95e89e8..3026d33cb55fdaa275d231f456deeda072691d7b 100644 --- a/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj +++ b/src/EditorFeatures/TestUtilities/ServicesTestUtilities.csproj @@ -131,6 +131,7 @@ + diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs index 7f994332aa71436512e0ead822ba46a7a3b1d55a..b29e7229e1dcc02d428dae5c21592b2abc399024 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs @@ -9,13 +9,11 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading; -using System.Windows.Threading; using System.Xml.Linq; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; @@ -29,7 +27,6 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces { - using System.Threading.Tasks; using RelativePathResolver = WORKSPACES::Microsoft.CodeAnalysis.RelativePathResolver; public partial class TestWorkspace diff --git a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs index a7467a84a29d2d135d7dc6e156c5d26f8c6b5202..0b336c4b18ced8089886a21fca3310164e55940f 100644 --- a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs @@ -113,6 +113,13 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb var identifierName = (IdentifierNameSyntax)argumentExpression; + // Don't offer to inline variables named "_". It can cause is to create a discard symbol + // which would cause a break. + if (identifierName.Identifier.ValueText == "_") + { + return; + } + var containingStatement = argumentExpression.FirstAncestorOrSelf(); if (containingStatement == null) { diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckCodeFixProvider.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckCodeFixProvider.cs index 5568740ac0182bce82762d268a34d3e76cd1fad0..6ad5a4499c9615092cd5805c20d15c087b5c7a07 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckCodeFixProvider.cs @@ -90,7 +90,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) private class MyCodeAction : CodeAction.DocumentChangeAction { public MyCodeAction(Func> createChangedDocument) - : base(CSharpFeaturesResources.Inline_temporary_variable, createChangedDocument) + : base(FeaturesResources.Use_pattern_matching, createChangedDocument) { } } diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckCodeFixProvider.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckCodeFixProvider.cs index a979dacc0ad7b2a632c1283ddf93abe477153748..dd72a53a224c6a66650b850f983aad388a3dd7d5 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckCodeFixProvider.cs @@ -97,7 +97,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) private class MyCodeAction : CodeAction.DocumentChangeAction { public MyCodeAction(Func> createChangedDocument) - : base(CSharpFeaturesResources.Inline_temporary_variable, createChangedDocument) + : base(FeaturesResources.Use_pattern_matching, createChangedDocument) { } } diff --git a/src/Tools/MicroBuild/Build.proj b/src/Tools/MicroBuild/Build.proj index 4da2212823acf52beef1bc5b6b51cba491e296db..fff47da340fc6ce9e4f5159e6fef8090ab734360 100644 --- a/src/Tools/MicroBuild/Build.proj +++ b/src/Tools/MicroBuild/Build.proj @@ -10,12 +10,13 @@ $(RepoRoot)Binaries\$(Configuration) "no key" -test + -msbuildPath "$(MSBuildBinPath)\msbuild.exe" master - -test -msbuildPath "$(MSBuildBinPath)\msbuild.exe" + $(SignRoslynArgs) -test -test -test FinalizeValidate=false;ManifestPublishUrl=https://vsdrop.corp.microsoft.com/file/v1/Products/DevDiv/dotnet/roslyn/master/20160729.6 diff --git a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb index f90d2e501187bf655e97add90757bb54c848b9ff..8f3671063e20b6b586bab1295cb79076adab9e4b 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb @@ -624,7 +624,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Return list End Function - Private Shared s_fieldModifiers As DeclarationModifiers = DeclarationModifiers.Const Or DeclarationModifiers.[New] Or DeclarationModifiers.ReadOnly Or DeclarationModifiers.Static + Private Shared s_fieldModifiers As DeclarationModifiers = DeclarationModifiers.Const Or DeclarationModifiers.[New] Or DeclarationModifiers.ReadOnly Or DeclarationModifiers.Static Or DeclarationModifiers.WithEvents Private Shared s_methodModifiers As DeclarationModifiers = DeclarationModifiers.Abstract Or DeclarationModifiers.Async Or DeclarationModifiers.[New] Or DeclarationModifiers.Override Or DeclarationModifiers.Partial Or DeclarationModifiers.Sealed Or DeclarationModifiers.Static Or DeclarationModifiers.Virtual Private Shared s_constructorModifiers As DeclarationModifiers = DeclarationModifiers.Static Private Shared s_propertyModifiers As DeclarationModifiers = DeclarationModifiers.Abstract Or DeclarationModifiers.[New] Or DeclarationModifiers.Override Or DeclarationModifiers.ReadOnly Or DeclarationModifiers.WriteOnly Or DeclarationModifiers.Sealed Or DeclarationModifiers.Static Or DeclarationModifiers.Virtual @@ -2468,6 +2468,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Return DirectCast(declaration, EnumBlockSyntax).EnumStatement.Modifiers Case SyntaxKind.EnumStatement Return DirectCast(declaration, EnumStatementSyntax).Modifiers + Case SyntaxKind.ModuleBlock + Return DirectCast(declaration, ModuleBlockSyntax).ModuleStatement.Modifiers + Case SyntaxKind.ModuleStatement + Return DirectCast(declaration, ModuleStatementSyntax).Modifiers Case SyntaxKind.DelegateFunctionStatement, SyntaxKind.DelegateSubStatement Return DirectCast(declaration, DelegateStatementSyntax).Modifiers @@ -2538,6 +2542,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Return DirectCast(declaration, EnumBlockSyntax).WithEnumStatement(DirectCast(declaration, EnumBlockSyntax).EnumStatement.WithModifiers(tokens)) Case SyntaxKind.EnumStatement Return DirectCast(declaration, EnumStatementSyntax).WithModifiers(tokens) + Case SyntaxKind.ModuleBlock + Return DirectCast(declaration, ModuleBlockSyntax).WithModuleStatement(DirectCast(declaration, ModuleBlockSyntax).ModuleStatement.WithModifiers(tokens)) + Case SyntaxKind.ModuleStatement + Return DirectCast(declaration, ModuleStatementSyntax).WithModifiers(tokens) Case SyntaxKind.DelegateFunctionStatement, SyntaxKind.DelegateSubStatement Return DirectCast(declaration, DelegateStatementSyntax).WithModifiers(tokens) @@ -2618,38 +2626,40 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Private Function CanHaveAccessibility(declaration As SyntaxNode) As Boolean Select Case declaration.Kind Case SyntaxKind.ClassBlock, - SyntaxKind.ClassStatement, - SyntaxKind.StructureBlock, - SyntaxKind.StructureStatement, - SyntaxKind.InterfaceBlock, - SyntaxKind.InterfaceStatement, - SyntaxKind.EnumBlock, - SyntaxKind.EnumStatement, - SyntaxKind.DelegateFunctionStatement, - SyntaxKind.DelegateSubStatement, - SyntaxKind.FieldDeclaration, - SyntaxKind.FunctionBlock, - SyntaxKind.SubBlock, - SyntaxKind.ConstructorBlock, - SyntaxKind.FunctionStatement, - SyntaxKind.SubStatement, - SyntaxKind.SubNewStatement, - SyntaxKind.PropertyBlock, - SyntaxKind.PropertyStatement, - SyntaxKind.OperatorBlock, - SyntaxKind.OperatorStatement, - SyntaxKind.EventBlock, - SyntaxKind.EventStatement, - SyntaxKind.GetAccessorBlock, - SyntaxKind.GetAccessorStatement, - SyntaxKind.SetAccessorBlock, - SyntaxKind.SetAccessorStatement, - SyntaxKind.AddHandlerAccessorBlock, - SyntaxKind.AddHandlerAccessorStatement, - SyntaxKind.RemoveHandlerAccessorBlock, - SyntaxKind.RemoveHandlerAccessorStatement, - SyntaxKind.RaiseEventAccessorBlock, - SyntaxKind.RaiseEventAccessorStatement + SyntaxKind.ClassStatement, + SyntaxKind.StructureBlock, + SyntaxKind.StructureStatement, + SyntaxKind.InterfaceBlock, + SyntaxKind.InterfaceStatement, + SyntaxKind.EnumBlock, + SyntaxKind.EnumStatement, + SyntaxKind.ModuleBlock, + SyntaxKind.ModuleStatement, + SyntaxKind.DelegateFunctionStatement, + SyntaxKind.DelegateSubStatement, + SyntaxKind.FieldDeclaration, + SyntaxKind.FunctionBlock, + SyntaxKind.SubBlock, + SyntaxKind.ConstructorBlock, + SyntaxKind.FunctionStatement, + SyntaxKind.SubStatement, + SyntaxKind.SubNewStatement, + SyntaxKind.PropertyBlock, + SyntaxKind.PropertyStatement, + SyntaxKind.OperatorBlock, + SyntaxKind.OperatorStatement, + SyntaxKind.EventBlock, + SyntaxKind.EventStatement, + SyntaxKind.GetAccessorBlock, + SyntaxKind.GetAccessorStatement, + SyntaxKind.SetAccessorBlock, + SyntaxKind.SetAccessorStatement, + SyntaxKind.AddHandlerAccessorBlock, + SyntaxKind.AddHandlerAccessorStatement, + SyntaxKind.RemoveHandlerAccessorBlock, + SyntaxKind.RemoveHandlerAccessorStatement, + SyntaxKind.RaiseEventAccessorBlock, + SyntaxKind.RaiseEventAccessorStatement Return True Case Else Return False diff --git a/src/Workspaces/VisualBasicTest/CodeGeneration/SyntaxGeneratorTests.vb b/src/Workspaces/VisualBasicTest/CodeGeneration/SyntaxGeneratorTests.vb index 03e3b2f052b8d1cdc4347474ccb8cc708e9386b5..fbc1d927f5a8105894712b32e3bd69f1719a7f9b 100644 --- a/src/Workspaces/VisualBasicTest/CodeGeneration/SyntaxGeneratorTests.vb +++ b/src/Workspaces/VisualBasicTest/CodeGeneration/SyntaxGeneratorTests.vb @@ -774,8 +774,8 @@ End Sub.Value) Public fld As Integer.Value) VerifySyntax(Of FieldDeclarationSyntax)( - _g.FieldDeclaration("fld", _g.TypeExpression(SpecialType.System_Int32), modifiers:=DeclarationModifiers.Static Or DeclarationModifiers.ReadOnly), - Shared ReadOnly fld As Integer.Value) + _g.FieldDeclaration("fld", _g.TypeExpression(SpecialType.System_Int32), modifiers:=DeclarationModifiers.Static Or DeclarationModifiers.ReadOnly Or DeclarationModifiers.WithEvents), + Shared ReadOnly WithEvents fld As Integer.Value) End Sub @@ -2301,7 +2301,7 @@ End Class Public Sub TestGetAccessibility() Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.ClassDeclaration("c", accessibility:=Accessibility.Internal))) Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.StructDeclaration("s", accessibility:=Accessibility.Internal))) - Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.EnumDeclaration("i", accessibility:=Accessibility.Internal))) + Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.InterfaceDeclaration("i", accessibility:=Accessibility.Internal))) Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.EnumDeclaration("e", accessibility:=Accessibility.Internal))) Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.DelegateDeclaration("d", accessibility:=Accessibility.Internal))) Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.MethodDeclaration("m", accessibility:=Accessibility.Internal))) @@ -2318,6 +2318,11 @@ End Class Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(_g.LocalDeclarationStatement(_g.IdentifierName("t"), "loc"))) Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(_g.Attribute("a"))) Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(SyntaxFactory.TypeParameter("tp"))) + + Dim m = SyntaxFactory.ModuleBlock( + SyntaxFactory.ModuleStatement("module2"). + WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)))) + Assert.Equal(Accessibility.Public, _g.GetAccessibility(m)) End Sub @@ -2341,6 +2346,11 @@ End Class Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(_g.WithAccessibility(_g.LocalDeclarationStatement(_g.IdentifierName("t"), "loc"), Accessibility.Private))) Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(_g.WithAccessibility(_g.Attribute("a"), Accessibility.Private))) Assert.Equal(Accessibility.NotApplicable, _g.GetAccessibility(_g.WithAccessibility(SyntaxFactory.TypeParameter("tp"), Accessibility.Private))) + + Dim m = SyntaxFactory.ModuleBlock( + SyntaxFactory.ModuleStatement("module2"). + WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)))) + Assert.Equal(Accessibility.Internal, _g.GetAccessibility(_g.WithAccessibility(m, Accessibility.Internal))) End Sub