-
Notifications
You must be signed in to change notification settings - Fork 4k
/
VisualBasicCommandLineParser.vb
2339 lines (1957 loc) · 117 KB
/
VisualBasicCommandLineParser.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
' 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.Immutable
Imports System.Globalization
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.Text
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts
Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' The VisualBasicCommandLineParser class contains members used to perform various Visual Basic command line parsing operations.
''' </summary>
Public Class VisualBasicCommandLineParser
Inherits CommandLineParser
''' <summary>
''' Gets the current command line parser.
''' </summary>
Public Shared ReadOnly Property [Default] As New VisualBasicCommandLineParser()
''' <summary>
''' Gets the current interactive command line parser.
''' </summary>
Public Shared ReadOnly Property Script As New VisualBasicCommandLineParser(isScriptCommandLineParser:=True)
''' <summary>
''' Creates a new command line parser.
''' </summary>
''' <param name="isScriptCommandLineParser">An optional parameter indicating whether to create a interactive command line parser.</param>
Friend Sub New(Optional isScriptCommandLineParser As Boolean = False)
MyBase.New(VisualBasic.MessageProvider.Instance, isScriptCommandLineParser)
End Sub
Private Const s_win32Manifest As String = "win32manifest"
Private Const s_win32Icon As String = "win32icon"
Private Const s_win32Res As String = "win32resource"
''' <summary>
''' Gets the standard Visual Basic source file extension
''' </summary>
''' <returns>A string representing the standard Visual Basic source file extension.</returns>
Protected Overrides ReadOnly Property RegularFileExtension As String
Get
Return ".vb"
End Get
End Property
''' <summary>
''' Gets the standard Visual Basic script file extension.
''' </summary>
''' <returns>A string representing the standard Visual Basic script file extension.</returns>
Protected Overrides ReadOnly Property ScriptFileExtension As String
Get
Return ".vbx"
End Get
End Property
Friend NotOverridable Overrides Function CommonParse(args As IEnumerable(Of String), baseDirectory As String, sdkDirectoryOpt As String, additionalReferenceDirectories As String) As CommandLineArguments
Return Parse(args, baseDirectory, sdkDirectoryOpt, additionalReferenceDirectories)
End Function
''' <summary>
''' Parses a command line.
''' </summary>
''' <param name="args">A collection of strings representing the command line arguments.</param>
''' <param name="baseDirectory">The base directory used for qualifying file locations.</param>
''' <param name="sdkDirectory">The directory to search for mscorlib, or Nothing if not available.</param>
''' <param name="additionalReferenceDirectories">A string representing additional reference paths.</param>
''' <returns>A CommandLineArguments object representing the parsed command line.</returns>
Public Shadows Function Parse(args As IEnumerable(Of String), baseDirectory As String, sdkDirectory As String, Optional additionalReferenceDirectories As String = Nothing) As VisualBasicCommandLineArguments
Debug.Assert(baseDirectory Is Nothing OrElse PathUtilities.IsAbsolute(baseDirectory))
Const GenerateFileNameForDocComment As String = "USE-OUTPUT-NAME"
Dim diagnostics As List(Of Diagnostic) = New List(Of Diagnostic)()
Dim flattenedArgs = ArrayBuilder(Of String).GetInstance()
Dim scriptArgs As List(Of String) = If(IsScriptCommandLineParser, New List(Of String)(), Nothing)
' normalized paths to directories containing response files:
Dim responsePaths As New List(Of String)
FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory, responsePaths)
Dim displayLogo As Boolean = True
Dim displayHelp As Boolean = False
Dim displayVersion As Boolean = False
Dim displayLangVersions As Boolean = False
Dim outputLevel As OutputLevel = OutputLevel.Normal
Dim optimize As Boolean = False
Dim checkOverflow As Boolean = True
Dim concurrentBuild As Boolean = True
Dim deterministic As Boolean = False
Dim emitPdb As Boolean
Dim debugInformationFormat As DebugInformationFormat = If(PathUtilities.IsUnixLikePlatform, DebugInformationFormat.PortablePdb, DebugInformationFormat.Pdb)
Dim noStdLib As Boolean = False
Dim utf8output As Boolean = False
Dim outputFileName As String = Nothing
Dim outputRefFileName As String = Nothing
Dim refOnly As Boolean = False
Dim outputDirectory As String = baseDirectory
Dim documentationPath As String = Nothing
Dim errorLogOptions As ErrorLogOptions = Nothing
Dim parseDocumentationComments As Boolean = False ' Don't just null check documentationFileName because we want to do this even if the file name is invalid.
Dim outputKind As OutputKind = OutputKind.ConsoleApplication
Dim ssVersion As SubsystemVersion = SubsystemVersion.None
Dim languageVersion As LanguageVersion = LanguageVersion.Default
Dim mainTypeName As String = Nothing
Dim win32ManifestFile As String = Nothing
Dim win32ResourceFile As String = Nothing
Dim win32IconFile As String = Nothing
Dim noWin32Manifest As Boolean = False
Dim managedResources = New List(Of ResourceDescription)()
Dim sourceFiles = New List(Of CommandLineSourceFile)()
Dim hasSourceFiles = False
Dim additionalFiles = New List(Of CommandLineSourceFile)()
Dim analyzerConfigPaths = ArrayBuilder(Of String).GetInstance()
Dim embeddedFiles = New List(Of CommandLineSourceFile)()
Dim embedAllSourceFiles = False
Dim codepage As Encoding = Nothing
Dim checksumAlgorithm = SourceHashAlgorithms.Default
Dim defines As IReadOnlyDictionary(Of String, Object) = Nothing
Dim metadataReferences = New List(Of CommandLineReference)()
Dim analyzers = New List(Of CommandLineAnalyzerReference)()
Dim sdkPaths As New List(Of String)()
Dim libPaths As New List(Of String)()
Dim sourcePaths As New List(Of String)()
Dim keyFileSearchPaths = New List(Of String)()
Dim globalImports = New List(Of GlobalImport)
Dim rootNamespace As String = ""
Dim optionStrict As OptionStrict = OptionStrict.Off
Dim optionInfer As Boolean = False ' MSDN says: ...The compiler default for this option is /optioninfer-.
Dim optionExplicit As Boolean = True
Dim optionCompareText As Boolean = False
Dim embedVbCoreRuntime As Boolean = False
Dim platform As Platform = Platform.AnyCpu
Dim preferredUILang As CultureInfo = Nothing
Dim fileAlignment As Integer = 0
Dim baseAddress As ULong = 0
Dim highEntropyVA As Boolean = False
Dim vbRuntimePath As String = Nothing
Dim includeVbRuntimeReference As Boolean = True
Dim generalDiagnosticOption As ReportDiagnostic = ReportDiagnostic.Default
Dim pathMap As ImmutableArray(Of KeyValuePair(Of String, String)) = ImmutableArray(Of KeyValuePair(Of String, String)).Empty
' Diagnostic ids specified via /nowarn /warnaserror must be processed in case-insensitive fashion.
Dim specificDiagnosticOptionsFromRuleSet = New Dictionary(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
Dim specificDiagnosticOptionsFromGeneralArguments = New Dictionary(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
Dim specificDiagnosticOptionsFromSpecificArguments = New Dictionary(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
Dim specificDiagnosticOptionsFromNoWarnArguments = New Dictionary(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
Dim keyFileSetting As String = Nothing
Dim keyContainerSetting As String = Nothing
Dim delaySignSetting As Boolean? = Nothing
Dim moduleAssemblyName As String = Nothing
Dim moduleName As String = Nothing
Dim touchedFilesPath As String = Nothing
Dim features = New List(Of String)()
Dim reportAnalyzer As Boolean = False
Dim skipAnalyzers As Boolean = False
Dim publicSign As Boolean = False
Dim interactiveMode As Boolean = False
Dim instrumentationKinds As ArrayBuilder(Of InstrumentationKind) = ArrayBuilder(Of InstrumentationKind).GetInstance()
Dim sourceLink As String = Nothing
Dim ruleSetPath As String = Nothing
' Process ruleset files first so that diagnostic severity settings specified on the command line via
' /nowarn and /warnaserror can override diagnostic severity settings specified in the ruleset file.
If Not IsScriptCommandLineParser Then
For Each arg In flattenedArgs
Dim name As String = Nothing
Dim value As String = Nothing
If TryParseOption(arg, name, value) AndAlso (name = "ruleset") Then
Dim unquoted = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(unquoted) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<file>")
Continue For
End If
ruleSetPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory)
generalDiagnosticOption = GetDiagnosticOptionsFromRulesetFile(ruleSetPath, specificDiagnosticOptionsFromRuleSet, diagnostics)
End If
Next
End If
For Each arg In flattenedArgs
Debug.Assert(Not arg.StartsWith("@", StringComparison.Ordinal))
Dim name As String = Nothing
Dim value As String = Nothing
If Not TryParseOption(arg, name, value) Then
Dim builder = ArrayBuilder(Of String).GetInstance()
ParseFileArgument(arg.AsMemory(), baseDirectory, builder, diagnostics)
For Each path In builder
sourceFiles.Add(ToCommandLineSourceFile(path))
Next
builder.Free()
hasSourceFiles = True
Continue For
End If
Select Case name
Case "?", "help"
If value IsNot Nothing Then
Exit Select
End If
displayHelp = True
Continue For
Case "version"
If value IsNot Nothing Then
Exit Select
End If
displayVersion = True
Continue For
Case "r", "reference"
metadataReferences.AddRange(ParseAssemblyReferences(name, value, diagnostics, embedInteropTypes:=False))
Continue For
Case "a", "analyzer"
analyzers.AddRange(ParseAnalyzers(name, value, diagnostics))
Continue For
Case "d", "define"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<symbol_list>")
Continue For
End If
Dim conditionalCompilationDiagnostics As IEnumerable(Of Diagnostic) = Nothing
defines = ParseConditionalCompilationSymbols(value, conditionalCompilationDiagnostics, defines)
diagnostics.AddRange(conditionalCompilationDiagnostics)
Continue For
Case "imports", "import"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, If(name = "import", ":<str>", ":<import_list>"))
Continue For
End If
ParseGlobalImports(value, globalImports, diagnostics)
Continue For
Case "optionstrict"
value = RemoveQuotesAndSlashes(value)
If value Is Nothing Then
optionStrict = VisualBasic.OptionStrict.On
ElseIf String.Equals(value, "custom", StringComparison.OrdinalIgnoreCase) Then
optionStrict = VisualBasic.OptionStrict.Custom
Else
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "optionstrict", ":custom")
End If
Continue For
Case "optionstrict+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optionstrict")
Continue For
End If
optionStrict = VisualBasic.OptionStrict.On
Continue For
Case "optionstrict-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optionstrict")
Continue For
End If
optionStrict = VisualBasic.OptionStrict.Off
Continue For
Case "optioncompare"
value = RemoveQuotesAndSlashes(value)
If value Is Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "optioncompare", ":binary|text")
ElseIf String.Equals(value, "text", StringComparison.OrdinalIgnoreCase) Then
optionCompareText = True
ElseIf String.Equals(value, "binary", StringComparison.OrdinalIgnoreCase) Then
optionCompareText = False
Else
AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "optioncompare", value)
End If
Continue For
Case "optionexplicit", "optionexplicit+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optionexplicit")
Continue For
End If
optionExplicit = True
Continue For
Case "optionexplicit-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optionexplicit")
Continue For
End If
optionExplicit = False
Continue For
Case "optioninfer", "optioninfer+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optioninfer")
Continue For
End If
optionInfer = True
Continue For
Case "optioninfer-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optioninfer")
Continue For
End If
optionInfer = False
Continue For
Case "codepage"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "codepage", ":<number>")
Continue For
End If
Dim encoding = TryParseEncodingName(value)
If encoding Is Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_BadCodepage, value)
Continue For
End If
codepage = encoding
Continue For
Case "checksumalgorithm"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "checksumalgorithm", ":<algorithm>")
Continue For
End If
Dim newChecksumAlgorithm = TryParseHashAlgorithmName(value)
If newChecksumAlgorithm = SourceHashAlgorithm.None Then
AddDiagnostic(diagnostics, ERRID.ERR_BadChecksumAlgorithm, value)
Continue For
End If
checksumAlgorithm = newChecksumAlgorithm
Continue For
Case "removeintchecks", "removeintchecks+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "removeintchecks")
Continue For
End If
checkOverflow = False
Continue For
Case "removeintchecks-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "removeintchecks")
Continue For
End If
checkOverflow = True
Continue For
Case "sqmsessionguid"
' The use of SQM is deprecated in the compiler but we still support the command line parsing for
' back compat reasons.
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrWhiteSpace(value) = True Then
AddDiagnostic(diagnostics, ERRID.ERR_MissingGuidForOption, value, name)
Else
Dim sqmsessionguid As Guid
If Not Guid.TryParse(value, sqmsessionguid) Then
AddDiagnostic(diagnostics, ERRID.ERR_InvalidFormatForGuidForOption, value, name)
End If
End If
Continue For
Case "preferreduilang"
value = RemoveQuotesAndSlashes(value)
If (String.IsNullOrEmpty(value)) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<string>")
Continue For
End If
Try
preferredUILang = New CultureInfo(value)
If (preferredUILang.CultureTypes And CultureTypes.UserCustomCulture) <> 0 Then
' Do not use user custom cultures.
preferredUILang = Nothing
End If
Catch ex As CultureNotFoundException
End Try
If preferredUILang Is Nothing Then
AddDiagnostic(diagnostics, ERRID.WRN_BadUILang, value)
End If
Continue For
Case "lib", "libpath", "libpaths"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<path_list>")
Continue For
End If
libPaths.AddRange(ParseSeparatedPaths(value))
Continue For
#If DEBUG Then
Case "attachdebugger"
Debugger.Launch()
Continue For
#End If
End Select
If IsScriptCommandLineParser Then
Select Case name
Case "-"
If Console.IsInputRedirected Then
sourceFiles.Add(New CommandLineSourceFile("-", isScript:=True, isInputRedirected:=True))
hasSourceFiles = True
Else
AddDiagnostic(diagnostics, ERRID.ERR_StdInOptionProvidedButConsoleInputIsNotRedirected)
End If
Continue For
Case "i", "i+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "i")
End If
interactiveMode = True
Continue For
Case "i-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "i")
End If
interactiveMode = False
Continue For
Case "loadpath", "loadpaths"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<path_list>")
Continue For
End If
sourcePaths.AddRange(ParseSeparatedPaths(value))
Continue For
End Select
Else
Select Case name
Case "out"
If String.IsNullOrWhiteSpace(value) Then
' When the value has " " (e.g., "/out: ")
' the Roslyn VB compiler reports "BC 2006 : option 'out' requires ':<file>',
' While the Dev11 VB compiler reports "BC2012 : can't open ' ' for writing,
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<file>")
Else
' Even when value is neither null or whitespace, the output file name still could be invalid. (e.g., "/out:sub\ ")
' While the Dev11 VB compiler reports "BC2012: can't open 'sub\ ' for writing,
' the Roslyn VB compiler reports "BC2032: File name 'sub\ ' is empty, contains invalid characters, ..."
' which is generated by the following ParseOutputFile.
ParseOutputFile(value, diagnostics, baseDirectory, outputFileName, outputDirectory)
End If
Continue For
Case "refout"
Dim unquoted = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(unquoted) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<file>")
Else
outputRefFileName = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory)
End If
Continue For
Case "refonly", "refonly+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "refonly")
End If
refOnly = True
Continue For
Case "t", "target"
value = RemoveQuotesAndSlashes(value)
outputKind = ParseTarget(name, value, diagnostics)
Continue For
Case "moduleassemblyname"
value = RemoveQuotesAndSlashes(value)
Dim identity As AssemblyIdentity = Nothing
' Note that native compiler also extracts public key, but Roslyn doesn't use it.
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "moduleassemblyname", ":<string>")
ElseIf Not AssemblyIdentity.TryParseDisplayName(value, identity) OrElse
Not MetadataHelpers.IsValidAssemblyOrModuleName(identity.Name) Then
AddDiagnostic(diagnostics, ERRID.ERR_InvalidAssemblyName, value, arg)
Else
moduleAssemblyName = identity.Name
End If
Continue For
Case "rootnamespace"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "rootnamespace", ":<string>")
Continue For
End If
rootNamespace = value
Continue For
Case "doc"
value = RemoveQuotesAndSlashes(value)
parseDocumentationComments = True
If value Is Nothing Then
' Illegal in C#, but works in VB
documentationPath = GenerateFileNameForDocComment
Continue For
End If
Dim unquoted = RemoveQuotesAndSlashes(value)
If unquoted.Length = 0 Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "doc", ":<file>")
Else
documentationPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory, generateDiagnostic:=False)
If String.IsNullOrWhiteSpace(documentationPath) Then
AddDiagnostic(diagnostics, ERRID.WRN_XMLCannotWriteToXMLDocFile2, unquoted, New LocalizableErrorArgument(ERRID.IDS_TheSystemCannotFindThePathSpecified))
documentationPath = Nothing
End If
End If
Continue For
Case "doc+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "doc")
End If
' Seems redundant with default values, but we need to clobber any preceding /doc switches
documentationPath = GenerateFileNameForDocComment
parseDocumentationComments = True
Continue For
Case "doc-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "doc")
End If
' Seems redundant with default values, but we need to clobber any preceding /doc switches
documentationPath = Nothing
parseDocumentationComments = False
Continue For
Case "errorlog"
Dim unquoted = RemoveQuotesAndSlashes(value)
If (String.IsNullOrWhiteSpace(unquoted)) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "errorlog", ErrorLogOptionFormat)
Else
Dim diagnosticAlreadyReported As Boolean
errorLogOptions = ParseErrorLogOptions(unquoted.AsMemory(), diagnostics, baseDirectory, diagnosticAlreadyReported)
If errorLogOptions Is Nothing And Not diagnosticAlreadyReported Then
AddDiagnostic(diagnostics, ERRID.ERR_BadSwitchValue, unquoted, "errorlog", ErrorLogOptionFormat)
Continue For
End If
End If
Continue For
Case "netcf"
' Do nothing as we no longer have any use for implementing this switch and
' want to avoid failing with any warnings/errors
Continue For
Case "sdkpath"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "sdkpath", ":<path>")
Continue For
End If
sdkPaths.Clear()
sdkPaths.AddRange(ParseSeparatedPaths(value))
Continue For
Case "nosdkpath"
sdkDirectory = Nothing
sdkPaths.Clear()
Continue For
Case "instrument"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "instrument", ":<string>")
Continue For
End If
For Each instrumentationKind As InstrumentationKind In ParseInstrumentationKinds(value, diagnostics)
If Not instrumentationKinds.Contains(instrumentationKind) Then
instrumentationKinds.Add(instrumentationKind)
End If
Next
Continue For
Case "recurse"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "recurse", ":<wildcard>")
Continue For
End If
Dim before As Integer = sourceFiles.Count
sourceFiles.AddRange(ParseRecurseArgument(value, baseDirectory, diagnostics))
If sourceFiles.Count > before Then
hasSourceFiles = True
End If
Continue For
Case "addmodule"
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "addmodule", ":<file_list>")
Continue For
End If
' NOTE(tomat): Dev10 reports "Command line error BC2017 : could not find library."
' Since we now support /referencePaths option we would need to search them to see if the resolved path is a directory.
' An error will be reported by the assembly manager anyways.
metadataReferences.AddRange(
ParseSeparatedPaths(value).Select(
Function(path) New CommandLineReference(path, New MetadataReferenceProperties(MetadataImageKind.Module))))
Continue For
Case "l", "link"
metadataReferences.AddRange(ParseAssemblyReferences(name, value, diagnostics, embedInteropTypes:=True))
Continue For
Case "win32resource"
win32ResourceFile = GetWin32Setting(s_win32Res, RemoveQuotesAndSlashes(value), diagnostics)
Continue For
Case "win32icon"
win32IconFile = GetWin32Setting(s_win32Icon, RemoveQuotesAndSlashes(value), diagnostics)
Continue For
Case "win32manifest"
win32ManifestFile = GetWin32Setting(s_win32Manifest, RemoveQuotesAndSlashes(value), diagnostics)
Continue For
Case "nowin32manifest"
If value IsNot Nothing Then
Exit Select
End If
noWin32Manifest = True
Continue For
Case "res", "resource"
Dim embeddedResource = ParseResourceDescription(name, value, baseDirectory, diagnostics, embedded:=True)
If embeddedResource IsNot Nothing Then
managedResources.Add(embeddedResource)
End If
Continue For
Case "linkres", "linkresource"
Dim linkedResource = ParseResourceDescription(name, value, baseDirectory, diagnostics, embedded:=False)
If linkedResource IsNot Nothing Then
managedResources.Add(linkedResource)
End If
Continue For
Case "sourcelink"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "sourcelink", ":<file>")
Else
sourceLink = ParseGenericPathToFile(value, diagnostics, baseDirectory)
End If
Continue For
Case "debug"
' parse only for backwards compat
value = RemoveQuotesAndSlashes(value)
If value IsNot Nothing Then
Select Case value.ToLower()
Case "full", "pdbonly"
debugInformationFormat = If(PathUtilities.IsUnixLikePlatform, DebugInformationFormat.PortablePdb, DebugInformationFormat.Pdb)
Case "portable"
debugInformationFormat = DebugInformationFormat.PortablePdb
Case "embedded"
debugInformationFormat = DebugInformationFormat.Embedded
Case Else
AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "debug", value)
End Select
End If
emitPdb = True
Continue For
Case "debug+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "debug")
End If
emitPdb = True
Continue For
Case "debug-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "debug")
End If
emitPdb = False
Continue For
Case "optimize", "optimize+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optimize")
Continue For
End If
optimize = True
Continue For
Case "optimize-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "optimize")
Continue For
End If
optimize = False
Continue For
Case "parallel", "p"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, name)
Continue For
End If
concurrentBuild = True
Continue For
Case "deterministic", "deterministic+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, name)
Continue For
End If
deterministic = True
Continue For
Case "deterministic-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, name)
Continue For
End If
deterministic = False
Continue For
Case "parallel+", "p+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, name.Substring(0, name.Length - 1))
Continue For
End If
concurrentBuild = True
Continue For
Case "parallel-", "p-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, name.Substring(0, name.Length - 1))
Continue For
End If
concurrentBuild = False
Continue For
Case "warnaserror", "warnaserror+"
If value Is Nothing Then
generalDiagnosticOption = ReportDiagnostic.Error
specificDiagnosticOptionsFromGeneralArguments.Clear()
For Each pair In specificDiagnosticOptionsFromRuleSet
If pair.Value = ReportDiagnostic.Warn Then
specificDiagnosticOptionsFromGeneralArguments.Add(pair.Key, ReportDiagnostic.Error)
End If
Next
Continue For
End If
AddWarnings(specificDiagnosticOptionsFromSpecificArguments, ReportDiagnostic.Error, ParseWarnings(value))
Continue For
Case "warnaserror-"
If value Is Nothing Then
If generalDiagnosticOption <> ReportDiagnostic.Suppress Then
generalDiagnosticOption = ReportDiagnostic.Default
End If
specificDiagnosticOptionsFromGeneralArguments.Clear()
Continue For
End If
For Each id In ParseWarnings(value)
Dim ruleSetValue As ReportDiagnostic
If specificDiagnosticOptionsFromRuleSet.TryGetValue(id, ruleSetValue) Then
specificDiagnosticOptionsFromSpecificArguments(id) = ruleSetValue
Else
specificDiagnosticOptionsFromSpecificArguments(id) = ReportDiagnostic.Default
End If
Next
Continue For
Case "nowarn"
If value Is Nothing Then
generalDiagnosticOption = ReportDiagnostic.Suppress
specificDiagnosticOptionsFromGeneralArguments.Clear()
For Each pair In specificDiagnosticOptionsFromRuleSet
If pair.Value <> ReportDiagnostic.Error Then
specificDiagnosticOptionsFromGeneralArguments.Add(pair.Key, ReportDiagnostic.Suppress)
End If
Next
Continue For
End If
AddWarnings(specificDiagnosticOptionsFromNoWarnArguments, ReportDiagnostic.Suppress, ParseWarnings(value))
Continue For
Case "langversion"
value = RemoveQuotesAndSlashes(value)
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "langversion", ":<number>")
ElseIf value = "?" Then
displayLangVersions = True
Else
If Not TryParse(value, languageVersion) Then
AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "langversion", value)
End If
End If
Continue For
Case "delaysign", "delaysign+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "delaysign")
Continue For
End If
delaySignSetting = True
Continue For
Case "delaysign-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "delaysign")
Continue For
End If
delaySignSetting = False
Continue For
Case "publicsign", "publicsign+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "publicsign")
Continue For
End If
publicSign = True
Continue For
Case "publicsign-"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "publicsign")
Continue For
End If
publicSign = False
Continue For
Case "keycontainer"
' NOTE: despite what MSDN says, Dev11 resets '/keyfile' in this case:
'
' MSDN: In case both /keyfile and /keycontainer are specified (either by command-line
' MSDN: option or by custom attribute) in the same compilation, the compiler first tries
' MSDN: the key container. If that succeeds, then the assembly is signed with the
' MSDN: information in the key container. If the compiler does not find the key container,
' MSDN: it tries the file specified with /keyfile. If this succeeds, the assembly is
' MSDN: signed with the information in the key file, and the key information is installed
' MSDN: in the key container (similar to sn -i) so that on the next compilation,
' MSDN: the key container will be valid.
value = RemoveQuotesAndSlashes(value)
keyFileSetting = Nothing
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "keycontainer", ":<string>")
Else
keyContainerSetting = value
End If
Continue For
Case "keyfile"
' NOTE: despite what MSDN says, Dev11 resets '/keycontainer' in this case:
'
' MSDN: In case both /keyfile and /keycontainer are specified (either by command-line
' MSDN: option or by custom attribute) in the same compilation, the compiler first tries
' MSDN: the key container. If that succeeds, then the assembly is signed with the
' MSDN: information in the key container. If the compiler does not find the key container,
' MSDN: it tries the file specified with /keyfile. If this succeeds, the assembly is
' MSDN: signed with the information in the key file, and the key information is installed
' MSDN: in the key container (similar to sn -i) so that on the next compilation,
' MSDN: the key container will be valid.
value = RemoveQuotesAndSlashes(value)
keyContainerSetting = Nothing
If String.IsNullOrWhiteSpace(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "keyfile", ":<file>")
Else
keyFileSetting = value
End If
Continue For
Case "highentropyva", "highentropyva+"
If value IsNot Nothing Then
Exit Select
End If
highEntropyVA = True
Continue For
Case "highentropyva-"
If value IsNot Nothing Then
Exit Select
End If
highEntropyVA = False
Continue For
Case "nologo", "nologo+"
If value IsNot Nothing Then
Exit Select
End If
displayLogo = False
Continue For
Case "nologo-"
If value IsNot Nothing Then
Exit Select
End If
displayLogo = True
Continue For
Case "quiet+"
If value IsNot Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "quiet")
Continue For
End If
outputLevel = VisualBasic.OutputLevel.Quiet
Continue For
Case "quiet"
If value IsNot Nothing Then
Exit Select
End If
outputLevel = VisualBasic.OutputLevel.Quiet
Continue For
Case "verbose"
If value IsNot Nothing Then
Exit Select
End If
outputLevel = VisualBasic.OutputLevel.Verbose
Continue For
Case "verbose+"
If value IsNot Nothing Then