diff --git a/cibuild.cmd b/cibuild.cmd index 1b68ee86855c5c9fbfabede0e1bca273a1571fc3..a0943eb5717e4f78d76f39738e6b1792f92866ae 100644 --- a/cibuild.cmd +++ b/cibuild.cmd @@ -16,9 +16,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd REM Build the compiler so we can self host it for the full build src\.nuget\NuGet.exe restore %RoslynRoot%/src/Toolset.sln -packagesdirectory packages -msbuild /nologo /v:m /m %RoslynRoot%/src/Compilers/Core/VBCSCompiler/VBCSCompiler.csproj /p:Configuration=%BuildConfiguration% -msbuild /nologo /v:m /m %RoslynRoot%/src/Compilers/CSharp/csc2/csc2.csproj /p:Configuration=%BuildConfiguration% -msbuild /nologo /v:m /m %RoslynRoot%/src/Compilers/VisualBasic/vbc2/vbc2.csproj /p:Configuration=%BuildConfiguration% +msbuild /nologo /v:m /m %RoslynRoot%/src/Toolset.sln /p:Configuration=%BuildConfiguration% mkdir %RoslynRoot%\Binaries\Bootstrap move Binaries\%BuildConfiguration%\* %RoslynRoot%\Binaries\Bootstrap @@ -32,6 +30,13 @@ if ERRORLEVEL 1 ( exit /b 1 ) +msbuild /v:m /m /p:BootstrapBuildPath=%RoslynRoot%\Binaries\Bootstrap src/Samples/Samples.sln /p:CIBuild=true /p:Configuration=%BuildConfiguration% +if ERRORLEVEL 1 ( + taskkill /F /IM vbcscompiler.exe + echo Build failed + exit /b 1 +) + REM Kill any instances of VBCSCompiler.exe to release locked files; REM otherwise future CI runs may fail while trying to delete those files. taskkill /F /IM vbcscompiler.exe @@ -44,8 +49,4 @@ exit /b 0 @echo Usage: cibuild.cmd [/debug^|/release] @echo /debug Perform debug build. This is the default. @echo /release Perform release build -<<<<<<< HEAD -@goto :eof -======= -@goto :eof ->>>>>>> origin/stabilization +@goto :eof \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index b4a407ae5f6d6b798dedb45c2bf0e9be5f457a3f..6786d4f4b07cb0962eeb139af7745c7883b406ea 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -346,7 +346,7 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, Diagnosti // result.Symbols can be empty in some malformed code, e.g. when a labeled statement is used an embedded statement in an if or foreach statement // In this case we create new label symbol on the fly, and an error is reported by parser - var symbol = result.Symbols.Count != 0 ? + var symbol = result.Symbols.Count > 0 && result.IsMultiViable ? (LabelSymbol)result.Symbols.First() : new SourceLabelSymbol((MethodSymbol)ContainingMemberOrLambda, node.Identifier); diff --git a/src/Compilers/CSharp/Portable/Symbols/ReferenceManager.cs b/src/Compilers/CSharp/Portable/Symbols/ReferenceManager.cs index 208a29ab65677ab264b358e4c694b2eab60cbe45..022191c9afd8d81c7c2d6a02b125ebd899dcb156 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ReferenceManager.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ReferenceManager.cs @@ -1027,6 +1027,8 @@ public override bool DeclaresTheObjectClass return _assembly.DeclaresTheObjectClass; } } + + public override Compilation SourceCompilation => null; } private sealed class AssemblyDataForCompilation : AssemblyDataForMetadataOrCompilation @@ -1130,6 +1132,8 @@ public override bool DeclaresTheObjectClass return _compilation.DeclaresTheObjectClass; } } + + public override Compilation SourceCompilation => _compilation; } /// diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 80ff3c00a5b6862b74c033c8d8644d17a650bbdc..00e874a32a532a8c24cfd9254592c5fb563a2757 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -22455,5 +22455,35 @@ static void Main() Diagnostic(ErrorCode.ERR_IllegalStatement, "x?.ToString()[1]").WithLocation(10, 9) ); } + + [Fact] + [WorkItem(1179322, "DevDiv")] + public void LabelSameNameAsParameter() + { + var text = @" +class Program +{ + static object M(object obj, object value) + { + if (((string)obj).Length == 0) value: new Program(); + } +} +"; + var compilation = CreateCompilationWithMscorlib(text); + compilation.GetParseDiagnostics().Verify( + // (6,41): error CS1023: Embedded statement cannot be a declaration or labeled statement + // if (((string)obj).Length == 0) value: new Program(); + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "value: new Program();").WithLocation(6, 41)); + + // Make sure the compiler can handle producing method body diagnostics for this pattern when + // queriied via an API (command line compile would exit after parse errors were reported). + compilation.GetMethodBodyDiagnostics().Verify( + // (6,41): warning CS0164: This label has not been referenced + // if (((string)obj).Length == 0) value: new Program(); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "value").WithLocation(6, 41), + // (4,19): error CS0161: 'Program.M(object, object)': not all code paths return a value + // static object M(object obj, object value) + Diagnostic(ErrorCode.ERR_ReturnExpected, "M").WithArguments("Program.M(object, object)").WithLocation(4, 19)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs index c671b6db59d1ee9a9b0d87a476d17cf5bbf09886..a212dcfedf0c77e41cca4421914ecc4d96acc71f 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs @@ -23,6 +23,34 @@ public class ReferenceManagerTests : CSharpTestBase WithCryptoKeyFile(SigningTestHelpers.KeyPairFile). WithStrongNameProvider(new SigningTestHelpers.VirtualizedStrongNameProvider(ImmutableArray.Create())); + [ClrOnlyFact(ClrOnlyReason.Signing)] + public void WinRtCompilationReferences() + { + var ifaceDef = CreateCompilationWithMscorlib( +@" +public interface ITest +{ +}", options: TestOptions.DebugWinMD, assemblyName: "ITest"); + + ifaceDef.VerifyDiagnostics(); + var ifaceImageRef = ifaceDef.EmitToImageReference(); + + var wimpl = AssemblyMetadata.CreateFromImage(TestResources.WinRt.WImpl).GetReference(display: "WImpl"); + + var implDef2 = CreateCompilationWithMscorlib( +@" +public class C +{ + public static void Main() + { + ITest test = new WImpl(); + } +}", references: new MetadataReference[] { ifaceDef.ToMetadataReference(), wimpl }, + options: TestOptions.DebugExe); + + implDef2.VerifyDiagnostics(); + } + [ClrOnlyFact(ClrOnlyReason.Signing)] public void VersionUnification_SymbolUsed() { diff --git a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentityComparer.cs b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentityComparer.cs index e80d68748d26b3fa0b168547d567fbf6c1caeb1d..05d65f619d6ae85d0d40a1dfee652a55637d3352 100644 --- a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentityComparer.cs +++ b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentityComparer.cs @@ -218,3 +218,4 @@ internal virtual bool ApplyUnificationPolicies(ref AssemblyIdentity reference, r } } } + diff --git a/src/Compilers/Core/Portable/ReferenceManager/AssemblyData.cs b/src/Compilers/Core/Portable/ReferenceManager/AssemblyData.cs index 964ec015726a6c2054a9cbed94f20b877f94e186..0fdbf3b196067a51c8e31ab33cc04f5ec86ac0cc 100644 --- a/src/Compilers/Core/Portable/ReferenceManager/AssemblyData.cs +++ b/src/Compilers/Core/Portable/ReferenceManager/AssemblyData.cs @@ -57,6 +57,12 @@ internal abstract class AssemblyData public abstract bool IsLinked { get; } public abstract bool DeclaresTheObjectClass { get; } + + /// + /// Get the source compilation backing this assembly, if one exists. + /// Returns null otherwise. + /// + public abstract Compilation SourceCompilation { get; } } } } diff --git a/src/Compilers/Core/Portable/ReferenceManager/AssemblyDataForAssemblyBeingBuilt.cs b/src/Compilers/Core/Portable/ReferenceManager/AssemblyDataForAssemblyBeingBuilt.cs index 43151833aa81b7a5589e6d1558187202801cda73..f04381b4d81d45bdf70f656f3b735fd155d182f1 100644 --- a/src/Compilers/Core/Portable/ReferenceManager/AssemblyDataForAssemblyBeingBuilt.cs +++ b/src/Compilers/Core/Portable/ReferenceManager/AssemblyDataForAssemblyBeingBuilt.cs @@ -144,6 +144,8 @@ public override bool DeclaresTheObjectClass return false; } } + + public override Compilation SourceCompilation => null; } } } diff --git a/src/Compilers/Core/Portable/ReferenceManager/CommonReferenceManager.Resolution.cs b/src/Compilers/Core/Portable/ReferenceManager/CommonReferenceManager.Resolution.cs index dbe076f24b252775168be0feb7cf1c13d07e674e..aad10d5136f65dd556529f93915ab2a1bce18317 100644 --- a/src/Compilers/Core/Portable/ReferenceManager/CommonReferenceManager.Resolution.cs +++ b/src/Compilers/Core/Portable/ReferenceManager/CommonReferenceManager.Resolution.cs @@ -10,6 +10,7 @@ namespace Microsoft.CodeAnalysis { + using System.Reflection; using MetadataOrDiagnostic = System.Object; /// @@ -850,6 +851,32 @@ private static PortableExecutableReference ResolveReferenceDirective(string refe } } + // In the IDE it is possible the reference we're looking for is a + // compilation reference to a source assembly. However, if the reference + // is of ContentType WindowsRuntime then the compilation will never + // match since all C#/VB WindowsRuntime compilations output .winmdobjs, + // not .winmds, and the ContentType of a .winmdobj is Default. + // If this is the case, we want to ignore the ContentType mismatch and + // allow the compilation to match the reference. + if (reference.ContentType == AssemblyContentType.WindowsRuntime) + { + for (int i = definitionOffset; i < definitions.Length; i++) + { + var definition = definitions[i].Identity; + var sourceCompilation = definitions[i].SourceCompilation; + if (definition.ContentType == AssemblyContentType.Default && + sourceCompilation?.Options.OutputKind == OutputKind.WindowsRuntimeMetadata && + AssemblyIdentityComparer.SimpleNameComparer.Equals(reference.Name, definition.Name) && + reference.Version.Equals(definition.Version) && + reference.IsRetargetable == definition.IsRetargetable && + AssemblyIdentityComparer.CultureComparer.Equals(reference.CultureName, definition.CultureName) && + AssemblyIdentity.KeysEqual(reference, definition)) + { + return new AssemblyReferenceBinding(reference, i); + } + } + } + // As in the native compiler (see IMPORTER::MapAssemblyRefToAid), we compare against the // compilation (i.e. source) assembly as a last resort. We follow the native approach of // skipping the public key comparison since we have yet to compute it. diff --git a/src/Compilers/Test/Resources/Core/CompilerTestResources.vbproj b/src/Compilers/Test/Resources/Core/CompilerTestResources.vbproj index f812b0e7a599e895fd97d78142a073acedda44f5..35eaad6b2d234a812b68bced13c52f4e2ab09522 100644 --- a/src/Compilers/Test/Resources/Core/CompilerTestResources.vbproj +++ b/src/Compilers/Test/Resources/Core/CompilerTestResources.vbproj @@ -401,6 +401,8 @@ + + diff --git a/src/Compilers/Test/Resources/Core/WinRt/MakeWinMds.cmd b/src/Compilers/Test/Resources/Core/WinRt/MakeWinMds.cmd index b4fde6e631827d1a5a5d25b000b197bc5eb1c4db..be139a5c3284e2ad3d297e14dd9cbcf8d3989f76 100644 --- a/src/Compilers/Test/Resources/Core/WinRt/MakeWinMds.cmd +++ b/src/Compilers/Test/Resources/Core/WinRt/MakeWinMds.cmd @@ -5,3 +5,4 @@ ilasm W1.il /mdv="WindowsRuntime 1.2" /msv:1.1 /dll /out=W1.winmd ilasm W2.il /mdv="WindowsRuntime 1.2" /msv:1.1 /dll /out=W2.winmd ilasm WB.il /mdv="WindowsRuntime 1.2" /msv:1.1 /dll /out=WB.winmd ilasm WB_Version1.il /mdv="WindowsRuntime 1.2" /msv:1.1 /dll /out=WB_Version1.winmd +ilasm WImpl.il /mdv="WindowsRuntime 1.3" /msv:1.1 /dll /out=WImpl.winmd diff --git a/src/Compilers/Test/Resources/Core/WinRt/WImpl.il b/src/Compilers/Test/Resources/Core/WinRt/WImpl.il new file mode 100644 index 0000000000000000000000000000000000000000..34bfe896330010512bab80faa352cec12ccaf862 --- /dev/null +++ b/src/Compilers/Test/Resources/Core/WinRt/WImpl.il @@ -0,0 +1,24 @@ +.assembly extern windowsruntime ITest {} +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 255:255:255:255 +} + +.assembly windowsruntime WImpl +{ + .hash algorithm 0x00008004 + .ver 255:255:255:255 +} + +.module WImpl.winmd + +.class public auto ansi windowsruntime sealed WImpl + extends System.Object + implements [ITest]ITest +{ + .method public hidebysig specialname rtspecialname + instance void .ctor() runtime managed + { + } +} \ No newline at end of file diff --git a/src/Compilers/Test/Resources/Core/WinRt/WImpl.winmd b/src/Compilers/Test/Resources/Core/WinRt/WImpl.winmd new file mode 100644 index 0000000000000000000000000000000000000000..8566f7ad82ea9993be1381e17fb0ebb7a85d34fe Binary files /dev/null and b/src/Compilers/Test/Resources/Core/WinRt/WImpl.winmd differ diff --git a/src/Compilers/Test/Resources/Core/WinRt/WinRt.Designer.vb b/src/Compilers/Test/Resources/Core/WinRt/WinRt.Designer.vb index 093950b60b2227e94b9405a15846046de393cfb2..bbe9423ec4cbaddbcb6fb622459d605ddcaba97e 100644 --- a/src/Compilers/Test/Resources/Core/WinRt/WinRt.Designer.vb +++ b/src/Compilers/Test/Resources/Core/WinRt/WinRt.Designer.vb @@ -1,7 +1,7 @@ '------------------------------------------------------------------------------ ' ' This code was generated by a tool. -' Runtime Version:4.0.30319.18326 +' Runtime Version:4.0.30319.42000 ' ' Changes to this file may cause incorrect behavior and will be lost if ' the code is regenerated. @@ -104,6 +104,16 @@ Namespace TestResources End Get End Property + ''' + ''' Looks up a localized resource of type System.Byte[]. + ''' + Public Shared ReadOnly Property WImpl() As Byte() + Get + Dim obj As Object = ResourceManager.GetObject("WImpl", resourceCulture) + Return CType(obj,Byte()) + End Get + End Property + ''' ''' Looks up a localized resource of type System.Byte[]. ''' diff --git a/src/Compilers/Test/Resources/Core/WinRt/WinRt.resx b/src/Compilers/Test/Resources/Core/WinRt/WinRt.resx index b526c60c676b6f7d5967b93dfc794cd57b805750..44beaf21bbca2363ceb5bfd0e489ff5201f8e6da 100644 --- a/src/Compilers/Test/Resources/Core/WinRt/WinRt.resx +++ b/src/Compilers/Test/Resources/Core/WinRt/WinRt.resx @@ -147,4 +147,7 @@ WinMDPrefixing.ildump;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + WImpl.winmd;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + diff --git a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb index 95d90e42d8a863e0c7ae7db2d9d935052f46e584..ed66ecaa56564d7ca5f75acbef45a319db909067 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb @@ -758,13 +758,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim methodSym = DirectCast(implementingMember, SourceMemberMethodSymbol) Dim diagbag = DiagnosticBag.GetInstance() - Dim boundClause = methodSym.BindSingleHandlesClause(handlesClause, - binder, - diagbag, - eventSymbolBuilder, - containerSymbolBuilder, - propertySymbolBuilder, - resultKind) + methodSym.BindSingleHandlesClause(handlesClause, + binder, + diagbag, + eventSymbolBuilder, + containerSymbolBuilder, + propertySymbolBuilder, + resultKind) diagbag.Free() End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ReferenceManager.vb b/src/Compilers/VisualBasic/Portable/Symbols/ReferenceManager.vb index a9f629f01af58691fd3e32fde6eef2a405cb02f3..f6d84dd3afb527741abef3aeb3b19dadb125815a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ReferenceManager.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ReferenceManager.vb @@ -869,6 +869,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return _assembly.DeclaresTheObjectClass End Get End Property + + Public Overrides ReadOnly Property SourceCompilation As Compilation + Get + Return Nothing + End Get + End Property End Class Private NotInheritable Class AssemblyDataForCompilation @@ -955,6 +961,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return _compilation.DeclaresTheObjectClass End Get End Property + + Public Overrides ReadOnly Property SourceCompilation As Compilation + Get + Return _compilation + End Get + End Property End Class ''' diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb index d9e5152725a5fae78c11d900c5aca4dbd1a7de3e..16a7703b757ce7dc58cc17e2fee159ed918a1a54 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb @@ -743,6 +743,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols diagBag) End If + Select Case ContainingType.TypeKind + Case TypeKind.Interface, TypeKind.Structure, TypeKind.Enum, TypeKind.Delegate + ' Handles clause is invalid in this context. + Return Nothing + + Case TypeKind.Class, TypeKind.Module + ' Valid context + + Case Else + Debug.Assert(False) + End Select + Dim receiverOpt As BoundExpression = Nothing ' synthesize delegate creation (may involve relaxation) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb index 5da84e18b431e820c7da090e05afc94cb9739c64..849721ac3624e31618af4c820e49d9b7c3e3423f 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb @@ -2100,5 +2100,114 @@ End Structure } ]]>) End Sub + + + Public Sub HandlesInAnInterface() + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +, options:=TestOptions.DebugDll) + + Dim expected = +BC30270: 'Handles' is not valid on an interface method declaration. + Sub M() Handles Me.E + ~~~~~~~~~~~~ + + + compilation.AssertTheseDiagnostics(expected) + compilation.AssertTheseEmitDiagnostics(expected) + + Dim tree = compilation.SyntaxTrees.Single() + Dim node = tree.GetRoot().DescendantNodes().OfType(Of IdentifierNameSyntax)().Where(Function(n) n.Identifier.ValueText = "E").Single() + + Assert.Equal("Me.E", node.Parent.ToString()) + + Dim semanticModel = compilation.GetSemanticModel(tree) + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + Assert.Equal("Event I.E()", symbolInfo.Symbol.ToTestDisplayString()) + End Sub + + + Public Sub HandlesInAStruct() + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +, options:=TestOptions.DebugDll) + + Dim expected = +BC30728: Methods declared in structures cannot have 'Handles' clauses. + Sub M() Handles Me.E + ~ + + + compilation.AssertTheseDiagnostics(expected) + compilation.AssertTheseEmitDiagnostics(expected) + + Dim tree = compilation.SyntaxTrees.Single() + Dim node = tree.GetRoot().DescendantNodes().OfType(Of IdentifierNameSyntax)().Where(Function(n) n.Identifier.ValueText = "E").Single() + + Assert.Equal("Me.E", node.Parent.ToString()) + + Dim semanticModel = compilation.GetSemanticModel(tree) + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + Assert.Equal("Event S.E()", symbolInfo.Symbol.ToTestDisplayString()) + End Sub + + + Public Sub HandlesInAnEnum() + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +, options:=TestOptions.DebugDll) + + Dim expected = +BC30185: 'Enum' must end with a matching 'End Enum'. +Enum E1 +~~~~~~~ +BC30280: Enum 'E1' must contain at least one member. +Enum E1 + ~~ +BC30619: Statement cannot appear within an Enum body. End of Enum assumed. + Sub M() Handles Me.E + ~~~~~~~~~~~~~~~~~~~~ +BC30590: Event 'E' cannot be found. + Sub M() Handles Me.E + ~ +BC30184: 'End Enum' must be preceded by a matching 'Enum'. +End Enum +~~~~~~~~ + + + compilation.AssertTheseDiagnostics(expected) + compilation.AssertTheseEmitDiagnostics(expected) + + Dim tree = compilation.SyntaxTrees.Single() + Dim node = tree.GetRoot().DescendantNodes().OfType(Of IdentifierNameSyntax)().Where(Function(n) n.Identifier.ValueText = "E").Single() + + Assert.Equal("Me.E", node.Parent.ToString()) + + Dim semanticModel = compilation.GetSemanticModel(tree) + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + Assert.Null(symbolInfo.Symbol) + Assert.Equal(0, symbolInfo.CandidateSymbols.Length) + End Sub + End Class End Namespace diff --git a/src/EditorFeatures/Test2/NavigationBar/VisualBasicNavigationBarTests.vb b/src/EditorFeatures/Test2/NavigationBar/VisualBasicNavigationBarTests.vb index 29e407fc2064d4b19d746136b96d86a49833bb6b..3d36b343dd7e009251fdd66d219a1272317b50fc 100644 --- a/src/EditorFeatures/Test2/NavigationBar/VisualBasicNavigationBarTests.vb +++ b/src/EditorFeatures/Test2/NavigationBar/VisualBasicNavigationBarTests.vb @@ -448,6 +448,207 @@ End Class Item("CancelKeyPress", Glyph.EventPublic, hasNavigationSymbolId:=False)})) End Sub + + Public Sub WithEventsField_EventsFromInheritedInterfaces() + AssertItemsAre( + + + +Interface I1 + Event I1Event(sender As Object, e As EventArgs) +End Interface + +Interface I2 + Event I2Event(sender As Object, e As EventArgs) +End Interface + +Interface I3 + Inherits I1, I2 + Event I3Event(sender As Object, e As EventArgs) +End Interface + +Class Test + WithEvents i3 As I3 +End Class + + + , + Item("I1", Glyph.InterfaceInternal, bolded:=True, children:={ + Item("I1Event", Glyph.EventPublic, bolded:=True)}), + Item("I2", Glyph.InterfaceInternal, bolded:=True, children:={ + Item("I2Event", Glyph.EventPublic, bolded:=True)}), + Item("I3", Glyph.InterfaceInternal, bolded:=True, children:={ + Item("I3Event", Glyph.EventPublic, bolded:=True)}), + Item("Test", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item("i3", Glyph.FieldPrivate, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("I1Event", Glyph.EventPublic, hasNavigationSymbolId:=False), + Item("I2Event", Glyph.EventPublic, hasNavigationSymbolId:=False), + Item("I3Event", Glyph.EventPublic, hasNavigationSymbolId:=False)})) + End Sub + + + Public Sub DoNotIncludeShadowedEvents() + AssertItemsAre( + + + +Class B + Event E(sender As Object, e As EventArgs) +End Class + +Class C + Inherits B + + Shadows Event E(sender As Object, e As EventArgs) +End Class + +Class Test + WithEvents c As C +End Class + + + , + Item("B", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False), + Item("E", Glyph.EventPublic, bolded:=True)}), + Item(String.Format(VBEditorResources.Events, "B"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPublic, hasNavigationSymbolId:=False)}), + Item("C", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False), + Item("E", Glyph.EventPublic, bolded:=True)}), + Item(String.Format(VBEditorResources.Events, "C"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPublic, hasNavigationSymbolId:=False)}), ' Only one E under the "(C Events)" node + Item("Test", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item("c", Glyph.FieldPrivate, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPublic, hasNavigationSymbolId:=False)})) ' Only one E for WithEvents handling + End Sub + + + Public Sub EventList_EnsureInternalEventsInEventListAndInInheritedEventList() + AssertItemsAre( + + + +Class C + Event E() +End Class + +Class D + Inherits C +End Class + + + , + Item("C", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False), + Item("E", Glyph.EventPublic, bolded:=True)}), + Item(String.Format(VBEditorResources.Events, "C"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPublic, hasNavigationSymbolId:=False)}), + Item("D", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item(String.Format(VBEditorResources.Events, "D"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPublic, hasNavigationSymbolId:=False)})) + + End Sub + + + Public Sub EventList_EnsurePrivateEventsInEventListButNotInInheritedEventList() + AssertItemsAre( + + + +Class C + Private Event E() +End Class + +Class D + Inherits C +End Class + + + , + Item("C", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False), + Item("E", Glyph.EventPrivate, bolded:=True)}), + Item(String.Format(VBEditorResources.Events, "C"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E", Glyph.EventPrivate, hasNavigationSymbolId:=False)}), + Item("D", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)})) + End Sub + + + Public Sub EventList_TestAccessibilityThroughNestedAndDerivedTypes() + AssertItemsAre( + + + +Class C + Public Event E0() + Protected Event E1() + Private Event E2() + + Class N1 + Class N2 + Inherits C + + End Class + End Class +End Class + +Class D2 + Inherits C + +End Class + +Class T + WithEvents c As C +End Class + + + , + Item("C", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False), + Item("E0", Glyph.EventPublic, bolded:=True), + Item("E1", Glyph.EventProtected, bolded:=True), + Item("E2", Glyph.EventPrivate, bolded:=True)}), + Item(String.Format(VBEditorResources.Events, "C"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E0", Glyph.EventPublic, hasNavigationSymbolId:=False), + Item("E1", Glyph.EventProtected, hasNavigationSymbolId:=False), + Item("E2", Glyph.EventPrivate, hasNavigationSymbolId:=False)}), + Item("D2", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item(String.Format(VBEditorResources.Events, "D2"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E0", Glyph.EventPublic, hasNavigationSymbolId:=False), + Item("E1", Glyph.EventProtected, hasNavigationSymbolId:=False)}), + Item("N1 (C)", Glyph.ClassPublic, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item("N2 (C.N1)", Glyph.ClassPublic, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item(String.Format(VBEditorResources.Events, "N2"), Glyph.EventPublic, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E0", Glyph.EventPublic, hasNavigationSymbolId:=False), + Item("E1", Glyph.EventProtected, hasNavigationSymbolId:=False), + Item("E2", Glyph.EventPrivate, hasNavigationSymbolId:=False)}), + Item("T", Glyph.ClassInternal, bolded:=True, children:={ + Item(NavigationItemNew, Glyph.MethodPublic, hasNavigationSymbolId:=False), + Item("Finalize", Glyph.MethodProtected, hasNavigationSymbolId:=False)}), + Item("c", Glyph.FieldPrivate, hasNavigationSymbolId:=False, indent:=1, children:={ + Item("E0", Glyph.EventPublic, hasNavigationSymbolId:=False)})) + End Sub + Public Sub GenerateEventHandler() AssertGeneratedResultIs( diff --git a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicNavigationBarItemService.vb b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicNavigationBarItemService.vb index 0128643673be60c724fd3ee45d0399874623baad..7da09e63cb14f34be4f011ffe7c16b6627ea23cf 100644 --- a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicNavigationBarItemService.vb +++ b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicNavigationBarItemService.vb @@ -45,7 +45,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Dim semanticModel = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False) Contract.ThrowIfNull(semanticModel) - Dim types = GetTypesInFile(semanticModel, cancellationToken) + Dim typesAndDeclarations = GetTypesAndDeclarationsInFile(semanticModel, cancellationToken) Dim typeItems As New List(Of NavigationBarItem) Dim typeSymbolIndexProvider As New NavigationBarSymbolIdIndexProvider(caseSensitive:=False) @@ -53,8 +53,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Dim symbolDeclarationService = document.GetLanguageService(Of ISymbolDeclarationService) Dim workspaceSupportsDocumentChanges = document.Project.Solution.Workspace.CanApplyChange(ApplyChangesKind.ChangeDocument) - For Each typeSymbol In types - typeItems.AddRange(CreateItemsForType(typeSymbol, typeSymbolIndexProvider.GetIndexForSymbolId(typeSymbol.GetSymbolKey()), semanticModel, workspaceSupportsDocumentChanges, symbolDeclarationService, cancellationToken)) + For Each typeAndDeclaration In typesAndDeclarations + Dim type = typeAndDeclaration.Item1 + Dim position = typeAndDeclaration.Item2.SpanStart + typeItems.AddRange(CreateItemsForType(type, position, typeSymbolIndexProvider.GetIndexForSymbolId(type.GetSymbolKey()), semanticModel, workspaceSupportsDocumentChanges, symbolDeclarationService, cancellationToken)) Next Return typeItems @@ -65,23 +67,23 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Return TypeOf item IsNot AbstractGenerateCodeItem End Function - Private Function GetTypesInFile(semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of INamedTypeSymbol) + Private Function GetTypesAndDeclarationsInFile(semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of Tuple(Of INamedTypeSymbol, SyntaxNode)) Try - Dim types As New HashSet(Of INamedTypeSymbol) + Dim typesAndDeclarations As New Dictionary(Of INamedTypeSymbol, SyntaxNode) Dim nodesToVisit As New Stack(Of SyntaxNode) nodesToVisit.Push(DirectCast(semanticModel.SyntaxTree.GetRoot(cancellationToken), SyntaxNode)) Do Until nodesToVisit.IsEmpty If cancellationToken.IsCancellationRequested Then - Return SpecializedCollections.EmptyEnumerable(Of INamedTypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of Tuple(Of INamedTypeSymbol, SyntaxNode))() End If Dim node = nodesToVisit.Pop() Dim type = TryCast(semanticModel.GetDeclaredSymbol(node, cancellationToken), INamedTypeSymbol) If type IsNot Nothing Then - types.Add(type) + typesAndDeclarations(type) = node End If If TypeOf node Is MethodBlockBaseSyntax OrElse @@ -99,13 +101,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Next Loop - Return types.OrderBy(Function(t) t.Name) + Return typesAndDeclarations.Select(Function(kvp) Tuple.Create(kvp.Key, kvp.Value)).OrderBy(Function(t) t.Item1.Name) Catch ex As Exception When FatalError.ReportUnlessCanceled(ex) Throw ExceptionUtilities.Unreachable End Try End Function Private Function CreateItemsForType(type As INamedTypeSymbol, + position As Integer, typeSymbolIdIndex As Integer, semanticModel As SemanticModel, workspaceSupportsDocumentChanges As Boolean, @@ -120,6 +123,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar If type.TypeKind <> TypeKind.Interface Then Dim typeEvents = CreateItemForEvents( type, + position, type, eventContainer:=Nothing, semanticModel:=semanticModel, @@ -139,6 +143,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar items.Add( CreateItemForEvents( type, + position, propertySymbol.Type, propertySymbol, semanticModel, @@ -279,6 +284,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar ''' If this is an entry for a WithEvents member, the WithEvents ''' property itself. Private Function CreateItemForEvents(containingType As INamedTypeSymbol, + position As Integer, eventType As ITypeSymbol, eventContainer As IPropertySymbol, semanticModel As SemanticModel, @@ -288,10 +294,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Dim rightHandMemberItems As New List(Of NavigationBarItem) - ' Get all of the events and methods implementing them. We must include events from base - ' types, as well as static events. - Dim allEvents = eventType.GetBaseTypesAndThis().SelectMany(Function(t) t.GetMembers()).OfType(Of IEventSymbol)().OrderBy(Function(e) e.Name) - Dim accessibleEvents = allEvents.Where(Function(e) e.IsAccessibleWithin(containingType)) + Dim accessibleEvents = semanticModel.LookupSymbols(position, eventType).OfType(Of IEventSymbol).OrderBy(Function(e) e.Name) + Dim methodsImplementingEvents = containingType.GetMembers().OfType(Of IMethodSymbol) _ .Where(Function(m) m.HandledEvents.Any(Function(he) Object.Equals(he.EventContainer, eventContainer))) @@ -299,10 +303,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar For Each method In methodsImplementingEvents For Each handledEvent In method.HandledEvents - Dim list As list(Of IMethodSymbol) = Nothing + Dim list As List(Of IMethodSymbol) = Nothing If Not eventToImplementingMethods.TryGetValue(handledEvent.EventSymbol, list) Then - list = New list(Of IMethodSymbol) + list = New List(Of IMethodSymbol) eventToImplementingMethods.Add(handledEvent.EventSymbol, list) End If diff --git a/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj b/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj index a7c039a6cc4fe9210026a4e24af4530df4368dae..01c8c4cf8b0da37b46042957c6ca6d0be0b93178 100644 --- a/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj +++ b/src/Samples/CSharp/AsyncPackage/AsyncPackage.csproj @@ -193,6 +193,6 @@ - + diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/AbstractProject.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/AbstractProject.cs index a9267eb4ce0d94d726a2f4ff218a79fcbc295765..46f72b65a370564e20dba6883bb005d292f4078c 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/AbstractProject.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/AbstractProject.cs @@ -413,7 +413,8 @@ private static string GetAssemblyName(string outputPath) // dev11 sometimes gives us output path w/o extension, so removing extension becomes problematic if (outputPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || outputPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || - outputPath.EndsWith(".netmodule", StringComparison.OrdinalIgnoreCase)) + outputPath.EndsWith(".netmodule", StringComparison.OrdinalIgnoreCase) || + outputPath.EndsWith(".winmdobj", StringComparison.OrdinalIgnoreCase)) { return Path.GetFileNameWithoutExtension(outputPath); }