예제 #1
0
        public async Task Parse_Then_BindingTreeToStringVisitorShouldOutputExpectedResult(string inputFile, string expectedResultFile)
        {
            var xDocument = await LoadXDocument(inputFile).ConfigureAwait(false);

            var xamlPlatformInfo        = XamlPlatformInfoProvider.GetXamlPlatformInfo(XamlPlatform.WPF);
            var bindingXamlPlatformInfo = new BindingXamlPlatformInfo(xamlPlatformInfo,
                                                                      new BindingCompilerSettings(
                                                                          new Dictionary <string, IReadOnlyDictionary <string, ReadOnlyDependencyPropertyToNotificationEvent> >(),
                                                                          new Dictionary <string, IReadOnlyDictionary <string, Namespace> >(),
                                                                          new Dictionary <string, IReadOnlyCollection <string> >()));
            var testee = new BindingTreeParser(
                bindingXamlPlatformInfo,
                new BindingMarkupExtensionParser(new BindingPathParser(new BindingPathLexicalAnalyzer())),
                false);

            var bindingTree = testee.Parse(
                xDocument.Root,
                Path.GetDirectoryName(inputFile),
                Path.GetFileNameWithoutExtension(inputFile),
                XamlTypeResolver.FromXDocument(xDocument, "Sundew.Xaml.Optimizations.TestData.ApiDesigner.Wpf", new IAssemblyReference[0], bindingXamlPlatformInfo.XamlTypeToSourceCodeNamespaces),
                new XamlElementNameResolver(xamlPlatformInfo.XamlNamespace));

            var visitor        = new BindingTreeToStringVisitor();
            var result         = visitor.Visit(bindingTree, null, 0);
            var expectedResult = GetExpectedResult(expectedResultFile);

            result.Should().Be(expectedResult);
        }
예제 #2
0
        public IEnumerable <string> GenerateXamlTypes()
        {
            var concurrentBag = new ConcurrentBag <string>();

            Parallel.ForEach(this.xDocumentProvider.FileReferences, (fileReference, state) =>
            {
                var xDocument = this.xDocumentProvider.Get(fileReference);
                if (xDocument.Root == null)
                {
                    return;
                }

                var classNameAttribute = xDocument.Root.Attribute(this.xClassName);
                var xamlTypeResolver   = XamlTypeResolver.FromXDocument(
                    xDocument,
                    this.assemblyName,
                    this.assemblyReferences,
                    this.xamlTypeToSourceCodeTypes);
                if (classNameAttribute != null)
                {
                    GetNamespaceAndTypeName(classNameAttribute.Value, out var namespaceName, out var typeName);
                    var baseType = xamlTypeResolver.Parse(xDocument.Root.Name);

                    var sourceCode = @$ "namespace {namespaceName}
{{
        /// <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());
        }
예제 #4
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());
        }