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
- CmsUtils.cs
- StatusBarDrawItemEvent.cs
- SchemaEntity.cs
- LocationFactory.cs
- ConnectionInterfaceCollection.cs
- ClockGroup.cs
- MessageQueuePermission.cs
- NativeConfigurationLoader.cs
- Utils.cs
- DispatchWrapper.cs
- WmlSelectionListAdapter.cs
- ConnectorSelectionGlyph.cs
- ManipulationStartedEventArgs.cs
- AlignmentYValidation.cs
- StandardBindingCollectionElement.cs
- SqlRowUpdatingEvent.cs
- FrameworkElementAutomationPeer.cs
- Completion.cs
- ProviderConnectionPoint.cs
- MouseGesture.cs
- Exceptions.cs
- Compiler.cs
- ReferenceConverter.cs
- WebPartRestoreVerb.cs
- ActivityExecutor.cs
- TreeViewTemplateSelector.cs
- ProtocolsConfigurationEntry.cs
- DataObjectAttribute.cs
- WpfKnownMemberInvoker.cs
- SchemaLookupTable.cs
- FileDialog_Vista_Interop.cs
- FormsAuthenticationConfiguration.cs
- XmlILModule.cs
- StringFunctions.cs
- ExpressionNormalizer.cs
- Context.cs
- Ref.cs
- ValidationHelper.cs
- UnmanagedMemoryStream.cs
- ListBindingHelper.cs
- AutomationPatternInfo.cs
- DataSourceBooleanViewSchemaConverter.cs
- Simplifier.cs
- StreamMarshaler.cs
- NavigationWindow.cs
- Accessors.cs
- XmlSchemaChoice.cs
- TransformGroup.cs
- Helpers.cs
- Cursor.cs
- RegistryKey.cs
- SlipBehavior.cs
- Paragraph.cs
- StyleModeStack.cs
- BooleanAnimationBase.cs
- HtmlProps.cs
- ParameterRetriever.cs
- SignatureDescription.cs
- SchemaElementDecl.cs
- BezierSegment.cs
- InvalidEnumArgumentException.cs
- RoutedEvent.cs
- GridViewUpdateEventArgs.cs
- BulletDecorator.cs
- BinaryExpression.cs
- ScriptControlManager.cs
- safelinkcollection.cs
- CultureSpecificCharacterBufferRange.cs
- DocumentAutomationPeer.cs
- ListViewAutomationPeer.cs
- XPathParser.cs
- Calendar.cs
- DispatcherProcessingDisabled.cs
- EndpointDispatcherTable.cs
- RadioButtonDesigner.cs
- DataSourceView.cs
- DesignerResources.cs
- JsonQueryStringConverter.cs
- DependencyPropertyDescriptor.cs
- KeysConverter.cs
- QuaternionAnimation.cs
- ExtendedProperty.cs
- InfiniteTimeSpanConverter.cs
- thaishape.cs
- SqlXmlStorage.cs
- TimeoutTimer.cs
- DataGridViewAccessibleObject.cs
- DefaultObjectSerializer.cs
- RadialGradientBrush.cs
- XmlQueryStaticData.cs
- ScrollChrome.cs
- BooleanToVisibilityConverter.cs
- RTLAwareMessageBox.cs
- RadioButtonList.cs
- ToolStripSplitStackLayout.cs
- MemberAccessException.cs
- Color.cs
- OleDbWrapper.cs
- MessageSmuggler.cs
- Double.cs