Example #1
0
        IEnumerable <EmbeddedText> CollectAdditionalEmbeddedTexts()
        {
            // TODO: if (EmbedPharContentIntoPdb):

            foreach (var f in this.SourceSymbolCollection.GetFiles())
            {
                var tree  = f.SyntaxTree;
                var fname = tree.FilePath;

                if (f.SyntaxTree.IsPharEntry) // embed phar entry
                {
                    // ok, fname is already a virtual file path of the phar entry
                }
                else if (fname.IsPharFile())                               // embed phar stub
                {
                    fname = PhpFileUtilities.BuildPharStubFileName(fname); // virtual file name for the phar stub entry
                }
                else
                {
                    continue; // not embedded into PDB
                }

                yield return(EmbeddedText.FromSource(fname, tree.GetText()));
            }
        }
        public IPhpScriptTypeSymbol ResolveFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }

            // normalize path
            path = FileUtilities.NormalizeRelativePath(path, null, _compilation.Options.BaseDirectory);

            // absolute path
            if (PathUtilities.IsAbsolute(path))
            {
                path = PhpFileUtilities.GetRelativePath(path, _compilation.Options.BaseDirectory);
            }

            // lookup referenced assemblies

            // ./ handled by context semantics

            // ../ handled by context semantics

            // TODO: lookup include paths
            // TODO: calling script directory

            // cwd
            var script = GetScriptsFromReferencedAssemblies().FirstOrDefault(t => t.RelativeFilePath == path);

            // TODO: RoutineSemantics // relative to current script

            return(script ?? _next.ResolveFile(path));
        }
Example #3
0
        public IPhpScriptTypeSymbol ResolveFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }

            // normalize path
            path = FileUtilities.NormalizeRelativePath(path, null, Compilation.Options.BaseDirectory);

            // absolute path
            if (PathUtilities.IsAbsolute(path))
            {
                path = PhpFileUtilities.GetRelativePath(path, Compilation.Options.BaseDirectory);
            }

            // ./ handled by context semantics

            // ../ handled by context semantics

            // TODO: lookup include paths
            // TODO: calling script directory

            // cwd
            return(_table.GetFile(path));
        }
Example #4
0
        /// <summary>
        /// Gets enumeration of user declared routines (global code, functions, methods and lambdas) in the specified file
        /// identified by its syntax tree.
        /// </summary>
        public IEnumerable <IPhpRoutineSymbol> GetUserDeclaredRoutinesInFile(PhpSyntaxTree syntaxTree)
        {
            string relativePath = PhpFileUtilities.GetRelativePath(
                PhpFileUtilities.NormalizeSlashes(syntaxTree.Source.FilePath),
                PhpFileUtilities.NormalizeSlashes(_options.BaseDirectory));
            var fileSymbol = _tables.GetFile(relativePath);

            return(fileSymbol?.GetAllRoutines() ?? ImmutableArray <SourceRoutineSymbol> .Empty);
        }
        public bool RemoveSyntaxTree(string fname)
        {
            var relative = PhpFileUtilities.GetRelativePath(fname, _compilation.Options.BaseDirectory);

            if (_files.Remove(relative))
            {
                _version++;

                return(true);
            }

            return(false);
        }
        protected string CreateRelativeFilePath(string fullPath)
        {
            var relpath = PhpFileUtilities.GetRelativePath(
                PhpFileUtilities.NormalizeSlashes(fullPath),
                PhpFileUtilities.NormalizeSlashes(_compilation.Options.BaseDirectory));

            if (!string.IsNullOrEmpty(_compilation.Options.SubDirectory))
            {
                relpath = PhpFileUtilities.NormalizeSlashes(PathUtilities.CombinePathsUnchecked(_compilation.Options.SubDirectory, relpath));
            }

            return(relpath);
        }
Example #7
0
        SourceFileSymbol ISemanticModel.GetFile(string path)
        {
            // normalize path
            path = FileUtilities.NormalizeRelativePath(path, null, _baseDirectory);

            // absolute path
            if (PathUtilities.IsAbsolute(path))
            {
                path = PhpFileUtilities.GetRelativePath(path, _baseDirectory);
            }

            // ./ handled by context semantics

            // ../ handled by context semantics

            // TODO: lookup include paths
            // TODO: calling script directory

            // cwd
            return(GetFile(path));
        }
Example #8
0
        public override T VisitInclude(BoundIncludeEx x)
        {
            // check arguments
            base.VisitRoutineCall(x);

            // check the target was not resolved
            if (x.TargetMethod == null)
            {
                foreach (var arg in x.ArgumentsInSourceOrder)
                {
                    // in case the include is in form (__DIR__ . LITERAL)
                    // it should get resolved
                    if (arg.Value is BoundConcatEx concat &&
                        concat.ArgumentsInSourceOrder.Length == 2 &&
                        concat.ArgumentsInSourceOrder[0].Value is BoundPseudoConst pc &&
                        pc.ConstType == PseudoConstUse.Types.Dir &&
                        concat.ArgumentsInSourceOrder[1].Value.ConstantValue.TryConvertToString(out var relativePath) &&
                        relativePath.Length != 0)
                    {
                        // WARNING: Script file '{0}' could not be resolved
                        if (_routine != null)
                        {
                            relativePath = PhpFileUtilities.NormalizeSlashes(_routine.ContainingFile.DirectoryRelativePath + relativePath);

                            if (Roslyn.Utilities.PathUtilities.IsAnyDirectorySeparator(relativePath[0]))
                            {
                                relativePath = relativePath.Substring(1); // trim leading slash
                            }

                            _diagnostics.Add(_routine, concat.PhpSyntax ?? x.PhpSyntax, ErrorCode.WRN_CannotIncludeFile, relativePath);
                        }
                    }
                }
            }

            //
            return default;
        }
        internal override CommandLineArguments CommonParse(IEnumerable <string> args, string baseDirectory, string sdkDirectoryOpt, string additionalReferenceDirectories)
        {
            List <Diagnostic> diagnostics   = new List <Diagnostic>();
            List <string>     flattenedArgs = new List <string>();
            List <string>     scriptArgs    = IsScriptCommandLineParser ? new List <string>() : null;

            FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory);

            var                    sourceFiles = new List <CommandLineSourceFile>();
            var                    metadataReferences = new List <CommandLineReference>();
            var                    analyzers = new List <CommandLineAnalyzerReference>();
            var                    additionalFiles = new List <CommandLineSourceFile>();
            var                    embeddedFiles = new List <CommandLineSourceFile>();
            var                    managedResources = new List <ResourceDescription>();
            var                    defines = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            string                 outputDirectory = baseDirectory;
            string                 subDirectory = null;
            string                 outputFileName = null;
            string                 documentationPath = null;
            string                 moduleName = null;
            string                 runtimeMetadataVersion = null; // will be read from cor library if not specified in cmd
            string                 compilationName = null;
            string                 versionString = null;
            Encoding               codepage = null;
            bool                   embedAllSourceFiles = false;
            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_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) || string.Equals(value, "latest", StringComparison.OrdinalIgnoreCase))
                    {
                        languageVersion = null;     // default
                    }
                    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 "xmldoc":
                case "doc":
                    documentationPath = value ?? string.Empty;
                    break;

                case "phpdoctypes+":
                    phpdocTypes = PhpDocTypes.All;
                    break;

                case "phpdoctypes-":
                    phpdocTypes = PhpDocTypes.None;
                    break;

                case "phpdoctypes":
                    if (value == null)
                    {
                        phpdocTypes = PhpDocTypes.All;
                    }
                    else
                    {
                        phpdocTypes = (PhpDocTypes)Enum.Parse(typeof(PhpDocTypes), value);
                    }
                    break;

                case "modulename":
                    var unquotedModuleName = RemoveQuotesAndSlashes(value);
                    if (string.IsNullOrEmpty(unquotedModuleName))
                    {
                        diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name));
                    }
                    else
                    {
                        moduleName = unquotedModuleName;
                    }

                    continue;

                case "version":
                case "v":
                    versionString = RemoveQuotesAndSlashes(value);
                    continue;

                case "runtimemetadataversion":
                    unquoted = RemoveQuotesAndSlashes(value);
                    if (string.IsNullOrEmpty(unquoted))
                    {
                        diagnostics.Add(Errors.MessageProvider.Instance.CreateDiagnostic(Errors.ErrorCode.ERR_SwitchNeedsValue, Location.None, name));
                    }
                    else
                    {
                        runtimeMetadataVersion = unquoted;
                    }
                    continue;

                case "res":
                case "resource":
                    if (value == null)
                    {
                        break;     // Dev11 reports unrecognized option
                    }

                    var embeddedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: true);
                    if (embeddedResource != null)
                    {
                        managedResources.Add(embeddedResource);
                        resourcesOrModulesSpecified = true;
                    }

                    continue;

                case "linkres":
                case "linkresource":
                    if (value == null)
                    {
                        break;     // Dev11 reports unrecognized option
                    }

                    var linkedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: false);
                    if (linkedResource != null)
                    {
                        managedResources.Add(linkedResource);
                        resourcesOrModulesSpecified = true;
                    }

                    continue;

                case "subdir":
                    if (!string.IsNullOrEmpty(value))
                    {
                        // TODO: check value
                        subDirectory = Utilities.PhpFileUtilities.NormalizeSlashes(RemoveQuotesAndSlashes(value));
                    }
                    continue;

                case "embed":
                    if (string.IsNullOrEmpty(value))
                    {
                        embedAllSourceFiles = true;
                        continue;
                    }

                    embeddedFiles.AddRange(ParseSeparatedFileArgument(value, baseDirectory, diagnostics));
                    continue;

                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,";

                    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;
                    }

                    // 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);

            // 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,
                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,
            };

            if (debugPlus)
            {
                options = options.WithDebugPlusMode(debugPlus);
            }

            var emitOptions = new EmitOptions
                              (
                metadataOnly: false,
                debugInformationFormat: debugInformationFormat,
                pdbFilePath: null,        // to be determined later
                pdbChecksumAlgorithm: System.Security.Cryptography.HashAlgorithmName.SHA1,
                outputNameOverride: null, // to be determined later
                                          //baseAddress: baseAddress,
                                          //highEntropyVirtualAddressSpace: highEntropyVA,
                                          //fileAlignment: fileAlignment,
                                          //subsystemVersion: subsystemVersion,
                runtimeMetadataVersion: runtimeMetadataVersion
                              );

            return(new PhpCommandLineArguments()
            {
                // TODO: parsed arguments
                IsScriptRunner = IsScriptCommandLineParser,
                //InteractiveMode = interactiveMode || IsScriptRunner && sourceFiles.Count == 0,
                BaseDirectory = baseDirectory,
                //PathMap = pathMap,
                Errors = ImmutableArray <Diagnostic> .Empty,
                Utf8Output = true,
                CompilationName = compilationName,
                OutputFileName = outputFileName,
                PdbPath = pdbPath,
                EmitPdb = emitPdb,
                SourceLink = sourceLink,
                OutputDirectory = outputDirectory,
                DocumentationPath = documentationPath,
                //ErrorLogPath = errorLogPath,
                //AppConfigPath = appConfigPath,
                SourceFiles = sourceFiles.AsImmutable(),
                Encoding = codepage,                          // Encoding.UTF8,
                ChecksumAlgorithm = SourceHashAlgorithm.Sha1, // checksumAlgorithm,
                MetadataReferences = metadataReferences.AsImmutable(),
                AnalyzerReferences = analyzers.AsImmutable(),
                AdditionalFiles = additionalFiles.AsImmutable(),
                ReferencePaths = referencePaths.AsImmutable(),
                SourcePaths = ImmutableArray <string> .Empty, //sourcePaths.AsImmutable(),
                KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(),
                //Win32ResourceFile = win32ResourceFile,
                //Win32Icon = win32IconFile,
                //Win32Manifest = win32ManifestFile,
                //NoWin32Manifest = noWin32Manifest,
                DisplayLogo = displayLogo,
                DisplayHelp = displayHelp,
                ManifestResources = managedResources.AsImmutable(),
                CompilationOptions = options,
                ParseOptions = IsScriptCommandLineParser ? scriptParseOptions : parseOptions,
                EmitOptions = emitOptions,
                //ScriptArguments = scriptArgs.AsImmutableOrEmpty(),
                //TouchedFilesPath = touchedFilesPath,
                PrintFullPaths = printFullPaths,
                //ShouldIncludeErrorEndLocation = errorEndLocation,
                //PreferredUILang = preferredUILang,
                //SqmSessionGuid = sqmSessionGuid,
                //ReportAnalyzer = reportAnalyzer
                EmbeddedFiles = embeddedFiles.AsImmutable(),
            });
        }
Example #10
0
        /// <summary>
        /// Generates method body that calls another method.
        /// Used for wrapping a method call into a method, e.g. an entry point.
        /// </summary>
        internal static MethodBody GenerateMethodBody(
            PEModuleBuilder moduleBuilder,
            MethodSymbol routine,
            Action <ILBuilder> builder,
            VariableSlotAllocator variableSlotAllocatorOpt,
            DiagnosticBag diagnostics,
            bool emittingPdb)
        {
            var compilation      = moduleBuilder.Compilation;
            var localSlotManager = new LocalSlotManager(variableSlotAllocatorOpt);
            var optimizations    = compilation.Options.OptimizationLevel;

            DebugDocumentProvider debugDocumentProvider = null;

            if (emittingPdb)
            {
                debugDocumentProvider = (path, basePath) =>
                {
                    if (path.IsPharFile())
                    {
                        path = PhpFileUtilities.BuildPharStubFileName(path);
                    }

                    return(moduleBuilder.DebugDocumentsBuilder.GetOrAddDebugDocument(
                               path,
                               basePath,
                               normalizedPath => CreateDebugSourceDocument(normalizedPath, routine)));
                };
            }

            ILBuilder il = new ILBuilder(moduleBuilder, localSlotManager, optimizations.AsOptimizationLevel());

            try
            {
                StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfo = null;

                builder(il);

                //
                il.Realize();

                //
                var localVariables = il.LocalSlotManager.LocalsInOrder();

                if (localVariables.Length > 0xFFFE)
                {
                    //diagnosticsForThisMethod.Add(ErrorCode.ERR_TooManyLocals, method.Locations.First());
                }

                //if (diagnosticsForThisMethod.HasAnyErrors())
                //{
                //    // we are done here. Since there were errors we should not emit anything.
                //    return null;
                //}

                //// We will only save the IL builders when running tests.
                //if (moduleBuilder.SaveTestData)
                //{
                //    moduleBuilder.SetMethodTestData(method, builder.GetSnapshot());
                //}

                // Only compiler-generated MoveNext methods have iterator scopes.  See if this is one.
                var stateMachineHoistedLocalScopes = default(ImmutableArray <StateMachineHoistedLocalScope>);
                //if (isStateMachineMoveNextMethod)
                //{
                //    stateMachineHoistedLocalScopes = builder.GetHoistedLocalScopes();
                //}

                var stateMachineHoistedLocalSlots = default(ImmutableArray <EncHoistedLocalInfo>);
                var stateMachineAwaiterSlots      = default(ImmutableArray <Cci.ITypeReference>);
                //if (optimizations == OptimizationLevel.Debug && stateMachineTypeOpt != null)
                //{
                //    Debug.Assert(method.IsAsync || method.IsIterator);
                //    GetStateMachineSlotDebugInfo(moduleBuilder, moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), variableSlotAllocatorOpt, diagnosticsForThisMethod, out stateMachineHoistedLocalSlots, out stateMachineAwaiterSlots);
                //    Debug.Assert(!diagnostics.HasAnyErrors());
                //}

                return(new MethodBody(
                           il.RealizedIL,
                           il.MaxStack,
                           (Cci.IMethodDefinition)routine.PartialDefinitionPart ?? routine,
                           variableSlotAllocatorOpt?.MethodId ?? new DebugId(0, moduleBuilder.CurrentGenerationOrdinal),
                           localVariables,
                           il.RealizedSequencePoints,
                           debugDocumentProvider,
                           il.RealizedExceptionHandlers,
                           il.GetAllScopes(),
                           il.HasDynamicLocal,
                           null,                                     // importScopeOpt,
                           ImmutableArray <LambdaDebugInfo> .Empty,  // lambdaDebugInfo,
                           ImmutableArray <ClosureDebugInfo> .Empty, // closureDebugInfo,
                           null,                                     //stateMachineTypeOpt?.Name,
                           stateMachineHoistedLocalScopes,
                           stateMachineHoistedLocalSlots,
                           stateMachineAwaiterSlots,
                           stateMachineMoveNextDebugInfo,
                           null)); // dynamicAnalysisDataOpt
            }
            finally
            {
                // Basic blocks contain poolable builders for IL and sequence points. Free those back
                // to their pools.
                il.FreeBasicBlocks();

                //// Remember diagnostics.
                //diagnostics.AddRange(diagnosticsForThisMethod);
                //diagnosticsForThisMethod.Free();
            }
        }
Example #11
0
        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
                });
            }
        }
Example #12
0
 /// <summary>
 /// Gets file path for the debug document and embedded text feature.
 /// In most cases it is equivalent to <see cref="FilePath"/>,
 /// in synthesized stubs (phar stub) it may be a generated file name.
 /// </summary>
 public string GetDebugSourceDocumentPath() => IsPharStub?PhpFileUtilities.BuildPharStubFileName(FilePath) : FilePath;
Example #13
0
 protected string CreateRelativeFilePath(string fullPath)
 {
     return(PhpFileUtilities.GetRelativePath(
                PhpFileUtilities.NormalizeSlashes(fullPath),
                PhpFileUtilities.NormalizeSlashes(_compilation.Options.BaseDirectory)));
 }