Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Build / 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: [....] 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 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- IPHostEntry.cs
- RegionData.cs
- HttpModuleCollection.cs
- XmlRawWriterWrapper.cs
- HttpCachePolicy.cs
- ReliableReplySessionChannel.cs
- WinEventHandler.cs
- DbDeleteCommandTree.cs
- MouseGestureValueSerializer.cs
- ConfigPathUtility.cs
- VisualBrush.cs
- OracleConnectionFactory.cs
- WindowsRegion.cs
- Timeline.cs
- DataViewListener.cs
- StorageTypeMapping.cs
- StylusDevice.cs
- Policy.cs
- URI.cs
- ColorComboBox.cs
- ConvertersCollection.cs
- Buffer.cs
- ClientScriptManagerWrapper.cs
- TextTreeObjectNode.cs
- MetadataUtilsSmi.cs
- DataGridViewComboBoxCell.cs
- BindingRestrictions.cs
- TextFindEngine.cs
- InheritedPropertyChangedEventArgs.cs
- ChannelOptions.cs
- DefaultHttpHandler.cs
- ListControl.cs
- Rotation3DAnimation.cs
- CqlBlock.cs
- DataControlLinkButton.cs
- ParserExtension.cs
- Console.cs
- ConfigurationPermission.cs
- PointValueSerializer.cs
- MethodResolver.cs
- ByteAnimationBase.cs
- initElementDictionary.cs
- DateTimeOffset.cs
- StateChangeEvent.cs
- MobileUITypeEditor.cs
- SafeArrayTypeMismatchException.cs
- hresults.cs
- Visual.cs
- RegisteredExpandoAttribute.cs
- ColorAnimationBase.cs
- CodeValidator.cs
- InkCanvasSelectionAdorner.cs
- HandlerFactoryWrapper.cs
- PolyLineSegment.cs
- LinqDataView.cs
- SmiEventSink.cs
- ToolStripGrip.cs
- DataTableMappingCollection.cs
- ResourceContainer.cs
- DeploymentSectionCache.cs
- CurrentTimeZone.cs
- PropertyGeneratedEventArgs.cs
- oledbconnectionstring.cs
- OutputCacheSettings.cs
- OleDbFactory.cs
- WorkflowEnvironment.cs
- CheckableControlBaseAdapter.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- EventLogEntry.cs
- AppSecurityManager.cs
- EncodingInfo.cs
- MaskedTextProvider.cs
- SmtpNtlmAuthenticationModule.cs
- DrawingImage.cs
- COAUTHINFO.cs
- OdbcEnvironmentHandle.cs
- LoginUtil.cs
- ShellProvider.cs
- JsonQueryStringConverter.cs
- Context.cs
- DataGridViewRowPostPaintEventArgs.cs
- ColumnReorderedEventArgs.cs
- InertiaRotationBehavior.cs
- IItemContainerGenerator.cs
- GroupQuery.cs
- ECDiffieHellmanPublicKey.cs
- CompressEmulationStream.cs
- WsdlHelpGeneratorElement.cs
- SQLByte.cs
- FontFamilyIdentifier.cs
- RowCache.cs
- MaskedTextBox.cs
- InstanceValue.cs
- CfgRule.cs
- GridViewRowEventArgs.cs
- MobileTextWriter.cs
- SubqueryTrackingVisitor.cs
- Int32AnimationBase.cs
- BinaryFormatter.cs
- FieldAccessException.cs