internal override CommandLineArguments CommonParse(IEnumerable <string> args, string baseDirectory, string sdkDirectoryOpt, string additionalReferenceDirectories) { List <Diagnostic> diagnostics = new List <Diagnostic>(); List <string> flattenedArgs = new List <string>(); List <string> scriptArgs = IsScriptRunner ? new List <string>() : null; FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory); var sourceFiles = new List <CommandLineSourceFile>(); var metadataReferences = new List <CommandLineReference>(); var analyzers = new List <CommandLineAnalyzerReference>(); var additionalFiles = new List <CommandLineSourceFile>(); var managedResources = new List <ResourceDescription>(); string outputDirectory = baseDirectory; string outputFileName = null; string documentationPath = null; string moduleName = null; string runtimeMetadataVersion = null; // will be read from cor library if not specified in cmd string compilationName = null; bool optimize = false; bool concurrentBuild = true; PhpDocTypes phpdocTypes = PhpDocTypes.None; OutputKind outputKind = OutputKind.ConsoleApplication; bool optionsEnded = false; bool displayHelp = false, displayLogo = true; bool emitPdb = true, debugPlus = false; string mainTypeName = null, pdbPath = null; DebugInformationFormat debugInformationFormat = DebugInformationFormat.Pdb; List <string> referencePaths = new List <string>(); if (sdkDirectoryOpt != null) { referencePaths.Add(sdkDirectoryOpt); } if (!string.IsNullOrEmpty(additionalReferenceDirectories)) { referencePaths.AddRange(additionalReferenceDirectories.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } foreach (string arg in flattenedArgs) { Debug.Assert(optionsEnded || !arg.StartsWith("@", StringComparison.Ordinal)); string name, value; if (optionsEnded || !TryParseOption2(arg, out name, out value)) { sourceFiles.AddRange(ExpandFileArgument(arg, baseDirectory, diagnostics)); continue; } switch (name) { case "?": case "help": displayHelp = true; continue; case "r": case "reference": metadataReferences.AddRange(ParseAssemblyReferences(arg, value, diagnostics, embedInteropTypes: false)); continue; case "debug": emitPdb = true; // unused, parsed for backward compat only if (!string.IsNullOrEmpty(value)) { switch (value.ToLower()) { case "full": case "pdbonly": debugInformationFormat = DebugInformationFormat.Pdb; break; case "portable": debugInformationFormat = DebugInformationFormat.PortablePdb; break; case "embedded": debugInformationFormat = DebugInformationFormat.Embedded; break; default: //AddDiagnostic(diagnostics, ErrorCode.ERR_BadDebugType, value); break; } } continue; case "debug+": //guard against "debug+:xx" if (value != null) { break; } emitPdb = true; debugPlus = true; continue; case "debug-": if (value != null) { break; } emitPdb = false; debugPlus = false; continue; case "o": case "optimize": case "o+": case "optimize+": if (value != null) { break; } optimize = true; continue; case "o-": case "optimize-": if (value != null) { break; } optimize = false; continue; case "p": case "parallel": case "p+": case "parallel+": if (value != null) { break; } concurrentBuild = true; continue; case "p-": case "parallel-": if (value != null) { break; } concurrentBuild = false; continue; case "nologo": displayLogo = false; continue; case "m": case "main": // Remove any quotes for consistent behavior as MSBuild can return quoted or // unquoted main. var unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); //continue; throw new ArgumentException("main"); // TODO: ErrorCode } mainTypeName = unquoted; continue; case "pdb": if (string.IsNullOrEmpty(value)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); throw new ArgumentException("pdb"); // TODO: ErrorCode } else { pdbPath = ParsePdbPath(value, diagnostics, baseDirectory); } continue; case "out": if (string.IsNullOrWhiteSpace(value)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); throw new ArgumentException("out"); // TODO: ErrorCode } else { ParseOutputFile(value, diagnostics, baseDirectory, out outputFileName, out outputDirectory); } continue; case "t": case "target": if (value == null) { break; // force 'unrecognized option' } if (string.IsNullOrEmpty(value)) { //AddDiagnostic(diagnostics, ErrorCode.FTL_InvalidTarget); throw new ArgumentException("target"); // TODO: ErrorCode } else { outputKind = ParseTarget(value, diagnostics); } continue; case "xmldoc": case "doc": documentationPath = value ?? string.Empty; break; case "phpdoctypes+": phpdocTypes = PhpDocTypes.All; break; case "phpdoctypes-": phpdocTypes = PhpDocTypes.None; break; case "phpdoctypes": if (value == null) { phpdocTypes = PhpDocTypes.All; } else { phpdocTypes = (PhpDocTypes)Enum.Parse(typeof(PhpDocTypes), value); } break; case "modulename": var unquotedModuleName = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquotedModuleName)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "modulename"); //continue; throw new ArgumentException("modulename"); // TODO: ErrorCode } else { moduleName = unquotedModuleName; } continue; case "runtimemetadataversion": unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); //continue; throw new ArgumentException("runtimemetadataversion"); // TODO: ErrorCode } runtimeMetadataVersion = unquoted; continue; default: break; } } GetCompilationAndModuleNames(diagnostics, outputKind, sourceFiles, sourceFiles.Count != 0, /*moduleAssemblyName*/ null, ref outputFileName, ref moduleName, out compilationName); // XML Documentation path if (documentationPath != null) { if (documentationPath.Length == 0) { // default xmldoc file name documentationPath = compilationName + ".xml"; } // resolve path documentationPath = PathUtilities.CombinePossiblyRelativeAndRelativePaths(outputDirectory, documentationPath); } var parseOptions = new PhpParseOptions ( //languageVersion: languageVersion, //preprocessorSymbols: defines.ToImmutableAndFree(), documentationMode: DocumentationMode.Diagnose, // always diagnose kind: SourceCodeKind.Regular //, //features: parsedFeatures ); var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); //// We want to report diagnostics with source suppression in the error log file. //// However, these diagnostics won't be reported on the command line. //var reportSuppressedDiagnostics = errorLogPath != null; var options = new PhpCompilationOptions ( outputKind: outputKind, baseDirectory: baseDirectory, sdkDirectory: sdkDirectoryOpt, moduleName: moduleName, mainTypeName: mainTypeName, scriptClassName: WellKnownMemberNames.DefaultScriptClassName, phpdocTypes: phpdocTypes, //usings: usings, optimizationLevel: optimize ? OptimizationLevel.Release : OptimizationLevel.Debug, checkOverflow: false, // checkOverflow, //deterministic: deterministic, concurrentBuild: concurrentBuild, //cryptoKeyContainer: keyContainerSetting, //cryptoKeyFile: keyFileSetting, //delaySign: delaySignSetting, platform: Platform.AnyCpu // platform, //generalDiagnosticOption: generalDiagnosticOption, //warningLevel: warningLevel, //specificDiagnosticOptions: diagnosticOptions, //reportSuppressedDiagnostics: reportSuppressedDiagnostics, //publicSign: publicSign ); if (debugPlus) { options = options.WithDebugPlusMode(debugPlus); } var emitOptions = new EmitOptions ( metadataOnly: false, debugInformationFormat: debugInformationFormat, //pdbFilePath: null, // to be determined later //outputNameOverride: null, // to be determined later //baseAddress: baseAddress, //highEntropyVirtualAddressSpace: highEntropyVA, //fileAlignment: fileAlignment, //subsystemVersion: subsystemVersion, runtimeMetadataVersion: runtimeMetadataVersion ); return(new PhpCommandLineArguments() { // TODO: parsed arguments IsScriptRunner = IsScriptRunner, //InteractiveMode = interactiveMode || IsScriptRunner && sourceFiles.Count == 0, BaseDirectory = baseDirectory, //PathMap = pathMap, Errors = ImmutableArray <Diagnostic> .Empty, Utf8Output = true, CompilationName = compilationName, OutputFileName = outputFileName, PdbPath = pdbPath, EmitPdb = emitPdb, OutputDirectory = outputDirectory, DocumentationPath = documentationPath, //ErrorLogPath = errorLogPath, //AppConfigPath = appConfigPath, SourceFiles = sourceFiles.AsImmutable(), Encoding = Encoding.UTF8, ChecksumAlgorithm = SourceHashAlgorithm.Sha1, // checksumAlgorithm, MetadataReferences = metadataReferences.AsImmutable(), AnalyzerReferences = analyzers.AsImmutable(), AdditionalFiles = additionalFiles.AsImmutable(), ReferencePaths = referencePaths.AsImmutable(), SourcePaths = ImmutableArray <string> .Empty, //sourcePaths.AsImmutable(), //KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(), //Win32ResourceFile = win32ResourceFile, //Win32Icon = win32IconFile, //Win32Manifest = win32ManifestFile, //NoWin32Manifest = noWin32Manifest, DisplayLogo = displayLogo, DisplayHelp = displayHelp, ManifestResources = managedResources.AsImmutable(), CompilationOptions = options, ParseOptions = IsScriptRunner ? scriptParseOptions : parseOptions, EmitOptions = emitOptions, //ScriptArguments = scriptArgs.AsImmutableOrEmpty(), //TouchedFilesPath = touchedFilesPath, //PrintFullPaths = printFullPaths, //ShouldIncludeErrorEndLocation = errorEndLocation, //PreferredUILang = preferredUILang, //SqmSessionGuid = sqmSessionGuid, //ReportAnalyzer = reportAnalyzer }); }
internal override CommandLineArguments CommonParse(IEnumerable <string> args, string baseDirectory, string sdkDirectoryOpt, string additionalReferenceDirectories) { List <Diagnostic> diagnostics = new List <Diagnostic>(); List <string> flattenedArgs = new List <string>(); List <string> scriptArgs = IsScriptCommandLineParser ? new List <string>() : null; FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory); var sourceFiles = new List <CommandLineSourceFile>(); var metadataReferences = new List <CommandLineReference>(); var analyzers = new List <CommandLineAnalyzerReference>(); var additionalFiles = new List <CommandLineSourceFile>(); var embeddedFiles = new List <CommandLineSourceFile>(); var managedResources = new List <ResourceDescription>(); var defines = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); string outputDirectory = baseDirectory; string subDirectory = null; string outputFileName = null; string documentationPath = null; string moduleName = null; string runtimeMetadataVersion = null; // will be read from cor library if not specified in cmd string compilationName = null; string versionString = null; Encoding codepage = null; bool embedAllSourceFiles = false; bool optimize = false; bool concurrentBuild = true; var diagnosticOptions = new Dictionary <string, ReportDiagnostic>(); PhpDocTypes phpdocTypes = PhpDocTypes.None; OutputKind outputKind = OutputKind.ConsoleApplication; bool optionsEnded = false; bool displayHelp = false, displayLogo = true; bool emitPdb = true, debugPlus = false; string sourceLink = null; string mainTypeName = null, pdbPath = null; Version languageVersion = null; bool? delaySignSetting = null; string keyFileSetting = null; string keyContainerSetting = null; bool publicSign = false; bool shortOpenTags = false; bool resourcesOrModulesSpecified = false; DebugInformationFormat debugInformationFormat = DebugInformationFormat.Pdb; List <string> referencePaths = new List <string>(); List <string> keyFileSearchPaths = new List <string>(); if (sdkDirectoryOpt != null) { referencePaths.Add(sdkDirectoryOpt); } if (!string.IsNullOrEmpty(additionalReferenceDirectories)) { referencePaths.AddRange(additionalReferenceDirectories.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } foreach (string arg in flattenedArgs) { Debug.Assert(optionsEnded || !arg.StartsWith("@", StringComparison.Ordinal)); string name, value; if (optionsEnded || !TryParseOption2(arg, out name, out value)) { sourceFiles.AddRange(ExpandFileArgument(arg, baseDirectory, diagnostics)); continue; } switch (name) { case "?": case "help": displayHelp = true; continue; case "d": case "define": ParseDefine(value, defines); continue; case "codepage": value = RemoveQuotesAndSlashes(value); if (value == null) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); continue; } var encoding = TryParseEncodingName(value); if (encoding == null) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.FTL_BadCodepage, Location.None, value)); continue; } codepage = encoding; continue; case "r": case "reference": metadataReferences.AddRange(ParseAssemblyReferences(arg, value, diagnostics, embedInteropTypes: false)); continue; case "sourcelink": value = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(value)) { //diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.no //AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); } else { sourceLink = ParseGenericPathToFile(value, diagnostics, baseDirectory); } continue; case "debug": case "debug-type": emitPdb = true; // unused, parsed for backward compat only if (!string.IsNullOrEmpty(value)) { switch (value.ToLower()) { case "full": case "pdbonly": debugInformationFormat = DebugInformationFormat.Pdb; break; case "portable": debugInformationFormat = DebugInformationFormat.PortablePdb; break; case "embedded": debugInformationFormat = DebugInformationFormat.Embedded; break; default: //AddDiagnostic(diagnostics, ErrorCode.ERR_BadDebugType, value); break; } } continue; case "debug+": //guard against "debug+:xx" if (value != null) { break; } emitPdb = true; debugPlus = true; continue; case "debug-": if (value != null) { break; } emitPdb = false; debugPlus = false; continue; case "o": case "optimize": case "o+": case "optimize+": if (value != null) { break; } optimize = true; continue; case "o-": case "optimize-": if (value != null) { break; } optimize = false; continue; case "p": case "parallel": case "p+": case "parallel+": if (value != null) { break; } concurrentBuild = true; continue; case "p-": case "parallel-": if (value != null) { break; } concurrentBuild = false; continue; case "nowarn": if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { foreach (var warn in value.Split(new char[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries)) { diagnosticOptions[warn] = ReportDiagnostic.Suppress; } } continue; case "langversion": value = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else if (string.Equals(value, "default", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "latest", StringComparison.OrdinalIgnoreCase)) { languageVersion = null; // latest } else if (!Version.TryParse(value, out languageVersion)) { throw new ArgumentException("langversion"); //AddDiagnostic(diagnostics, ErrorCode.ERR_BadCompatMode, value); } continue; case "delaysign": case "delaysign+": if (value != null) { break; } delaySignSetting = true; continue; case "delaysign-": if (value != null) { break; } delaySignSetting = false; continue; case "publicsign": case "publicsign+": if (value != null) { break; } publicSign = true; continue; case "publicsign-": if (value != null) { break; } publicSign = false; continue; case "keyfile": value = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); // TODO: AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, "keyfile"); } else { keyFileSetting = value; } // NOTE: Dev11/VB also clears "keycontainer", see also: // // MSDN: In case both /keyfile and /keycontainer are specified (either by command line option or by // MSDN: custom attribute) in the same compilation, the compiler will first try the key container. // MSDN: If that succeeds, then the assembly is signed with the information in the key container. // MSDN: If the compiler does not find the key container, it will try the file specified with /keyfile. // MSDN: If that succeeds, the assembly is signed with the information in the key file and the key // MSDN: information will be installed in the key container (similar to sn -i) so that on the next // MSDN: compilation, the key container will be valid. continue; case "keycontainer": if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { keyContainerSetting = value; } // NOTE: Dev11/VB also clears "keyfile", see also: // // MSDN: In case both /keyfile and /keycontainer are specified (either by command line option or by // MSDN: custom attribute) in the same compilation, the compiler will first try the key container. // MSDN: If that succeeds, then the assembly is signed with the information in the key container. // MSDN: If the compiler does not find the key container, it will try the file specified with /keyfile. // MSDN: If that succeeds, the assembly is signed with the information in the key file and the key // MSDN: information will be installed in the key container (similar to sn -i) so that on the next // MSDN: compilation, the key container will be valid. continue; case "shortopentag": shortOpenTags = string.IsNullOrEmpty(value) || (RemoveQuotesAndSlashes(value).ToLowerInvariant() == "true"); continue; case "shortopentag+": shortOpenTags = true; continue; case "shortopentag-": shortOpenTags = false; continue; case "nologo": displayLogo = false; continue; case "m": case "main": // Remove any quotes for consistent behavior as MSBuild can return quoted or // unquoted main. var unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { mainTypeName = unquoted; } continue; case "pdb": if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { pdbPath = ParsePdbPath(value, diagnostics, baseDirectory); } continue; case "out": if (string.IsNullOrWhiteSpace(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { ParseOutputFile(value, diagnostics, baseDirectory, out outputFileName, out outputDirectory); } continue; case "t": case "target": if (value == null) { break; // force 'unrecognized option' } if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { outputKind = ParseTarget(value, diagnostics); } continue; case "xmldoc": case "doc": documentationPath = value ?? string.Empty; break; case "phpdoctypes+": phpdocTypes = PhpDocTypes.All; break; case "phpdoctypes-": phpdocTypes = PhpDocTypes.None; break; case "phpdoctypes": if (value == null) { phpdocTypes = PhpDocTypes.All; } else { phpdocTypes = (PhpDocTypes)Enum.Parse(typeof(PhpDocTypes), value); } break; case "modulename": var unquotedModuleName = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquotedModuleName)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { moduleName = unquotedModuleName; } continue; case "version": case "v": versionString = RemoveQuotesAndSlashes(value); continue; case "runtimemetadataversion": unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { runtimeMetadataVersion = unquoted; } continue; case "res": case "resource": if (value == null) { break; // Dev11 reports unrecognized option } var embeddedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: true); if (embeddedResource != null) { managedResources.Add(embeddedResource); resourcesOrModulesSpecified = true; } continue; case "linkres": case "linkresource": if (value == null) { break; // Dev11 reports unrecognized option } var linkedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: false); if (linkedResource != null) { managedResources.Add(linkedResource); resourcesOrModulesSpecified = true; } continue; case "subdir": if (!string.IsNullOrEmpty(value)) { // TODO: check value subDirectory = Utilities.PhpFileUtilities.NormalizeSlashes(RemoveQuotesAndSlashes(value)); } continue; case "embed": if (string.IsNullOrEmpty(value)) { embedAllSourceFiles = true; continue; } embeddedFiles.AddRange(ParseSeparatedFileArgument(value, baseDirectory, diagnostics)); continue; default: break; } } GetCompilationAndModuleNames(diagnostics, outputKind, sourceFiles, sourceFiles.Count != 0, /*moduleAssemblyName*/ null, ref outputFileName, ref moduleName, out compilationName); // if (sourceFiles.Count == 0 && !IsScriptCommandLineParser && (outputKind.IsNetModule() || !resourcesOrModulesSpecified)) { // warning: no source files specified diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.WRN_NoSourceFiles, Location.None)); } // XML Documentation path if (documentationPath != null) { if (documentationPath.Length == 0) { // default xmldoc file name documentationPath = PathUtilities.CombinePossiblyRelativeAndRelativePaths(outputDirectory, compilationName + ".xml"); } else { // resolve path documentationPath = PathUtilities.CombinePossiblyRelativeAndRelativePaths(baseDirectory, documentationPath); } } // event source // TODO: change to EventSource var evetsources = new[] { CreateObserver("Peachpie.Compiler.Diagnostics.Observer,Peachpie.Compiler.Diagnostics", moduleName) }.WhereNotNull(); #if TRACE evetsources = evetsources.Concat(new Utilities.CompilationTrackerExtension.TraceObserver()); #endif // Dev11 searches for the key file in the current directory and assembly output directory. // We always look to base directory and then examine the search paths. keyFileSearchPaths.Add(baseDirectory); if (baseDirectory != outputDirectory) { keyFileSearchPaths.Add(outputDirectory); } // Public sign doesn't use the legacy search path settings if (publicSign && !string.IsNullOrWhiteSpace(keyFileSetting)) { keyFileSetting = ParseGenericPathToFile(keyFileSetting, diagnostics, baseDirectory); } if (sourceLink != null && !emitPdb) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SourceLinkRequiresPdb); } if (embedAllSourceFiles) { embeddedFiles.AddRange(sourceFiles); } if (embeddedFiles.Count > 0 && !emitPdb) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_CannotEmbedWithoutPdb, Location.None)); } var parseOptions = new PhpParseOptions ( documentationMode: DocumentationMode.Diagnose, // always diagnose kind: SourceCodeKind.Regular, languageVersion: languageVersion, shortOpenTags: shortOpenTags, features: ImmutableDictionary <string, string> .Empty, // features: parsedFeatures defines: defines.ToImmutableDictionary() ); var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); //// We want to report diagnostics with source suppression in the error log file. //// However, these diagnostics won't be reported on the command line. //var reportSuppressedDiagnostics = errorLogPath != null; var options = new PhpCompilationOptions ( outputKind: outputKind, baseDirectory: baseDirectory, sdkDirectory: sdkDirectoryOpt, subDirectory: subDirectory, moduleName: moduleName, mainTypeName: mainTypeName, scriptClassName: WellKnownMemberNames.DefaultScriptClassName, versionString: versionString, phpdocTypes: phpdocTypes, parseOptions: parseOptions, diagnostics: diagnostics.AsImmutable(), specificDiagnosticOptions: diagnosticOptions, //usings: usings, optimizationLevel: optimize ? OptimizationLevel.Release : OptimizationLevel.Debug, checkOverflow: false, // checkOverflow, //deterministic: deterministic, concurrentBuild: concurrentBuild, cryptoKeyContainer: keyContainerSetting, cryptoKeyFile: keyFileSetting, delaySign: delaySignSetting, platform: Platform.AnyCpu, //generalDiagnosticOption: generalDiagnosticOption, //warningLevel: warningLevel, //specificDiagnosticOptions: diagnosticOptions, //reportSuppressedDiagnostics: reportSuppressedDiagnostics, publicSign: publicSign ) { EventSources = evetsources.AsImmutableOrEmpty(), }; if (debugPlus) { options = options.WithDebugPlusMode(debugPlus); } var emitOptions = new EmitOptions ( metadataOnly: false, debugInformationFormat: debugInformationFormat, pdbFilePath: null, // to be determined later pdbChecksumAlgorithm: System.Security.Cryptography.HashAlgorithmName.SHA1, outputNameOverride: null, // to be determined later //baseAddress: baseAddress, //highEntropyVirtualAddressSpace: highEntropyVA, //fileAlignment: fileAlignment, //subsystemVersion: subsystemVersion, runtimeMetadataVersion: runtimeMetadataVersion ); return(new PhpCommandLineArguments() { // TODO: parsed arguments IsScriptRunner = IsScriptCommandLineParser, //InteractiveMode = interactiveMode || IsScriptRunner && sourceFiles.Count == 0, BaseDirectory = baseDirectory, //PathMap = pathMap, Errors = ImmutableArray <Diagnostic> .Empty, Utf8Output = true, CompilationName = compilationName, OutputFileName = outputFileName, PdbPath = pdbPath, EmitPdb = emitPdb, SourceLink = sourceLink, OutputDirectory = outputDirectory, DocumentationPath = documentationPath, //ErrorLogPath = errorLogPath, //AppConfigPath = appConfigPath, SourceFiles = sourceFiles.AsImmutable(), Encoding = codepage, // Encoding.UTF8, ChecksumAlgorithm = SourceHashAlgorithm.Sha1, // checksumAlgorithm, MetadataReferences = metadataReferences.AsImmutable(), AnalyzerReferences = analyzers.AsImmutable(), AdditionalFiles = additionalFiles.AsImmutable(), ReferencePaths = referencePaths.AsImmutable(), SourcePaths = ImmutableArray <string> .Empty, //sourcePaths.AsImmutable(), KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(), //Win32ResourceFile = win32ResourceFile, //Win32Icon = win32IconFile, //Win32Manifest = win32ManifestFile, //NoWin32Manifest = noWin32Manifest, DisplayLogo = displayLogo, DisplayHelp = displayHelp, ManifestResources = managedResources.AsImmutable(), CompilationOptions = options, ParseOptions = IsScriptCommandLineParser ? scriptParseOptions : parseOptions, EmitOptions = emitOptions, //ScriptArguments = scriptArgs.AsImmutableOrEmpty(), //TouchedFilesPath = touchedFilesPath, //PrintFullPaths = printFullPaths, //ShouldIncludeErrorEndLocation = errorEndLocation, //PreferredUILang = preferredUILang, //SqmSessionGuid = sqmSessionGuid, //ReportAnalyzer = reportAnalyzer EmbeddedFiles = embeddedFiles.AsImmutable(), }); }
internal override CommandLineArguments CommonParse(IEnumerable<string> args, string baseDirectory, string sdkDirectoryOpt, string additionalReferenceDirectories) { List<Diagnostic> diagnostics = new List<Diagnostic>(); List<string> flattenedArgs = new List<string>(); List<string> scriptArgs = IsScriptRunner ? new List<string>() : null; FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory); var sourceFiles = new List<CommandLineSourceFile>(); var metadataReferences = new List<CommandLineReference>(); var analyzers = new List<CommandLineAnalyzerReference>(); var additionalFiles = new List<CommandLineSourceFile>(); var managedResources = new List<ResourceDescription>(); string outputDirectory = baseDirectory; string outputFileName = null; string moduleName = null; string runtimeMetadataVersion = null; // will be read from cor library if not specified in cmd string compilationName = null; bool optimize = false; OutputKind outputKind = OutputKind.ConsoleApplication; bool optionsEnded = false; bool displayHelp = false, displayLogo = true; bool emitPdb = true, debugPlus = false; string mainTypeName = null, pdbPath = null; DebugInformationFormat debugInformationFormat = DebugInformationFormat.Pdb; List<string> referencePaths = new List<string>(); if (sdkDirectoryOpt != null) referencePaths.Add(sdkDirectoryOpt); if (!string.IsNullOrEmpty(additionalReferenceDirectories)) referencePaths.AddRange(additionalReferenceDirectories.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); foreach (string arg in flattenedArgs) { Debug.Assert(optionsEnded || !arg.StartsWith("@", StringComparison.Ordinal)); string name, value; if (optionsEnded || !TryParseOption2(arg, out name, out value)) { sourceFiles.AddRange(ParseFileArgument(arg, baseDirectory, diagnostics)); continue; } switch (name) { case "?": case "help": displayHelp = true; continue; case "r": case "reference": metadataReferences.AddRange(ParseAssemblyReferences(arg, value, diagnostics, embedInteropTypes: false)); continue; case "debug": emitPdb = true; // unused, parsed for backward compat only if (!string.IsNullOrEmpty(value)) { switch (value.ToLower()) { case "full": case "pdbonly": debugInformationFormat = DebugInformationFormat.Pdb; break; case "portable": debugInformationFormat = DebugInformationFormat.PortablePdb; break; case "embedded": debugInformationFormat = DebugInformationFormat.Embedded; break; default: //AddDiagnostic(diagnostics, ErrorCode.ERR_BadDebugType, value); break; } } continue; case "debug+": //guard against "debug+:xx" if (value != null) break; emitPdb = true; debugPlus = true; continue; case "debug-": if (value != null) break; emitPdb = false; debugPlus = false; continue; case "o": case "optimize": case "o+": case "optimize+": if (value != null) break; optimize = true; continue; case "o-": case "optimize-": if (value != null) break; optimize = false; continue; case "nologo": displayLogo = false; continue; case "m": case "main": // Remove any quotes for consistent behavior as MSBuild can return quoted or // unquoted main. var unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); //continue; throw new ArgumentException("main"); // TODO: ErrorCode } mainTypeName = unquoted; continue; case "pdb": if (string.IsNullOrEmpty(value)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); throw new ArgumentException("pdb"); // TODO: ErrorCode } else { pdbPath = ParsePdbPath(value, diagnostics, baseDirectory); } continue; case "out": if (string.IsNullOrWhiteSpace(value)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); throw new ArgumentException("out"); // TODO: ErrorCode } else { ParseOutputFile(value, diagnostics, baseDirectory, out outputFileName, out outputDirectory); } continue; case "t": case "target": if (value == null) { break; // force 'unrecognized option' } if (string.IsNullOrEmpty(value)) { //AddDiagnostic(diagnostics, ErrorCode.FTL_InvalidTarget); throw new ArgumentException("target"); // TODO: ErrorCode } else { outputKind = ParseTarget(value, diagnostics); } continue; case "modulename": var unquotedModuleName = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquotedModuleName)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "modulename"); //continue; throw new ArgumentException("modulename"); // TODO: ErrorCode } else { moduleName = unquotedModuleName; } continue; case "runtimemetadataversion": unquoted = RemoveQuotesAndSlashes(value); if (string.IsNullOrEmpty(unquoted)) { //AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); //continue; throw new ArgumentException("runtimemetadataversion"); // TODO: ErrorCode } runtimeMetadataVersion = unquoted; continue; default: break; } } GetCompilationAndModuleNames(diagnostics, outputKind, sourceFiles, sourceFiles.Count != 0, /*moduleAssemblyName*/null, ref outputFileName, ref moduleName, out compilationName); var parseOptions = new PhpParseOptions ( //languageVersion: languageVersion, //preprocessorSymbols: defines.ToImmutableAndFree(), //documentationMode: parseDocumentationComments ? DocumentationMode.Diagnose : DocumentationMode.None, kind: SourceCodeKind.Regular//, //features: parsedFeatures ); var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); //// We want to report diagnostics with source suppression in the error log file. //// However, these diagnostics won't be reported on the command line. //var reportSuppressedDiagnostics = errorLogPath != null; var options = new PhpCompilationOptions ( outputKind: outputKind, baseDirectory: baseDirectory, sdkDirectory: sdkDirectoryOpt, moduleName: moduleName, mainTypeName: mainTypeName, scriptClassName: WellKnownMemberNames.DefaultScriptClassName, //usings: usings, optimizationLevel: optimize ? OptimizationLevel.Release : OptimizationLevel.Debug, checkOverflow: false, // checkOverflow, //deterministic: deterministic, concurrentBuild: false, //concurrentBuild, // TODO: true in Release //cryptoKeyContainer: keyContainerSetting, //cryptoKeyFile: keyFileSetting, //delaySign: delaySignSetting, platform: Platform.AnyCpu //, // platform, //generalDiagnosticOption: generalDiagnosticOption, //warningLevel: warningLevel, //specificDiagnosticOptions: diagnosticOptions, //reportSuppressedDiagnostics: reportSuppressedDiagnostics, //publicSign: publicSign ); if (debugPlus) { options = options.WithDebugPlusMode(debugPlus); } var emitOptions = new EmitOptions ( //metadataOnly: false, debugInformationFormat: debugInformationFormat, //pdbFilePath: null, // to be determined later //outputNameOverride: null, // to be determined later //baseAddress: baseAddress, //highEntropyVirtualAddressSpace: highEntropyVA, //fileAlignment: fileAlignment, //subsystemVersion: subsystemVersion, runtimeMetadataVersion: runtimeMetadataVersion ); return new PhpCommandLineArguments() { // TODO: parsed arguments IsScriptRunner = IsScriptRunner, //InteractiveMode = interactiveMode || IsScriptRunner && sourceFiles.Count == 0, BaseDirectory = baseDirectory, //PathMap = pathMap, Errors = ImmutableArray<Diagnostic>.Empty, Utf8Output = true, CompilationName = compilationName, OutputFileName = outputFileName, PdbPath = pdbPath, EmitPdb = emitPdb, OutputDirectory = outputDirectory, //DocumentationPath = documentationPath, //ErrorLogPath = errorLogPath, //AppConfigPath = appConfigPath, SourceFiles = sourceFiles.AsImmutable(), Encoding = Encoding.UTF8, ChecksumAlgorithm = SourceHashAlgorithm.Sha1, // checksumAlgorithm, MetadataReferences = metadataReferences.AsImmutable(), AnalyzerReferences = analyzers.AsImmutable(), AdditionalFiles = additionalFiles.AsImmutable(), ReferencePaths = referencePaths.AsImmutable(), SourcePaths = ImmutableArray<string>.Empty, //sourcePaths.AsImmutable(), //KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(), //Win32ResourceFile = win32ResourceFile, //Win32Icon = win32IconFile, //Win32Manifest = win32ManifestFile, //NoWin32Manifest = noWin32Manifest, DisplayLogo = displayLogo, DisplayHelp = displayHelp, ManifestResources = managedResources.AsImmutable(), CompilationOptions = options, ParseOptions = IsScriptRunner ? scriptParseOptions : parseOptions, EmitOptions = emitOptions, //ScriptArguments = scriptArgs.AsImmutableOrEmpty(), //TouchedFilesPath = touchedFilesPath, //PrintFullPaths = printFullPaths, //ShouldIncludeErrorEndLocation = errorEndLocation, //PreferredUILang = preferredUILang, //SqmSessionGuid = sqmSessionGuid, //ReportAnalyzer = reportAnalyzer }; }