' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.IO
Imports System.Reflection
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Roslyn.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic
Friend MustInherit Class VisualBasicCompiler
Inherits CommonCompiler
Friend Const ResponseFileName As String = "vbc.rsp"
Friend Const VbcCommandLinePrefix = "vbc : " 'Common prefix String For VB diagnostic output with no location.
Private Shared s_responseFileName As String
Private ReadOnly _responseFile As String
Private ReadOnly _diagnosticFormatter As CommandLineDiagnosticFormatter
Protected Sub New(parser As VisualBasicCommandLineParser, responseFile As String, args As String(), clientDirectory As String, baseDirectory As String, sdkDirectory As String, additionalReferenceDirectories As String)
MyBase.New(parser, responseFile, args, clientDirectory, baseDirectory, sdkDirectory, additionalReferenceDirectories)
_diagnosticFormatter = New CommandLineDiagnosticFormatter(baseDirectory)
End Sub
Friend Overloads ReadOnly Property Arguments As VisualBasicCommandLineArguments
Get
Return DirectCast(MyBase.Arguments, VisualBasicCommandLineArguments)
End Get
End Property
Public Overrides ReadOnly Property DiagnosticFormatter As DiagnosticFormatter
Get
Return _diagnosticFormatter
End Get
End Property
Private Function ParseFile(consoleOutput As TextWriter,
parseOptions As VisualBasicParseOptions,
scriptParseOptions As VisualBasicParseOptions,
ByRef hadErrors As Boolean,
file As CommandLineSourceFile,
errorLogger As ErrorLogger) As SyntaxTree
Dim fileReadDiagnostics As New List(Of DiagnosticInfo)()
Dim content = ReadFileContent(file, fileReadDiagnostics, Arguments.Encoding, Arguments.ChecksumAlgorithm)
If content Is Nothing Then
ReportErrors(fileReadDiagnostics, consoleOutput, errorLogger)
fileReadDiagnostics.Clear()
hadErrors = True
Return Nothing
End If
Dim tree = VisualBasicSyntaxTree.ParseText(content, If(file.IsScript, scriptParseOptions, parseOptions), file.Path)
' prepopulate line tables.
' we will need line tables anyways and it is better to Not wait until we are in emit
' where things run sequentially.
Dim isHiddenDummy As Boolean
tree.GetMappedLineSpanAndVisibility(Nothing, isHiddenDummy)
Return tree
End Function
Public Overrides Function CreateCompilation(consoleOutput As TextWriter, touchedFilesLogger As TouchedFileLogger, errorLogger As ErrorLogger) As Compilation
Dim parseOptions = Arguments.ParseOptions
Dim scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script)
Dim hadErrors As Boolean = False
Dim sourceFiles As ImmutableArray(Of CommandLineSourceFile) = Arguments.SourceFiles
Dim trees(sourceFiles.Length - 1) As SyntaxTree
If Arguments.CompilationOptions.ConcurrentBuild Then
Parallel.For(0, sourceFiles.Length,
UICultureUtilities.WithCurrentUICulture(Of Integer)(
Sub(i As Integer)
' NOTE: order of trees is important!!
trees(i) = ParseFile(consoleOutput, parseOptions, scriptParseOptions, hadErrors, sourceFiles(i), errorLogger)
End Sub))
Else
For i = 0 To sourceFiles.Length - 1
' NOTE: order of trees is important!!
trees(i) = ParseFile(consoleOutput, parseOptions, scriptParseOptions, hadErrors, sourceFiles(i), errorLogger)
Next
End If
' If there were any errors while trying to read files, then exit.
If hadErrors Then
Return Nothing
End If
If Arguments.TouchedFilesPath IsNot Nothing Then
For Each file In sourceFiles
touchedFilesLogger.AddRead(file.Path)
Next
End If
Dim diagnostics = New List(Of DiagnosticInfo)()
Dim assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default
Dim referenceDirectiveResolver As MetadataFileReferenceResolver = Nothing
Dim metadataProvider As MetadataFileReferenceProvider = GetMetadataProvider()
Dim externalReferenceResolver = GetExternalMetadataResolver(touchedFilesLogger)
Dim resolvedReferences = ResolveMetadataReferences(externalReferenceResolver, metadataProvider, diagnostics, assemblyIdentityComparer, touchedFilesLogger, referenceDirectiveResolver)
If ReportErrors(diagnostics, consoleOutput, errorLogger) Then
Return Nothing
End If
If Arguments.OutputLevel = OutputLevel.Verbose Then
PrintReferences(resolvedReferences, consoleOutput)
End If
Dim strongNameProvider = New LoggingStrongNameProvider(Arguments.KeyFileSearchPaths, touchedFilesLogger)
Dim xmlFileResolver = New LoggingXmlFileResolver(Arguments.BaseDirectory, touchedFilesLogger)
' TODO: support for #load search paths
Dim sourceFileResolver = New LoggingSourceFileResolver(ImmutableArray(Of String).Empty, Arguments.BaseDirectory, touchedFilesLogger)
Dim result = VisualBasicCompilation.Create(
Arguments.CompilationName,
trees,
resolvedReferences,
Arguments.CompilationOptions.
WithMetadataReferenceResolver(New AssemblyReferenceResolver(referenceDirectiveResolver, metadataProvider)).
WithAssemblyIdentityComparer(assemblyIdentityComparer).
WithStrongNameProvider(strongNameProvider).
WithXmlReferenceResolver(xmlFileResolver).
WithSourceReferenceResolver(sourceFileResolver))
Return result
End Function
Private Sub PrintReferences(resolvedReferences As List(Of MetadataReference), consoleOutput As TextWriter)
For Each reference In resolvedReferences
If reference.Properties.Kind = MetadataImageKind.Module Then
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_MSG_ADDMODULE, Culture), reference.Display)
ElseIf reference.Properties.EmbedInteropTypes Then
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_MSG_ADDLINKREFERENCE, Culture), reference.Display)
Else
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_MSG_ADDREFERENCE, Culture), reference.Display)
End If
Next
consoleOutput.WriteLine()
End Sub
Protected Overrides Sub PrintError(Diagnostic As DiagnosticInfo, consoleOutput As TextWriter)
consoleOutput.Write(VisualBasicCompiler.VbcCommandLinePrefix)
consoleOutput.WriteLine(Diagnostic.ToString(Culture))
End Sub
Friend Overrides Function SuppressDefaultResponseFile(args As IEnumerable(Of String)) As Boolean
For Each arg In args
Select Case arg.ToLowerInvariant
Case "/noconfig", "-noconfig", "/nostdlib", "-nostdlib"
Return True
End Select
Next
Return False
End Function
'''
''' Print compiler logo
'''
'''
Public Overrides Sub PrintLogo(consoleOutput As TextWriter)
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_LogoLine1, Culture), GetToolName(), GetAssemblyFileVersion())
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_LogoLine2, Culture))
consoleOutput.WriteLine()
End Sub
Friend Overrides Function GetToolName() As String
Return ErrorFactory.IdToString(ERRID.IDS_ToolName, Culture)
End Function
'''
''' Print Commandline help message (up to 80 English characters per line)
'''
'''
Public Overrides Sub PrintHelp(consoleOutput As TextWriter)
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_VBCHelp, Culture))
End Sub
Protected Overrides Function TryGetCompilerDiagnosticCode(diagnosticId As String, ByRef code As UInteger) As Boolean
Return CommonCompiler.TryGetCompilerDiagnosticCode(diagnosticId, "BC", code)
End Function
Protected Overrides Function ResolveAnalyzersFromArguments(diagnostics As List(Of DiagnosticInfo), messageProvider As CommonMessageProvider, touchedFiles As TouchedFileLogger) As ImmutableArray(Of DiagnosticAnalyzer)
Return Arguments.ResolveAnalyzersFromArguments(LanguageNames.VisualBasic, diagnostics, messageProvider, touchedFiles, AddressOf LoadAssembly)
End Function
End Class
End Namespace