/// <summary> /// Launches the debugger at the end of the given phase if specified /// </summary> public static void TryLaunchDebuggerAfterPhase(EnginePhases phase) { if (LaunchDebuggerAfterPhase != null && LaunchDebuggerAfterPhase.Value == phase) { Debugger.Launch(); } }
private static CommandLineConfiguration GetCommandLineConfiguration( WorkspaceBuilderConfiguration configuration, EnginePhases phase, AbsolutePath configFile) { return(new CommandLineConfiguration { Startup = { ConfigFile = configFile, }, FrontEnd = { DebugScript = false, PreserveFullNames = true, PreserveTrivia = true, // We want to preserve comments, so let's not skip trivia CancelParsingOnFirstFailure = configuration.CancelOnFirstParsingFailure, UseSpecPublicFacadeAndAstWhenAvailable = configuration.PublicFacadeOptimization, ConstructAndSaveBindingFingerprint = configuration.SaveBindingFingerprint, NameResolutionSemantics = NameResolutionSemantics.ImplicitProjectReferences, // If SkipNuget is specified, then all the packages should be on disk. // Skipping nuget restore in this case. UsePackagesFromFileSystem = configuration.SkipNuget, }, Engine = { Phase = phase, }, }); }
/// <summary> /// Returns the action associated with a given key in a given dictionary. If no entry /// is found, returns an empty action. /// </summary> private static Action GetPhaseHook(Dictionary <EnginePhases, Action> hooks, EnginePhases phase) { Action hook; return(hooks.TryGetValue(phase, out hook) ? hook : () => { }); }
private static CommandLineConfiguration GetCommandLineConfiguration( WorkspaceBuilderConfiguration configuration, EnginePhases phase, AbsolutePath configFile, AbsolutePath outputDirectory, AbsolutePath objectDirectory) { return(new CommandLineConfiguration { Startup = { ConfigFile = configFile, }, FrontEnd = { DebugScript = false, PreserveFullNames = true, PreserveTrivia = true, // We want to preserve comments, so let's not skip trivia CancelParsingOnFirstFailure = configuration.CancelOnFirstParsingFailure, UseSpecPublicFacadeAndAstWhenAvailable = configuration.PublicFacadeOptimization, ConstructAndSaveBindingFingerprint = configuration.SaveBindingFingerprint, NameResolutionSemantics = NameResolutionSemantics.ImplicitProjectReferences, // If SkipNuget is specified, then all the packages should be on disk. // Skipping nuget restore in this case. UsePackagesFromFileSystem = configuration.SkipNuget, // Don't release workspace so that analyses can still be done if the min required phase is evaluation. // TODO: Hack -- when phase Evaluate is use, then release workspace. This is for Office to be performant. ReleaseWorkspaceBeforeEvaluation = !phase.HasFlag(EnginePhases.Evaluate), UnsafeOptimizedAstConversion = true, AllowUnsafeAmbient = true, }, Engine = { Phase = phase, }, Schedule = { UseFixedApiServerMoniker = true }, Layout = { OutputDirectory = outputDirectory, ObjectDirectory = objectDirectory, }, Logging = { LogsToRetain = 0, }, Cache = { CacheSpecs = SpecCachingOption.Disabled } }); }
/// <summary> /// Composes a given action with any action previously associated with a given key in a given dictionary. /// </summary> private void AddPhaseHook(Dictionary <EnginePhases, Action> hooks, EnginePhases phase, Action hook) { Contract.Requires(hooks != null); Contract.Requires(hook != null); Contract.Requires(!IsSealed); var oldHook = GetPhaseHook(hooks, phase); hooks[phase] = () => { oldHook(); hook(); }; }
/// <summary> /// Composes a given hook with any 'end' hook previously associated with a given phase. /// </summary> public void AddPhaseEndHook(EnginePhases phase, Action hook) { AddPhaseHook(m_phaseEndHooks, phase, hook); }
/// <summary> /// Returns the 'end' hook associated with a given phase. /// If no hook has been associated, an empty action is returned. /// </summary> public Action GetPhaseEndHook(EnginePhases phase) { return(GetPhaseHook(m_phaseEndHooks, phase)); }
/// <summary> /// Builds a workspace and uses filter to find specs to evaluate. /// </summary> public static bool TryCollectFilesToAnalyze( Tracing.Logger logger, PathTable pathTable, EnginePhases phase, string configFile, string filter, out Workspace workspace, out IReadOnlyDictionary <AbsolutePath, ISourceFile> filesToAnalyze, out FrontEndContext context) { workspace = null; filesToAnalyze = null; var loggingContext = new LoggingContext("DScriptAnalyzer"); var fileSystem = new PassThroughFileSystem(pathTable); var engineContext = EngineContext.CreateNew(CancellationToken.None, pathTable, fileSystem); context = engineContext.ToFrontEndContext(loggingContext); // Parse filter string into EvaluationFilter var evaluationFilter = EvaluationFilter.Empty; if (!string.IsNullOrEmpty(filter)) { if (!TryGetEvaluationFilter(logger, loggingContext, engineContext, filter, out evaluationFilter)) { // Error has been reported already return(false); } } var configFilePath = AbsolutePath.Create(pathTable, configFile); // Try parsing the workspace from config and evaluation filter if (!TryBuildWorkspace( phase, context, engineContext, configFilePath, evaluationFilter, progressHandler: null, workspace: out workspace, frontEndHostController: out _, configuration: GetDefaultConfiguration())) { return(false); } // Find strict subset of specs in workspace that should be analyzed var collectedFilesToAnalyze = CollectFilesToAnalyze( workspace, pathTable, configFilePath, evaluationFilter); if (collectedFilesToAnalyze.Count == 0) { logger.ErrorFilterHasNoMatchingSpecs(loggingContext, filter); return(false); } filesToAnalyze = collectedFilesToAnalyze; return(true); }
public static bool TryBuildWorkspace( EnginePhases phase, FrontEndContext frontEndContext, PipExecutionContext engineContext, AbsolutePath configFile, EvaluationFilter evaluationFilter, EventHandler <WorkspaceProgressEventArgs> progressHandler, out Workspace workspace, out FrontEndHostController frontEndHostController, WorkspaceBuilderConfiguration configuration, FrontEndEngineAbstraction frontEndEngineAbstraction = null, bool collectMemoryAsSoonAsPossible = true) { Contract.Requires((phase & (EnginePhases.ParseWorkspace | EnginePhases.AnalyzeWorkspace)) != EnginePhases.None); Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(configFile.IsValid); Contract.Requires(evaluationFilter != null); workspace = null; var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var commandlineConfig = GetCommandLineConfiguration(configuration, phase, configFile); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(commandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(progressHandler); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: commandlineConfig, collector: null, statistics: statistics, collectMemoryAsSoonAsPossible: collectMemoryAsSoonAsPossible); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, commandlineConfig); frontEndHostController = controller as FrontEndHostController; // If there is an explicit engine abstraction, we set it if (frontEndEngineAbstraction != null) { frontEndHostController.SetState(frontEndEngineAbstraction, pipGraph: null, configuration: commandlineConfig); } var config = controller.ParseConfig(commandlineConfig); if (config == null) { frontEndHostController = null; return(false); } using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache( new SchedulerContext( CancellationToken.None, frontEndContext.StringTable, frontEndContext.PathTable, frontEndContext.SymbolTable, frontEndContext.QualifierTable)), // Note that we have an 'empty' store (no hits ever) rather than a normal in memory one. new EmptyTwoPhaseFingerprintStore()))) { // Attempt to build and/or analyze the workspace if (!controller.PopulateGraph( cache: cache, graph: null /* No need to create pips */, engineAbstraction: frontEndEngineAbstraction ?? new BasicFrontEndEngineAbstraction(frontEndContext.PathTable, frontEndContext.FileSystem, config), evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: commandlineConfig.Startup)) { Contract.Assert(frontEndHostController != null); workspace = frontEndHostController.GetWorkspace(); // Error has been reported already return(false); } } Contract.Assert(frontEndHostController != null); // If workspace construction is successfull, we run the linter on all specs. // This makes sure the workspace will carry all the errors that will occur when running the same specs in the regular engine path workspace = CreateLintedWorkspace( frontEndHostController.GetWorkspace(), frontEndContext.LoggingContext, config.FrontEnd, pathTable); return(true); }
public static bool TryBuildWorkspace( EnginePhases phase, FrontEndContext frontEndContext, EngineContext engineContext, AbsolutePath configFile, EvaluationFilter evaluationFilter, AbsolutePath outputDirectory, AbsolutePath objectDirectory, EventHandler <WorkspaceProgressEventArgs> progressHandler, out Workspace workspace, out FrontEndHostController frontEndHostController, out IPipGraph pipGraph, WorkspaceBuilderConfiguration configuration, FrontEndEngineAbstraction frontEndEngineAbstraction = null, bool collectMemoryAsSoonAsPossible = true) { Contract.Requires((phase & (EnginePhases.ParseWorkspace | EnginePhases.AnalyzeWorkspace)) != EnginePhases.None); Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(configFile.IsValid); Contract.Requires(evaluationFilter != null); workspace = null; frontEndHostController = null; pipGraph = null; var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var commandlineConfig = GetCommandLineConfiguration( configuration, phase, configFile, outputDirectory, objectDirectory); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(commandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(progressHandler); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: commandlineConfig, collector: null, statistics: statistics, collectMemoryAsSoonAsPossible: collectMemoryAsSoonAsPossible); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, commandlineConfig); frontEndHostController = (FrontEndHostController)controller; // If there is an explicit engine abstraction, we set it. This is used by IDE test. if (frontEndEngineAbstraction != null) { frontEndHostController.SetState(frontEndEngineAbstraction, pipGraph: null, configuration: commandlineConfig); } var config = controller.ParseConfig(commandlineConfig); if (config == null) { return(false); } IPipGraph pipGraphBuilder = null; using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache(), // Note that we have an 'empty' store (no hits ever) rather than a normal in memory one. new EmptyTwoPhaseFingerprintStore()))) { if (frontEndEngineAbstraction == null) { if (phase.HasFlag(EnginePhases.Schedule)) { var mountsTable = MountsTable.CreateAndRegister(loggingContext, engineContext, config, commandlineConfig.Startup.Properties); frontEndEngineAbstraction = new FrontEndEngineImplementation( loggingContext, frontEndContext.PathTable, config, commandlineConfig.Startup, mountsTable, InputTracker.CreateDisabledTracker(loggingContext), null, null, () => FileContentTable.CreateStub(), 5000, false); pipGraphBuilder = new GraphFragmentBuilder(loggingContext, engineContext, config); // TODO: Think more if an analyzer wants to use the real pip graph builder. //pipGraphBuilder = new PipGraph.Builder( // EngineSchedule.CreateEmptyPipTable(engineContext), // engineContext, // Scheduler.Tracing.Logger.Log, // loggingContext, // config, // mountsTable.MountPathExpander, // fingerprintSalt: config.Cache.CacheSalt, // directoryMembershipFingerprinterRules: new DirectoryMembershipFingerprinterRuleSet(config, engineContext.StringTable)); if (!AddConfigurationMountsAndCompleteInitialization(config, loggingContext, mountsTable)) { return(false); } IDictionary <ModuleId, MountsTable> moduleMountsTableMap; if (!mountsTable.PopulateModuleMounts(config.ModulePolicies.Values, out moduleMountsTableMap)) { Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.PopulateModuleMounts()"); return(false); } } else { frontEndEngineAbstraction = new BasicFrontEndEngineAbstraction(frontEndContext.PathTable, frontEndContext.FileSystem, config); } } using (frontEndEngineAbstraction is IDisposable ? (IDisposable)frontEndEngineAbstraction : null) { // Attempt to build and/or analyze the workspace if (!controller.PopulateGraph( cache: cache, graph: pipGraphBuilder, engineAbstraction: frontEndEngineAbstraction, evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: commandlineConfig.Startup)) { workspace = frontEndHostController.GetWorkspace(); // Error has been reported already return(false); } pipGraph = pipGraphBuilder; //if (pipGraphBuilder != null) //{ // pipGraph = pipGraphBuilder.Build(); // if (pipGraph == null) // { // // Error has been reported already. // return false; // } //} } } Contract.Assert(frontEndHostController != null); workspace = frontEndHostController.GetWorkspace(); if (phase == EnginePhases.AnalyzeWorkspace) { // If workspace construction is successful, we run the linter on all specs. // This makes sure the workspace will carry all the errors that will occur when running the same specs in the regular engine path workspace = CreateLintedWorkspace( workspace, frontEndContext.LoggingContext, config.FrontEnd, pathTable); } return(true); }