/// <summary> /// Gets a value indicating whether anything is different between this cache and the specified cache. /// </summary> /// <param name="other">The cache to compare against this cache.</param> /// <returns><see langword="true"/> if this cache is different from the specified cache; otherwise, <see langword="false"/>.</returns> public Boolean IsDifferentFrom(CompilerCache other) { Contract.Require(other, nameof(other)); if (!String.Equals(versionUltraviolet, other.versionUltraviolet, StringComparison.Ordinal) || !String.Equals(versionMscorlib, other.versionMscorlib, StringComparison.Ordinal)) { return(true); } var keys = Enumerable.Union(this.hashes.Keys, other.hashes.Keys).ToList(); foreach (var key in keys) { if (!this.hashes.TryGetValue(key, out var hash1)) { return(true); } if (!other.hashes.TryGetValue(key, out var hash2)) { return(true); } if (!String.Equals(hash1, hash2, StringComparison.Ordinal)) { return(true); } } return(false); }
/// <summary> /// Creates a new instance of <see cref="CompilerCache"/> by loading the contents of the specified file. /// </summary> /// <param name="path">The path to the file to load.</param> /// <returns>The <see cref="CompilerCache"/> instance that was created.</returns> public static CompilerCache FromFile(String path) { Contract.RequireNotEmpty(path, nameof(path)); var cache = new CompilerCache(); var lines = File.ReadAllLines(path); var compilerType = default(String); var versionUltraviolet = default(String); var versionMscorlib = default(String); for (int i = 0; i < lines.Length; i++) { var line = lines[i]; if (String.IsNullOrEmpty(line)) { continue; } if (i == 0 && line.StartsWith("#compiler ")) { compilerType = line.Substring("#compiler ".Length).Trim(); continue; } if (versionUltraviolet == default(String)) { versionUltraviolet = line; continue; } if (versionMscorlib == default(String)) { versionMscorlib = line; continue; } var components = line.Split((Char[])null, StringSplitOptions.RemoveEmptyEntries); if (components.Length != 2) { throw new InvalidDataException(); } var name = components[0]; var hash = components[1]; cache.hashes[name] = hash; } cache.compilerType = compilerType; cache.versionUltraviolet = versionUltraviolet; cache.versionMscorlib = versionMscorlib; return(cache); }
/// <inheritdoc/> public BindingExpressionCompilationResult Compile(UltravioletContext uv, BindingExpressionCompilerOptions options) { Contract.Require(uv, nameof(uv)); Contract.Require(options, nameof(options)); if (String.IsNullOrEmpty(options.Input) || String.IsNullOrEmpty(options.Output)) { throw new ArgumentException(PresentationStrings.InvalidCompilerOptions); } var compiler = CreateCodeProvider(); var state = new LegacyExpressionCompilerState(uv, compiler) { GenerateInMemory = options.GenerateInMemory, WorkInTemporaryDirectory = options.WorkInTemporaryDirectory, WriteErrorsToFile = options.WriteErrorsToFile }; var dataSourceWrapperInfos = DataSourceLoader.GetDataSourceWrapperInfos(state, options.Input); var cacheFile = Path.ChangeExtension(options.Output, "cache"); var cacheNew = CompilerCache.FromDataSourceWrappers(this, dataSourceWrapperInfos); if (File.Exists(options.Output)) { var cacheOld = CompilerCache.TryFromFile(cacheFile); if (cacheOld != null && !options.IgnoreCache && !cacheOld.IsDifferentFrom(cacheNew)) { return(BindingExpressionCompilationResult.CreateSucceeded()); } } var result = CompileViewModels(state, dataSourceWrapperInfos, options.Output, options.GenerateDebugAssembly); if (result.Succeeded) { if (!options.GenerateInMemory) { cacheNew.Save(cacheFile); } if (!options.WriteCompiledFilesToWorkingDirectory && !options.WorkInTemporaryDirectory) { state.DeleteWorkingDirectory(); } } if (options.WriteCompiledFilesToWorkingDirectory && !options.WorkInTemporaryDirectory) { WriteCompiledFilesToWorkingDirectory(state, dataSourceWrapperInfos); } return(result); }
/// <summary> /// Creates a new instance of <see cref="CompilerCache"/> from the specified collection of data source wrappers. /// </summary> /// <param name="compiler">The compiler which is creating this cache.</param> /// <param name="dataSourceWrappers">A collection of data source wrappers from which to create a cache object.</param> /// <returns>The <see cref="CompilerCache"/> instance that was created.</returns> public static CompilerCache FromDataSourceWrappers(IBindingExpressionCompiler compiler, IEnumerable <DataSourceWrapperInfo> dataSourceWrappers) { Contract.Require(compiler, nameof(compiler)); Contract.Require(dataSourceWrappers, nameof(dataSourceWrappers)); var types = new HashSet <Type>(); var cache = new CompilerCache(); cache.compilerType = compiler.GetType().FullName; foreach (var dataSourceWrapper in dataSourceWrappers) { if (!cache.hashes.ContainsKey(dataSourceWrapper.DataSourcePath)) { var dataSourceWrapperHash = GenerateHashForXElement(dataSourceWrapper.DataSourceDefinition.Definition); cache.hashes[dataSourceWrapper.DataSourcePath] = dataSourceWrapperHash; } AddTypeReferences(dataSourceWrapper.DataSourceType, types); if (dataSourceWrapper.DependentWrapperInfos != null) { foreach (var dependentWrapper in dataSourceWrapper.DependentWrapperInfos) { AddTypeReferences(dependentWrapper.DataSourceType, types); } } } foreach (var type in types) { var typeHash = GenerateHashForType(type); cache.hashes[type.FullName] = typeHash; } return(cache); }