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)); }
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)); }
/// <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); }
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)); }
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(), }); }
/// <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(); } }
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 }); } }
/// <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;
protected string CreateRelativeFilePath(string fullPath) { return(PhpFileUtilities.GetRelativePath( PhpFileUtilities.NormalizeSlashes(fullPath), PhpFileUtilities.NormalizeSlashes(_compilation.Options.BaseDirectory))); }