예제 #1
0
        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
                }
            });
        }
예제 #2
0
        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);
        }