示例#1
0
 /// <summary>
 /// Evaluates a string representing a condition from a "condition" attribute.
 /// If the condition is a malformed string, it throws an InvalidProjectFileException.
 /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
 /// This method is thread safe and is called from engine and task execution module threads
 /// </summary>
 internal static bool EvaluateCondition <P, I>
 (
     string condition,
     ParserOptions options,
     Expander <P, I> expander,
     ExpanderOptions expanderOptions,
     string evaluationDirectory,
     ElementLocation elementLocation,
     ILoggingService loggingServices,
     BuildEventContext buildEventContext,
     IFileSystem fileSystem,
     ProjectRootElementCache projectRootElementCache = null)
     where P : class, IProperty
     where I : class, IItem
 {
     return(EvaluateConditionCollectingConditionedProperties(
                condition,
                options,
                expander,
                expanderOptions,
                null /* do not collect conditioned properties */,
                evaluationDirectory,
                elementLocation,
                loggingServices,
                buildEventContext,
                fileSystem,
                projectRootElementCache));
 }
示例#2
0
            internal ConditionEvaluationState
            (
                string condition,
                Expander <P, I> expander,
                ExpanderOptions expanderOptions,
                Dictionary <string, List <string> > conditionedPropertiesInProject,
                string evaluationDirectory,
                ElementLocation elementLocation,
                IFileSystem fileSystem,
                ProjectRootElementCache projectRootElementCache = null
            )
            {
                ErrorUtilities.VerifyThrowArgumentNull(condition, "condition");
                ErrorUtilities.VerifyThrowArgumentNull(expander, "expander");
                ErrorUtilities.VerifyThrowArgumentNull(evaluationDirectory, "evaluationDirectory");
                ErrorUtilities.VerifyThrowArgumentNull(elementLocation, "elementLocation");

                Condition        = condition;
                _expander        = expander;
                _expanderOptions = expanderOptions;
                ConditionedPropertiesInProject = conditionedPropertiesInProject; // May be null
                EvaluationDirectory            = evaluationDirectory;
                ElementLocation     = elementLocation;
                LoadedProjectsCache = projectRootElementCache;
                FileSystem          = fileSystem;
            }
示例#3
0
 /// <summary>
 /// Creates a new ProjectRootElement for a specific PRE cache
 /// </summary>
 /// <param name="path">The path to the file to load.</param>
 /// <param name="projectRootElementCache">The cache to load the PRE into.</param>
 private static ProjectRootElement OpenLoader(string path, ProjectRootElementCache projectRootElementCache)
 {
     return new ProjectRootElement(
         path,
         projectRootElementCache,
         new BuildEventContext(0, BuildEventContext.InvalidNodeId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId));
 }
示例#4
0
        /// <summary>
        /// Centralization of the common parts of construction.
        /// </summary>
        private void Initialize(PropertyDictionary<ProjectPropertyInstance> environmentProperties, ProjectRootElementCache projectRootElementCache, ToolsetProvider toolsetProvider)
        {
            _buildProcessEnvironment = CommunicationsUtilities.GetEnvironmentVariables();
            _environmentProperties = environmentProperties;
            this.ProjectRootElementCache = projectRootElementCache;
            this.ResetCaches = true;
            _toolsetProvider = toolsetProvider;

            if (Environment.GetEnvironmentVariable("MSBUILDDISABLENODEREUSE") == "1") // For example to disable node reuse within Visual Studio
            {
                _enableNodeReuse = false;
            }

            if (Environment.GetEnvironmentVariable("MSBUILDDETAILEDSUMMARY") == "1") // For example to get detailed summary within Visual Studio
            {
                _detailedSummary = true;
            }

            FindMSBuildExe();
        }
示例#5
0
        /// <summary>
        /// Used to load information about default MSBuild tasks i.e. tasks that do not need to be explicitly declared in projects
        /// with the &lt;UsingTask&gt; element. Default task information is read from special files, which are located in the same
        /// directory as the MSBuild binaries.
        /// </summary>
        /// <remarks>
        /// 1) a default tasks file needs the &lt;Project&gt; root tag in order to be well-formed
        /// 2) the XML declaration tag &lt;?xml ...&gt; is ignored
        /// 3) comment tags are always ignored regardless of their placement
        /// 4) the rest of the tags are expected to be &lt;UsingTask&gt; tags
        /// </remarks>
        /// <param name="loggingServices">The logging services to use to log during this registration.</param>
        /// <param name="buildEventContext">The build event context to use to log during this registration.</param>
        private void RegisterDefaultTasks(ILoggingService loggingServices, BuildEventContext buildEventContext, ProjectRootElementCache projectRootElementCache)
        {
            if (!_defaultTasksRegistrationAttempted)
            {
                try
                {
                    _defaultTaskRegistry = new TaskRegistry(projectRootElementCache);

                    InitializeProperties(loggingServices, buildEventContext);

                    string[] defaultTasksFiles = GetTaskFiles(_getFiles, loggingServices, buildEventContext, DefaultTasksFilePattern, ToolsPath, "DefaultTasksFileLoadFailureWarning");
                    LoadAndRegisterFromTasksFile(ToolsPath, defaultTasksFiles, loggingServices, buildEventContext, DefaultTasksFilePattern, "DefaultTasksFileFailure", projectRootElementCache, _defaultTaskRegistry);
                }
                finally
                {
                    _defaultTasksRegistrationAttempted = true;
                }
            }
        }
示例#6
0
 /// <summary>
 /// Return a task registry stub for the tasks in the *.tasks file for this toolset         
 /// </summary>
 /// <param name="loggingServices">The logging services used to log during task registration.</param>
 /// <param name="buildEventContext">The build event context used to log during task registration.</param>
 /// <returns>The task registry</returns>
 internal TaskRegistry GetTaskRegistry(ILoggingService loggingServices, BuildEventContext buildEventContext, ProjectRootElementCache projectRootElementCache)
 {
     RegisterDefaultTasks(loggingServices, buildEventContext, projectRootElementCache);
     return _defaultTaskRegistry;
 }
        public void GetProjectRootElementChangedOnDisk2()
        {
            string path = null;

            try
            {
                ProjectRootElementCache cache = new ProjectRootElementCache(false /* do not auto reload from disk */);

                path = FileUtilities.GetTemporaryFile();

                ProjectRootElement xml0 = ProjectRootElement.Create(path);
                xml0.Save();

                cache.AddEntry(xml0);

                ProjectRootElement xml1 = cache.TryGet(path);
                Assert.Equal(true, Object.ReferenceEquals(xml0, xml1));

                File.SetLastWriteTime(path, DateTime.Now + new TimeSpan(1, 0, 0));

                ProjectRootElement xml2 = cache.TryGet(path);
                Assert.Equal(true, Object.ReferenceEquals(xml0, xml2));
            }
            finally
            {
                File.Delete(path);
            }
        }
示例#8
0
        /// <summary>
        /// Initialize a ProjectRootElement instance from an existing document.
        /// May throw InvalidProjectFileException.
        /// Leaves the project dirty, indicating there are unsaved changes.
        /// </summary>
        /// <remarks>
        /// Do not make public: we do not wish to expose particular XML API's.
        /// </remarks>
        private ProjectRootElement(XmlDocumentWithLocation document, ProjectRootElementCache projectRootElementCache)
            : base()
        {
            ErrorUtilities.VerifyThrowArgumentNull(document, "document");
            ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache, "projectRootElementCache");

            _projectRootElementCache = projectRootElementCache;
            _directory = NativeMethodsShared.GetCurrentDirectory();
            IncrementVersion();

            ProjectParser.Parse(document, this);
        }
示例#9
0
 private static ProjectRootElement OpenLoaderPreserveFormatting(string path, ProjectRootElementCache projectRootElementCache)
 {
     return OpenLoader(path, projectRootElementCache,
         preserveFormatting: true);
 }
示例#10
0
        /// <summary>
        /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later.
        /// Leaves the project dirty, indicating there are unsaved changes.
        /// </summary>
        private ProjectRootElement(ProjectRootElementCache projectRootElementCache, NewProjectFileOptions projectFileOptions)
        {
            ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache, "projectRootElementCache");

            _projectRootElementCache = projectRootElementCache;
            _directory = NativeMethodsShared.GetCurrentDirectory();
            IncrementVersion();

            XmlDocumentWithLocation document = new XmlDocumentWithLocation();

            XmlReaderSettings xrs = new XmlReaderSettings();
            xrs.DtdProcessing = DtdProcessing.Ignore;
            
            var emptyProjectFile = string.Format(EmptyProjectFileContent,
                (projectFileOptions & NewProjectFileOptions.IncludeXmlDeclaration) != 0 ? EmptyProjectFileXmlDeclaration : string.Empty,
                (projectFileOptions & NewProjectFileOptions.IncludeToolsVersion) != 0 ? EmptyProjectFileToolsVersion : string.Empty,
                (projectFileOptions & NewProjectFileOptions.IncludeXmlNamespace) != 0 ? EmptyProjectFileXmlNamespace : string.Empty);

            using (XmlReader xr = XmlReader.Create(new StringReader(emptyProjectFile), xrs))
            {
                document.Load(xr);
            }

            ProjectParser.Parse(document, this);
        }
示例#11
0
        /// <summary>
        /// Initialize a ProjectRootElement instance by loading from the specified file path.
        /// Assumes path is already normalized.
        /// Uses the specified project root element cache.
        /// May throw InvalidProjectFileException.
        /// </summary>
        internal static ProjectRootElement Open(string path, ProjectRootElementCache projectRootElementCache, bool isExplicitlyLoaded,
            bool preserveFormatting)
        {
            ErrorUtilities.VerifyThrowInternalRooted(path);

            ProjectRootElement projectRootElement = projectRootElementCache.Get(path,
                preserveFormatting ? s_openLoaderPreserveFormattingDelegate : s_openLoaderDelegate,
                isExplicitlyLoaded, preserveFormatting);

            return projectRootElement;
        }
示例#12
0
 internal static ProjectRootElement Create(ProjectRootElementCache projectRootElementCache, NewProjectFileOptions projectFileOptions)
 {
     return new ProjectRootElement(projectRootElementCache, projectFileOptions);
 }
示例#13
0
 /// <summary>
 /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later.
 /// Uses the specified project root element cache.
 /// </summary>
 internal static ProjectRootElement Create(ProjectRootElementCache projectRootElementCache)
 {
     return new ProjectRootElement(projectRootElementCache, Project.DefaultNewProjectTemplateOptions);
 }
示例#14
0
        private void CleanupCaches()
        {
            IConfigCache configCache = _componentFactories.GetComponent(BuildComponentType.ConfigCache) as IConfigCache;
            if (null != configCache)
            {
                configCache.ClearConfigurations();
            }

            IResultsCache resultsCache = _componentFactories.GetComponent(BuildComponentType.ResultsCache) as IResultsCache;
            if (null != resultsCache)
            {
                resultsCache.ClearResults();
            }

            if (Environment.GetEnvironmentVariable("MSBUILDCLEARXMLCACHEONCHILDNODES") == "1")
            {
                // Optionally clear out the cache. This has the advantage of releasing memory,
                // but the disadvantage of causing the next build to repeat the load and parse.
                // We'll experiment here and ship with the best default.
                s_projectRootElementCache = null;
            }

            // Since we aren't going to be doing any more work, lets clean up all our memory usage.
            GC.Collect();
        }
示例#15
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public OutOfProcNode()
        {
            s_isOutOfProcNode = true;

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandling.UnhandledExceptionHandler);

            _debugCommunications = (Environment.GetEnvironmentVariable("MSBUILDDEBUGCOMM") == "1");

            _receivedPackets = new Queue<INodePacket>();
            _packetReceivedEvent = new AutoResetEvent(false);
            _shutdownEvent = new ManualResetEvent(false);
            _legacyThreadingData = new LegacyThreadingData();

            _componentFactories = new BuildComponentFactoryCollection(this);
            _componentFactories.RegisterDefaultFactories();
            _packetFactory = new NodePacketFactory();

            _buildRequestEngine = (this as IBuildComponentHost).GetComponent(BuildComponentType.RequestEngine) as IBuildRequestEngine;
            _globalConfigCache = (this as IBuildComponentHost).GetComponent(BuildComponentType.ConfigCache) as IConfigCache;
            _taskHostNodeManager = (this as IBuildComponentHost).GetComponent(BuildComponentType.TaskHostNodeManager) as INodeManager;

            if (s_projectRootElementCache == null)
            {
                s_projectRootElementCache = new ProjectRootElementCache(true /* automatically reload any changes from disk */);
            }

            _buildRequestEngine.OnEngineException += new EngineExceptionDelegate(OnEngineException);
            _buildRequestEngine.OnNewConfigurationRequest += new NewConfigurationRequestDelegate(OnNewConfigurationRequest);
            _buildRequestEngine.OnRequestBlocked += new RequestBlockedDelegate(OnNewRequest);
            _buildRequestEngine.OnRequestComplete += new RequestCompleteDelegate(OnRequestComplete);

            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.BuildRequest, BuildRequest.FactoryForDeserialization, this);
            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.BuildRequestConfiguration, BuildRequestConfiguration.FactoryForDeserialization, this);
            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.BuildRequestConfigurationResponse, BuildRequestConfigurationResponse.FactoryForDeserialization, this);
            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.BuildRequestUnblocker, BuildRequestUnblocker.FactoryForDeserialization, this);
            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.NodeConfiguration, NodeConfiguration.FactoryForDeserialization, this);
            (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.NodeBuildComplete, NodeBuildComplete.FactoryForDeserialization, this);
        }
示例#16
0
        /// <summary>
        /// Creates a ProjectRootElement representing a file, where the file may be a .sln instead of
        /// an MSBuild format file.
        /// Assumes path is already normalized.
        /// If the file is in MSBuild format, may throw InvalidProjectFileException.
        /// If the file is a solution, will throw an IO-related exception if the file cannot be read.
        /// </summary>
        private static ProjectRootElement CreateProjectFromPath
            (
                string projectFile,
                IDictionary<string, string> globalProperties,
                string toolsVersion,
                ILoggingService loggingService,
                ProjectRootElementCache projectRootElementCache,
                BuildEventContext buildEventContext
            )
        {
            ErrorUtilities.VerifyThrowInternalRooted(projectFile);

            try
            {
                if (FileUtilities.IsVCProjFilename(projectFile))
                {
                    ProjectFileErrorUtilities.ThrowInvalidProjectFile(new BuildEventFileInfo(projectFile), "ProjectUpgradeNeededToVcxProj", projectFile);
                }

                // OK it's a regular project file, load it normally.
                return new ProjectRootElement(projectFile, projectRootElementCache, buildEventContext);
            }
            catch (InvalidProjectFileException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if (!ExceptionHandling.NotExpectedException(ex))
                {
                    ProjectFileErrorUtilities.ThrowInvalidProjectFile(new BuildEventFileInfo(projectFile), ex, "InvalidProjectFile", ex.Message);
                }

                throw;
            }
        }
示例#17
0
        /// <summary>
        /// Initialize a ProjectRootElement instance over a project with the specified file path.
        /// Assumes path is already normalized.
        /// May throw InvalidProjectFileException.
        /// </summary>
        private ProjectRootElement(string path, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext)
            : base()
        {
            ErrorUtilities.VerifyThrowArgumentLength(path, "path");
            ErrorUtilities.VerifyThrowInternalRooted(path);
            ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache, "projectRootElementCache");
            ErrorUtilities.VerifyThrowArgumentNull(buildEventContext, "buildEventContext");
            _projectRootElementCache = projectRootElementCache;
            _buildEventContext = buildEventContext;

            IncrementVersion();
            _versionOnDisk = _version;
            _timeLastChangedUtc = DateTime.UtcNow;

            XmlDocumentWithLocation document = LoadDocument(path);

            ProjectParser.Parse(document, this);

            projectRootElementCache.AddEntry(this);
        }
示例#18
0
        /// <summary>
        /// Creates a ProjectRootElement representing a file, where the file may be a .sln instead of
        /// an MSBuild format file.
        /// Assumes path is already normalized.
        /// If the file is in MSBuild format, may throw InvalidProjectFileException.
        /// If the file is a solution, will throw an IO-related exception if the file cannot be read.
        /// </summary>
        private static ProjectRootElement CreateProjectFromPath
            (
                string projectFile,
                IDictionary<string, string> globalProperties,
                string toolsVersion,
                ILoggingService loggingService,
                ProjectRootElementCache projectRootElementCache,
                BuildEventContext buildEventContext,
                bool preserveFormatting
            )
        {
            ErrorUtilities.VerifyThrowInternalRooted(projectFile);

            try
            {
                if (FileUtilities.IsVCProjFilename(projectFile))
                {
                    ProjectFileErrorUtilities.ThrowInvalidProjectFile(new BuildEventFileInfo(projectFile), "ProjectUpgradeNeededToVcxProj", projectFile);
                }

                // OK it's a regular project file, load it normally.
                return new ProjectRootElement(projectFile, projectRootElementCache, buildEventContext, preserveFormatting);
            }
            catch (InvalidProjectFileException)
            {
                throw;
            }
            catch (Exception ex) when (ExceptionHandling.IsIoRelatedException(ex))
            {
                ProjectFileErrorUtilities.ThrowInvalidProjectFile(new BuildEventFileInfo(projectFile), ex, "InvalidProjectFile", ex.Message);
                throw; // Without this there's a spurious CS0161 because csc 1.2.0.60317 can't see that the above is an unconditional throw.
            }
        }
示例#19
0
        /// <summary>
        /// Evaluates a string representing a condition from a "condition" attribute.
        /// If the condition is a malformed string, it throws an InvalidProjectFileException.
        /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
        /// This method is thread safe and is called from engine and task execution module threads
        /// Logging service may be null.
        /// </summary>
        internal static bool EvaluateConditionCollectingConditionedProperties <P, I>
        (
            string condition,
            ParserOptions options,
            Expander <P, I> expander,
            ExpanderOptions expanderOptions,
            Dictionary <string, List <string> > conditionedPropertiesTable,
            string evaluationDirectory,
            ElementLocation elementLocation,
            ILoggingService loggingServices,
            BuildEventContext buildEventContext,
            ProjectRootElementCache projectRootElementCache = null
        )
            where P : class, IProperty
            where I : class, IItem
        {
            ErrorUtilities.VerifyThrowArgumentNull(condition, "condition");
            ErrorUtilities.VerifyThrowArgumentNull(expander, "expander");
            ErrorUtilities.VerifyThrowArgumentLength(evaluationDirectory, "evaluationDirectory");
            ErrorUtilities.VerifyThrowArgumentNull(buildEventContext, "buildEventContext");

            // An empty condition is equivalent to a "true" condition.
            if (condition.Length == 0)
            {
                return(true);
            }

            // If the condition wasn't empty, there must be a location for it
            ErrorUtilities.VerifyThrowArgumentNull(elementLocation, "elementLocation");

            // Get the expression tree cache for the current parsing options.
            ExpressionTreeForCurrentOptionsWithSize cachedExpressionTreesForCurrentOptions = s_cachedExpressionTrees.GetOrAdd(
                (int)options,
                _ => new ExpressionTreeForCurrentOptionsWithSize(new ConcurrentDictionary <string, ConcurrentStack <GenericExpressionNode> >(StringComparer.Ordinal)));

            cachedExpressionTreesForCurrentOptions = FlushCacheIfLargerThanThreshold(options, cachedExpressionTreesForCurrentOptions);

            // Get the pool of expressions for this condition.
            var expressionPool = cachedExpressionTreesForCurrentOptions.GetOrAdd(condition, _ => new ConcurrentStack <GenericExpressionNode>());

            // Try and see if there's an available expression tree in the pool.
            // If not, parse a new expression tree and add it back to the pool.
            GenericExpressionNode parsedExpression;

            if (!expressionPool.TryPop(out parsedExpression))
            {
                Parser conditionParser = new Parser();

                #region REMOVE_COMPAT_WARNING
                conditionParser.LoggingServices      = loggingServices;
                conditionParser.LogBuildEventContext = buildEventContext;
                #endregion

                parsedExpression = conditionParser.Parse(condition, options, elementLocation);
            }

            bool result;

            ConditionEvaluationState <P, I> state = new ConditionEvaluationState <P, I>(condition, expander, expanderOptions, conditionedPropertiesTable, evaluationDirectory, elementLocation, projectRootElementCache);

            // We are evaluating this expression now and it can cache some state for the duration,
            // so we don't want multiple threads working on the same expression
            lock (parsedExpression)
            {
                try
                {
                    result = parsedExpression.Evaluate(state);
                }
                finally
                {
                    parsedExpression.ResetState();
                    if (!s_disableExpressionCaching)
                    {
                        // Finished using the expression tree. Add it back to the pool so other threads can use it.
                        expressionPool.Push(parsedExpression);
                    }
                }
            }

            return(result);
        }
示例#20
0
        /// <summary>
        /// Initialize a ProjectRootElement instance from a XmlReader.
        /// May throw InvalidProjectFileException.
        /// Leaves the project dirty, indicating there are unsaved changes.
        /// Used to create a root element for solutions loaded by the 3.5 version of the solution wrapper.
        /// </summary>
        internal ProjectRootElement(XmlReader xmlReader, ProjectRootElementCache projectRootElementCache, bool isExplicitlyLoaded)
            : base()
        {
            ErrorUtilities.VerifyThrowArgumentNull(xmlReader, "xmlReader");
            ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache, "projectRootElementCache");

            this.IsExplicitlyLoaded = isExplicitlyLoaded;
            _projectRootElementCache = projectRootElementCache;
            _directory = NativeMethodsShared.GetCurrentDirectory();
            IncrementVersion();

            XmlDocumentWithLocation document = LoadDocument(xmlReader);

            ProjectParser.Parse(document, this);
        }
示例#21
0
        /// <summary>
        /// Do the actual loading of the tasks or override tasks file and register the tasks in the task registry
        /// </summary>
        private void LoadAndRegisterFromTasksFile(string searchPath, string[] defaultTaskFiles, ILoggingService loggingServices, BuildEventContext buildEventContext, string defaultTasksFilePattern, string taskFileError, ProjectRootElementCache projectRootElementCache, TaskRegistry registry)
        {
            foreach (string defaultTasksFile in defaultTaskFiles)
            {
                try
                {
                    // Important to keep the following line since unit tests use the delegate.
                    ProjectRootElement projectRootElement;
                    if (_loadXmlFromPath != null)
                    {
                        XmlDocumentWithLocation defaultTasks = _loadXmlFromPath(defaultTasksFile);
                        projectRootElement = ProjectRootElement.Open(defaultTasks);
                    }
                    else
                    {
                        projectRootElement = ProjectRootElement.Open(defaultTasksFile, projectRootElementCache, false /*The tasks file is not a explicitly loaded file*/);
                    }

                    foreach (ProjectElement elementXml in projectRootElement.Children)
                    {
                        ProjectUsingTaskElement usingTask = elementXml as ProjectUsingTaskElement;

                        if (null == usingTask)
                        {
                            ProjectErrorUtilities.ThrowInvalidProject
                                (
                                elementXml.Location,
                                "UnrecognizedElement",
                                elementXml.XmlElement.Name
                                );
                        }

                        TaskRegistry.RegisterTasksFromUsingTaskElement<ProjectPropertyInstance, ProjectItemInstance>
                            (
                            loggingServices,
                            buildEventContext,
                            Path.GetDirectoryName(defaultTasksFile),
                            usingTask,
                            registry,
                            _expander,
                            ExpanderOptions.ExpandProperties
                            );
                    }
                }
                catch (XmlException e)
                {
                    // handle XML errors in the default tasks file
                    ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, new BuildEventFileInfo(e), taskFileError, e.Message);
                }
                catch (Exception e)
                {
                    if (ExceptionHandling.NotExpectedException(e))
                    {
                        // Catching Exception, but rethrowing unless it's an IO related exception.
                        throw;
                    }

                    loggingServices.LogError(buildEventContext, new BuildEventFileInfo(defaultTasksFile), taskFileError, e.Message);
                    break;
                }
            }
        }
示例#22
0
 /// <summary>
 /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later.
 /// Uses the specified project root element cache.
 /// </summary>
 internal static ProjectRootElement Create(ProjectRootElementCache projectRootElementCache)
 {
     return new ProjectRootElement(projectRootElementCache);
 }
示例#23
0
 /// <summary>
 /// Return a task registry for the override tasks in the *.overridetasks file for this toolset         
 /// </summary>
 /// <param name="loggingServices">The logging services used to log during task registration.</param>
 /// <param name="buildEventContext">The build event context used to log during task registration.</param>
 /// <returns>The task registry</returns>
 internal TaskRegistry GetOverrideTaskRegistry(ILoggingService loggingServices, BuildEventContext buildEventContext, ProjectRootElementCache projectRootElementCache)
 {
     RegisterOverrideTasks(loggingServices, buildEventContext, projectRootElementCache);
     return _overrideTaskRegistry;
 }
示例#24
0
        /// <summary>
        /// Initialize a ProjectRootElement instance by loading from the specified file path.
        /// Assumes path is already normalized.
        /// Uses the specified project root element cache.
        /// May throw InvalidProjectFileException.
        /// </summary>
        internal static ProjectRootElement Open(string path, ProjectRootElementCache projectRootElementCache, bool isExplicitlyLoaded)
        {
            ErrorUtilities.VerifyThrowInternalRooted(path);

            ProjectRootElement projectRootElement = projectRootElementCache.Get(path, s_openLoaderDelegate, isExplicitlyLoaded);

            return projectRootElement;
        }
示例#25
0
        /// <summary>
        /// Used to load information about MSBuild override tasks i.e. tasks that override tasks declared in tasks or project files.
        /// </summary>
        private void RegisterOverrideTasks(ILoggingService loggingServices, BuildEventContext buildEventContext, ProjectRootElementCache projectRootElementCache)
        {
            if (!_overrideTasksRegistrationAttempted)
            {
                try
                {
                    _overrideTaskRegistry = new TaskRegistry(projectRootElementCache);
                    bool overrideDirectoryExists = false;

                    try
                    {
                        // Make sure the override directory exists and is not empty before trying to find the files
                        if (!String.IsNullOrEmpty(_overrideTasksPath))
                        {
                            if (Path.IsPathRooted(_overrideTasksPath))
                            {
                                if (null != _directoryExists)
                                {
                                    overrideDirectoryExists = _directoryExists(_overrideTasksPath);
                                }
                                else
                                {
                                    overrideDirectoryExists = Directory.Exists(_overrideTasksPath);
                                }
                            }

                            if (!overrideDirectoryExists)
                            {
                                string rootedPathMessage = ResourceUtilities.FormatResourceString("OverrideTaskNotRootedPath", _overrideTasksPath);
                                loggingServices.LogWarning(buildEventContext, null, new BuildEventFileInfo(String.Empty /* this warning truly does not involve any file*/), "OverrideTasksFileFailure", rootedPathMessage);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        if (ExceptionHandling.NotExpectedException(e))
                        {
                            // Catching Exception, but rethrowing unless it's an IO related exception.
                            throw;
                        }

                        string rootedPathMessage = ResourceUtilities.FormatResourceString("OverrideTaskProblemWithPath", _overrideTasksPath, e.Message);
                        loggingServices.LogWarning(buildEventContext, null, new BuildEventFileInfo(String.Empty /* this warning truly does not involve any file*/), "OverrideTasksFileFailure", rootedPathMessage);
                    }

                    if (overrideDirectoryExists)
                    {
                        InitializeProperties(loggingServices, buildEventContext);
                        string[] overrideTasksFiles = GetTaskFiles(_getFiles, loggingServices, buildEventContext, OverrideTasksFilePattern, _overrideTasksPath, "OverrideTasksFileLoadFailureWarning");

                        // Load and register any override tasks
                        LoadAndRegisterFromTasksFile(_overrideTasksPath, overrideTasksFiles, loggingServices, buildEventContext, OverrideTasksFilePattern, "OverrideTasksFileFailure", projectRootElementCache, _overrideTaskRegistry);
                    }
                }
                finally
                {
                    _overrideTasksRegistrationAttempted = true;
                }
            }
        }
示例#26
0
        /// <summary>
        /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later.
        /// Leaves the project dirty, indicating there are unsaved changes.
        /// </summary>
        private ProjectRootElement(ProjectRootElementCache projectRootElementCache)
        {
            ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache, "projectRootElementCache");

            _projectRootElementCache = projectRootElementCache;
            _directory = NativeMethodsShared.GetCurrentDirectory();
            IncrementVersion();

            XmlDocumentWithLocation document = new XmlDocumentWithLocation();

            XmlReaderSettings xrs = new XmlReaderSettings();
            xrs.DtdProcessing = DtdProcessing.Ignore;

            using (XmlReader xr = XmlReader.Create(new StringReader(ProjectRootElement.EmptyProjectFileContent), xrs))
            {
                document.Load(xr);
            }

            ProjectParser.Parse(document, this);
        }
示例#27
0
        /// <summary>
        /// Evaluates a string representing a condition from a "condition" attribute.
        /// If the condition is a malformed string, it throws an InvalidProjectFileException.
        /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
        /// This method is thread safe and is called from engine and task execution module threads
        /// Logging service may be null.
        /// </summary>
        internal static bool EvaluateConditionCollectingConditionedProperties <P, I>
        (
            string condition,
            ParserOptions options,
            Expander <P, I> expander,
            ExpanderOptions expanderOptions,
            Dictionary <string, List <string> > conditionedPropertiesTable,
            string evaluationDirectory,
            ElementLocation elementLocation,
            ILoggingService loggingServices,
            BuildEventContext buildEventContext,
            ProjectRootElementCache projectRootElementCache = null
        )
            where P : class, IProperty
            where I : class, IItem
        {
            ErrorUtilities.VerifyThrowArgumentNull(condition, "condition");
            ErrorUtilities.VerifyThrowArgumentNull(expander, "expander");
            ErrorUtilities.VerifyThrowArgumentLength(evaluationDirectory, "evaluationDirectory");
            ErrorUtilities.VerifyThrowArgumentNull(buildEventContext, "buildEventContext");

            // An empty condition is equivalent to a "true" condition.
            if (condition.Length == 0)
            {
                return(true);
            }

            // If the condition wasn't empty, there must be a location for it
            ErrorUtilities.VerifyThrowArgumentNull(elementLocation, "elementLocation");

            Hashtable cachedExpressionTreesForCurrentOptions = s_cachedExpressionTrees[(int)options];

            // We only need to lock on writes to the table
            if (cachedExpressionTreesForCurrentOptions == null)
            {
                // Given property functions, casing in conditional expressions isn't necessarily ignored.
                cachedExpressionTreesForCurrentOptions = new Hashtable(50, StringComparer.Ordinal);

                lock (s_cachedExpressionTrees)
                {
                    s_cachedExpressionTrees[(int)options] = cachedExpressionTreesForCurrentOptions;
                }
            }

            // VS stress tests could fill up this cache without end, for example if they use
            // random configuration names - those appear in conditional expressions.
            // So if we hit a limit that we should never hit in normal circumstances in VS,
            // and rarely, periodically hit in normal circumstances in large tree builds,
            // just clear out the cache. It can start repopulating again. Some kind of prioritized
            // aging isn't worth it: although the hit rate of these caches is excellent (nearly 100%)
            // the cost of reparsing expressions should the cache be cleared is not particularly large.
            // Loading Australian Government in VS, there are 3 of these tables, two with about 50
            // entries and one with about 650 entries. So 3000 seems large enough.
            if (cachedExpressionTreesForCurrentOptions.Count > 3000) // threadsafe
            {
                lock (cachedExpressionTreesForCurrentOptions)
                {
                    cachedExpressionTreesForCurrentOptions.Clear();
                }
            }

            // Try and see if we have an expression tree for this condition already
            GenericExpressionNode parsedExpression = (GenericExpressionNode)cachedExpressionTreesForCurrentOptions[condition];

            if (parsedExpression == null)
            {
                Parser conditionParser = new Parser();

                #region REMOVE_COMPAT_WARNING
                conditionParser.LoggingServices      = loggingServices;
                conditionParser.LogBuildEventContext = buildEventContext;
                #endregion

                parsedExpression = conditionParser.Parse(condition, options, elementLocation);

                // It's possible two threads will add a different tree to the same entry in the hashtable,
                // but it should be rare and it's not a problem - the previous entry will be thrown away.
                // We could ensure no dupes with double check locking but it's not really necessary here.
                // Also, we don't want to lock on every read.
                lock (cachedExpressionTreesForCurrentOptions)
                {
                    if (!s_disableExpressionCaching)
                    {
                        cachedExpressionTreesForCurrentOptions[condition] = parsedExpression;
                    }
                }
            }

            bool result;

            ConditionEvaluationState <P, I> state = new ConditionEvaluationState <P, I>(condition, expander, expanderOptions, conditionedPropertiesTable, evaluationDirectory, elementLocation, projectRootElementCache);

            // We are evaluating this expression now and it can cache some state for the duration,
            // so we don't want multiple threads working on the same expression
            lock (parsedExpression)
            {
                try
                {
                    result = parsedExpression.Evaluate(state);
                }
                finally
                {
                    parsedExpression.ResetState();
                }
            }

            return(result);
        }
示例#28
0
        /// <summary>
        /// Gets a ProjectRootElement representing an MSBuild file.
        /// Path provided must be a canonicalized full path.
        /// May throw InvalidProjectFileException or an IO-related exception.
        /// </summary>
        internal static ProjectRootElement OpenProjectOrSolution(string fullPath, IDictionary<string, string> globalProperties, string toolsVersion, ILoggingService loggingService, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext, bool isExplicitlyLoaded)
        {
            ErrorUtilities.VerifyThrowInternalRooted(fullPath);

            ProjectRootElement projectRootElement = projectRootElementCache.Get(
                fullPath,
                (path, cache) => CreateProjectFromPath(path, globalProperties, toolsVersion, loggingService, cache, buildEventContext),
                isExplicitlyLoaded);

            return projectRootElement;
        }