/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/Binder_Imports.vb
256 строк
15 KB
AlekseyTs
Pool `BindingDiagnosticBag`s (#68108)
09 май 2023, 05:03
Не верифицирован
09 май 2023, 05:03
604c14b
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Generic Imports System.Threading Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic ''' <summary> ''' Data for Binder.BindImportClause that exposes dictionaries of ''' the members and aliases that have been bound during the ''' execution of BindImportClause. It is the responsibility of derived ''' classes to update the dictionaries in AddMember and AddAlias. ''' </summary> Friend MustInherit Class ImportData Protected Sub New(members As HashSet(Of NamespaceOrTypeSymbol), aliases As Dictionary(Of String, AliasAndImportsClausePosition), xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition)) Me.Members = members Me.Aliases = aliases Me.XmlNamespaces = xmlNamespaces End Sub Public ReadOnly Members As HashSet(Of NamespaceOrTypeSymbol) Public ReadOnly Aliases As Dictionary(Of String, AliasAndImportsClausePosition) Public ReadOnly XmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) Public MustOverride Sub AddMember(syntaxRef As SyntaxReference, member As NamespaceOrTypeSymbol, importsClausePosition As Integer, dependencies As IReadOnlyCollection(Of AssemblySymbol), isProjectImportsDeclaration As Boolean) Public MustOverride Sub AddAlias(syntaxRef As SyntaxReference, name As String, [alias] As AliasSymbol, importsClausePosition As Integer, dependencies As IReadOnlyCollection(Of AssemblySymbol)) End Class Partial Friend Class Binder ' Bind one import clause, add it to the correct collection of imports. ' Warnings and errors are emitted to the diagnostic bag, including detecting duplicates. ' Note that this binder should have been already been set up to only bind to things in the global namespace. Public Sub BindImportClause(importClauseSyntax As ImportsClauseSyntax, data As ImportData, diagBag As DiagnosticBag) ImportsBinder.BindImportClause(importClauseSyntax, Me, data, diagBag) End Sub ''' <summary> ''' The Imports binder handles binding of Imports statements in files, and also the project-level imports. ''' </summary> Private Class ImportsBinder ' Bind one import clause, add it to the correct collection of imports. ' Warnings and errors are emitted to the diagnostic bag, including detecting duplicates. ' Note that the binder should have been already been set up to only bind to things in the global namespace. Public Shared Sub BindImportClause(importClauseSyntax As ImportsClauseSyntax, binder As Binder, data As ImportData, diagBag As DiagnosticBag) Select Case importClauseSyntax.Kind Case SyntaxKind.SimpleImportsClause Dim simpleImportsClause = DirectCast(importClauseSyntax, SimpleImportsClauseSyntax) If simpleImportsClause.Alias Is Nothing Then BindMembersImportsClause(simpleImportsClause, binder, data, diagBag) Else BindAliasImportsClause(simpleImportsClause, binder, data, diagBag) End If Case SyntaxKind.XmlNamespaceImportsClause BindXmlNamespaceImportsClause(DirectCast(importClauseSyntax, XmlNamespaceImportsClauseSyntax), binder, data, diagBag) Case Else End Select End Sub ' Bind an alias imports clause. If it is OK, and also unique, add it to the dictionary. Private Shared Sub BindAliasImportsClause(aliasImportSyntax As SimpleImportsClauseSyntax, binder As Binder, data As ImportData, diagnostics As DiagnosticBag) Dim diagBag = BindingDiagnosticBag.GetInstance() Dim aliasesName = aliasImportSyntax.Name Dim aliasTarget As NamespaceOrTypeSymbol = binder.BindNamespaceOrTypeSyntax(aliasesName, diagBag) If aliasTarget.Kind <> SymbolKind.Namespace Then Dim type = TryCast(aliasTarget, TypeSymbol) If type Is Nothing OrElse type.IsDelegateType Then Binder.ReportDiagnostic(diagBag, aliasImportSyntax, ERRID.ERR_InvalidTypeForAliasesImport2, aliasTarget, aliasTarget.Name) End If End If Dim aliasIdentifier = aliasImportSyntax.Alias.Identifier Dim aliasText = aliasIdentifier.ValueText ' Parser checks for type characters on alias text, so don't need to check again here. ' Check for duplicate symbol. If data.Aliases.ContainsKey(aliasText) Then Binder.ReportDiagnostic(diagBag, aliasIdentifier, ERRID.ERR_DuplicateNamedImportAlias1, aliasText) Else ' Make sure that the Import's alias doesn't have the same name as a type or a namespace in the global namespace Dim conflictsWith = binder.Compilation.GlobalNamespace.GetMembers(aliasText) If Not conflictsWith.IsEmpty Then ' TODO: Note that symbol's name in this error message is supposed to include Class/Namespace word at the beginning. ' Might need to use special format for that parameter in the error message. Binder.ReportDiagnostic(diagBag, aliasImportSyntax, ERRID.ERR_ImportAliasConflictsWithType2, aliasText, conflictsWith(0)) Else If aliasTarget.Kind <> SymbolKind.ErrorType Then Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = aliasTarget.GetUseSiteInfo() If ShouldReportUseSiteErrorForAlias(useSiteInfo.DiagnosticInfo) Then Binder.ReportUseSite(diagBag, aliasImportSyntax, useSiteInfo) Else diagBag.AddDependencies(useSiteInfo) End If Else diagBag.DependenciesBag.Clear() End If ' We create the alias symbol even when the target is erroneous, ' so that we can bind to the alias and avoid cascading errors. ' As a result the further consumers of the aliases have to account for the error case. Dim aliasSymbol = New AliasSymbol(binder.Compilation, binder.ContainingNamespaceOrType, aliasText, aliasTarget, If(binder.BindingLocation = BindingLocation.ProjectImportsDeclaration, NoLocation.Singleton, aliasIdentifier.GetLocation())) data.AddAlias(binder.GetSyntaxReference(aliasImportSyntax), aliasText, aliasSymbol, aliasImportSyntax.SpanStart, DirectCast(diagBag.DependenciesBag, IReadOnlyCollection(Of AssemblySymbol))) End If End If diagnostics.AddRange(diagBag.DiagnosticBag) diagBag.Free() End Sub ''' <summary> ''' Checks use site error and returns True in case it should be reported for the alias. ''' In current implementation checks for errors #36924 and #36925 ''' </summary> Private Shared Function ShouldReportUseSiteErrorForAlias(useSiteErrorInfo As DiagnosticInfo) As Boolean Return useSiteErrorInfo IsNot Nothing AndAlso useSiteErrorInfo.Code <> ERRID.ERR_CannotUseGenericTypeAcrossAssemblyBoundaries AndAlso useSiteErrorInfo.Code <> ERRID.ERR_CannotUseGenericBaseTypeAcrossAssemblyBoundaries End Function ' Bind a members imports clause. If it is OK, and also unique, add it to the members imports set. Private Shared Sub BindMembersImportsClause(membersImportsSyntax As SimpleImportsClauseSyntax, binder As Binder, data As ImportData, diagnostics As DiagnosticBag) Dim diagBag = BindingDiagnosticBag.GetInstance() Debug.Assert(membersImportsSyntax.Alias Is Nothing) Dim importsName = membersImportsSyntax.Name Dim importedSymbol As NamespaceOrTypeSymbol = binder.BindNamespaceOrTypeSyntax(importsName, diagBag) If importedSymbol.Kind <> SymbolKind.Namespace Then Dim type = TryCast(importedSymbol, TypeSymbol) ' Non-aliased interface imports are disallowed If type Is Nothing OrElse type.IsDelegateType OrElse type.IsInterfaceType Then Binder.ReportDiagnostic(diagBag, membersImportsSyntax, ERRID.ERR_NonNamespaceOrClassOnImport2, importedSymbol, importedSymbol.Name) End If End If If importedSymbol.Kind <> SymbolKind.ErrorType Then ' Check for duplicate symbol. If data.Members.Contains(importedSymbol) Then ' NOTE: Dev10 doesn't report this error for project level imports. We still ' generate the error but filter it out when bind project level imports Binder.ReportDiagnostic(diagBag, importsName, ERRID.ERR_DuplicateImport1, importedSymbol) Else Dim importedSymbolIsValid As Boolean = True ' Disallow importing different instantiations of the same generic type. If importedSymbol.Kind = SymbolKind.NamedType Then Dim namedType = DirectCast(importedSymbol, NamedTypeSymbol) If namedType.IsGenericType Then namedType = namedType.OriginalDefinition For Each contender In data.Members If contender.OriginalDefinition Is namedType Then importedSymbolIsValid = False Binder.ReportDiagnostic(diagBag, importsName, ERRID.ERR_DuplicateRawGenericTypeImport1, namedType) Exit For End If Next End If End If If importedSymbolIsValid Then data.AddMember(binder.GetSyntaxReference(importsName), importedSymbol, membersImportsSyntax.SpanStart, DirectCast(diagBag.DependenciesBag, IReadOnlyCollection(Of AssemblySymbol)), binder.BindingLocation = BindingLocation.ProjectImportsDeclaration) End If End If End If diagnostics.AddRange(diagBag.DiagnosticBag) diagBag.Free() End Sub Private Shared Sub BindXmlNamespaceImportsClause(syntax As XmlNamespaceImportsClauseSyntax, binder As Binder, data As ImportData, diagnostics As DiagnosticBag) #If DEBUG Then Dim diagBag = BindingDiagnosticBag.GetInstance() #Else Dim diagBag = BindingDiagnosticBag.GetInstance(withDiagnostics:=True, withDependencies:=False) #End If Dim prefix As String = Nothing Dim namespaceName As String = Nothing Dim [namespace] As BoundExpression = Nothing Dim hasErrors As Boolean = False If binder.TryGetXmlnsAttribute(syntax.XmlNamespace, prefix, namespaceName, [namespace], hasErrors, fromImport:=True, diagnostics:=diagBag) AndAlso Not hasErrors Then Debug.Assert([namespace] Is Nothing) ' Binding should have been skipped. If data.XmlNamespaces.ContainsKey(prefix) Then ' "XML namespace prefix '{0}' is already declared." Binder.ReportDiagnostic(diagBag, syntax, ERRID.ERR_DuplicatePrefix, prefix) Else ' Do not expose any locations for project level xml namespaces. This matches the effective ' logic we have for aliases, which are given NoLocation.Singleton (which never translates to a ' DeclaringSyntaxReference). Dim reference = If(binder.BindingLocation = BindingLocation.ProjectImportsDeclaration, Nothing, binder.GetSyntaxReference(syntax)) data.XmlNamespaces.Add(prefix, New XmlNamespaceAndImportsClausePosition(namespaceName, syntax.SpanStart, reference)) End If End If #If DEBUG Then Debug.Assert(diagBag.DependenciesBag.Count = 0) #End If diagnostics.AddRange(diagBag.DiagnosticBag) diagBag.Free() End Sub End Class End Class End Namespace