private static SourceUnit ParseFile( TextWriter consoleOutput, PhpParseOptions parseOptions, PhpParseOptions scriptParseOptions, SourceText content, CommandLineSourceFile file) { // TODO: new parser implementation based on Roslyn // TODO: file.IsScript ? scriptParseOptions : parseOptions var tree = CodeSourceUnit.ParseCode(content.ToString(), file.Path); return(tree); }
private SourceUnit ParseFile( TextWriter consoleOutput, PhpParseOptions parseOptions, PhpParseOptions scriptParseOptions, ref bool hadErrors, CommandLineSourceFile file, ErrorLogger errorLogger) { var fileReadDiagnostics = new List <DiagnosticInfo>(); var content = ReadFileContent(file, fileReadDiagnostics); if (content == null) { ReportErrors(fileReadDiagnostics, consoleOutput, errorLogger); fileReadDiagnostics.Clear(); hadErrors = true; return(null); } else { return(ParseFile(consoleOutput, parseOptions, scriptParseOptions, content, file)); } }
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>(); var defines = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); 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; string versionString = null; 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 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 "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 "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; default: break; } } GetCompilationAndModuleNames(diagnostics, outputKind, sourceFiles, sourceFiles.Count != 0, /*moduleAssemblyName*/ null, ref outputFileName, ref moduleName, out compilationName); // if (sourceFiles.Count == 0 && !IsScriptRunner && (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 = compilationName + ".xml"; } // resolve path documentationPath = PathUtilities.CombinePossiblyRelativeAndRelativePaths(outputDirectory, documentationPath); } // 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); } 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, 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 ); 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 }); }
private ParsedSource ParseFile( TextWriter consoleOutput, PhpParseOptions parseOptions, PhpParseOptions scriptParseOptions, ref bool hadErrors, CommandLineSourceFile file, ErrorLogger errorLogger) { if (file.Path.IsPharFile()) { // phar file archive var phar = Devsense.PHP.Phar.PharFile.OpenPharFile(file.Path); // TODO: report exception // treat the stub as a regular source code: var stub = PhpSyntaxTree.ParseCode(SourceText.From(GetPharStub(phar), Encoding.UTF8), parseOptions, scriptParseOptions, file.Path); // TODO: ConcurrentBuild -> Parallel var prefix = PhpFileUtilities.NormalizeSlashes(PhpFileUtilities.GetRelativePath(file.Path, Arguments.BaseDirectory)); var trees = new List <PhpSyntaxTree>(); var content = new List <Devsense.PHP.Phar.Entry>(); foreach (var entry in phar.Manifest.Entries.Values) { var entryName = PhpFileUtilities.NormalizeSlashes(entry.Name); if (entry.IsCompileEntry()) { var tree = PhpSyntaxTree.ParseCode(SourceText.From(entry.Code, Encoding.UTF8), parseOptions, scriptParseOptions, prefix + "/" + entryName); tree.PharStubFile = stub; trees.Add(tree); } else { content.Add(entry); } } // create resource file var resources = new ResourceDescription($"phar://{prefix}.resources", () => { var stream = new MemoryStream(); var writer = new System.Resources.ResourceWriter(stream); foreach (var entry in content) { var entryName = PhpFileUtilities.NormalizeSlashes(entry.Name); writer.AddResource(entryName, entry.Code); } // writer.Generate(); stream.Position = 0; return(stream); }, isPublic: true); // TODO: report errors if any return(new ParsedSource { SyntaxTree = stub, Manifest = phar.Manifest, Trees = trees, Resources = resources, }); } else { // single source file var diagnosticInfos = new List <DiagnosticInfo>(); var content = TryReadFileContent(file, diagnosticInfos); if (diagnosticInfos.Count != 0) { ReportErrors(diagnosticInfos, consoleOutput, errorLogger); hadErrors = true; } PhpSyntaxTree result = null; if (content != null) { result = PhpSyntaxTree.ParseCode(content, parseOptions, scriptParseOptions, file.Path); } if (result != null && result.Diagnostics.HasAnyErrors()) { ReportErrors(result.Diagnostics, consoleOutput, errorLogger); hadErrors = true; } return(new ParsedSource { SyntaxTree = result }); } }
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 analyzerConfigPaths = new List <string>(); 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 targetFramework = 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; PhpOptimizationLevel optimization = PhpOptimizationLevel.Debug; 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 printFullPaths = false; bool resourcesOrModulesSpecified = false; DebugInformationFormat debugInformationFormat = DebugInformationFormat.Pdb; List <string> referencePaths = new List <string>(); List <string> keyFileSearchPaths = new List <string>(); var autoload_classmapfiles = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); var autoload_files = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); var autoload_psr4 = new List <(string prefix, string path)>(); 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) { optimization = PhpOptimizationLevel.Release; } else if (bool.TryParse(value, out var optimizationBool)) { optimization = optimizationBool ? PhpOptimizationLevel.Release : PhpOptimizationLevel.Debug; } else if (int.TryParse(value, out var optimizationNumber) && Enum.IsDefined(typeof(PhpOptimizationLevel), optimizationNumber)) { optimization = (PhpOptimizationLevel)optimizationNumber; } else if (Enum.TryParse(value, true, out optimization)) { // } else { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_BadCompilationOptionValue, Location.None, name, value)); } continue; case "o-": case "optimize-": if (value != null) { break; } optimization = PhpOptimizationLevel.Debug; 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)) { languageVersion = PhpSyntaxTree.DefaultLanguageVersion; } else if (string.Equals(value, "latest", StringComparison.OrdinalIgnoreCase)) { languageVersion = PhpSyntaxTree.LatestLanguageVersion; } 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": if (string.IsNullOrEmpty(value)) { shortOpenTags = true; } else if (!bool.TryParse(RemoveQuotesAndSlashes(value), out shortOpenTags)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_BadCompilationOptionValue, Location.None, name, value)); } 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 "fullpaths": if (value != null) { if (!bool.TryParse(RemoveQuotesAndSlashes(value), out printFullPaths)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_BadCompilationOptionValue, Location.None, name, value)); } } else { printFullPaths = true; } 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 "target-framework": if (string.IsNullOrEmpty(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); } else { targetFramework = value; } 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; } foreach (var path in ParseSeparatedFileArgument(value, baseDirectory, diagnostics)) { embeddedFiles.Add(ToCommandLineSourceFile(path)); } continue; case "autoload": if (string.IsNullOrWhiteSpace(value)) { diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name)); break; } const string classmapprefix = "classmap,"; const string psr4prefix = "psr-4,"; const string filesprefix = "files,"; if (value.StartsWith(classmapprefix, StringComparison.OrdinalIgnoreCase)) { // "classmap,<fullfilename>" autoload_classmapfiles.Add(value.Substring(classmapprefix.Length)); break; } else if (value.StartsWith(psr4prefix, StringComparison.OrdinalIgnoreCase)) { // "psr-4,<prefix>,<path>" var prefix_dir = value.Substring(psr4prefix.Length); var comma = prefix_dir.IndexOf(','); if (comma >= 0) { autoload_psr4.Add((prefix_dir.Remove(comma), prefix_dir.Substring(comma + 1))); } break; } else if (value.StartsWith(filesprefix, StringComparison.OrdinalIgnoreCase)) { // "files,<fullfilename>" autoload_files.Add(value.Substring(filesprefix.Length)); break; } // not handled diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_BadCompilationOptionValue, Location.None, name, value)); break; 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); } } // sanitize autoload paths, prefix them with subdir for (int i = 0; i < autoload_psr4.Count; i++) { var value = autoload_psr4[i]; var path = subDirectory == null ? value.path : PathUtilities.CombinePathsUnchecked(subDirectory, value.path); autoload_psr4[i] = (value.prefix, PhpFileUtilities.NormalizeSlashes(path)); } autoload_classmapfiles = new HashSet <string>( autoload_classmapfiles.Select(path => PhpFileUtilities.NormalizeSlashes(subDirectory == null ? path : PathUtilities.CombinePathsUnchecked(subDirectory, path))), autoload_classmapfiles.Comparer); autoload_files = new HashSet <string>( autoload_files.Select(path => PhpFileUtilities.NormalizeSlashes(subDirectory == null ? path : PathUtilities.CombinePathsUnchecked(subDirectory, path))), autoload_files.Comparer); // 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 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 ); 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, targetFramework: targetFramework, moduleName: moduleName, mainTypeName: mainTypeName, scriptClassName: WellKnownMemberNames.DefaultScriptClassName, versionString: versionString, phpdocTypes: phpdocTypes, parseOptions: parseOptions, defines: defines.ToImmutableDictionary(), diagnostics: diagnostics.AsImmutable(), specificDiagnosticOptions: diagnosticOptions, //usings: usings, optimizationLevel: optimization, 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(), Autoload_PSR4 = autoload_psr4, Autoload_ClassMapFiles = autoload_classmapfiles, Autoload_Files = autoload_files, }; 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(), AnalyzerConfigPaths = analyzerConfigPaths.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 }; }