public override void VisitSpan(Span span) { // We're only interested in spans with an AddOrRemoveTagHelperChunkGenerator. if (span.ChunkGenerator is AddOrRemoveTagHelperChunkGenerator) { var chunkGenerator = (AddOrRemoveTagHelperChunkGenerator)span.ChunkGenerator; var directive = chunkGenerator.RemoveTagHelperDescriptors ? TagHelperDirectiveType.RemoveTagHelper : TagHelperDirectiveType.AddTagHelper; var directiveDescriptor = new TagHelperDirectiveDescriptor( chunkGenerator.LookupText, span.Start, directive); _directiveDescriptors.Add(directiveDescriptor); } else if (span.ChunkGenerator is TagHelperPrefixDirectiveChunkGenerator) { var chunkGenerator = (TagHelperPrefixDirectiveChunkGenerator)span.ChunkGenerator; var directiveDescriptor = new TagHelperDirectiveDescriptor( chunkGenerator.Prefix, span.Start, TagHelperDirectiveType.TagHelperPrefix); _directiveDescriptors.Add(directiveDescriptor); } }
private static LookupInfo GetLookupInfo(TagHelperDirectiveDescriptor directiveDescriptor, ErrorSink errorSink) { var lookupText = directiveDescriptor.DirectiveText; var lookupStrings = lookupText?.Split(new[] { ',' }); // Ensure that we have valid lookupStrings to work with. Valid formats are: // "assemblyName" // "typeName, assemblyName" if (lookupStrings == null || lookupStrings.Any(string.IsNullOrWhiteSpace) || lookupStrings.Length != 2) { errorSink.OnError( directiveDescriptor.Location, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText)); return(null); } return(new LookupInfo { TypePattern = lookupStrings[0].Trim(), AssemblyName = lookupStrings[1].Trim() }); }
private static LookupInfo GetLookupInfo( TagHelperDirectiveDescriptor directiveDescriptor, ErrorSink errorSink) { var lookupText = directiveDescriptor.DirectiveText; var lookupStrings = lookupText?.Split(new[] { ',' }); // Ensure that we have valid lookupStrings to work with. The valid format is "typeName, assemblyName" if (lookupStrings == null || lookupStrings.Any(string.IsNullOrWhiteSpace) || lookupStrings.Length != 2) { errorSink.OnError( directiveDescriptor.Location, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText), GetErrorLength(lookupText)); return(null); } var trimmedAssemblyName = lookupStrings[1].Trim(); // + 1 is for the comma separator in the lookup text. var assemblyNameIndex = lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName, StringComparison.Ordinal); var assemblyNamePrefix = directiveDescriptor.DirectiveText.Substring(0, assemblyNameIndex); var assemblyNameLocation = SourceLocation.Advance(directiveDescriptor.Location, assemblyNamePrefix); return(new LookupInfo { TypePattern = lookupStrings[0].Trim(), AssemblyName = trimmedAssemblyName, AssemblyNameLocation = assemblyNameLocation, }); }
private static IEnumerable <TagHelperDirectiveDescriptor> MergeDirectiveDescriptors( IEnumerable <TagHelperDirectiveDescriptor> descriptors, IEnumerable <TagHelperDirectiveDescriptor> inheritedDescriptors) { var mergedDescriptors = new List <TagHelperDirectiveDescriptor>(); TagHelperDirectiveDescriptor prefixDirectiveDescriptor = null; foreach (var descriptor in inheritedDescriptors) { if (descriptor.DirectiveType == TagHelperDirectiveType.TagHelperPrefix) { // Always take the latest @tagHelperPrefix descriptor. Can only have 1 per page. prefixDirectiveDescriptor = descriptor; } else { mergedDescriptors.Add(descriptor); } } // We need to see if the provided descriptors contain a @tagHelperPrefix directive. If so, it // takes precedence and overrides any provided by the inheritedDescriptors. If not we need to add the // inherited @tagHelperPrefix directive back into the merged list. if (prefixDirectiveDescriptor != null && !descriptors.Any(descriptor => descriptor.DirectiveType == TagHelperDirectiveType.TagHelperPrefix)) { mergedDescriptors.Add(prefixDirectiveDescriptor); } mergedDescriptors.AddRange(descriptors); return(mergedDescriptors); }
// Internal for testing internal string ProcessTagHelperPrefix(List <TagHelperDirectiveDescriptor> directives, RazorCodeDocument codeDocument) { // We only support a single prefix directive. TagHelperDirectiveDescriptor prefixDirective = null; for (var i = 0; i < directives.Count; i++) { if (directives[i].DirectiveType == TagHelperDirectiveType.TagHelperPrefix) { // We only expect to see a single one of these per file, but that's enforced at another level. prefixDirective = directives[i]; } } var prefix = prefixDirective?.DirectiveText; if (prefix != null && !IsValidTagHelperPrefix(prefix, prefixDirective.Location, prefixDirective.Diagnostics)) { prefix = null; } if (!string.IsNullOrEmpty(prefix)) { return(prefixDirective.DirectiveText); } return(null); }
private static string ResolveTagHelperPrefix(TagHelperDescriptorResolutionContext context) { var prefixDirectiveDescriptors = context.DirectiveDescriptors.Where( descriptor => descriptor.DirectiveType == TagHelperDirectiveType.TagHelperPrefix); TagHelperDirectiveDescriptor prefixDirective = null; foreach (var directive in prefixDirectiveDescriptors) { if (prefixDirective == null) { prefixDirective = directive; } else { // For each invalid @tagHelperPrefix we need to create an error. context.ErrorSink.OnError( directive.Location, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperDirective( SyntaxConstants.CSharp.TagHelperPrefixKeyword), GetErrorLength(directive.DirectiveText)); } } var prefix = prefixDirective?.DirectiveText; if (prefix != null && !EnsureValidPrefix(prefix, prefixDirective.Location, context.ErrorSink)) { prefix = null; } return(prefix); }
private static IEnumerable <TagHelperDirectiveDescriptor> GetTagHelperDirectiveDescriptors( IReadOnlyList <ChunkTree> inheritedChunkTrees, IReadOnlyList <Chunk> defaultInheritedChunks) { var descriptors = new List <TagHelperDirectiveDescriptor>(); // For tag helpers, the @removeTagHelper only applies tag helpers that were added prior to it. // Consequently we must visit tag helpers outside-in - furthest _ViewImports first and nearest one last. // This is different from the behavior of chunk merging where we visit the nearest one first and ignore // chunks that were previously visited. var chunksFromViewImports = inheritedChunkTrees .Reverse() .SelectMany(tree => tree.Chunks); var chunksInOrder = defaultInheritedChunks.Concat(chunksFromViewImports); foreach (var chunk in chunksInOrder) { // All TagHelperDirectiveDescriptors created here have undefined source locations because the source // that created them is not in the same file. var addTagHelperChunk = chunk as AddTagHelperChunk; if (addTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor( addTagHelperChunk.LookupText, chunk.Start, TagHelperDirectiveType.AddTagHelper); descriptors.Add(descriptor); continue; } var removeTagHelperChunk = chunk as RemoveTagHelperChunk; if (removeTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor( removeTagHelperChunk.LookupText, chunk.Start, TagHelperDirectiveType.RemoveTagHelper); descriptors.Add(descriptor); continue; } var tagHelperPrefixDirectiveChunk = chunk as TagHelperPrefixDirectiveChunk; if (tagHelperPrefixDirectiveChunk != null) { var descriptor = new TagHelperDirectiveDescriptor( tagHelperPrefixDirectiveChunk.Prefix, chunk.Start, TagHelperDirectiveType.TagHelperPrefix); descriptors.Add(descriptor); } } return(descriptors); }
private static IEnumerable <TagHelperDirectiveDescriptor> GetTagHelperDirectiveDescriptors( IReadOnlyList <ChunkTree> inheritedChunkTrees, IReadOnlyList <Chunk> defaultInheritedChunks) { var descriptors = new List <TagHelperDirectiveDescriptor>(); var inheritedChunks = defaultInheritedChunks.Concat(inheritedChunkTrees.SelectMany(tree => tree.Chunks)); foreach (var chunk in inheritedChunks) { // All TagHelperDirectiveDescriptors created here have undefined source locations because the source // that created them is not in the same file. var addTagHelperChunk = chunk as AddTagHelperChunk; if (addTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = addTagHelperChunk.LookupText, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.AddTagHelper }; descriptors.Add(descriptor); continue; } var removeTagHelperChunk = chunk as RemoveTagHelperChunk; if (removeTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = removeTagHelperChunk.LookupText, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.RemoveTagHelper }; descriptors.Add(descriptor); continue; } var tagHelperPrefixDirectiveChunk = chunk as TagHelperPrefixDirectiveChunk; if (tagHelperPrefixDirectiveChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = tagHelperPrefixDirectiveChunk.Prefix, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.TagHelperPrefix }; descriptors.Add(descriptor); } } return(descriptors); }
public override void VisitSpan(Span span) { if (span == null) { throw new ArgumentNullException(nameof(span)); } string directiveText; TagHelperDirectiveType directiveType; var addTagHelperChunkGenerator = span.ChunkGenerator as AddTagHelperChunkGenerator; var removeTagHelperChunkGenerator = span.ChunkGenerator as RemoveTagHelperChunkGenerator; var tagHelperPrefixChunkGenerator = span.ChunkGenerator as TagHelperPrefixDirectiveChunkGenerator; if (addTagHelperChunkGenerator != null) { directiveType = TagHelperDirectiveType.AddTagHelper; directiveText = addTagHelperChunkGenerator.LookupText; } else if (removeTagHelperChunkGenerator != null) { directiveType = TagHelperDirectiveType.RemoveTagHelper; directiveText = removeTagHelperChunkGenerator.LookupText; } else if (tagHelperPrefixChunkGenerator != null) { directiveType = TagHelperDirectiveType.TagHelperPrefix; directiveText = tagHelperPrefixChunkGenerator.Prefix; } else { // Not a chunk generator that we're interested in. return; } directiveText = directiveText.Trim(); var startOffset = span.Content.IndexOf(directiveText, StringComparison.Ordinal); var offsetContent = span.Content.Substring(0, startOffset); var offsetTextLocation = SourceLocation.Advance(span.Start, offsetContent); var directiveDescriptor = new TagHelperDirectiveDescriptor { DirectiveText = directiveText, Location = offsetTextLocation, DirectiveType = directiveType }; _directiveDescriptors.Add(directiveDescriptor); }
private TagHelperDirectiveDescriptor CreateDirective( Span span, string directiveText, TagHelperDirectiveType directiveType, List <RazorDiagnostic> diagnostics) { directiveText = directiveText.Trim(); if (directiveText.Length >= 2 && directiveText.StartsWith("\"", StringComparison.Ordinal) && directiveText.EndsWith("\"", StringComparison.Ordinal)) { directiveText = directiveText.Substring(1, directiveText.Length - 2); } // If this is the "string literal" form of a directive, we'll need to postprocess the location // and content. // // Ex: @addTagHelper "*, Microsoft.AspNetCore.CoolLibrary" // ^ ^ // Start End var directiveStart = span.Start; if (span.Symbols.Count == 1 && (span.Symbols[0] as CSharpSymbol)?.Type == CSharpSymbolType.StringLiteral) { var offset = span.Content.IndexOf(directiveText, StringComparison.Ordinal); // This is safe because inside one of these directives all of the text needs to be on the // same line. var original = span.Start; directiveStart = new SourceLocation( original.FilePath, original.AbsoluteIndex + offset, original.LineIndex, original.CharacterIndex + offset); } var directiveDescriptor = new TagHelperDirectiveDescriptor { DirectiveText = directiveText, Location = directiveStart, DirectiveType = directiveType, Diagnostics = diagnostics, }; return(directiveDescriptor); }
public override void VisitSpan(Span span) { // We're only interested in spans with an AddOrRemoveTagHelperCodeGenerator. if (span.CodeGenerator is AddOrRemoveTagHelperCodeGenerator) { var codeGenerator = (AddOrRemoveTagHelperCodeGenerator)span.CodeGenerator; var directive = codeGenerator.RemoveTagHelperDescriptors ? TagHelperDirectiveType.RemoveTagHelper : TagHelperDirectiveType.AddTagHelper; var directiveDescriptor = new TagHelperDirectiveDescriptor(codeGenerator.LookupText, span.Start, directive); _directiveDescriptors.Add(directiveDescriptor); } }
private static IEnumerable <TagHelperDirectiveDescriptor> GetTagHelperDescriptors( IReadOnlyList <CodeTree> inheritedCodeTrees, IReadOnlyList <Chunk> defaultInheritedChunks) { var descriptors = new List <TagHelperDirectiveDescriptor>(); // For tag helpers, the @removeTagHelper only applies tag helpers that were added prior to it. // Consequently we must visit tag helpers outside-in - furthest _ViewStart first and nearest one last. This // is different from the behavior of chunk merging where we visit the nearest one first and ignore chunks // that were previously visited. var chunksFromViewStarts = inheritedCodeTrees.Reverse() .SelectMany(tree => tree.Chunks); var chunksInOrder = defaultInheritedChunks.Concat(chunksFromViewStarts); foreach (var chunk in chunksInOrder) { var addHelperChunk = chunk as AddTagHelperChunk; if (addHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor(addHelperChunk.LookupText, SourceLocation.Undefined, TagHelperDirectiveType.AddTagHelper); descriptors.Add(descriptor); } else { var removeHelperChunk = chunk as RemoveTagHelperChunk; if (removeHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor(removeHelperChunk.LookupText, SourceLocation.Undefined, TagHelperDirectiveType.RemoveTagHelper); descriptors.Add(descriptor); } } } return(descriptors); }
// Internal for testing internal ParsedDirective ParseAddOrRemoveDirective(TagHelperDirectiveDescriptor directive) { var text = directive.DirectiveText; var lookupStrings = text?.Split(new[] { ',' }); // Ensure that we have valid lookupStrings to work with. The valid format is "typeName, assemblyName" if (lookupStrings == null || lookupStrings.Any(string.IsNullOrWhiteSpace) || lookupStrings.Length != 2) { directive.Diagnostics.Add( RazorDiagnostic.Create( new RazorError( Resources.FormatInvalidTagHelperLookupText(text), directive.Location, Math.Max(text.Length, 1)))); return(null); } var trimmedAssemblyName = lookupStrings[1].Trim(); // + 1 is for the comma separator in the lookup text. var assemblyNameIndex = lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName, StringComparison.Ordinal); var assemblyNamePrefix = directive.DirectiveText.Substring(0, assemblyNameIndex); var assemblyNameLocation = new SourceLocation( directive.Location.FilePath, directive.Location.AbsoluteIndex + assemblyNameIndex, directive.Location.LineIndex, directive.Location.CharacterIndex + assemblyNameIndex); return(new ParsedDirective { TypePattern = lookupStrings[0].Trim(), AssemblyName = trimmedAssemblyName, AssemblyNameLocation = assemblyNameLocation, }); }
private static LookupInfo GetLookupInfo(TagHelperDirectiveDescriptor directiveDescriptor, ParserErrorSink errorSink) { var lookupText = directiveDescriptor.LookupText; var lookupStrings = lookupText?.Split(new[] { ',' }); // Ensure that we have valid lookupStrings to work with. Valid formats are: // "assemblyName" // "typeName, assemblyName" if (lookupStrings == null || lookupStrings.Any(string.IsNullOrWhiteSpace) || (lookupStrings.Length != 1 && lookupStrings.Length != 2)) { errorSink.OnError( directiveDescriptor.Location, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText)); return(null); } // Grab the assembly name from the lookup text strings. Due to our supported lookupText formats it will // always be the last element provided. var assemblyName = lookupStrings.Last().Trim(); string typeName = null; // Check if the lookupText specifies a type to search for. if (lookupStrings.Length == 2) { // The user provided a type name. Retrieve it so we can prune our descriptors. typeName = lookupStrings[0].Trim(); } return(new LookupInfo { AssemblyName = assemblyName, TypeName = typeName }); }
public override void VisitSpan(Span span) { // We're only interested in spans with an AddOrRemoveTagHelperChunkGenerator. if (span.ChunkGenerator is AddOrRemoveTagHelperChunkGenerator) { var chunkGenerator = (AddOrRemoveTagHelperChunkGenerator)span.ChunkGenerator; var directive = chunkGenerator.RemoveTagHelperDescriptors ? TagHelperDirectiveType.RemoveTagHelper : TagHelperDirectiveType.AddTagHelper; var textLocation = GetSubTextSourceLocation(span, chunkGenerator.LookupText); var directiveDescriptor = new TagHelperDirectiveDescriptor { DirectiveText = chunkGenerator.LookupText, Location = textLocation, DirectiveType = directive }; _directiveDescriptors.Add(directiveDescriptor); } else if (span.ChunkGenerator is TagHelperPrefixDirectiveChunkGenerator) { var chunkGenerator = (TagHelperPrefixDirectiveChunkGenerator)span.ChunkGenerator; var textLocation = GetSubTextSourceLocation(span, chunkGenerator.Prefix); var directiveDescriptor = new TagHelperDirectiveDescriptor { DirectiveText = chunkGenerator.Prefix, Location = textLocation, DirectiveType = TagHelperDirectiveType.TagHelperPrefix }; _directiveDescriptors.Add(directiveDescriptor); } }
public void TagHelperResolution(bool designTime) { var descriptorResolver = new TagHelperDescriptorResolver(designTime); var errorSink = new ErrorSink(); var addTagHelperDirective = new TagHelperDirectiveDescriptor { DirectiveText = "*, Microsoft.AspNetCore.Mvc.TagHelpers", DirectiveType = TagHelperDirectiveType.AddTagHelper, Location = SourceLocation.Zero }; var resolutionContext = new TagHelperDescriptorResolutionContext( new[] { addTagHelperDirective }, errorSink); IEnumerable <TagHelperDescriptor> descriptors; using (Collector.StartCollection()) { descriptors = descriptorResolver.Resolve(resolutionContext); } Assert.NotEmpty(descriptors); Assert.Empty(errorSink.Errors); }
private static IEnumerable<TagHelperDirectiveDescriptor> GetTagHelperDirectiveDescriptors( IReadOnlyList<ChunkTree> inheritedChunkTrees, IReadOnlyList<Chunk> defaultInheritedChunks) { var descriptors = new List<TagHelperDirectiveDescriptor>(); var inheritedChunks = defaultInheritedChunks.Concat(inheritedChunkTrees.SelectMany(tree => tree.Children)); foreach (var chunk in inheritedChunks) { // All TagHelperDirectiveDescriptors created here have undefined source locations because the source // that created them is not in the same file. var addTagHelperChunk = chunk as AddTagHelperChunk; if (addTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = addTagHelperChunk.LookupText, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.AddTagHelper }; descriptors.Add(descriptor); continue; } var removeTagHelperChunk = chunk as RemoveTagHelperChunk; if (removeTagHelperChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = removeTagHelperChunk.LookupText, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.RemoveTagHelper }; descriptors.Add(descriptor); continue; } var tagHelperPrefixDirectiveChunk = chunk as TagHelperPrefixDirectiveChunk; if (tagHelperPrefixDirectiveChunk != null) { var descriptor = new TagHelperDirectiveDescriptor { DirectiveText = tagHelperPrefixDirectiveChunk.Prefix, Location = chunk.Start, DirectiveType = TagHelperDirectiveType.TagHelperPrefix }; descriptors.Add(descriptor); } } return descriptors; }
public void GetTagHelperDescriptors_ReturnsExpectedDirectiveDescriptors( ChunkTree[] chunkTrees, TagHelperDirectiveDescriptor[] expectedDirectiveDescriptors) { // Arrange var builder = new BlockBuilder { Type = BlockType.Comment }; var block = new Block(builder); IList<TagHelperDirectiveDescriptor> descriptors = null; var resolver = new Mock<ITagHelperDescriptorResolver>(); resolver.Setup(r => r.Resolve(It.IsAny<TagHelperDescriptorResolutionContext>())) .Callback((TagHelperDescriptorResolutionContext context) => { descriptors = context.DirectiveDescriptors; }) .Returns(Enumerable.Empty<TagHelperDescriptor>()) .Verifiable(); var baseParser = new RazorParser( new CSharpCodeParser(), new HtmlMarkupParser(), tagHelperDescriptorResolver: resolver.Object); var parser = new TestableMvcRazorParser(baseParser, chunkTrees, defaultInheritedChunks: new Chunk[0]); // Act parser.GetTagHelperDescriptorsPublic(block, errorSink: new ErrorSink()).ToArray(); // Assert Assert.NotNull(descriptors); Assert.Equal(expectedDirectiveDescriptors.Length, descriptors.Count); for (var i = 0; i < expectedDirectiveDescriptors.Length; i++) { var expected = expectedDirectiveDescriptors[i]; var actual = descriptors[i]; Assert.Equal(expected.DirectiveText, actual.DirectiveText, StringComparer.Ordinal); Assert.Equal(SourceLocation.Zero, actual.Location); Assert.Equal(expected.DirectiveType, actual.DirectiveType); } }
public override void VisitSpan(Span span) { if (span == null) { throw new ArgumentNullException(nameof(span)); } TagHelperDirectiveType directiveType; if (span.ChunkGenerator is AddTagHelperChunkGenerator) { directiveType = TagHelperDirectiveType.AddTagHelper; } else if (span.ChunkGenerator is RemoveTagHelperChunkGenerator) { directiveType = TagHelperDirectiveType.RemoveTagHelper; } else if (span.ChunkGenerator is TagHelperPrefixDirectiveChunkGenerator) { directiveType = TagHelperDirectiveType.TagHelperPrefix; } else { // Not a chunk generator that we're interested in. return; } var directiveText = span.Content.Trim(); var startOffset = span.Content.IndexOf(directiveText, StringComparison.Ordinal); var offsetContent = span.Content.Substring(0, startOffset); var offsetTextLocation = SourceLocation.Advance(span.Start, offsetContent); var directiveDescriptor = new TagHelperDirectiveDescriptor { DirectiveText = directiveText, Location = offsetTextLocation, DirectiveType = directiveType }; _directiveDescriptors.Add(directiveDescriptor); }
private static LookupInfo GetLookupInfo( TagHelperDirectiveDescriptor directiveDescriptor, ErrorSink errorSink) { var lookupText = directiveDescriptor.DirectiveText; var lookupStrings = lookupText?.Split(new[] { ',' }); // Ensure that we have valid lookupStrings to work with. The valid format is "typeName, assemblyName" if (lookupStrings == null || lookupStrings.Any(string.IsNullOrWhiteSpace) || lookupStrings.Length != 2) { errorSink.OnError( directiveDescriptor.Location, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText), GetErrorLength(lookupText)); return null; } var trimmedAssemblyName = lookupStrings[1].Trim(); // + 1 is for the comma separator in the lookup text. var assemblyNameIndex = lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName, StringComparison.Ordinal); var assemblyNamePrefix = directiveDescriptor.DirectiveText.Substring(0, assemblyNameIndex); var assemblyNameLocation = SourceLocation.Advance(directiveDescriptor.Location, assemblyNamePrefix); return new LookupInfo { TypePattern = lookupStrings[0].Trim(), AssemblyName = trimmedAssemblyName, AssemblyNameLocation = assemblyNameLocation, }; }