internal ImmutableContextBase( ContextTree contextTree, ImmutableContextBase parent, [NotNull] ModuleLiteral module, TopLevelValueInfo topLevelValueInfo, FileType fileType, EvaluatorConfiguration configuration, [NotNull] IEvaluationScheduler evaluationScheduler) { Contract.Requires(contextTree.IsValid); Contract.Requires(parent == null || parent.ContextTree == contextTree); Contract.Requires(module != null); Contract.Requires(evaluationScheduler != null); ParentContext = parent; LastActiveUsedModule = module; TopLevelValueInfo = topLevelValueInfo; ContextTree = contextTree; DebugState = new DebugState(); m_relativePath = RelativePath.Invalid; EvaluatorConfiguration = configuration; EvaluationScheduler = evaluationScheduler; FileType = fileType; if (parent != null) { m_callStack = parent.m_callStack; } }
public Task <bool?> TryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition module, QualifierId qualifierId) { Contract.Requires(scheduler != null); Contract.Requires(module != null); Contract.Requires(qualifierId.IsValid); throw new System.NotImplementedException(); }
/// <nodoc /> protected ContextTree CreateContext( FileModuleLiteral instantiatedModule, IEvaluationScheduler evaluationScheduler, IDecorator <EvaluationResult> decorator, EvaluatorConfiguration configuration, FileType fileType) { Contract.Requires(instantiatedModule != null); Contract.Requires(evaluationScheduler != null); return(new ContextTree( FrontEndHost, Context, Constants, SharedModuleRegistry, Logger, Statistics, qualifierValueCache: QualifierValueCache, isBeingDebugged: IsBeingDebugged, decorator: decorator, module: instantiatedModule, configuration: configuration, evaluationScheduler: evaluationScheduler, fileType: fileType)); }
/// <inheritdoc/> public async Task <bool?> TryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition iModule, QualifierId qualifierId) { if (!iModule.Equals(ModuleDef)) { return(null); } return(await Task.FromResult(TryEvaluate(ModuleDef, qualifierId))); }
/// <inheritdoc/> public async Task <bool?> TryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition iModule, QualifierId qualifierId) { if (!iModule.Equals(ModuleDefinition)) { return(null); } var module = (ModuleDefinition)iModule; return(await EvaluateAllFilesAsync(module.Specs, qualifierId)); }
/// <inheritdoc/> public async Task <bool?> TryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition iModule, QualifierId qualifierId) { if (!iModule.Equals(ModuleDef)) { return(null); } // Note: we are effectively evaluating iModule // Using await to suppress compiler warnings // TODO: Async? return(await Task.FromResult(TryEvaluate(ModuleDef, qualifierId))); }
/// <inheritdoc /> public Task <bool?> TryEvaluateModuleAsync([NotNull] IEvaluationScheduler scheduler, [NotNull] ModuleDefinition module, QualifierId qualifierId) { // Abstraction between SDK/Workspace/Core/Resolvers is broken here... var moduleDefinition = (ModuleDefinition)module; if (!string.Equals(moduleDefinition.Descriptor.ResolverName, Name, StringComparison.Ordinal)) { return(Task.FromResult <bool?>(null)); } // Downloads are not individually requested to be evaluated, we want them to be on demand. return(Task.FromResult <bool?>(true)); }
public ContextTree( [NotNull] FrontEndHost frontEndHost, [NotNull] FrontEndContext frontEndContext, [NotNull] GlobalConstants constants, [NotNull] ModuleRegistry moduleRegistry, [NotNull] Logger logger, [NotNull] EvaluationStatistics statistics, QualifierValueCache qualifierValueCache, bool isBeingDebugged, IDecorator <EvaluationResult> decorator, [NotNull] FileModuleLiteral module, [NotNull] EvaluatorConfiguration configuration, [NotNull] IEvaluationScheduler evaluationScheduler, FileType fileType) { Contract.Requires(frontEndHost != null); Contract.Requires(frontEndContext != null); Contract.Requires(constants != null); Contract.Requires(moduleRegistry != null); Contract.Requires(logger != null); Contract.Requires(statistics != null); Contract.Requires(module != null); EvaluationScheduler = evaluationScheduler; FrontEndHost = frontEndHost; FrontEndContext = frontEndContext; Constants = constants; ModuleRegistry = moduleRegistry; Logger = logger; Statistics = statistics; IsBeingDebugged = isBeingDebugged; Decorator = decorator; EvaluationScheduler = evaluationScheduler; QualifierValueCache = qualifierValueCache; ToolDefinitionCache = new ConcurrentDictionary <ObjectLiteral, CachedToolDefinition>(); ValueCache = new ConcurrentDictionary <Fingerprint, EvaluationResult>(); CommonConstants = new CommonConstants(frontEndContext.StringTable); RootContext = new Context( contextTree: this, parent: null, module: module, topLevelValueInfo: null, fileType: fileType, configuration: configuration, evaluationScheduler: evaluationScheduler); Interlocked.Increment(ref statistics.ContextTrees); }
/// <inheritdoc /> public async Task <bool?> TryEvaluateModuleAsync([NotNull] IEvaluationScheduler scheduler, [NotNull] ModuleDefinition module, QualifierId qualifierId) { // Abstraction between SDK/Workspace/Core/Resolvers is broken here... var moduleDefinition = (ModuleDefinition)module; if (!string.Equals(moduleDefinition.Descriptor.ResolverName, Name, StringComparison.Ordinal)) { return(null); } var downloadData = m_workspaceResolver.Downloads[module.Descriptor.Name]; // Make sure evaluating is guarded by the semaphore, so it only happens one at a time // There is no need to make sure we don't evaluate duplicate work here since module evaluation // happens once per qualifier. await m_evaluationSemaphore.WaitAsync(); try { // Modules of the download resolver are always instantiated with the empty qualifier var moduleRegistry = (ModuleRegistry)m_frontEndHost.ModuleRegistry; var moduleLiteral = moduleRegistry .GetUninstantiatedModuleInfoByPath(downloadData.ModuleSpecFile) .FileModuleLiteral .InstantiateFileModuleLiteral(moduleRegistry, QualifierValue.CreateEmpty(m_context.QualifierTable)); // Evaluate all values of the module using (var contextTree = new ContextTree( m_frontEndHost, m_context, m_logger, m_evaluationStatistics, new QualifierValueCache(), isBeingDebugged: false, decorator: null, moduleLiteral, new EvaluatorConfiguration(trackMethodInvocations: false, cycleDetectorStartupDelay: TimeSpanUtilities.MillisecondsToTimeSpan(10)), scheduler, FileType.Project)) { var moduleTracker = VisitedModuleTracker.Create(isDebug: false); var success = await moduleLiteral.EvaluateAllAsync(contextTree.RootContext, moduleTracker, ModuleEvaluationMode.None); return(success); } } finally { m_evaluationSemaphore.Release(); } }
/// <summary> /// Evaluates a single package, and all projects that the package owns. /// </summary> private IReadOnlyList <Task <EvaluationResult> > EvaluatePackage(IEvaluationScheduler scheduler, Package package, QualifierValue qualifier) { Contract.Requires(package != null); Contract.Requires(qualifier != null); var projectsToEvaluate = GetProjectsOfPackage(package); var shouldEvaluateLocalTransitive = ShouldEvaluateLocalTransitivePackage(package); // Note that, if package does not explicitly specifies the projects that it owns, then // we only evaluate the package's main file, and rely on the import/export relation to evaluate all // specs in the package. Another alternative is to glob all projects in the package's cone, and // evaluate those projects as well. Globbing involves IO, and can be expensive in a spinning disk. // For a consideration, WDG may only have one package, and may not specifiy all projects that the package // owns. Globbing the entire WDG tree will be very costly. return(projectsToEvaluate.Select(project => EvaluateAsync(scheduler, project, qualifier, asPackageEvaluation: shouldEvaluateLocalTransitive)).ToList()); }
/// <inheritdoc/> public async Task <bool?> TryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition module, QualifierId qualifierId) { Contract.Requires(scheduler != null); Contract.Requires(module != null); Contract.Requires(qualifierId.IsValid); Contract.Assert(m_resolverState == State.ResolverInitialized); Contract.Assert(m_owningModules != null, "Owning modules should not be null if the instance is initialized."); var moduleDefinition = (ModuleDefinition)module; if (!m_owningModules.TryGetValue(moduleDefinition.Descriptor.Id, out Package package)) { // Current resolver doesn't own the given module. return(null); } return(await DoTryEvaluateModuleAsync(scheduler, moduleDefinition, qualifierId)); }
private async Task <bool> DoTryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition module, QualifierId qualifierId) { var qualifier = QualifierValue.Create(qualifierId, QualifierValueCache, Context.QualifierTable, Context.StringTable); // We don't want to evaluate the transitive closure of the import/export relationship, just the package. var evalJobs = module.Specs.Select( spec => EvaluateAsync(scheduler, spec, qualifier, asPackageEvaluation: false)); var allTasks = await Task.WhenAll(evalJobs); var result = allTasks.All(t => t.Success); if (m_evaluationDecorator != null) { foreach (var evaluationResult in allTasks) { m_evaluationResults.Enqueue(evaluationResult); } } return(result); }
private async Task <EvaluationResult> CollectProjectOutputsAsync(IReadOnlySet <AbsolutePath> evaluationGoals, QualifierId qualifierId, ResolvedJavaScriptExport export, IEvaluationScheduler scheduler) { // Make sure all project files are evaluated before collecting their outputs if (!await EvaluateAllFilesOnceAsync(evaluationGoals, qualifierId, scheduler)) { return(EvaluationResult.Error); } var processOutputs = export.ExportedProjects.SelectMany(project => { if (!m_scheduledProcessOutputs.TryGetValue(project, out var projectOutputs)) { // The requested project was not scheduled. This can happen when a filter gets applied, so even // though the export points to a valid project (which is already validated), the project is not part // of the graph. In this case just log an informational message. Tracing.Logger.Log.RequestedExportIsNotPresent( Context.LoggingContext, m_resolverSettings.Location(Context.PathTable), export.FullSymbol.ToString(Context.SymbolTable), project.Name, project.ScriptCommandName); } return(projectOutputs); }); // Let's put together all output directories for all pips under this project var sealedDirectories = processOutputs.SelectMany(process => process.GetOutputDirectories().Select(staticDirectory => new EvaluationResult(staticDirectory))).ToArray(); return(new EvaluationResult(new EvaluatedArrayLiteral(sealedDirectories, default, m_javaScriptWorkspaceResolver.ExportsFile)));
/// <summary> /// Evaluates a file given the file path and a qualifier. /// </summary> /// <remarks> /// If the evaluation is part of package evaluation, then all files in the transitive closure of /// local import/export relation will be evaluated as well. /// </remarks> private async Task <EvaluationResult> EvaluateAsync(IEvaluationScheduler scheduler, AbsolutePath fullPath, QualifierValue qualifier, bool asPackageEvaluation) { Contract.Requires(fullPath.IsValid); Contract.Requires(qualifier != null); // Get an uninstantiated module. if (!((ModuleRegistry)FrontEndHost.ModuleRegistry).TryGetUninstantiatedModuleInfoByPath(fullPath, out UninstantiatedModuleInfo moduleInfo)) { Logger.ReportSourceResolverFailEvaluateUnregisteredFileModule(Context.LoggingContext, Name, fullPath.ToString(Context.PathTable)); return(CreateResult(false)); } // If this spec belongs to a V1 module, then coercion happens at this point, since in V1 the qualifier space is always defined at the file level // and we want an explicit failure if coercion fails, to keep V1 modules back compat // Otherwise, we don't coerce, since coercion will happen on a namespace level in FileModuleLiteral.EvaluateAllNamedValues if (!FrontEndHost.SpecBelongsToImplicitSemanticsModule(fullPath)) { // Coerce qualifier. if (!qualifier.TryCoerce( moduleInfo.QualifierSpaceId, Context.QualifierTable, QualifierValueCache, Context.PathTable, Context.StringTable, Context.LoggingContext, out QualifierValue coercedQualifier, default(LineInfo), FrontEndHost.ShouldUseDefaultsOnCoercion(moduleInfo.ModuleLiteral.Path), fullPath)) { string qualifierName = Context.QualifierTable.GetQualifier(qualifier.QualifierId).ToDisplayString(Context.StringTable); string qualifierSpace = Context.QualifierTable.GetQualifierSpace(moduleInfo.QualifierSpaceId).ToDisplayString(Context.StringTable); Logger.ReportQualifierCannotBeCoarcedToQualifierSpace( Context.LoggingContext, new Location { // Ideally the referencing location is used for this error, but that is a big replumbing effort. // Task 615531 File = fullPath.ToString(Context.PathTable), }, qualifierName, qualifierSpace); return(CreateResult(false)); } qualifier = coercedQualifier; } // Instantiate module with the coerced qualifier. var module = InstantiateModule(moduleInfo.FileModuleLiteral, qualifier); // Create an evaluation context tree and root context. using (var contextTree = CreateContext(module, scheduler, m_evaluationDecorator, CreateEvaluatorConfiguration(), FileType.Project)) using (FrontEndStatistics.SpecEvaluation.Start(fullPath.ToString(Context.PathTable))) { var context = contextTree.RootContext; // Evaluate module. var moduleTracker = VisitedModuleTracker.Create(IsBeingDebugged); var mode = asPackageEvaluation ? ModuleEvaluationMode.LocalImportExportTransitive : ModuleEvaluationMode.None; var success = await module.EvaluateAllAsync(context, moduleTracker, mode); return(CreateResult(success, moduleTracker)); } }