diff --git a/Src/Compilers/CSharp/Test/Semantic/Semantics/SupressAccessibilityChecksTests.cs b/Src/Compilers/CSharp/Test/Semantic/Semantics/SupressAccessibilityChecksTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..c02da5d0457890bea9b24fb2b9b6b714921618a0 --- /dev/null +++ b/Src/Compilers/CSharp/Test/Semantic/Semantics/SupressAccessibilityChecksTests.cs @@ -0,0 +1,234 @@ +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics +{ + public class SupressAccessibilityChecksTests : CSharpTestBase + { + private static SemanticModel GetSemanticModelWithSuppressAccessChecks() + { + var compilationA = CreateCompilationWithMscorlib(@" +namespace N +{ + class A + { + A M() { return new A(); } + int _num; + } +}" + ); + + var referenceA = MetadataReference.CreateFromStream(compilationA.EmitToStream()); + + var compilationB = CreateCompilationWithMscorlib(@" +using A = N.A; + +class B +{ + void Main() + { + new A().M(); + } +} + +", new MetadataReference[] {referenceA}, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); + + var syntaxTree = compilationB.SyntaxTrees[0]; + return compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks: true); + } + + [Fact] + public void TestAccessPrivateMemberOfInternalType() + { + var semanticModel = GetSemanticModelWithSuppressAccessChecks(); + var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType().Single(); + var position = invocation.FullSpan.Start; + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name); + Assert.NotEmpty(semanticModel.LookupSymbols(position, name: "A")); + } + + [Fact] + public void TestAccessChecksInSpeculativeExpression() + { + var semanticModel = GetSemanticModelWithSuppressAccessChecks(); + var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType().Single(); + var position = invocation.FullSpan.Start; + + var exp = SyntaxFactory.ParseExpression("new A().M()._num"); + Assert.Equal("Int32", + semanticModel.GetSpeculativeTypeInfo(position, exp, SpeculativeBindingOption.BindAsExpression).Type.Name); + + Assert.Equal("_num", + semanticModel.GetSpeculativeSymbolInfo(position, exp, SpeculativeBindingOption.BindAsExpression).Symbol.Name); + } + + [Fact] + public void TestAccessChecksInSpeculativeSemanticModel() + { + var semanticModel = GetSemanticModelWithSuppressAccessChecks(); + var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType().Single(); + var position = invocation.FullSpan.Start; + + + SemanticModel speculativeSemanticModel; + var statement = SyntaxFactory.ParseStatement("var foo = new A().M();"); + + semanticModel.TryGetSpeculativeSemanticModel(position, statement, out speculativeSemanticModel); + var creationExpression = + speculativeSemanticModel.GetTypeInfo( + statement.DescendantNodes().OfType().Single()); + + Assert.Equal("A", creationExpression.Type.Name); + } + + + [Fact] + public void TestAccessChecksInsideLambdaExpression() + { + var source = @" +using System.Collections.Generic; + +class P { bool _p; } + +class C +{ + static void M() + { + var tmp = new List

(); + tmp.Find(a => true); + } +} +"; + + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateCompilationWithMscorlib(tree); + var model = comp.GetSemanticModel(tree,suppressAccessChecks: true); + + var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single().Body; + + var symbolInfo = model.GetSpeculativeSymbolInfo(expr.FullSpan.Start, + SyntaxFactory.ParseExpression("a._p"), + SpeculativeBindingOption.BindAsExpression); + + Assert.Equal("_p", symbolInfo.Symbol.Name); + } + + [Fact] + public void TestExtensionMethodInInternalClass() + { + var compilationA = CreateCompilationWithMscorlibAndSystemCore(@" +public class A +{ + A M() { return new A(); } + internal int _num; +} + +internal static class E +{ + internal static int InternalExtension(this A theClass, int newNum) + { + theClass._num = newNum; + + return newNum; + } +} +"); + + var referenceA = MetadataReference.CreateFromStream(compilationA.EmitToStream()); + + var compilationB = CreateCompilationWithMscorlib(@" +class B +{ + void Main() + { + new A().M(); + } +} + +", new MetadataReference[] { referenceA }, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); + + var syntaxTree = compilationB.SyntaxTrees[0]; + var semanticModel = compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks: true); + + var invocation = syntaxTree.GetRoot().DescendantNodes().OfType().Single(); + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name); + + var speculativeInvocation = SyntaxFactory.ParseExpression("new A().InternalExtension(67)"); + var position = invocation.FullSpan.Start; + + Assert.Equal("Int32", semanticModel.GetSpeculativeTypeInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Type.Name); + Assert.Equal("InternalExtension", semanticModel.GetSpeculativeSymbolInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Symbol.Name); + } + + [Fact] + public void TestGetSpeculativeSemanticModelForPropertyAccessorBody() + { + var compilation = CreateCompilationWithMscorlib(@" +class R +{ + private int _p; +} + +class C : R +{ + + private int M + { + set + { + int y = 1000; + } + } +} +"); + + var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@" +{ + int z = 0; + + _p = 123L; +} +"); + + var tree = compilation.SyntaxTrees[0]; + var root = tree.GetCompilationUnitRoot(); + var model = compilation.GetSemanticModel(tree, suppressAccessChecks: true); + + AccessorDeclarationSyntax accesorDecl = root.DescendantNodes().OfType().Single(); + + var speculatedMethod = accesorDecl.ReplaceNode(accesorDecl.Body, blockStatement); + + SemanticModel speculativeModel; + var success = + model.TryGetSpeculativeSemanticModelForMethodBody( + accesorDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel); + + Assert.True(success); + Assert.NotNull(speculativeModel); + + var p = + speculativeModel.SyntaxTree.GetRoot() + .DescendantNodes() + .OfType() + .Single(s => s.Identifier.ValueText == "_p"); + + var symbolSpeculation = + speculativeModel.GetSpeculativeSymbolInfo(p.FullSpan.Start, p, SpeculativeBindingOption.BindAsExpression); + + Assert.Equal("_p", symbolSpeculation.Symbol.Name); + + var typeSpeculation = + speculativeModel.GetSpeculativeTypeInfo(p.FullSpan.Start, p, SpeculativeBindingOption.BindAsExpression); + + Assert.Equal("Int32", typeSpeculation.Type.Name); + } + } +} diff --git a/Src/Compilers/VisualBasic/Test/Semantic/Compilation/SupressAccessibilityChecksTests.vb b/Src/Compilers/VisualBasic/Test/Semantic/Compilation/SupressAccessibilityChecksTests.vb new file mode 100644 index 0000000000000000000000000000000000000000..c23e636aadcbc01b9d4fde20bdd356ad14edcfb7 --- /dev/null +++ b/Src/Compilers/VisualBasic/Test/Semantic/Compilation/SupressAccessibilityChecksTests.vb @@ -0,0 +1,273 @@ +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests + +Imports Xunit + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests + Public Class SupressAccessibilityChecksTests + Inherits BasicTestBase + + Private Function GetSemanticModelWithSuppressAccessChecks() As SemanticModel + + + Dim compilationA = CreateVisualBasicCompilation(.Value) + + Dim referenceA = MetadataReference.CreateFromStream(compilationA.EmitToStream()) + + Dim compilationB = CreateVisualBasicCompilation(.Value, referencedAssemblies:=New MetadataReference() {referenceA}, + compilationOptions:=TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)) + + Dim syntaxTree2 = compilationB.SyntaxTrees(0) + Return compilationB.GetSemanticModel(syntaxTree2, suppressAccessChecks:=True) + End Function + + + Public Sub TestAccessPrivateMemberOfInternalType() + Dim semanticModel = GetSemanticModelWithSuppressAccessChecks() + Dim invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single() + Dim position = invocation.FullSpan.Start + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name) + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name) + + Assert.NotEmpty(semanticModel.LookupSymbols(position, name:="A")) + + End Sub + + + Public Sub TestAccessChecksInSpeculativeExpression() + Dim semanticModel = GetSemanticModelWithSuppressAccessChecks() + Dim invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single() + + Dim speculativeInvocation = SyntaxFactory.ParseExpression("New A().M()._num") + Dim position = invocation.FullSpan.Start + + Assert.Equal("Int32", semanticModel.GetSpeculativeTypeInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Type.Name) + Assert.Equal("_num", semanticModel.GetSpeculativeSymbolInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Symbol.Name) + End Sub + + + Public Sub TestAccessChecksInSpeculativeSemanticModel() + Dim semanticModel = GetSemanticModelWithSuppressAccessChecks() + Dim syntaxTree = semanticModel.SyntaxTree + Dim invocation = syntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single() + Dim position = invocation.FullSpan.Start + + Dim speculativeSemanticModel As SemanticModel = Nothing + Dim statement = DirectCast(SyntaxFactory.ParseExecutableStatement("Dim v = New A().M()"), ExecutableStatementSyntax) + + semanticModel.TryGetSpeculativeSemanticModel(position, statement, speculativeSemanticModel) + Dim creationExpression = speculativeSemanticModel.GetTypeInfo(statement.DescendantNodes().OfType(Of ObjectCreationExpressionSyntax)().Single()) + + Assert.Equal("A", creationExpression.Type.Name) + End Sub + + + Public Sub AccessChecksInsideLambdaExpression() + + Dim source = .Value + + Dim tree = SyntaxFactory.ParseSyntaxTree(source) + Dim comp = CreateCompilationWithMscorlib(tree) + Dim model = comp.GetSemanticModel(tree, suppressAccessChecks:=True) + + Dim root = tree.GetCompilationUnitRoot() + Dim expr = DirectCast(root.DescendantNodes().OfType(Of SingleLineLambdaExpressionSyntax)().Single().Body, ExpressionSyntax) + + Dim symbolInfo = model.GetSpeculativeSymbolInfo(expr.SpanStart, SyntaxFactory.ParseExpression("a._p"), SpeculativeBindingOption.BindAsExpression) + + Assert.Equal("_p", symbolInfo.Symbol.Name) + End Sub + + + Public Sub AccessCheckCrossAssemblyPrivateExtensions() + + Dim source = + + +Imports System.Runtime.CompilerServices + +Public Class A + + Function M() As A + + Return New A() + + End Function + + Friend _num As Integer + +End Class + +Friend Module E + + <Extension> + Friend Function InternalExtension(theClass As A, newNum As Integer) As Integer + + theClass._num = newNum + + Return newNum + + End Function +End Module + +Namespace System.Runtime.CompilerServices + + <AttributeUsage(AttributeTargets.Assembly Or AttributeTargets.Class Or AttributeTargets.Method)> + Class ExtensionAttribute + Inherits Attribute + End Class + +End Namespace + + + + + Dim compilationA = CreateCompilationWithMscorlibAndVBRuntime(source) + + Dim referenceA = MetadataReference.CreateFromStream(compilationA.EmitToStream()) + + Dim compilationB = CreateCompilationWithMscorlib(New String() {.Value}, New MetadataReference() {referenceA}, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)) + + Dim syntaxTree = compilationB.SyntaxTrees(0) + Dim semanticModel = compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks:=True) + + Dim invocation = syntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single() + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name) + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name) + + Dim speculativeInvocation = SyntaxFactory.ParseExpression("new A().InternalExtension(67)") + Dim position = invocation.FullSpan.Start + + Assert.Equal("Int32", semanticModel.GetSpeculativeTypeInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Type.Name) + Assert.Equal("InternalExtension", semanticModel.GetSpeculativeSymbolInfo(position, speculativeInvocation, SpeculativeBindingOption.BindAsExpression).Symbol.Name) + + Assert.NotNull(semanticModel.LookupSymbols(position, name:="A")) + End Sub + + + Public Sub TestGetSpeculativeSemanticModelForPropertyAccessorBody() + + Dim source = .Value + + Dim treet = SyntaxFactory.ParseSyntaxTree(source) + + Dim compilationA = CreateCompilationWithMscorlib(treet) + + Dim blockStatement = SyntaxFactory.ParseSyntaxTree(.Value).GetRoot() + + Dim tree = compilationA.SyntaxTrees(0) + Dim root = tree.GetCompilationUnitRoot() + Dim typeDecl = DirectCast(root.Members(1), ClassBlockSyntax) + Dim propertyDecl = DirectCast(typeDecl.Members(0), PropertyBlockSyntax) + Dim methodDecl = propertyDecl.Accessors(0) + Dim model = compilationA.GetSemanticModel(tree, suppressAccessChecks:=True) + + Dim speculatedMethod = + propertyDecl.ReplaceNode(propertyDecl.Accessors(0), blockStatement.ChildNodes().OfType(Of PropertyBlockSyntax).Single().Accessors(0)) + + Dim speculativeModel As SemanticModel = Nothing + + Dim success = + model.TryGetSpeculativeSemanticModelForMethodBody( + methodDecl.Statements(0).SpanStart, speculatedMethod.Accessors(0), speculativeModel) + + Assert.True(success) + Assert.NotNull(speculativeModel) + + Dim privateCandidate = + speculativeModel.SyntaxTree.GetRoot() _ + .DescendantNodes() _ + .OfType(Of IdentifierNameSyntax)() _ + .Single(Function(s) s.Identifier.ValueText = "_p") + + Dim symbolSpeculation = + speculativeModel.GetSpeculativeSymbolInfo(privateCandidate.FullSpan.Start, privateCandidate, + SpeculativeBindingOption.BindAsExpression) + + Dim typeSpeculation = + speculativeModel.GetSpeculativeTypeInfo(privateCandidate.FullSpan.Start, privateCandidate, + SpeculativeBindingOption.BindAsExpression) + + Assert.Equal("_p", symbolSpeculation.Symbol.Name) + Assert.Equal("Int32", typeSpeculation.Type.Name) + + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs index 205804acb6c4fae77b3b6b5e9d79d244a958d3db..7571c9ad6b99fd2998088738d6c287b18951e4d7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs @@ -614,13 +614,6 @@ private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diag AssemblySymbol within, ref HashSet useSiteDiagnostics) { - if (this.Flags.Includes(BinderFlags.SuppressAccessChecks)) - { - // This is an untested code path. If we - // reach here, add a corresponding test. - throw ExceptionUtilities.Unreachable; - } - return AccessCheck.IsSymbolAccessible(symbol, within, ref useSiteDiagnostics); } @@ -630,10 +623,6 @@ private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diag ref HashSet useSiteDiagnostics, TypeSymbol throughTypeOpt = null) { - if (this.Flags.Includes(BinderFlags.SuppressAccessChecks)) - { - return true; - } return AccessCheck.IsSymbolAccessible(symbol, within, ref useSiteDiagnostics, throughTypeOpt); } @@ -645,11 +634,6 @@ private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diag ref HashSet useSiteDiagnostics, ConsList basesBeingResolved = null) { - if (this.Flags.Includes(BinderFlags.SuppressAccessChecks)) - { - failedThroughTypeCheck = false; - return true; - } return AccessCheck.IsSymbolAccessible(symbol, within, throughTypeOpt, out failedThroughTypeCheck, ref useSiteDiagnostics, basesBeingResolved); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index cfe0765147b947010a66fc28b68432db229c0455..33c720ba950475c3e64e25fc3fae02170355fbd1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -1262,6 +1262,12 @@ internal bool IsAccessible(Symbol symbol, ref HashSet useSiteDia /// internal virtual bool IsAccessible(Symbol symbol, TypeSymbol accessThroughType, out bool failedThroughTypeCheck, ref HashSet useSiteDiagnostics, ConsList basesBeingResolved = null) { + if (this.Flags.Includes(BinderFlags.SuppressAccessChecks)) + { + failedThroughTypeCheck = false; + return true; + } + // By default, just delegate to containing binder. return Next.IsAccessible(symbol, accessThroughType, out failedThroughTypeCheck, ref useSiteDiagnostics, basesBeingResolved); } diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 3c6576f72a8bfade3dc215cacf62946b07c18c67..4499885edb5d99aebc58b0bba315fa2aef803ea5 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -1628,7 +1628,7 @@ internal PointerTypeSymbol CreatePointerTypeSymbol(TypeSymbol elementType) ///

/// Gets a new SyntaxTreeSemanticModel for the specified syntax tree. /// - public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree) + public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks) { if (syntaxTree == null) { @@ -1640,7 +1640,7 @@ public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree) throw new ArgumentException("tree"); } - return new SyntaxTreeSemanticModel(this, (SyntaxTree)syntaxTree); + return new SyntaxTreeSemanticModel(this, (SyntaxTree)syntaxTree, suppressAccessChecks); } // When building symbols from the declaration table (lazily), or inside a type, or when @@ -2729,9 +2729,9 @@ protected override Compilation CommonPreviousSubmission get { return _previousSubmission; } } - protected override SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree) + protected override SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks) { - return this.GetSemanticModel((SyntaxTree)syntaxTree); + return this.GetSemanticModel((SyntaxTree)syntaxTree, suppressAccessChecks); } protected override IEnumerable CommonSyntaxTrees diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 1c3a93b22149f10a2da49f42535f66254f49ff86..e0676a175aca7c4d4506eb2b3f784bb87436cdb1 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -51,6 +51,7 @@ internal abstract class CSharpSemanticModel : SemanticModel /// internal abstract CSharpSyntaxNode Root { get; } + // Is this node one that could be successfully interrogated by GetSymbolInfo/GetTypeInfo/GetMemberGroup/GetConstantValue? // WARN: If isSpeculative is true, then don't look at .Parent - there might not be one. internal static bool CanGetSemanticInfo(CSharpSyntaxNode node, bool allowNamedArgumentName = false, bool isSpeculative = false) @@ -2747,6 +2748,13 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp /// public abstract ITypeParameterSymbol GetDeclaredSymbol(TypeParameterSyntax typeParameter, CancellationToken cancellationToken = default(CancellationToken)); + internal BinderFlags GetSemanticModelBinderFlags() + { + return this.HasAccessChecksSuppressed + ? BinderFlags.SemanticModel | BinderFlags.SuppressAccessChecks + : BinderFlags.SemanticModel; + } + /// /// Given a foreach statement, get the symbol for the iteration variable /// @@ -2771,7 +2779,7 @@ public ILocalSymbol GetDeclaredSymbol(ForEachStatementSyntax forEachStatement, C return null; } - foreachBinder = foreachBinder.WithAdditionalFlags(BinderFlags.SemanticModel); + foreachBinder = foreachBinder.WithAdditionalFlags(GetSemanticModelBinderFlags()); LocalSymbol local = foreachBinder.Locals.FirstOrDefault(); return ((object)local != null && local.DeclarationKind == LocalDeclarationKind.ForEachIterationVariable) ? local @@ -2805,7 +2813,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration, C return null; } - catchBinder = catchBinder.WithAdditionalFlags(BinderFlags.SemanticModel); + catchBinder = enclosingBinder.GetBinder(catchClause).WithAdditionalFlags(GetSemanticModelBinderFlags()); LocalSymbol local = catchBinder.Locals.FirstOrDefault(); return ((object)local != null && local.DeclarationKind == LocalDeclarationKind.CatchVariable) ? local diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 19797bd4e5cec1884cec28eedc8aea29cdff4cf4..86125ab59a2f2abc77c83ebb5d4d6d1794a6a622 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -42,7 +42,7 @@ protected MemberSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode ro _compilation = compilation; _root = root; _memberSymbol = memberSymbol; - this.RootBinder = rootBinder.WithAdditionalFlags(BinderFlags.SemanticModel); + this.RootBinder = rootBinder.WithAdditionalFlags(GetSemanticModelBinderFlags()); _parentSemanticModelOpt = parentSemanticModelOpt; _speculatedPosition = speculatedPosition; } @@ -241,7 +241,7 @@ private Binder GetEnclosingBinder(CSharpSyntaxNode node, int position) binder = new TypeofBinder(typeOfArgument, binder); } - return binder.WithAdditionalFlags(BinderFlags.SemanticModel); + return binder.WithAdditionalFlags(GetSemanticModelBinderFlags()); } private static Binder AdjustBinderForPositionWithinStatement(int position, Binder binder, StatementSyntax stmt) @@ -1223,7 +1223,7 @@ internal override Binder GetEnclosingBinderInternal(int position) } Debug.Assert(result != null); - return result.WithAdditionalFlags(BinderFlags.SemanticModel); + return result.WithAdditionalFlags(GetSemanticModelBinderFlags()); } /// diff --git a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs index e7e4bed42441f9c18c15ea64f7aefb7abb5aae53..856a10eca667e387d5836f6cdf215f7293c3305e 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs @@ -97,7 +97,7 @@ private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel pa var methodSymbol = (MethodSymbol)this.MemberSymbol; var executablebinder = new ExecutableCodeBinder(body, methodSymbol, this.RootBinder.Next); // Strip off ExecutableCodeBinder (see ctor). - var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(BinderFlags.SemanticModel); + var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags()); speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position); return true; } diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 02e2b8b9f166c03d102108bcde92c315e8de5e35..2ad814437b0a6b2f7012e43818c6017a3047bb11 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -26,13 +26,16 @@ internal partial class SyntaxTreeSemanticModel : CSharpSemanticModel private readonly BinderFactory _binderFactory; private Func _createMemberModelFunction; + private readonly bool _hasAccessChecksSuppressed; private static readonly Func s_isMemberDeclarationFunction = IsMemberDeclaration; - internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree) + internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree, bool suppressAccessChecks = false) { _compilation = compilation; _syntaxTree = syntaxTree; + _hasAccessChecksSuppressed = suppressAccessChecks; + if (!this.Compilation.SyntaxTrees.Contains(syntaxTree)) { throw new ArgumentOutOfRangeException("tree", CSharpResources.TreeNotPartOfCompilation); @@ -81,6 +84,14 @@ public override SyntaxTree SyntaxTree } } + /// + /// Returns true if this is a SemanticModel that ignores accessibility rules when answering semantic questions. + /// + public override bool HasAccessChecksSuppressed + { + get { return _hasAccessChecksSuppressed; } + } + private void VerifySpanForGetDiagnostics(TextSpan? span) { if (span.HasValue && !this.Root.FullSpan.Contains(span.Value)) @@ -143,7 +154,7 @@ internal override Binder GetEnclosingBinderInternal(int position) // the binder for the compilation unit. if (position == 0 && position != token.SpanStart) { - return _binderFactory.GetBinder(this.Root, position).WithAdditionalFlags(BinderFlags.SemanticModel); + return _binderFactory.GetBinder(this.Root, position).WithAdditionalFlags(GetSemanticModelBinderFlags()); } MemberSemanticModel memberModel = GetMemberModel(position); @@ -152,7 +163,7 @@ internal override Binder GetEnclosingBinderInternal(int position) return memberModel.GetEnclosingBinder(position); } - return _binderFactory.GetBinder((CSharpSyntaxNode)token.Parent, position).WithAdditionalFlags(BinderFlags.SemanticModel); + return _binderFactory.GetBinder((CSharpSyntaxNode)token.Parent, position).WithAdditionalFlags(GetSemanticModelBinderFlags()); } internal override SymbolInfo GetSymbolInfoWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken)) @@ -891,6 +902,12 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node) private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) { var outer = _binderFactory.GetBinder(node); + + if (this.HasAccessChecksSuppressed) + { + outer = outer.WithAdditionalFlags(BinderFlags.SuppressAccessChecks); + } + switch (node.Kind()) { case SyntaxKind.Block: diff --git a/src/Compilers/CSharp/Portable/PublicAPI.txt b/src/Compilers/CSharp/Portable/PublicAPI.txt index 8bd65100d4c6a6f818f63adf4adcd8e6d70cc26c..19226759f19d9f48a5a731816644deb1de5618c4 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.txt @@ -10,7 +10,7 @@ Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Clone() Microsoft.CodeAnalysis.CSharp.CSharpCompilation.ContainsSyntaxTree(Microsoft.CodeAnalysis.SyntaxTree syntaxTree) Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDirectiveReference(Microsoft.CodeAnalysis.CSharp.Syntax.ReferenceDirectiveTriviaSyntax directive) Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol) -Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree) +Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks) Microsoft.CodeAnalysis.CSharp.CSharpCompilation.LanguageVersion.get Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Options.get Microsoft.CodeAnalysis.CSharp.CSharpCompilation.RemoveAllReferences() @@ -2436,7 +2436,7 @@ override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetAssemblyOrModu override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol) override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetEntryPoint(System.Threading.CancellationToken cancellationToken) override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol) -override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree) +override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks) override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType) override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSubmissionResultType(out bool hasValue) override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetTypeByMetadataName(string metadataName) diff --git a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj index 5ddc581975561e2ab06bf712a7a1e4ff3b4a06e2..bec257276ef86aebf8c8197c32076e994ae7dc4b 100644 --- a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj +++ b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj @@ -128,6 +128,7 @@ + diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 5f584357f72c0786890bc4fdbc22eb9ec9dbfa13..0361d63f112ed85c85521b20bced2314e79e95c9 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -159,12 +159,16 @@ public Compilation Clone() /// /// Gets a new for the specified syntax tree. /// - public SemanticModel GetSemanticModel(SyntaxTree syntaxTree) + /// The specificed syntax tree. + /// + /// True if the SemanticModel should ignore accessibility rules when answering semantic questions. + /// + public SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks = false) { - return CommonGetSemanticModel(syntaxTree); + return CommonGetSemanticModel(syntaxTree, suppressAccessChecks); } - protected abstract SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree); + protected abstract SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks); /// /// Returns a new INamedTypeSymbol representing an error type with the given name and arity diff --git a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs index b4cbaf631fc249eb95748d7929bc43aa5db598bb..f7ba2b348371fdd7623219efb2d961d16578af9a 100644 --- a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs +++ b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs @@ -62,6 +62,14 @@ public SyntaxTree SyntaxTree /// protected abstract SyntaxTree SyntaxTreeCore { get; } + /// + /// Returns true if this is a SemanticModel that ignores accessibility rules when answering semantic questions. + /// + public virtual bool HasAccessChecksSuppressed + { + get { return false; } + } + /// /// Gets symbol information about a syntax node. /// diff --git a/src/Compilers/Core/Portable/PublicAPI.txt b/src/Compilers/Core/Portable/PublicAPI.txt index b66ce2c2c73b28be783b78efbca940b362864b77..f97a8a672ab3884acf05f896b4e0601eed0617a0 100644 --- a/src/Compilers/Core/Portable/PublicAPI.txt +++ b/src/Compilers/Core/Portable/PublicAPI.txt @@ -117,7 +117,7 @@ Microsoft.CodeAnalysis.Compilation.GetAssemblyOrModuleSymbol(Microsoft.CodeAnaly Microsoft.CodeAnalysis.Compilation.GetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol) Microsoft.CodeAnalysis.Compilation.GetEntryPoint(System.Threading.CancellationToken cancellationToken) Microsoft.CodeAnalysis.Compilation.GetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol) -Microsoft.CodeAnalysis.Compilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree) +Microsoft.CodeAnalysis.Compilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks = false) Microsoft.CodeAnalysis.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType) Microsoft.CodeAnalysis.Compilation.GetSubmissionResultType(out bool hasValue) Microsoft.CodeAnalysis.Compilation.GetTypeByMetadataName(string fullyQualifiedMetadataName) @@ -1448,7 +1448,7 @@ abstract Microsoft.CodeAnalysis.Compilation.CommonGetAssemblyOrModuleSymbol(Micr abstract Microsoft.CodeAnalysis.Compilation.CommonGetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol) abstract Microsoft.CodeAnalysis.Compilation.CommonGetEntryPoint(System.Threading.CancellationToken cancellationToken) abstract Microsoft.CodeAnalysis.Compilation.CommonGetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol) -abstract Microsoft.CodeAnalysis.Compilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree) +abstract Microsoft.CodeAnalysis.Compilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks) abstract Microsoft.CodeAnalysis.Compilation.CommonGetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType) abstract Microsoft.CodeAnalysis.Compilation.CommonGetSubmissionResultType(out bool hasValue) abstract Microsoft.CodeAnalysis.Compilation.CommonGetTypeByMetadataName(string metadataName) @@ -2060,6 +2060,7 @@ virtual Microsoft.CodeAnalysis.Location.MetadataModule.get virtual Microsoft.CodeAnalysis.Location.SourceSpan.get virtual Microsoft.CodeAnalysis.Location.SourceTree.get virtual Microsoft.CodeAnalysis.MetadataReference.Display.get +virtual Microsoft.CodeAnalysis.SemanticModel.HasAccessChecksSuppressed.get virtual Microsoft.CodeAnalysis.SemanticModel.GetTopmostNodeForDiagnosticAnalysis(Microsoft.CodeAnalysis.ISymbol symbol, Microsoft.CodeAnalysis.SyntaxNode declaringSyntax) virtual Microsoft.CodeAnalysis.SymbolVisitor.DefaultVisit(Microsoft.CodeAnalysis.ISymbol symbol) virtual Microsoft.CodeAnalysis.SymbolVisitor.Visit(Microsoft.CodeAnalysis.ISymbol symbol) diff --git a/src/Compilers/VisualBasic/Portable/Binding/AttributeSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Binding/AttributeSemanticModel.vb index b6eaabda1644079d07d987bbf8a01719f244f1b2..58e601a0bfd5cd3a9ac62f0ce8386680a59eb0de 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/AttributeSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/AttributeSemanticModel.vb @@ -11,15 +11,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend NotInheritable Class AttributeSemanticModel Inherits MemberSemanticModel - Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0) - MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition) + Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSupressingAccessChecks As Boolean = False) + MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSupressingAccessChecks) End Sub ''' ''' Creates an AttributeSemanticModel that allows asking semantic questions about an attribute node. ''' - Friend Shared Function Create(binder As AttributeBinder) As AttributeSemanticModel - Return New AttributeSemanticModel(binder.Root, binder) + Friend Shared Function Create(binder As AttributeBinder, Optional isSupressingAccessChecks As Boolean = False) As AttributeSemanticModel + Return New AttributeSemanticModel(binder.Root, binder, isSupressingAccessChecks:=isSupressingAccessChecks) End Function ''' diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb index 9f617f3a767d4c7db430f1c5f48c22d94a0de8f3..8c9a0476794ee33c0d5febd88f87fd56e60fc96f 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb @@ -114,7 +114,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return m_containingBinder.BinderSpecificLookupOptions(options) End Function - Protected ReadOnly Property IgnoresAccessibility As Boolean + Friend ReadOnly Property IgnoresAccessibility As Boolean Get Return (BinderSpecificLookupOptions(Nothing) And LookupOptions.IgnoreAccessibility) = LookupOptions.IgnoreAccessibility diff --git a/src/Compilers/VisualBasic/Portable/Binding/InitializerSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Binding/InitializerSemanticModel.vb index 7a8e8ae95157ebd39df6310434658280930e9d48..570e759fc6f01a9646df9d4002e1897cbec05878 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/InitializerSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/InitializerSemanticModel.vb @@ -10,15 +10,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend NotInheritable Class InitializerSemanticModel Inherits MemberSemanticModel - Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0) - MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition) + Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSupressingAccessChecks As Boolean = False) + MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSupressingAccessChecks) End Sub ''' ''' Creates an InitializerSemanticModel that allows asking semantic questions about an initializer node. ''' - Friend Shared Function Create(binder As DeclarationInitializerBinder) As InitializerSemanticModel - Return New InitializerSemanticModel(binder.Root, binder) + Friend Shared Function Create(binder As DeclarationInitializerBinder, Optional isSupressingAccessChecks As Boolean = False) As InitializerSemanticModel + Return New InitializerSemanticModel(binder.Root, binder, isSupressingAccessChecks:=isSupressingAccessChecks) End Function ''' diff --git a/src/Compilers/VisualBasic/Portable/Binding/MemberSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Binding/MemberSemanticModel.vb index a66c737fafbe76d02b8c9f09eb72bc7da179ad68..7489087f337b4157611d08cf8d0c7855a450928d 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/MemberSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/MemberSemanticModel.vb @@ -22,12 +22,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' Fields specific to speculative MemberSemanticModel Private ReadOnly m_parentSemanticModelOpt As SyntaxTreeSemanticModel Private ReadOnly m_speculatedPosition As Integer + Private ReadOnly m_hasAccessChecksSuppressed As Boolean - Friend Sub New(root As VisualBasicSyntaxNode, rootBinder As Binder, parentSemanticModelOpt As SyntaxTreeSemanticModel, speculatedPosition As Integer) + Friend Sub New(root As VisualBasicSyntaxNode, rootBinder As Binder, parentSemanticModelOpt As SyntaxTreeSemanticModel, speculatedPosition As Integer, Optional isSupressingAccessChecks As Boolean = False) Debug.Assert(parentSemanticModelOpt Is Nothing OrElse Not parentSemanticModelOpt.IsSpeculativeSemanticModel, VBResources.ChainingSpeculativeModelIsNotSupported) m_Root = root - m_RootBinder = SemanticModelBinder.Mark(rootBinder) + m_hasAccessChecksSuppressed = isSupressingAccessChecks + m_RootBinder = SemanticModelBinder.Mark(rootBinder, isSupressingAccessChecks) m_parentSemanticModelOpt = parentSemanticModelOpt m_speculatedPosition = speculatedPosition End Sub @@ -62,16 +64,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + Public NotOverridable Overrides ReadOnly Property HasAccessChecksSuppressed As Boolean + Get + Return Me.m_hasAccessChecksSuppressed + End Get + End Property + Friend NotOverridable Overloads Overrides Function GetEnclosingBinder(position As Integer) As Binder Dim binder = GetEnclosingBinderInternal(Me.RootBinder, Me.Root, FindInitialNodeFromPosition(position), position) Debug.Assert(binder IsNot Nothing) - Return SemanticModelBinder.Mark(binder) + Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed) End Function Private Overloads Function GetEnclosingBinder(node As VisualBasicSyntaxNode) As Binder Dim binder = GetEnclosingBinderInternal(Me.RootBinder, Me.Root, node, node.SpanStart) Debug.Assert(binder IsNot Nothing) - Return SemanticModelBinder.Mark(binder) + Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed) End Function ' Get the bound node corresponding to the root. diff --git a/src/Compilers/VisualBasic/Portable/Binding/MethodBodySemanticModel.vb b/src/Compilers/VisualBasic/Portable/Binding/MethodBodySemanticModel.vb index 140b3b7ea6d357d7b8c254c1157486caab7e3841..8defa9a8230333c32316af62d0784bf98d49299f 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/MethodBodySemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/MethodBodySemanticModel.vb @@ -9,15 +9,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend NotInheritable Class MethodBodySemanticModel Inherits MemberSemanticModel - Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0) - MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition) + Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSupressingAccessChecks As Boolean = False) + MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSupressingAccessChecks:=isSupressingAccessChecks) End Sub ''' ''' Creates an MethodBodySemanticModel that allows asking semantic questions about an attribute node. ''' - Friend Shared Function Create(binder As MethodBodyBinder) As MethodBodySemanticModel - Return New MethodBodySemanticModel(binder.Root, binder) + Friend Shared Function Create(binder As MethodBodyBinder, Optional isSupressingAccessChecks As Boolean = False) As MethodBodySemanticModel + Return New MethodBodySemanticModel(binder.Root, binder, isSupressingAccessChecks:=isSupressingAccessChecks) End Function ''' @@ -53,7 +53,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic containingBinder = containingBinder.ContainingBinder Loop - Dim methodBodyBinder = BinderBuilder.CreateBinderForMethodBody(methodSymbol, method, SemanticModelBinder.Mark(namedTypeBinder)) + Dim methodBodyBinder = BinderBuilder.CreateBinderForMethodBody(methodSymbol, method, SemanticModelBinder.Mark(namedTypeBinder, HasAccessChecksSuppressed)) ' Wrap this binder with a BlockBaseBinder to hold onto the locals declared within the statement. Dim binder = New StatementListBinder(methodBodyBinder, method.Statements) @@ -91,8 +91,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend NotInheritable Class TopLevelCodeSemanticModel Inherits MemberSemanticModel - Public Sub New(binder As TopLevelCodeBinder) - MyBase.New(binder.Root, binder, parentSemanticModelOpt:=Nothing, speculatedPosition:=0) + Public Sub New(binder As TopLevelCodeBinder, Optional isSupressingAccessChecks As Boolean = False) + MyBase.New(binder.Root, binder, parentSemanticModelOpt:=Nothing, speculatedPosition:=0, isSupressingAccessChecks:=isSupressingAccessChecks) End Sub Friend Overrides Function TryGetSpeculativeSemanticModelForMethodBodyCore(parentModel As SyntaxTreeSemanticModel, position As Integer, method As MethodBlockBaseSyntax, ByRef speculativeModel As SemanticModel) As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Binding/SemanticModelBinder.vb b/src/Compilers/VisualBasic/Portable/Binding/SemanticModelBinder.vb index 93eee866b963aec8690447f9d62e69a7a0fae2ee..ca3d86c1fcc0bfd516ffe8c3ca7eec6260a82eee 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/SemanticModelBinder.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/SemanticModelBinder.vb @@ -8,15 +8,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend Class SemanticModelBinder Inherits Binder - Protected Sub New(containingBinder As Binder) + Private ReadOnly _ignoreAccessibility As Boolean = False + + Protected Sub New(containingBinder As Binder, Optional ignoreAccessibility As Boolean = False) MyBase.New(containingBinder) + + _ignoreAccessibility = ignoreAccessibility End Sub - Public Shared Function Mark(binder As Binder) As Binder + Public Shared Function Mark(binder As Binder, Optional ignoreAccessibility As Boolean = False) As Binder Return If( - binder.IsSemanticModelBinder, + binder.IsSemanticModelBinder AndAlso binder.IgnoresAccessibility = ignoreAccessibility, binder, - New SemanticModelBinder(binder)) + New SemanticModelBinder(binder, ignoreAccessibility)) + End Function + + Friend Overrides Function BinderSpecificLookupOptions(ByVal options As LookupOptions) As LookupOptions + If (_ignoreAccessibility) Then + Return MyBase.BinderSpecificLookupOptions(options) Or LookupOptions.IgnoreAccessibility + Else + Return MyBase.BinderSpecificLookupOptions(options) + End If End Function Public NotOverridable Overrides ReadOnly Property IsSemanticModelBinder As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb index 8e7cea133297120b687c8d9a01601e822d057e0f..d4209ec13f14dee57e40986f990615a7c1bce527 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb @@ -25,14 +25,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private ReadOnly _sourceModule As SourceModuleSymbol Private ReadOnly _syntaxTree As SyntaxTree Private ReadOnly _binderFactory As BinderFactory + Private ReadOnly _hasAccessChecksSuppressed As Boolean ' maps from a higher-level binder to an appropriate SemanticModel for the construct (such as a method, or initializer). - Private ReadOnly _semanticModelCache As New ConcurrentDictionary(Of Binder, MemberSemanticModel)() + Private ReadOnly _semanticModelCache As New ConcurrentDictionary(Of Tuple(Of Binder, Boolean), MemberSemanticModel)() - Friend Sub New(compilation As VisualBasicCompilation, sourceModule As SourceModuleSymbol, syntaxTree As SyntaxTree) + Friend Sub New(compilation As VisualBasicCompilation, sourceModule As SourceModuleSymbol, syntaxTree As SyntaxTree, Optional suppressAccessChecks As Boolean = False) _compilation = compilation _sourceModule = sourceModule _syntaxTree = syntaxTree + _hasAccessChecksSuppressed = suppressAccessChecks _binderFactory = New BinderFactory(sourceModule, syntaxTree) End Sub @@ -63,6 +65,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + ''' + ''' Returns true if this Is a SemanticModel that ignores accessibility rules when answering semantic questions. + ''' + Public NotOverridable Overrides ReadOnly Property HasAccessChecksSuppressed As Boolean + Get + Return Me._hasAccessChecksSuppressed + End Get + End Property + + ''' ''' Get all the errors within the syntax tree associated with this object. Includes errors involving compiling ''' method bodies or initializers, in addition to the errors returned by GetDeclarationDiagnostics and parse errors. @@ -131,27 +143,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function ' PERF: These shared variables avoid repeated allocation of Func(Of Binder, MemberSemanticModel) in GetMemberSemanticModel - Private Shared ReadOnly _methodBodySemanticModelCreator As Func(Of Binder, MemberSemanticModel) = Function(key As Binder) MethodBodySemanticModel.Create(DirectCast(key, MethodBodyBinder)) - Private Shared ReadOnly _initializerSemanticModelCreator As Func(Of Binder, MemberSemanticModel) = Function(key As Binder) InitializerSemanticModel.Create(DirectCast(key, DeclarationInitializerBinder)) - Private Shared ReadOnly _attributeSemanticModelCreator As Func(Of Binder, MemberSemanticModel) = Function(key As Binder) AttributeSemanticModel.Create(DirectCast(key, AttributeBinder)) - Private Shared ReadOnly _topLevelCodeSemanticModelCreator As Func(Of Binder, MemberSemanticModel) = Function(key As Binder) New TopLevelCodeSemanticModel(DirectCast(key, TopLevelCodeBinder)) + Private Shared ReadOnly _methodBodySemanticModelCreator As Func(Of Tuple(Of Binder, Boolean), MemberSemanticModel) = Function(key As Tuple(Of Binder, Boolean)) MethodBodySemanticModel.Create(DirectCast(key.Item1, MethodBodyBinder), key.Item2) + Private Shared ReadOnly _initializerSemanticModelCreator As Func(Of Tuple(Of Binder, Boolean), MemberSemanticModel) = Function(key As Tuple(Of Binder, Boolean)) InitializerSemanticModel.Create(DirectCast(key.Item1, DeclarationInitializerBinder), key.Item2) + Private Shared ReadOnly _attributeSemanticModelCreator As Func(Of Tuple(Of Binder, Boolean), MemberSemanticModel) = Function(key As Tuple(Of Binder, Boolean)) AttributeSemanticModel.Create(DirectCast(key.Item1, AttributeBinder), key.Item2) + Private Shared ReadOnly _topLevelCodeSemanticModelCreator As Func(Of Tuple(Of Binder, Boolean), MemberSemanticModel) = Function(key As Tuple(Of Binder, Boolean)) New TopLevelCodeSemanticModel(DirectCast(key.Item1, TopLevelCodeBinder), key.Item2) Public Function GetMemberSemanticModel(binder As Binder) As MemberSemanticModel If TypeOf binder Is MethodBodyBinder Then - Return _semanticModelCache.GetOrAdd(binder, _methodBodySemanticModelCreator) + Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _methodBodySemanticModelCreator) End If If TypeOf binder Is DeclarationInitializerBinder Then - Return _semanticModelCache.GetOrAdd(binder, _initializerSemanticModelCreator) + Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _initializerSemanticModelCreator) End If If TypeOf binder Is AttributeBinder Then - Return _semanticModelCache.GetOrAdd(binder, _attributeSemanticModelCreator) + Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _attributeSemanticModelCreator) End If If TypeOf binder Is TopLevelCodeBinder Then - Return _semanticModelCache.GetOrAdd(binder, _topLevelCodeSemanticModelCreator) + Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _topLevelCodeSemanticModelCreator) End If Return Nothing @@ -177,7 +189,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return model.GetEnclosingBinder(position) Else Dim binder As binder = _binderFactory.GetBinderForPosition(FindInitialNodeFromPosition(position), position) - Return SemanticModelBinder.Mark(binder) + Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed) End If End Function @@ -571,7 +583,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If Dim docCommentBinder = Me._binderFactory.GetBinderForPosition(node, node.SpanStart) - docCommentBinder = SemanticModelBinder.Mark(docCommentBinder) + docCommentBinder = SemanticModelBinder.Mark(docCommentBinder, HasAccessChecksSuppressed) If isCrefAttribute Then Dim symbols As ImmutableArray(Of Symbol) diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index 73141eddd7ed8f9f40aa854b86887d9f359cbcf7..56d10a80db158cd2b36d040425057746d4631889 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -1829,8 +1829,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' which has a cache. Therefore, one effectively clears the cache by discarding the ''' SemanticModel. ''' - Public Shadows Function GetSemanticModel(syntaxTree As SyntaxTree) As SemanticModel - Return New SyntaxTreeSemanticModel(Me, DirectCast(Me.SourceModule, SourceModuleSymbol), syntaxTree) + Public Shadows Function GetSemanticModel(syntaxTree As SyntaxTree, Optional suppressAccessChecks As Boolean = False) As SemanticModel + Return New SyntaxTreeSemanticModel(Me, DirectCast(Me.SourceModule, SourceModuleSymbol), syntaxTree, suppressAccessChecks) End Function #End Region @@ -2504,8 +2504,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property - Protected Overrides Function CommonGetSemanticModel(syntaxTree As SyntaxTree) As SemanticModel - Return Me.GetSemanticModel(syntaxTree) + Protected Overrides Function CommonGetSemanticModel(syntaxTree As SyntaxTree, suppressAccessChecks As Boolean) As SemanticModel + Return Me.GetSemanticModel(syntaxTree, suppressAccessChecks) End Function Protected Overrides ReadOnly Property CommonSyntaxTrees As IEnumerable(Of SyntaxTree) diff --git a/src/Compilers/VisualBasic/Portable/PublicAPI.txt b/src/Compilers/VisualBasic/Portable/PublicAPI.txt index ba9272b641eac1034f9cdcbfcae2469b01417e09..06c089870834df6c953496da79d7bd56244f32b6 100644 --- a/src/Compilers/VisualBasic/Portable/PublicAPI.txt +++ b/src/Compilers/VisualBasic/Portable/PublicAPI.txt @@ -3048,7 +3048,7 @@ Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.AddSyntaxTrees(trees A Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.ClassifyConversion(source As Microsoft.CodeAnalysis.ITypeSymbol, destination As Microsoft.CodeAnalysis.ITypeSymbol) Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.Clone() Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.ContainsSyntaxTree(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree) -Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.GetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree) +Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.GetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, suppressAccessChecks As Boolean = False) Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.LanguageVersion() Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.Options() Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.RemoveAllReferences() @@ -4360,7 +4360,7 @@ Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetAss Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetCompilationNamespace(namespaceSymbol As Microsoft.CodeAnalysis.INamespaceSymbol) Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetEntryPoint(cancellationToken As System.Threading.CancellationToken) Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetMetadataReference(_assemblySymbol As Microsoft.CodeAnalysis.IAssemblySymbol) -Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree) +Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, suppressAccessChecks As Boolean) Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSpecialType(specialType As Microsoft.CodeAnalysis.SpecialType) Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSubmissionResultType(ByRef hasValue As Boolean) Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetTypeByMetadataName(metadataName As String) diff --git a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj index e71e2d533f2b0821b4f1706182a7d2c510e2d534..6a2fd1c9eaf9b0d4dc8b151cb0b5c6931ff7ec0e 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj +++ b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj @@ -120,6 +120,7 @@ +