Exemplo n.º 1
0
        // Internal for testing
        internal TagHelperResolutionResult GetTagHelpers(Compilation compilation)
        {
            var descriptors = new List <TagHelperDescriptor>();

            var providers = new ITagHelperDescriptorProvider[]
            {
                new DefaultTagHelperDescriptorProvider()
                {
                    DesignTime = true,
                },
                new ViewComponentTagHelperDescriptorProvider()
                {
                    ForceEnabled = ForceEnableViewComponentDiscovery
                },
            };

            var results = new List <TagHelperDescriptor>();
            var context = TagHelperDescriptorProviderContext.Create(results);

            context.SetCompilation(compilation);

            for (var i = 0; i < providers.Length; i++)
            {
                var provider = providers[i];
                provider.Execute(context);
            }

            var diagnostics      = new List <RazorDiagnostic>();
            var resolutionResult = new TagHelperResolutionResult(results, diagnostics);

            return(resolutionResult);
        }
Exemplo n.º 2
0
        public void TagHelperDescriptor_CanReadCamelCasedData()
        {
            // Arrange
            var descriptor = CreateTagHelperDescriptor(
                kind: TagHelperConventions.DefaultKind,
                tagName: "tag-name",
                typeName: "type name",
                assemblyName: "assembly name",
                attributes: new Action <BoundAttributeDescriptorBuilder>[]
            {
                builder => builder
                .Name("test-attribute")
                .PropertyName("TestAttribute")
                .TypeName("string"),
            },
                ruleBuilders: new Action <TagMatchingRuleDescriptorBuilder>[]
            {
                builder => builder
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-one")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.PrefixMatch))
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-two")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)
                                            .Value("something")
                                            .ValueComparisonMode(RequiredAttributeDescriptor.ValueComparisonMode.PrefixMatch))
                .RequireParentTag("parent-name")
                .RequireTagStructure(TagStructure.WithoutEndTag),
            },
                configureAction: builder =>
            {
                builder.AllowChildTag("allowed-child-one");
                builder.AddMetadata("foo", "bar");
                builder.AddDiagnostic(RazorDiagnostic.Create(
                                          RazorDiagnosticFactory.TagHelper_InvalidTargetedTagNameNullOrWhitespace,
                                          new SourceSpan("Test.razor", 5, 17, 18, 22)));
            });
            var serializerSettings = new JsonSerializerSettings()
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                Converters       = Converters,
            };
            var expectedResult = new TagHelperResolutionResult(new[] { descriptor }, Array.Empty <RazorDiagnostic>());

            // Act
            var serialized = JsonConvert.SerializeObject(expectedResult, serializerSettings);
            var result     = JsonConvert.DeserializeObject <TagHelperResolutionResult>(serialized, Converters);

            // Assert
            Assert.Equal(expectedResult, result, TagHelperResolutionResultComparer.Default);
        }
Exemplo n.º 3
0
        public override async Task <TagHelperResolutionResult> GetTagHelpersAsync(Project workspaceProject, ProjectSnapshot projectSnapshot, CancellationToken cancellationToken = default)
        {
            if (workspaceProject == null)
            {
                throw new ArgumentNullException(nameof(workspaceProject));
            }

            if (projectSnapshot == null)
            {
                throw new ArgumentNullException(nameof(projectSnapshot));
            }

            if (projectSnapshot.Configuration == null)
            {
                return(TagHelperResolutionResult.Empty);
            }

            // Not every custom factory supports the OOP host. Our priority system should work like this:
            //
            // 1. Use custom factory out of process
            // 2. Use custom factory in process
            // 3. Use fallback factory in process
            //
            // Calling into RazorTemplateEngineFactoryService.Create will accomplish #2 and #3 in one step.
            var factory = _factory.FindSerializableFactory(projectSnapshot);

            try
            {
                TagHelperResolutionResult result = null;
                if (factory != null)
                {
                    result = await ResolveTagHelpersOutOfProcessAsync(factory, workspaceProject, projectSnapshot).ConfigureAwait(false);
                }

                if (result == null)
                {
                    // Was unable to get tag helpers OOP, fallback to default behavior.
                    result = await ResolveTagHelpersInProcessAsync(workspaceProject, projectSnapshot).ConfigureAwait(false);
                }

                return(result);
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException(
                          Resources.FormatUnexpectedException(
                              typeof(DefaultTagHelperResolver).FullName,
                              nameof(GetTagHelpersAsync)),
                          exception);
            }
        }
        public void TagHelperResolutionResult_DefaultBlazorServerProject_RoundTrips()
        {
            // Arrange
            var testFileName = "test.taghelpers.json";
            var current      = new DirectoryInfo(AppContext.BaseDirectory);

            while (current != null && !File.Exists(Path.Combine(current.FullName, testFileName)))
            {
                current = current.Parent;
            }

            var tagHelperFilePath = Path.Combine(current.FullName, testFileName);
            var buffer            = File.ReadAllBytes(tagHelperFilePath);
            var serializer        = new JsonSerializer();

            serializer.Converters.Add(new TagHelperDescriptorJsonConverter());
            serializer.Converters.Add(new TagHelperResolutionResultJsonConverter());

            IReadOnlyList <TagHelperDescriptor> deserializedTagHelpers;

            using (var stream = new MemoryStream(buffer))
                using (var reader = new JsonTextReader(new StreamReader(stream)))
                {
                    deserializedTagHelpers = serializer.Deserialize <IReadOnlyList <TagHelperDescriptor> >(reader);
                }

            var expectedResult = new TagHelperResolutionResult(deserializedTagHelpers, Array.Empty <RazorDiagnostic>());

            // Act
            MemoryStream serializedStream;

            using (serializedStream = new MemoryStream())
                using (var writer = new StreamWriter(serializedStream, Encoding.UTF8, bufferSize: 4096))
                {
                    serializer.Serialize(writer, expectedResult);
                }

            TagHelperResolutionResult deserializedResult;
            var reserializedStream = new MemoryStream(serializedStream.GetBuffer());

            using (reserializedStream)
                using (var reader = new JsonTextReader(new StreamReader(reserializedStream)))
                {
                    deserializedResult = serializer.Deserialize <TagHelperResolutionResult>(reader);
                }

            // Assert
            Assert.Equal(expectedResult, deserializedResult, TagHelperResolutionResultComparer.Default);
        }
Exemplo n.º 5
0
        public override async Task <TagHelperResolutionResult> GetTagHelpersAsync(Project project, CancellationToken cancellationToken)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            try
            {
                TagHelperResolutionResult result = null;

                // We're being defensive here because the OOP host can return null for the client/session/operation
                // when it's disconnected (user stops the process).
                var client = await RazorLanguageServiceClientFactory.CreateAsync(_workspace, cancellationToken);

                if (client != null)
                {
                    using (var session = await client.CreateSessionAsync(project.Solution))
                    {
                        if (session != null)
                        {
                            var jsonObject = await session.InvokeAsync <JObject>(
                                "GetTagHelpersAsync",
                                new object[] { project.Id.Id, "Foo", },
                                cancellationToken).ConfigureAwait(false);

                            result = GetTagHelperResolutionResult(jsonObject);
                        }
                    }
                }

                if (result == null)
                {
                    // Was unable to get tag helpers OOP, fallback to default behavior.
                    result = await _defaultResolver.GetTagHelpersAsync(project, cancellationToken);
                }

                return(result);
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException(
                          Resources.FormatUnexpectedException(
                              typeof(DefaultTagHelperResolver).FullName,
                              nameof(GetTagHelpersAsync)),
                          exception);
            }
        }
Exemplo n.º 6
0
        public void TagHelperDescriptor_WithIndexerAttributes_RoundTripsProperly()
        {
            // Arrange
            var descriptor = CreateTagHelperDescriptor(
                kind: TagHelperConventions.DefaultKind,
                tagName: "tag-name",
                typeName: "type name",
                assemblyName: "assembly name",
                attributes: new Action <BoundAttributeDescriptorBuilder>[]
            {
                builder => builder
                .Name("test-attribute")
                .PropertyName("TestAttribute")
                .TypeName("SomeEnum")
                .AsEnum()
                .Documentation("Summary"),
                builder => builder
                .Name("test-attribute2")
                .PropertyName("TestAttribute2")
                .TypeName("SomeDictionary")
                .AsDictionaryAttribute("dict-prefix-", "string"),
            },
                ruleBuilders: new Action <TagMatchingRuleDescriptorBuilder>[]
            {
                builder => builder
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-one")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.PrefixMatch))
            },
                configureAction: builder =>
            {
                builder
                .AllowChildTag("allowed-child-one")
                .AddMetadata("foo", "bar")
                .TagOutputHint("Hint");
            });

            var expectedResult = new TagHelperResolutionResult(new[] { descriptor }, Array.Empty <RazorDiagnostic>());

            // Act
            var serialized         = JsonConvert.SerializeObject(expectedResult, Converters);
            var deserializedResult = JsonConvert.DeserializeObject <TagHelperResolutionResult>(serialized, Converters);

            // Assert
            Assert.Equal(expectedResult, deserializedResult, TagHelperResolutionResultComparer.Default);
        }
Exemplo n.º 7
0
        public void TagHelperDescriptor_WithDiagnostic_RoundTripsProperly()
        {
            // Arrange
            var descriptor = CreateTagHelperDescriptor(
                kind: TagHelperConventions.DefaultKind,
                tagName: "tag-name",
                typeName: "type name",
                assemblyName: "assembly name",
                attributes: new Action <BoundAttributeDescriptorBuilder>[]
            {
                builder => builder
                .Name("test-attribute")
                .PropertyName("TestAttribute")
                .TypeName("string"),
            },
                ruleBuilders: new Action <TagMatchingRuleDescriptorBuilder>[]
            {
                builder => builder
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-one")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.PrefixMatch))
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-two")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)
                                            .Value("something")
                                            .ValueComparisonMode(RequiredAttributeDescriptor.ValueComparisonMode.PrefixMatch))
                .RequireParentTag("parent-name"),
            },
                configureAction: builder =>
            {
                builder.AllowChildTag("allowed-child-one")
                .AddMetadata("foo", "bar")
                .AddDiagnostic(RazorDiagnostic.Create(
                                   new RazorDiagnosticDescriptor("id", () => "Test Message", RazorDiagnosticSeverity.Error), new SourceSpan(null, 10, 20, 30, 40)));
            });

            var expectedResult = new TagHelperResolutionResult(new[] { descriptor }, Array.Empty <RazorDiagnostic>());

            // Act
            var serialized         = JsonConvert.SerializeObject(expectedResult, Converters);
            var deserializedResult = JsonConvert.DeserializeObject <TagHelperResolutionResult>(serialized, Converters);

            // Assert
            Assert.Equal(expectedResult, deserializedResult, TagHelperResolutionResultComparer.Default);
        }
        public void ViewComponentTagHelperDescriptor_RoundTripsProperly()
        {
            // Arrange
            var descriptor = CreateTagHelperDescriptor(
                kind: ViewComponentTagHelperConventions.Kind,
                tagName: "tag-name",
                typeName: "type name",
                assemblyName: "assembly name",
                attributes: new Action <BoundAttributeDescriptorBuilder>[]
            {
                builder => builder
                .Name("test-attribute")
                .PropertyName("TestAttribute")
                .TypeName("string"),
            },
                ruleBuilders: new Action <TagMatchingRuleDescriptorBuilder>[]
            {
                builder => builder
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-one")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.PrefixMatch))
                .RequireAttributeDescriptor(attribute => attribute
                                            .Name("required-attribute-two")
                                            .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)
                                            .Value("something")
                                            .ValueComparisonMode(RequiredAttributeDescriptor.ValueComparisonMode.PrefixMatch))
                .RequireParentTag("parent-name")
                .RequireTagStructure(TagStructure.WithoutEndTag),
            },
                configureAction: builder =>
            {
                builder.AllowChildTag("allowed-child-one");
                builder.AddMetadata("foo", "bar");
            });

            var expectedResult = new TagHelperResolutionResult(new[] { descriptor }, Array.Empty <RazorDiagnostic>());

            // Act
            var serialized         = JsonConvert.SerializeObject(expectedResult, s_converters);
            var deserializedResult = JsonConvert.DeserializeObject <TagHelperResolutionResult>(serialized, s_converters);

            // Assert
            Assert.Equal(expectedResult, deserializedResult, TagHelperResolutionResultComparer.Default);
        }
        public TagHelperResolutionResultSerializationBenchmark()
        {
            var current = new DirectoryInfo(AppContext.BaseDirectory);

            while (current != null && !File.Exists(Path.Combine(current.FullName, "taghelpers.json")))
            {
                current = current.Parent;
            }

            var tagHelperFilePath = Path.Combine(current.FullName, "taghelpers.json");
            var tagHelperBuffer   = File.ReadAllBytes(tagHelperFilePath);

            // Deserialize from json file.
            Serializer = new JsonSerializer();
            Serializer.Converters.Add(new TagHelperDescriptorJsonConverter());
            Serializer.Converters.Add(new TagHelperResolutionResultJsonConverter());
            using (var stream = new MemoryStream(tagHelperBuffer))
                using (var reader = new JsonTextReader(new StreamReader(stream)))
                {
                    var tagHelpers = Serializer.Deserialize <IReadOnlyList <TagHelperDescriptor> >(reader);
                    TagHelperResolutionResult = new TagHelperResolutionResult(tagHelpers, Array.Empty <RazorDiagnostic>());
                }
        }
Exemplo n.º 10
0
        protected virtual async Task <TagHelperResolutionResult> ResolveTagHelpersOutOfProcessAsync(IProjectEngineFactory factory, Project workspaceProject, ProjectSnapshot projectSnapshot, CancellationToken cancellationToken)
        {
            // We're being overly defensive here because the OOP host can return null for the client/session/operation
            // when it's disconnected (user stops the process).
            //
            // This will change in the future to an easier to consume API but for VS RTM this is what we have.
            var remoteClient = await RazorRemoteHostClient.TryGetClientAsync(_workspace.Services, RazorServiceDescriptors.TagHelperProviderServiceDescriptors, RazorRemoteServiceCallbackDispatcherRegistry.Empty, cancellationToken);

            if (remoteClient is null)
            {
                // Could not resolve
                return(null);
            }

            if (!_resultCache.TryGetId(projectSnapshot.FilePath, out var lastResultId))
            {
                lastResultId = -1;
            }

            var projectHandle = new ProjectSnapshotHandle(projectSnapshot.FilePath, projectSnapshot.Configuration, projectSnapshot.RootNamespace);
            var result        = await remoteClient.TryInvokeAsync <IRemoteTagHelperProviderService, TagHelperDeltaResult>(
                workspaceProject.Solution,
                (service, solutionInfo, innerCancellationToken) => service.GetTagHelpersDeltaAsync(solutionInfo, projectHandle, factory?.GetType().AssemblyQualifiedName, lastResultId, innerCancellationToken),
                cancellationToken
                );

            if (!result.HasValue)
            {
                return(null);
            }

            var tagHelpers = ProduceTagHelpersFromDelta(projectSnapshot.FilePath, lastResultId, result.Value);

            var resolutionResult = new TagHelperResolutionResult(tagHelpers, diagnostics: Array.Empty <RazorDiagnostic>());

            return(resolutionResult);
        }