Пример #1
0
        ///// <summary>
        ///// Flags applied to the top-level binder created for each syntax tree in the compilation
        ///// as well as for the binder of global imports.
        ///// </summary>
        //internal BinderFlags TopLevelBinderFlags { get; private set; }

        // Defaults correspond to the compiler's defaults or indicate that the user did not specify when that is significant.
        // That's significant when one option depends on another's setting. SubsystemVersion depends on Platform and Target.
        public PhpCompilationOptions(
            OutputKind outputKind,
            string baseDirectory,
            string sdkDirectory,
            string subDirectory = null,
            bool reportSuppressedDiagnostics = false,
            string moduleName      = null,
            string mainTypeName    = null,
            string scriptClassName = null,
            string versionString   = null,
            PhpOptimizationLevel optimizationLevel = PhpOptimizationLevel.Debug,
            bool checkOverflow                    = false,
            string cryptoKeyContainer             = null,
            string cryptoKeyFile                  = null,
            ImmutableArray <byte> cryptoPublicKey = default,
            bool?delaySign    = null,
            Platform platform = Platform.AnyCpu,
            ReportDiagnostic generalDiagnosticOption = ReportDiagnostic.Default,
            int warningLevel = 4,
            IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions = null,
            bool concurrentBuild      = true,
            bool deterministic        = false,
            DateTime currentLocalTime = default(DateTime),
            XmlReferenceResolver xmlReferenceResolver           = null,
            SourceReferenceResolver sourceReferenceResolver     = null,
            MetadataReferenceResolver metadataReferenceResolver = null,
            AssemblyIdentityComparer assemblyIdentityComparer   = null,
            StrongNameProvider strongNameProvider = null,
            bool publicSign          = false,
            PhpDocTypes phpdocTypes  = PhpDocTypes.None,
            bool embedSourceMetadata = true,
            ImmutableArray <Diagnostic> diagnostics      = default,
            PhpParseOptions parseOptions                 = null,
            ImmutableDictionary <string, string> defines = default,
            bool referencesSupersedeLowerVersions        = false)
            : this(outputKind, baseDirectory, sdkDirectory, subDirectory,
                   reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName,
                   versionString,
                   optimizationLevel, checkOverflow,
                   cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, platform,
                   generalDiagnosticOption, warningLevel,
                   specificDiagnosticOptions, concurrentBuild, deterministic,
                   debugPlusMode : false,
                   currentLocalTime : currentLocalTime,
                   xmlReferenceResolver : xmlReferenceResolver,
                   sourceReferenceResolver : sourceReferenceResolver,
                   metadataReferenceResolver : metadataReferenceResolver,
                   assemblyIdentityComparer : assemblyIdentityComparer,
                   strongNameProvider : strongNameProvider,
                   metadataImportOptions : MetadataImportOptions.Public,
                   publicSign : publicSign,
                   phpdocTypes : phpdocTypes,
                   embedSourceMetadata : embedSourceMetadata,
                   diagnostics : diagnostics,
                   defines : defines,
                   parseOptions : parseOptions,
                   referencesSupersedeLowerVersions : referencesSupersedeLowerVersions)
        {
        }
Пример #2
0
 // Expects correct arguments.
 internal PhpCompilationOptions(
     OutputKind outputKind,
     string baseDirectory,
     string sdkDirectory,
     string subDirectory,
     bool reportSuppressedDiagnostics,
     string moduleName,
     string mainTypeName,
     string scriptClassName,
     string versionString,
     PhpOptimizationLevel optimizationLevel,
     bool checkOverflow,
     string cryptoKeyContainer,
     string cryptoKeyFile,
     ImmutableArray <byte> cryptoPublicKey,
     bool?delaySign,
     Platform platform,
     ReportDiagnostic generalDiagnosticOption,
     int warningLevel,
     IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions,
     bool concurrentBuild,
     bool deterministic,
     DateTime currentLocalTime,
     bool debugPlusMode,
     XmlReferenceResolver xmlReferenceResolver,
     SourceReferenceResolver sourceReferenceResolver,
     MetadataReferenceResolver metadataReferenceResolver,
     AssemblyIdentityComparer assemblyIdentityComparer,
     StrongNameProvider strongNameProvider,
     MetadataImportOptions metadataImportOptions,
     bool publicSign,
     PhpDocTypes phpdocTypes,
     bool embedSourceMetadata,
     ImmutableArray <Diagnostic> diagnostics,
     PhpParseOptions parseOptions,
     ImmutableDictionary <string, string> defines,
     bool referencesSupersedeLowerVersions)
     : base(outputKind, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName,
            cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, publicSign, optimizationLevel.AsOptimizationLevel(), checkOverflow,
            platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions.ToImmutableDictionaryOrEmpty(),
            concurrentBuild, deterministic, currentLocalTime, debugPlusMode, xmlReferenceResolver,
            sourceReferenceResolver, metadataReferenceResolver, assemblyIdentityComparer,
            strongNameProvider, metadataImportOptions, referencesSupersedeLowerVersions)
 {
     this.BaseDirectory       = baseDirectory;
     this.SdkDirectory        = sdkDirectory;
     this.SubDirectory        = subDirectory;
     this.PhpDocTypes         = phpdocTypes;
     this.EmbedSourceMetadata = embedSourceMetadata;
     this.ParseOptions        = parseOptions;
     this.Diagnostics         = diagnostics;
     this.VersionString       = versionString;
     this.OptimizationLevel   = optimizationLevel;
     this.Defines             = defines;
 }
Пример #3
0
        ///// <summary>
        ///// Flags applied to the top-level binder created for each syntax tree in the compilation
        ///// as well as for the binder of global imports.
        ///// </summary>
        //internal BinderFlags TopLevelBinderFlags { get; private set; }

        // Defaults correspond to the compiler's defaults or indicate that the user did not specify when that is significant.
        // That's significant when one option depends on another's setting. SubsystemVersion depends on Platform and Target.
        public PhpCompilationOptions(
            OutputKind outputKind,
            string baseDirectory,
            string sdkDirectory,
            bool reportSuppressedDiagnostics = false,
            string moduleName      = null,
            string mainTypeName    = null,
            string scriptClassName = null,
            OptimizationLevel optimizationLevel = OptimizationLevel.Debug,
            bool checkOverflow                    = false,
            string cryptoKeyContainer             = null,
            string cryptoKeyFile                  = null,
            ImmutableArray <byte> cryptoPublicKey = default(ImmutableArray <byte>),
            bool?delaySign    = null,
            Platform platform = Platform.AnyCpu,
            ReportDiagnostic generalDiagnosticOption = ReportDiagnostic.Default,
            int warningLevel = 4,
            IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions = null,
            bool concurrentBuild = true,
            bool deterministic   = false,
            XmlReferenceResolver xmlReferenceResolver           = null,
            SourceReferenceResolver sourceReferenceResolver     = null,
            MetadataReferenceResolver metadataReferenceResolver = null,
            AssemblyIdentityComparer assemblyIdentityComparer   = null,
            StrongNameProvider strongNameProvider = null,
            bool publicSign              = false,
            PhpDocTypes phpdocTypes      = PhpDocTypes.None,
            PhpParseOptions parseOptions = null)
            : this(outputKind, baseDirectory, sdkDirectory,
                   reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName,
                   optimizationLevel, checkOverflow,
                   cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, platform,
                   generalDiagnosticOption, warningLevel,
                   specificDiagnosticOptions, concurrentBuild, deterministic,
                   extendedCustomDebugInformation : true,
                   debugPlusMode : false,
                   xmlReferenceResolver : xmlReferenceResolver,
                   sourceReferenceResolver : sourceReferenceResolver,
                   metadataReferenceResolver : metadataReferenceResolver,
                   assemblyIdentityComparer : assemblyIdentityComparer,
                   strongNameProvider : strongNameProvider,
                   metadataImportOptions : MetadataImportOptions.Public,
                   publicSign : publicSign,
                   phpdocTypes : phpdocTypes,
                   parseOptions : parseOptions)
        {
        }
Пример #4
0
 // Expects correct arguments.
 internal PhpCompilationOptions(
     OutputKind outputKind,
     string baseDirectory,
     string sdkDirectory,
     bool reportSuppressedDiagnostics,
     string moduleName,
     string mainTypeName,
     string scriptClassName,
     OptimizationLevel optimizationLevel,
     bool checkOverflow,
     string cryptoKeyContainer,
     string cryptoKeyFile,
     ImmutableArray <byte> cryptoPublicKey,
     bool?delaySign,
     Platform platform,
     ReportDiagnostic generalDiagnosticOption,
     int warningLevel,
     IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions,
     bool concurrentBuild,
     bool deterministic,
     bool extendedCustomDebugInformation,
     bool debugPlusMode,
     XmlReferenceResolver xmlReferenceResolver,
     SourceReferenceResolver sourceReferenceResolver,
     MetadataReferenceResolver metadataReferenceResolver,
     AssemblyIdentityComparer assemblyIdentityComparer,
     StrongNameProvider strongNameProvider,
     MetadataImportOptions metadataImportOptions,
     bool publicSign,
     PhpDocTypes phpdocTypes,
     PhpParseOptions parseOptions)
     : base(outputKind, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName,
            cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, publicSign, optimizationLevel, checkOverflow,
            platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions.ToImmutableDictionaryOrEmpty(),
            concurrentBuild, deterministic, extendedCustomDebugInformation, debugPlusMode, xmlReferenceResolver,
            sourceReferenceResolver, metadataReferenceResolver, assemblyIdentityComparer,
            strongNameProvider, metadataImportOptions)
 {
     this.BaseDirectory = baseDirectory;
     this.SdkDirectory  = sdkDirectory;
     this.PhpDocTypes   = phpdocTypes;
     this.ParseOptions  = parseOptions;
 }
Пример #5
0
        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
            });
        }
        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
            });
        }
Пример #7
0
        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(),
            });
        }