IncrementalCompileAnalyzer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / BuildTasks / MS / Internal / Tasks / IncrementalCompileAnalyzer.cs / 2 / IncrementalCompileAnalyzer.cs

                             
//----------------------------------------------------------------------------------------
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved. 
// 
// 
// Description: 
//       Analyze the current project inputs, the compiler state file and local reference
//       cache, determine which xaml files require to recompile. 
//
//  History:
//
//  11/21/05: weibz   Created 
//
//--------------------------------------------------------------------------------------- 
 
using System;
using System.IO; 
using System.Collections;
using System.Diagnostics;
using System.Reflection;
 
using Microsoft.Build.Tasks.Windows;
using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 
using MS.Utility;
 
namespace MS.Internal.Tasks
{
    //
    // Keep different categories of recompilation. 
    //
    [Flags] 
    internal enum RecompileCategory : byte 
    {
        NoRecompile        = 0x00, 
        ApplicationFile    = 0x01,
        ModifiedPages      = 0x02,
        PagesWithLocalType = 0x04,
        ContentFiles       = 0x08, 
        All                = 0x0F
    } 
 
    // 
    // IncrementalCompileAnalyzer 
    // 
    internal class IncrementalCompileAnalyzer
    {
        //  
        // ctor of IncrementalCompileAnalyzer
        //  
        internal IncrementalCompileAnalyzer(MarkupCompilePass1 mcPass1) 
        {
            _mcPass1 = mcPass1; 
            _analyzeResult = RecompileCategory.NoRecompile;
        }

        #region internal methods 

 
        // 
        // Analyze the input files based on the compiler cache files.
        // 
        // Put the analyze result in _analyzeResult and other related data fields,
        // such as RecompileMarkupPages, RecompileApplicationFile, etc.
        //
        // If analyze is failed somehow, throw exception. 
        //
        internal void AnalyzeInputFiles() 
        { 

            // 
            // First: Detect if the entire project requires re-compile.
            //

            // 
            // If the compiler state file doesn't exist, recompile all the xaml files.
            // 
            if (!CompilerState.StateFileExists()) 
            {
                _analyzeResult = RecompileCategory.All; 
            }
            else
            {
                // Load the compiler state file. 
                CompilerState.LoadStateInformation();
 
                // if PresenationBuildTasks.dll is changed last build, rebuild the entire project for sure. 

                if (IsFileChanged(Assembly.GetExecutingAssembly().Location) || 
                    IsFileListChanged(_mcPass1.ExtraBuildControlFiles))
                {
                    _analyzeResult = RecompileCategory.All;
                } 
                else
                { 
                    // 
                    // Any one single change in below list would request completely re-compile.
                    // 
                    if (IsSettingModified(CompilerState.References, _mcPass1.ReferencesCache) ||
                        IsSettingModified(CompilerState.ApplicationFile, _mcPass1.ApplicationFile) ||
                        IsSettingModified(CompilerState.RootNamespace, _mcPass1.RootNamespace) ||
                        IsSettingModified(CompilerState.AssemblyName, _mcPass1.AssemblyName) || 
                        IsSettingModified(CompilerState.AssemblyVersion, _mcPass1.AssemblyVersion) ||
                        IsSettingModified(CompilerState.AssemblyPublicKeyToken, _mcPass1.AssemblyPublicKeyToken) || 
                        IsSettingModified(CompilerState.OutputType, _mcPass1.OutputType) || 
                        IsSettingModified(CompilerState.Language, _mcPass1.Language) ||
                        IsSettingModified(CompilerState.LanguageSourceExtension, _mcPass1.LanguageSourceExtension) || 
                        IsSettingModified(CompilerState.OutputPath, _mcPass1.OutputPath) ||
                        IsSettingModified(CompilerState.LocalizationDirectivesToLocFile, _mcPass1.LocalizationDirectivesToLocFile))
                    {
                        _analyzeResult = RecompileCategory.All; 
                    }
                    else 
                    { 
                        if (_mcPass1.IsApplicationTarget)
                        { 
                            //
                            // When application definition file is modified, it could potentially change the application
                            // class name, it then has impact on all other xaml file compilation, so recompile the entire
                            // project for this case. 
                            //
                            if (TaskFileService.Exists(_mcPass1.ApplicationFile) && IsFileChanged(_mcPass1.ApplicationFile)) 
                            { 
                                _analyzeResult = RecompileCategory.All;
                            } 
                        }

                        //
                        // If any one referenced assembly is updated since last build, the entire project needs to recompile. 
                        //
 
                        if (IsFileListChanged(_mcPass1.References)) 
                        {
                            _analyzeResult = RecompileCategory.All; 
                        }
                    }
                }
            } 

            if (_analyzeResult == RecompileCategory.All) 
            { 
                UpdateFileListForCleanbuild();
                return; 
            }

            //
            // The entire project recompilation should have already been handled when code goes here. 
            // Now, Detect the individual xaml files which require to recompile.
            // 
 
            if (_mcPass1.IsApplicationTarget)
            { 
                if (IsSettingModified(CompilerState.ContentFiles, _mcPass1.ContentFilesCache))
                {
                    _analyzeResult |= RecompileCategory.ContentFiles;
                } 

                // if HostInBrowser setting is changed, it would affect the application file compilation only. 
                if (IsSettingModified(CompilerState.HostInBrowser, _mcPass1.HostInBrowser)) 
                {
                    _analyzeResult |= RecompileCategory.ApplicationFile; 
                }

                if (IsSettingModified(CompilerState.SplashImage, _mcPass1.SplashImageName))
                { 
                    _analyzeResult |= RecompileCategory.ApplicationFile;
                } 
            } 

            // 
            // If code files are changed, or Define flags are changed, it would affect the xaml file with local types.
            //
            // If previous build didn't have such local-ref-xaml files, don't bother to do further check for this.
            // 

            if (CompilerLocalReference.CacheFileExists()) 
            { 
                if (IsSettingModified(CompilerState.DefineConstants, _mcPass1.DefineConstants) ||
                    IsSettingModified(CompilerState.SourceCodeFiles, _mcPass1.SourceCodeFilesCache) || 
                    IsFileListChanged(_mcPass1.SourceCodeFiles) )
                {
                    _analyzeResult |= RecompileCategory.PagesWithLocalType;
                } 
            }
 
            ArrayList modifiedXamlFiles = new ArrayList(); 

            // 
            // Detect if any .xaml page is updated since last build
            //
            if (ListIsNotEmpty(_mcPass1.PageMarkup))
            { 

                // 
                // If the PageMarkup file number or hashcode is changed, it would affect 
                // the xaml files with local types.
                // 
                // This check is necessary for the senario that a xaml file is removed and the
                // removed xaml file could be referenced by other xaml files with local types.
                //
                if (IsSettingModified(CompilerState.PageMarkup, _mcPass1.PageMarkupCache)) 
                {
                    if (CompilerLocalReference.CacheFileExists()) 
                    { 
                        _analyzeResult |= RecompileCategory.PagesWithLocalType;
                    } 
                }

                // Below code detects which invidual xaml files are modified since last build.
                for (int i = 0; i < _mcPass1.PageMarkup.Length; i++) 
                {
                    string fileName = _mcPass1.PageMarkup[i].ItemSpec; 
                    string filepath = Path.GetFullPath(fileName); 

                    if (IsFileChanged(filepath)) 
                    {
                        // add this file to the modified file list.
                        modifiedXamlFiles.Add(filepath);
                    } 
                    else
                    { 
                        // A previously generated xaml file (with timestamp earlier than of the cache file) 
                        // could be added to the project.  This means that the above check for time stamp
                        // will skip compiling the newly added xaml file.  We save the name all the xaml 
                        // files we previously built to the cache file.  Retrieve that list and see if
                        // this xaml file is already in it.  If so, we'll skip compiling this xaml file,
                        // else, this xaml file was just added to the project and thus compile it.
 
                        if (!CompilerState.PageMarkupFileNames.Contains(fileName))
                        { 
                            modifiedXamlFiles.Add(filepath); 
                        }
                    } 
                }

                if (modifiedXamlFiles.Count > 0)
                { 
                    _analyzeResult |= RecompileCategory.ModifiedPages;
 
                    if (CompilerLocalReference.CacheFileExists()) 
                    {
                        _analyzeResult |= RecompileCategory.PagesWithLocalType; 
                    }
                }
            }
 
            UpdateFileListForIncrementalBuild(modifiedXamlFiles);
 
        } 

        #endregion 

        #region internal properties

        // 
        // Keep the AnlyzeResult.
        // 
        internal RecompileCategory AnalyzeResult 
        {
            get { return _analyzeResult; } 
        }

        //
        // Keep a list of markup pages which require to recompile 
        //
        internal string[] RecompileMarkupPages 
        { 
            get { return _recompileMarkupPages; }
        } 

        //
        // Application file which requires re-compile.
        // If the value is String.Empty, the appdef file is not required 
        // to recompile.
        // 
        internal string RecompileApplicationFile 
        {
            get { return _recompileApplicationFile; } 
        }


        internal string[] ContentFiles 
        {
            get { return _contentFiles; } 
        } 

        #endregion 

        #region private properties and methods

        private CompilerState CompilerState 
        {
            get { return _mcPass1.CompilerState; } 
        } 

        private CompilerLocalReference CompilerLocalReference 
        {
            get { return _mcPass1.CompilerLocalReference; }
        }
 
        private ITaskFileService TaskFileService
        { 
            get { return _mcPass1.TaskFileService; } 
        }
 
        private DateTime LastCompileTime
        {
            get
            { 
                DateTime nonSet = new DateTime(0);
                if (_lastCompileTime == nonSet) 
                { 
                    _lastCompileTime = TaskFileService.GetLastChangeTime(CompilerState.CacheFilePath);
 
                }

                return _lastCompileTime;
            } 
        }
 
        // 
        // Compare two strings.
        // 
        private bool IsSettingModified(string textSource, string textTarget)
        {
            bool IsSettingModified;
 
            bool isSrcEmpty = String.IsNullOrEmpty(textSource);
            bool istgtEmpty = String.IsNullOrEmpty(textTarget); 
 
            if (isSrcEmpty != istgtEmpty)
            { 
                IsSettingModified = true;
            }
            else
            { 
                if (isSrcEmpty)  // Both source and target strings are empty.
                { 
                    IsSettingModified = false; 
                }
                else  // Both source and target strings are not empty. 
                {
                    IsSettingModified = String.Compare(textSource, textTarget, StringComparison.OrdinalIgnoreCase) == 0 ? false : true;
                }
            } 

            return IsSettingModified; 
        } 

        // 
        // Generate new list of files that require to recompile for incremental build based on _analyzeResult
        //
        private void UpdateFileListForIncrementalBuild(ArrayList modifiedXamlFiles)
        { 
            ArrayList recompiledXaml = new ArrayList();
            bool recompileApp = false; 
            int numLocalTypeXamls = 0; 

            if ((_analyzeResult & RecompileCategory.ContentFiles) == RecompileCategory.ContentFiles) 
            {
                RecompileContentFiles();
            }
 
            if ((_analyzeResult & RecompileCategory.ApplicationFile) == RecompileCategory.ApplicationFile)
            { 
                recompileApp = true; 
            }
 
            if ((_analyzeResult & RecompileCategory.PagesWithLocalType) == RecompileCategory.PagesWithLocalType)
            {
                CompilerLocalReference.LoadCacheFile();
 
                if (CompilerLocalReference.LocalApplicationFile != null)
                { 
                    // Application file contains local types, it will be recompiled. 
                    recompileApp = true;
                } 

                if (ListIsNotEmpty(CompilerLocalReference.LocalMarkupPages))
                {
                    numLocalTypeXamls = CompilerLocalReference.LocalMarkupPages.Length; 

                    for (int i = 0; i < CompilerLocalReference.LocalMarkupPages.Length; i++) 
                    { 
                        recompiledXaml.Add(CompilerLocalReference.LocalMarkupPages[i].FilePath);
                    } 
                }

            }
 
            if ((_analyzeResult & RecompileCategory.ModifiedPages) == RecompileCategory.ModifiedPages)
            { 
                // If the xaml is already in the local-type-ref xaml file list, don't add a duplicate file path to recompiledXaml list. 

                for (int i = 0; i < modifiedXamlFiles.Count; i++) 
                {
                    string xamlfile = modifiedXamlFiles[i] as string;
                    bool addToList;
 
                    addToList = true;
 
                    if (numLocalTypeXamls > 0) 
                    {
                        for (int j = 0; j < numLocalTypeXamls; j++) 
                        {
                            if (String.Compare(xamlfile, CompilerLocalReference.LocalMarkupPages[j].FilePath, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                addToList = false; 
                                break;
                            } 
                        } 
                    }
 
                    if (addToList)
                    {
                        recompiledXaml.Add(xamlfile);
                    } 
                }
            } 
 
            if (recompiledXaml.Count > 0)
            { 
                _recompileMarkupPages = (string[])recompiledXaml.ToArray(typeof(string));
            }

            // Set ApplicationFile appropriatelly for this incremental build. 
            ProcessApplicationFile(recompileApp);
        } 
 
        //
        // To recompile all the xaml files ( including page and application file). 
        // Transfer all the xaml files to the recompileMarkupPages.
        //
        private void UpdateFileListForCleanbuild()
        { 
            if (ListIsNotEmpty(_mcPass1.PageMarkup))
            { 
                int count = _mcPass1.PageMarkup.Length; 
                _recompileMarkupPages = new string[count];
 
                for (int i = 0; i < count; i++)
                {
                    _recompileMarkupPages[i] = Path.GetFullPath(_mcPass1.PageMarkup[i].ItemSpec);
                } 
            }
 
            RecompileContentFiles(); 

            ProcessApplicationFile(true); 
        }

        //
        // Content files are only for Application target type. 
        //
        private void RecompileContentFiles() 
        { 
            if (!_mcPass1.IsApplicationTarget)
                return; 

            if (_contentFiles == null)
            {
                if (ListIsNotEmpty(_mcPass1.ContentFiles)) 
                {
                    string curDir = Directory.GetCurrentDirectory() + "\\"; 
 
                    int count = _mcPass1.ContentFiles.Length;
 
                    _contentFiles = new string[count];

                    for (int i = 0; i < count; i++)
                    { 
                        string fullPath = Path.GetFullPath(_mcPass1.ContentFiles[i].ItemSpec);
 
                        string relContentFilePath = TaskHelper.GetRootRelativePath(curDir, fullPath); 

                        if (String.IsNullOrEmpty(relContentFilePath)) 
                        {
                           relContentFilePath = Path.GetFileName(fullPath);
                        }
 
                        _contentFiles[i] = relContentFilePath;
                    } 
 
                }
            } 
        }

        //
        // Handle Application definition xaml file and Application Class name. 
        // recompile parameter indicates whether or not to recompile the appdef file.
        // If the appdef file is not recompiled, a specially handling is required to 
        // take application class name from previous build. 
        //
        private void ProcessApplicationFile(bool recompile) 
        {
            if (!_mcPass1.IsApplicationTarget)
            {
                return; 
            }
 
            if (recompile) 
            {
                // 
                // Take whatever setting in _mcPass1 task.
                //
                _recompileApplicationFile = _mcPass1.ApplicationFile;
 
            }
            else 
            { 
                _recompileApplicationFile = String.Empty;
 
            }
        }

        // 
        // Detect if at least one file in the same item list has changed since last build.
        // 
        private bool IsFileListChanged(ITaskItem[] fileList) 
        {
            bool isChanged = false; 

            if (ListIsNotEmpty(fileList))
            {
                for (int i = 0; i < fileList.Length; i++) 
                {
                    if (IsFileChanged(fileList[i].ItemSpec)) 
                    { 
                        isChanged = true;
                        break; 
                    }
                }
            }
 
            return isChanged;
 
        } 

        // 
        // Detect if the input file was changed since last build.
        //
        private bool IsFileChanged(string inputFile)
        { 
            bool isChanged = false;
 
            DateTime dtFile; 

 
            dtFile = TaskFileService.GetLastChangeTime(inputFile);

            if (dtFile > LastCompileTime)
            { 
                isChanged = true;
            } 
 
            return isChanged;
        } 

        // A helper to detect if the list is not empty.
        private bool ListIsNotEmpty(object [] list)
        { 
            bool isNotEmpty = false;
 
            if (list != null && list.Length > 0) 
            {
                isNotEmpty = true; 
            }

            return isNotEmpty;
        } 

        #endregion 
 
        #region private data
 
        private MarkupCompilePass1 _mcPass1;
        private RecompileCategory  _analyzeResult;
        private DateTime           _lastCompileTime = new DateTime(0);
 
        private string[]           _recompileMarkupPages;
        private string             _recompileApplicationFile = null; 
        private string[]           _contentFiles = null; 

        #endregion 

    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
 
//----------------------------------------------------------------------------------------
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved. 
// 
// 
// Description: 
//       Analyze the current project inputs, the compiler state file and local reference
//       cache, determine which xaml files require to recompile. 
//
//  History:
//
//  11/21/05: weibz   Created 
//
//--------------------------------------------------------------------------------------- 
 
using System;
using System.IO; 
using System.Collections;
using System.Diagnostics;
using System.Reflection;
 
using Microsoft.Build.Tasks.Windows;
using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 
using MS.Utility;
 
namespace MS.Internal.Tasks
{
    //
    // Keep different categories of recompilation. 
    //
    [Flags] 
    internal enum RecompileCategory : byte 
    {
        NoRecompile        = 0x00, 
        ApplicationFile    = 0x01,
        ModifiedPages      = 0x02,
        PagesWithLocalType = 0x04,
        ContentFiles       = 0x08, 
        All                = 0x0F
    } 
 
    // 
    // IncrementalCompileAnalyzer 
    // 
    internal class IncrementalCompileAnalyzer
    {
        //  
        // ctor of IncrementalCompileAnalyzer
        //  
        internal IncrementalCompileAnalyzer(MarkupCompilePass1 mcPass1) 
        {
            _mcPass1 = mcPass1; 
            _analyzeResult = RecompileCategory.NoRecompile;
        }

        #region internal methods 

 
        // 
        // Analyze the input files based on the compiler cache files.
        // 
        // Put the analyze result in _analyzeResult and other related data fields,
        // such as RecompileMarkupPages, RecompileApplicationFile, etc.
        //
        // If analyze is failed somehow, throw exception. 
        //
        internal void AnalyzeInputFiles() 
        { 

            // 
            // First: Detect if the entire project requires re-compile.
            //

            // 
            // If the compiler state file doesn't exist, recompile all the xaml files.
            // 
            if (!CompilerState.StateFileExists()) 
            {
                _analyzeResult = RecompileCategory.All; 
            }
            else
            {
                // Load the compiler state file. 
                CompilerState.LoadStateInformation();
 
                // if PresenationBuildTasks.dll is changed last build, rebuild the entire project for sure. 

                if (IsFileChanged(Assembly.GetExecutingAssembly().Location) || 
                    IsFileListChanged(_mcPass1.ExtraBuildControlFiles))
                {
                    _analyzeResult = RecompileCategory.All;
                } 
                else
                { 
                    // 
                    // Any one single change in below list would request completely re-compile.
                    // 
                    if (IsSettingModified(CompilerState.References, _mcPass1.ReferencesCache) ||
                        IsSettingModified(CompilerState.ApplicationFile, _mcPass1.ApplicationFile) ||
                        IsSettingModified(CompilerState.RootNamespace, _mcPass1.RootNamespace) ||
                        IsSettingModified(CompilerState.AssemblyName, _mcPass1.AssemblyName) || 
                        IsSettingModified(CompilerState.AssemblyVersion, _mcPass1.AssemblyVersion) ||
                        IsSettingModified(CompilerState.AssemblyPublicKeyToken, _mcPass1.AssemblyPublicKeyToken) || 
                        IsSettingModified(CompilerState.OutputType, _mcPass1.OutputType) || 
                        IsSettingModified(CompilerState.Language, _mcPass1.Language) ||
                        IsSettingModified(CompilerState.LanguageSourceExtension, _mcPass1.LanguageSourceExtension) || 
                        IsSettingModified(CompilerState.OutputPath, _mcPass1.OutputPath) ||
                        IsSettingModified(CompilerState.LocalizationDirectivesToLocFile, _mcPass1.LocalizationDirectivesToLocFile))
                    {
                        _analyzeResult = RecompileCategory.All; 
                    }
                    else 
                    { 
                        if (_mcPass1.IsApplicationTarget)
                        { 
                            //
                            // When application definition file is modified, it could potentially change the application
                            // class name, it then has impact on all other xaml file compilation, so recompile the entire
                            // project for this case. 
                            //
                            if (TaskFileService.Exists(_mcPass1.ApplicationFile) && IsFileChanged(_mcPass1.ApplicationFile)) 
                            { 
                                _analyzeResult = RecompileCategory.All;
                            } 
                        }

                        //
                        // If any one referenced assembly is updated since last build, the entire project needs to recompile. 
                        //
 
                        if (IsFileListChanged(_mcPass1.References)) 
                        {
                            _analyzeResult = RecompileCategory.All; 
                        }
                    }
                }
            } 

            if (_analyzeResult == RecompileCategory.All) 
            { 
                UpdateFileListForCleanbuild();
                return; 
            }

            //
            // The entire project recompilation should have already been handled when code goes here. 
            // Now, Detect the individual xaml files which require to recompile.
            // 
 
            if (_mcPass1.IsApplicationTarget)
            { 
                if (IsSettingModified(CompilerState.ContentFiles, _mcPass1.ContentFilesCache))
                {
                    _analyzeResult |= RecompileCategory.ContentFiles;
                } 

                // if HostInBrowser setting is changed, it would affect the application file compilation only. 
                if (IsSettingModified(CompilerState.HostInBrowser, _mcPass1.HostInBrowser)) 
                {
                    _analyzeResult |= RecompileCategory.ApplicationFile; 
                }

                if (IsSettingModified(CompilerState.SplashImage, _mcPass1.SplashImageName))
                { 
                    _analyzeResult |= RecompileCategory.ApplicationFile;
                } 
            } 

            // 
            // If code files are changed, or Define flags are changed, it would affect the xaml file with local types.
            //
            // If previous build didn't have such local-ref-xaml files, don't bother to do further check for this.
            // 

            if (CompilerLocalReference.CacheFileExists()) 
            { 
                if (IsSettingModified(CompilerState.DefineConstants, _mcPass1.DefineConstants) ||
                    IsSettingModified(CompilerState.SourceCodeFiles, _mcPass1.SourceCodeFilesCache) || 
                    IsFileListChanged(_mcPass1.SourceCodeFiles) )
                {
                    _analyzeResult |= RecompileCategory.PagesWithLocalType;
                } 
            }
 
            ArrayList modifiedXamlFiles = new ArrayList(); 

            // 
            // Detect if any .xaml page is updated since last build
            //
            if (ListIsNotEmpty(_mcPass1.PageMarkup))
            { 

                // 
                // If the PageMarkup file number or hashcode is changed, it would affect 
                // the xaml files with local types.
                // 
                // This check is necessary for the senario that a xaml file is removed and the
                // removed xaml file could be referenced by other xaml files with local types.
                //
                if (IsSettingModified(CompilerState.PageMarkup, _mcPass1.PageMarkupCache)) 
                {
                    if (CompilerLocalReference.CacheFileExists()) 
                    { 
                        _analyzeResult |= RecompileCategory.PagesWithLocalType;
                    } 
                }

                // Below code detects which invidual xaml files are modified since last build.
                for (int i = 0; i < _mcPass1.PageMarkup.Length; i++) 
                {
                    string fileName = _mcPass1.PageMarkup[i].ItemSpec; 
                    string filepath = Path.GetFullPath(fileName); 

                    if (IsFileChanged(filepath)) 
                    {
                        // add this file to the modified file list.
                        modifiedXamlFiles.Add(filepath);
                    } 
                    else
                    { 
                        // A previously generated xaml file (with timestamp earlier than of the cache file) 
                        // could be added to the project.  This means that the above check for time stamp
                        // will skip compiling the newly added xaml file.  We save the name all the xaml 
                        // files we previously built to the cache file.  Retrieve that list and see if
                        // this xaml file is already in it.  If so, we'll skip compiling this xaml file,
                        // else, this xaml file was just added to the project and thus compile it.
 
                        if (!CompilerState.PageMarkupFileNames.Contains(fileName))
                        { 
                            modifiedXamlFiles.Add(filepath); 
                        }
                    } 
                }

                if (modifiedXamlFiles.Count > 0)
                { 
                    _analyzeResult |= RecompileCategory.ModifiedPages;
 
                    if (CompilerLocalReference.CacheFileExists()) 
                    {
                        _analyzeResult |= RecompileCategory.PagesWithLocalType; 
                    }
                }
            }
 
            UpdateFileListForIncrementalBuild(modifiedXamlFiles);
 
        } 

        #endregion 

        #region internal properties

        // 
        // Keep the AnlyzeResult.
        // 
        internal RecompileCategory AnalyzeResult 
        {
            get { return _analyzeResult; } 
        }

        //
        // Keep a list of markup pages which require to recompile 
        //
        internal string[] RecompileMarkupPages 
        { 
            get { return _recompileMarkupPages; }
        } 

        //
        // Application file which requires re-compile.
        // If the value is String.Empty, the appdef file is not required 
        // to recompile.
        // 
        internal string RecompileApplicationFile 
        {
            get { return _recompileApplicationFile; } 
        }


        internal string[] ContentFiles 
        {
            get { return _contentFiles; } 
        } 

        #endregion 

        #region private properties and methods

        private CompilerState CompilerState 
        {
            get { return _mcPass1.CompilerState; } 
        } 

        private CompilerLocalReference CompilerLocalReference 
        {
            get { return _mcPass1.CompilerLocalReference; }
        }
 
        private ITaskFileService TaskFileService
        { 
            get { return _mcPass1.TaskFileService; } 
        }
 
        private DateTime LastCompileTime
        {
            get
            { 
                DateTime nonSet = new DateTime(0);
                if (_lastCompileTime == nonSet) 
                { 
                    _lastCompileTime = TaskFileService.GetLastChangeTime(CompilerState.CacheFilePath);
 
                }

                return _lastCompileTime;
            } 
        }
 
        // 
        // Compare two strings.
        // 
        private bool IsSettingModified(string textSource, string textTarget)
        {
            bool IsSettingModified;
 
            bool isSrcEmpty = String.IsNullOrEmpty(textSource);
            bool istgtEmpty = String.IsNullOrEmpty(textTarget); 
 
            if (isSrcEmpty != istgtEmpty)
            { 
                IsSettingModified = true;
            }
            else
            { 
                if (isSrcEmpty)  // Both source and target strings are empty.
                { 
                    IsSettingModified = false; 
                }
                else  // Both source and target strings are not empty. 
                {
                    IsSettingModified = String.Compare(textSource, textTarget, StringComparison.OrdinalIgnoreCase) == 0 ? false : true;
                }
            } 

            return IsSettingModified; 
        } 

        // 
        // Generate new list of files that require to recompile for incremental build based on _analyzeResult
        //
        private void UpdateFileListForIncrementalBuild(ArrayList modifiedXamlFiles)
        { 
            ArrayList recompiledXaml = new ArrayList();
            bool recompileApp = false; 
            int numLocalTypeXamls = 0; 

            if ((_analyzeResult & RecompileCategory.ContentFiles) == RecompileCategory.ContentFiles) 
            {
                RecompileContentFiles();
            }
 
            if ((_analyzeResult & RecompileCategory.ApplicationFile) == RecompileCategory.ApplicationFile)
            { 
                recompileApp = true; 
            }
 
            if ((_analyzeResult & RecompileCategory.PagesWithLocalType) == RecompileCategory.PagesWithLocalType)
            {
                CompilerLocalReference.LoadCacheFile();
 
                if (CompilerLocalReference.LocalApplicationFile != null)
                { 
                    // Application file contains local types, it will be recompiled. 
                    recompileApp = true;
                } 

                if (ListIsNotEmpty(CompilerLocalReference.LocalMarkupPages))
                {
                    numLocalTypeXamls = CompilerLocalReference.LocalMarkupPages.Length; 

                    for (int i = 0; i < CompilerLocalReference.LocalMarkupPages.Length; i++) 
                    { 
                        recompiledXaml.Add(CompilerLocalReference.LocalMarkupPages[i].FilePath);
                    } 
                }

            }
 
            if ((_analyzeResult & RecompileCategory.ModifiedPages) == RecompileCategory.ModifiedPages)
            { 
                // If the xaml is already in the local-type-ref xaml file list, don't add a duplicate file path to recompiledXaml list. 

                for (int i = 0; i < modifiedXamlFiles.Count; i++) 
                {
                    string xamlfile = modifiedXamlFiles[i] as string;
                    bool addToList;
 
                    addToList = true;
 
                    if (numLocalTypeXamls > 0) 
                    {
                        for (int j = 0; j < numLocalTypeXamls; j++) 
                        {
                            if (String.Compare(xamlfile, CompilerLocalReference.LocalMarkupPages[j].FilePath, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                addToList = false; 
                                break;
                            } 
                        } 
                    }
 
                    if (addToList)
                    {
                        recompiledXaml.Add(xamlfile);
                    } 
                }
            } 
 
            if (recompiledXaml.Count > 0)
            { 
                _recompileMarkupPages = (string[])recompiledXaml.ToArray(typeof(string));
            }

            // Set ApplicationFile appropriatelly for this incremental build. 
            ProcessApplicationFile(recompileApp);
        } 
 
        //
        // To recompile all the xaml files ( including page and application file). 
        // Transfer all the xaml files to the recompileMarkupPages.
        //
        private void UpdateFileListForCleanbuild()
        { 
            if (ListIsNotEmpty(_mcPass1.PageMarkup))
            { 
                int count = _mcPass1.PageMarkup.Length; 
                _recompileMarkupPages = new string[count];
 
                for (int i = 0; i < count; i++)
                {
                    _recompileMarkupPages[i] = Path.GetFullPath(_mcPass1.PageMarkup[i].ItemSpec);
                } 
            }
 
            RecompileContentFiles(); 

            ProcessApplicationFile(true); 
        }

        //
        // Content files are only for Application target type. 
        //
        private void RecompileContentFiles() 
        { 
            if (!_mcPass1.IsApplicationTarget)
                return; 

            if (_contentFiles == null)
            {
                if (ListIsNotEmpty(_mcPass1.ContentFiles)) 
                {
                    string curDir = Directory.GetCurrentDirectory() + "\\"; 
 
                    int count = _mcPass1.ContentFiles.Length;
 
                    _contentFiles = new string[count];

                    for (int i = 0; i < count; i++)
                    { 
                        string fullPath = Path.GetFullPath(_mcPass1.ContentFiles[i].ItemSpec);
 
                        string relContentFilePath = TaskHelper.GetRootRelativePath(curDir, fullPath); 

                        if (String.IsNullOrEmpty(relContentFilePath)) 
                        {
                           relContentFilePath = Path.GetFileName(fullPath);
                        }
 
                        _contentFiles[i] = relContentFilePath;
                    } 
 
                }
            } 
        }

        //
        // Handle Application definition xaml file and Application Class name. 
        // recompile parameter indicates whether or not to recompile the appdef file.
        // If the appdef file is not recompiled, a specially handling is required to 
        // take application class name from previous build. 
        //
        private void ProcessApplicationFile(bool recompile) 
        {
            if (!_mcPass1.IsApplicationTarget)
            {
                return; 
            }
 
            if (recompile) 
            {
                // 
                // Take whatever setting in _mcPass1 task.
                //
                _recompileApplicationFile = _mcPass1.ApplicationFile;
 
            }
            else 
            { 
                _recompileApplicationFile = String.Empty;
 
            }
        }

        // 
        // Detect if at least one file in the same item list has changed since last build.
        // 
        private bool IsFileListChanged(ITaskItem[] fileList) 
        {
            bool isChanged = false; 

            if (ListIsNotEmpty(fileList))
            {
                for (int i = 0; i < fileList.Length; i++) 
                {
                    if (IsFileChanged(fileList[i].ItemSpec)) 
                    { 
                        isChanged = true;
                        break; 
                    }
                }
            }
 
            return isChanged;
 
        } 

        // 
        // Detect if the input file was changed since last build.
        //
        private bool IsFileChanged(string inputFile)
        { 
            bool isChanged = false;
 
            DateTime dtFile; 

 
            dtFile = TaskFileService.GetLastChangeTime(inputFile);

            if (dtFile > LastCompileTime)
            { 
                isChanged = true;
            } 
 
            return isChanged;
        } 

        // A helper to detect if the list is not empty.
        private bool ListIsNotEmpty(object [] list)
        { 
            bool isNotEmpty = false;
 
            if (list != null && list.Length > 0) 
            {
                isNotEmpty = true; 
            }

            return isNotEmpty;
        } 

        #endregion 
 
        #region private data
 
        private MarkupCompilePass1 _mcPass1;
        private RecompileCategory  _analyzeResult;
        private DateTime           _lastCompileTime = new DateTime(0);
 
        private string[]           _recompileMarkupPages;
        private string             _recompileApplicationFile = null; 
        private string[]           _contentFiles = null; 

        #endregion 

    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK