/// <summary>Optimizes the specified xml document.</summary>
        /// <param name="xamlDocument">The xaml document.</param>
        /// <param name="xamlFile">The file info.</param>
        /// <returns>The result of the xaml optimization.</returns>
        public OptimizationResult Optimize(XDocument xamlDocument, IFileReference xamlFile)
        {
            var containingAssemblyName = this.projectInfo.AssemblyName;
            var xamlTypeResolver       = XamlTypeResolver.FromXDocument(
                xamlDocument,
                containingAssemblyName,
                this.projectInfo.AssemblyReferences,
                this.bindingXamlPlatformInfo.XamlTypeToSourceCodeNamespaces);
            var xamlElementNameResolver = new XamlElementNameResolver(this.xamlPlatformInfo.XamlNamespace);
            var bindingTree             = this.bindingTreeParser.Parse(
                xamlDocument.Root,
                Path.Combine(containingAssemblyName, Path.GetDirectoryName(xamlFile.Id)),
                Path.GetFileNameWithoutExtension(xamlFile.Id),
                xamlTypeResolver,
                xamlElementNameResolver);

            var generatorInfo = GeneratorInfo.Get(xamlFile, containingAssemblyName, this.projectInfo.RootNamespace);
            var xamlModificationCollectionResult = this.bindingContainerXamlModificationCollector.Visit(
                bindingTree,
                new Internal.XamlModification.BindingContainer.Parameters(generatorInfo, xamlTypeResolver),
                new Internal.XamlModification.BindingContainer.Context(new XamlElementNameProvider(xamlElementNameResolver)));

            if (!xamlModificationCollectionResult)
            {
                return(OptimizationResult.Error());
            }

            if (this.useSourceGenerator)
            {
                this.bindingOptimizationWriter.ApplyOptimizations(
                    xamlModificationCollectionResult.Value.XamlModificationInfos,
                    this.bindingXamlPlatformInfo.SundewBindingsXamlNamespace);
                return(OptimizationResult.Success(xamlDocument, new[] { new AdditionalFile(FileAction.AdditionalFile, null) }));
            }

            var generatedContainers = this.bindingContainerCodeGenerator.Visit(
                bindingTree,
                new Internal.CodeGenerators.BindingContainer.Parameters(generatorInfo, xamlTypeResolver, xamlModificationCollectionResult.Value.BindingRootNodeTypes),
                new Internal.CodeGenerators.BindingContainer.Context(new XamlElementNameProvider(xamlElementNameResolver), new BindingSourceProvider(this.typeResolver)));

            if (generatedContainers)
            {
                this.bindingOptimizationWriter.ApplyOptimizations(xamlModificationCollectionResult.Value.XamlModificationInfos, this.bindingXamlPlatformInfo.SundewBindingsXamlNamespace);
                var result = this.bindingOptimizationWriter.ApplyOptimizations(generatedContainers.Value);
                return(OptimizationResult.Success(xamlDocument, result));
            }

            return(OptimizationResult.Error());
        }
Beispiel #2
0
        public async Task Visit_Then_BindingTreeToStringVisitorShouldOutputExpectedResult(string inputFilePath, string[] compiles, string expectedXamlDocumentPath, string[] expectedSourceCodePaths)
        {
            var xamlDocument = await LoadXDocument(inputFilePath).ConfigureAwait(false);

            var assemblyReferences = GetAssemblyReferences(xamlPlatformInfo.XamlPlatform);
            var codeAnalyzer       = new CodeAnalyzer(ContainingAssemblyName, compiles.Select(x =>
            {
                var compile = Substitute.For <IFileReference>();
                compile.Path.Returns(x);
                return(compile);
            }).ToList(),
                                                      assemblyReferences,
                                                      this.fileSystem.File,
                                                      null,
                                                      false);
            var typeResolver            = new TypeResolver(codeAnalyzer);
            var xamlTypeResolver        = XamlTypeResolver.FromXDocument(xamlDocument, ContainingAssemblyName, assemblyReferences, bindingXamlPlatformInfo.XamlTypeToSourceCodeNamespaces);
            var xamlElementNameResolver = new XamlElementNameResolver(xamlPlatformInfo.XamlNamespace);
            var bindingTreeParser       = new BindingTreeParser(
                bindingXamlPlatformInfo,
                new BindingMarkupExtensionParser(new BindingPathParser(new BindingPathLexicalAnalyzer())),
                false);
            var bindingTree = bindingTreeParser.Parse(xamlDocument.Root, Path.GetDirectoryName(inputFilePath), Path.GetFileNameWithoutExtension(inputFilePath), xamlTypeResolver, xamlElementNameResolver);

            var fileReference = Substitute.For <IFileReference>();

            fileReference.Id.Returns(inputFilePath);
            var generatorInfo = GeneratorInfo.Get(fileReference, ContainingAssemblyName, RootNamespace);
            var xamlModificationCollectionResult = this.bindingContainerXamlModificationCollector.Visit(
                bindingTree,
                new Xaml.Optimizations.Bindings.Internal.XamlModification.BindingContainer.Parameters(generatorInfo, xamlTypeResolver),
                new Xaml.Optimizations.Bindings.Internal.XamlModification.BindingContainer.Context(new XamlElementNameProvider(xamlElementNameResolver)));

            var testee = new BindingContainerCodeGenerator(
                new BindingPathCodeGenerator(
                    typeResolver,
                    this.bindingXamlPlatformInfo,
                    new ReadOnlyDependencyPropertyToNotificationEventResolver(
                        codeAnalyzer,
                        bindingXamlPlatformInfo.ReadOnlyDependencyPropertyNotificationEvents),
                    new BindingModeResolver(bindingXamlPlatformInfo.OneWayBindingProperties, codeAnalyzer, xamlPlatformInfo.XamlPlatform),
                    new TypeAssignmentCompatibilityAssessor(codeAnalyzer)),
                this.bindingXamlPlatformInfo, typeResolver);

            var result = testee.Visit(
                bindingTree,
                new Xaml.Optimizations.Bindings.Internal.CodeGenerators.BindingContainer.Parameters(in generatorInfo, xamlTypeResolver, xamlModificationCollectionResult.Value.BindingRootNodeTypes),
                new Context(new XamlElementNameProvider(xamlElementNameResolver), new BindingSourceProvider(typeResolver)));

            this.bindingOptimizationWriter.ApplyOptimizations(result.Value);
            this.bindingOptimizationWriter.ApplyOptimizations(xamlModificationCollectionResult.Value.XamlModificationInfos, this.bindingXamlPlatformInfo.SundewBindingsXamlNamespace);

            var sourceCodePairs = expectedSourceCodePaths.Zip(result.Value, (path, container) => new { FileName = Path.GetFileNameWithoutExtension(path), ExpectedContent = ReadResourceStreamToEnd(path), container.SourceCode });

            foreach (var sourceCodePair in sourceCodePairs)
            {
                sourceCodePair.SourceCode.Should().Be(sourceCodePair.ExpectedContent);
                this.fileSystem.File.Received(1).WriteAllText(Arg.Any <string>(), sourceCodePair.ExpectedContent);
            }

            xamlDocument.ToString().Trim().Should().Be((await LoadXDocument(expectedXamlDocumentPath).ConfigureAwait(false)).ToString().Trim());
        }