Changing to IReadOnlyList since we always want to support indexing.
Replacing ToArray() with non-linq when needed, and with a static
EmptyArray when not needed.
Eliminates 50mb of list copies.
- Roslyn currently has an issue where too large of strings result in out of memory exceptions at compile time. To combat this I broke down literal strings into 1024 length pieces each resulting in their own `WriteLiteral`/`WriteLiteralTo` calls. The 1024 number corresponds directly with MVCs response string buffer.
- Added tests to validate large string rendering.
#614
- Prior to this change we'd hit the disk every time we'd create a `TagHelperDesignTimeDescriptor` to locate an assemblies XML files.
- Did not want to tie the XML cache to a static member in-case a user updates their XML information between parses. Therefore, changed `TagHelperDescriptorFactory` and `TagHelperDesignTimeDescriptorFactory` to no longer be static.
- Put the same `TagHeleprDescriptorFactory` extensibility point as we had for its counterpart `TagHelperTypeResolver` to stay consistent. This involved making `CreateDescriptors` virtual and allowing it to be provided in the `TagHelperDescriptorResolver` constructor.
#630
- Updated existing tests and added a new case to understand `@section {....` scenarios.
- Instead of trying to guess 1 character prior to EOF decided to log error on opening brace since we know its position. Updated error to account for change in location.
#625
- This allows users to write `TagHelperOutput` directly to an `IHtmlContent` accepting `TextWriter`.
- This also enables us to inspect backing fields for all of the various contents to lazily initialize them.
#358
This change significantly reduces the amount of string and List<ISymbol>
allocations that occur during compilation by changing the way
LiteralChunks are combined.
This is a low impact fix that addresses the performance issue, the design
issues that caused it still exist.
The problem here lies in what Razor fundamentally does - it parses HTML/C#
into tokens, and then combines them back into 'chunks' a representation
friendly to code generation. When presenting with a large block of static
HTML, Razor parses it into individual HTML tokens, and then tries to join
them in back into a single chunk for rendering. Due to details of Razor's
representation of chunks/tokens, the process of combining literals is too
expensive.
Mainly, what's done here is to not try to combine instances of
LiteralChunk. The process of merging them is too expensive and requires
lots of interm List<ISymbol> and string allocations.
Instead we produce a new 'chunk' ParentLiteralChunk, which doesn't do so
much up-front computing. Various pieces of the code that deal with
LiteralChunk need to be updated to deal with ParentLiteralChunk also,
which is the bulk of the changes here.
Note that we still have the potential for LOH allocations to occur during
codegen, but it's likely to occur O(1) for each large block of HTML
instead of O(N) as it did in the old code.
- Updated .cshtml files to not provide quotes for the various `TagHelper` directives.
- Updated `TagHelper` directive parsing tests. This also involved removing several tests that expected errors which no longer occur since we don't have to ensure quotes are balanced.
- Updated line mappings which significantly changed due to us no longer generating line pragmas at design time for `TagHelper` directives.
#561
- Template attributes should be of type `Func<TextWriter, Task>`. We weren't generating an `async` lambda for attributes prior to this change resulting in a compilation failure when used at runtime and the inability to `@await` code (unless a user returns some sort of `Task`).
- Updated code generation files to reflect the new code generation behavior.
#594
- The using statements had a chance to conflict with user code. Removed them and changed the default configured type names to be `global::` full name based.
- Updated test file `TagHelperDescriptor.TypeName`s to have namespaces to make them easier to read.
#580
- If a `TagHelper` attribute is an `enum` then you no longer need to provide the `enum` name. To override this functionality you can add the `@` symbol.
- Added code generation tests.
- Added `TagHelperDescriptorFactoryTest`s that double for Precompilation tests.
#196
- The init method allows multiple `TagHelper`s to inject data into the `context.Items` bag to properly function when running in unison with other `TagHelper`s that need to communicate with children.
- Transition `GetChildContentAsync` from `TagHelperContext` to `TagHelperOutput`.
- Move `TagHelperContext.GetChildContentAsync` tests to `TagHelperOutputTest`.
- Added `Init` test to ensure `TagHelperRunner` calls it in the correct order.
#571
- Changed non-user facing type names to `Microsoft.AspNet.Razor.TagHelpers`.
- Updated folder structure to reflect new namespaces.
- Updated generated code files to reflect new runtime type namespaces.
#578
- `TagHelper`s used to not flatten correctly resulting in inconsistent start locations for `SyntaxTreeNode`s following/within `TagHelper`s.
- This change indirectly corrected bad indentation that existed in generated C#.
- Added a test to validate `TreesAreDifferent` returns expected behavior when modifying content inside of `TagHelper`.
- Added `TagHelperBlock` `Flatten` test.
#553
- This enables debugging and proper error reporting for dynamic attributes. Without the pragmas errors would showcase generated Razor C# instead of their corresponding .cshtml files.
- Did not have to do any `TagHelper` specific changes since they utilize the same core attribute rendering logic.
- Updated generated C# files for tests.
#569
These changes make TagHelperContent with the IHtmlBuilder pattern, but
retain the signatures returning TagHelperContent.
Removed a bunch of tests that are no redundant with tests for the
extension methods in HttpAbstractions. Kept a few explemars in place to
ensure that the basic plumbing functions as desired.
- Updated the `TagHelperParseTreeRewriter` loosen child restrictions to non-`TagHelper` HTML elements.
- Updated tests to showcase that non-`TagHelper` elements are allowed to be restricted.
- Added an additional test case to showcase sub-sub nesting of non-`TagHelper` restricted children.
#543
- `ParentTag` allows `TagHelper`s to restrict where they apply based on their immediate parent tag.
- Changed the `TagHelperParseTreeRewriter` to understand non-`TagHelper` HTML elements to properly determine a parent tag when applying `TagHelperDescriptor.RequiredParent`. This change will also enable `[RestrictChildren]` to apply to more than just `TagHelper`s.
- Added tests to validate that partial and well formed tags properly discover `TagHelper`s. Also added tests that validate that descriptors are properly created based on `TagHelper` types.
#474
The code generator generates calls to ToString() on a TagHelperContent
when used with dynamic content inside an attribute that needs to be passed
to a TagHelper as a string.
This change updates the codegen to use GetContent(IHtmlEncoder)
- Took the HTML5 spec approach of disallowing specific characters and accepting all others.
- Added several parser and code generation tests to cover both `TagHelper` and non-`TagHelper` variations of symbol bound attribute names.
#137
- To limit the impact of the change ensured that we only do extra work in the case that we detect a script tag with a `type` attribute.
- The parsing changes include normal HTML parsing behaviors when we detect that a script tag has a `type` attribute with value `text/html`.
- Added unit and code generation tests to validate `text/html` script tag behavior.
#502
- Nearly every other `TagHelper` related element targeting attribute has `Html` a part of its name. With this rename, the attribute will be consistent.
#516
- Prior to this change adding a `.` after an implicit expression would result in compile errors due to Razor thinking the `.` was part of the C# (normally not the case).
- Added a code generation and unit tests to validate behavior.
#491
- Specifying the `RestrictChildrenAttribute` enables `TagHelper`s to only allow other `TagHelper`s targeting specified names to be in the children.
- Used the `null` value to indicate that `AllowedChildren` was not specified and therefore everything is allowed. This is the default.
- Added name verification to name values to ensure that no bad values pass through the system.
- Added parsing tests to validate a mixture of content generates errors when expected.
#255
- To write a start tag only `TagHelper` you can now utilize the `TagStructure` property on the `TargetElement` attribute. If none is specified it'll be treated as unspecified and default to old behavior of being start/end tag or self-closing.
- Added `TagMode` to showcase what the user initially wrote in their Razor document. This way `TagHelper`s can flow end-to-end in thesame format as they were written with.
- Updated code generation to specify `TagMode` instead of the boolean self-closing.
- Updated existing tests to move from `SelfClosing` => `TagMode`.
- Added `TagStructure` related tests to the set of tests that we currently have for `TagHelperBlockRewriter` and `TagHelperParseTreeRewriter`.
#450
- Today MVC has specific rules about resolving Razor attribute values. Ex: `true` => attribute name being used as attribute value. This change ensures that unbound complex `TagHelper` attribute use that same logic.
- Added configuration to `GeneratedTagHelperContext` for `AddHtmlAttributeValues`.
- Had to be careful with code generating `AddHtmlAttributeValues`. In the case of `data-`; they can appear as complex attributes but may not contain any pieces that are `DynamicAttributeBlockChunk`s. Had to protect against this scenario.
- Updated existing test files.
- Added a new code gen test case to showcase the various use-cases of unbound dynamic `TagHelper` attributes.
#247
- Removed parsing, chunk generation and code generation.
- Removed related tests.
- Did not modify existing unrelated tests with ~/ since it's just plain text and may be valid for end-users.
#427
- Added a boolean overload that specifies whether the user wants to retrieve cached content.
- Added tests to validate `TagHelperExecutionContext` `GetChildContentAsync` and that `TagHelperContext` passes the appropriate values through.
#459
- Updated `LocationTagged<TValue>` to handle `null` implicit values.
- Removed `InternalsVisibleTo` declaration on `Microsoft.AspNet.Razor` to the runtime test project.
- Updated `TagHelperDescriptor` tests to utilize helper methods to construct `TagHelperDescriptor`s. This was needed since the `InternalsVisibleTo` declaration was removed.
#449
- Prior to this change we'd return early and not generate any found descriptors if ANY property on a `TagHelper` had editor browsable never.
- This issue was hidden from tests due to us using the wrong comparer. Updated the comparer and failures occurred without the `TagHelperDescriptorFactory` change (yay).
#454
- Changed `TagHelperDescriptorFactory` to not create individual descriptors when `EditorBrowsableAttribute` is present and set to `EditorBrowsableState.Never`.
- Added tests to validate the `TagHelperDescriptorFactory` creates the attribute correctly.
- Did not look down the inheritance chain for `EditorBrowsableAttribute` because `TargetElement` is not inherited.
#447
- #399
- move invalid `HtmlAttributeNameAttribute.Name` checking to `TagHelperDescriptorFactory`
- add a few new error cases
- but does not cover all the new error cases e.g. `[HtmlAttributeName(...)]` on a get-only `int` property
nit:
- `resx` target removed some older resources from `RazorResources.Designer.cs`
- Decided to not have the attribute inheritable since TargetElement is not inheritable.
- Added tests to validate serialization, deserialization and construction of TagHelperDescriptors with OutputElementHints.
- Changed TagHelperUsageDescriptor to TagHelperDesignTimeDescriptor and TagHelperAttributeDesignTImeDescriptor.
#382
- Could not add tests to validate the full TagHelperDescriptorFactory.CreateDescriptors => TagHelperUsageDescriptors due to how the runtime loads assemblies (does it in memory without XML).
- Added serialization tests to include TagHelperUsageDescriptors.
- Updated existing tests to use new TagHelperDescriptor/TagHelperAttributeDescriptor constructors.
#352
- Duplicate TagHelper bound attributes used to be ignored entirely; they now flow to the output as if they were unbound.
- Added code generation test to verify duplicate attributes. Added runtime and design time versions.
- Updated existing tests that happened to have duplicate bound attributes.
#418
- TagHelper attributes that have expressions intermingled within them (resulting in Block elements) resulted in Spans in the attribute being falsely marked as SpanKind.Markup.
- Updated tests to account for new SpanKind.Code behavior.
- Added complex scenario to validate SpanKind.Code is flowed through to surround attributes.
#387
- Removed old code that disabled instrumentation for TagHelper bodies. Instrumentation will throw out sections for begin/end context that don't make it to the final output.
- Added instrumentation around WriteTagHelperAsync. Any content inside of the TagHelper will get sub-mapped via begin/end context.
- Hand verified BasicTagHelpers.cs begin/end context tests to ensure correctness.
#172
- Added new handling of the C# try catch statement to allow exception filters after catch statements.
- Added tests to validate valid and invalid scenarios.
#402
- Split the tests into their corresponding impact areas. We were testing a lot of bits that were not specific to the TagHelperParseTreeRewriter in its corresponding tests.
#370
- This was accomplished by changing when/how TagHelper attributes are rendered. Previously they were rendered: Bound => Unbound. Now they're rendered in the order that they exist on the TagHelperChunk.
- Regenerated test files to account for new re-ordering of TagHelper attributes.
- Added duplicate, unbound HTML attribute, unminimized same name test to ComplexTagHelpers.
- Did not add additional tests (other than the one noted above) since the current tests seem to be heavily impacted by the re-organization of code rendering; effectively showcasing the fix.
#225
- ignore missing expected output resources in this mode
- update `BaselineWriter` to avoid `IOException`s (file access issues)
- serialize file operations
- one file handle per file
- repeatedly `rm TestFiles/CodeGenerator/Output/*; `dnx . test`; no errors
also
- add generation of design-time line mappings
- fix ChunkGenerator -> CodeGenerator typo in path names
- update files only if they have changed
- new `TestFiles.Exists()` method to support this check
- do not check results in `CSharpCodeBuilderTests` if `GENERATE_BASELINES` set
nits:
- update BOM in CodeBlockWithTextElement.cs to avoid future `git diff`s
- use more `var` and improve variable names in `TestFile`
- wrap long lines
- Requesting a '*' tagName from the TagHelperDescriptorProvider could only happen if a user was directly calling into it (extremely unlikely). Therefore I've removed the special casing to make the logic more simple.
- Removed tests that expected this behavior.
#324
- Now that what used to be CodeGenerators are now ChunkGenerators we can rename the CodeBuilder into its correct structure: a CodeGenerator.
- Moved the TagHelperAttributeValueCodeRenderer from the TagHelpers namespace into the CodeGeneration namespace.
- Went through several classes and remove and sorted usings.
- Updated test files to abide by the new naming convention of Builders => CodeGenerators.
#140
- Renamed CodeGenerators to ChunkGenerators.
- Updated location of TestFiles from TestFiles/CodeGenerator/CS/{Output|Source} => TestFiles/CodeGenerator/{Output|Source}.
- Removed ChunkTree test; it was a legacy test used to experiment with Razor rendering (not a real test).
- Removed CSharpRazorCodeGenerator; it's now replaced with RazorCodeGenerator. It was an empty class that did nothing.
- Updated ChunkBlock => ParentChunk. Also updated several patterns throughout the code base that referenced these blocks as blocks and not parents.
- Moved Chunks and ChunkGenerators into the Chunks/Chunks.Generators namespace/folder structure. Updated test project to reflect the same.
- Moved CodeBuilders and CodeVisitors to the CodeGeneration/CodeGeneration.Visitors namespace/folder structure. Updated test project to reflect the same.
- Moved several TagHelper assets outside of their own namespaces and into Razors more general structures; such as CodeGeneration and Chunks/Chunks.Generators.
#140
- [TargetElement(Attributes ="prefix-*")] is now supported.
- Added '*' to the list of invalid non whitespace characters in TagHelperDescriptorFactory.
- Modified TagHelperDescriptorProvider to respect suffixed wildcards in TagHelperAttributeDescriptor.Attributes.
- Added tests to validate wildcard required attributes
#361
- #89 remainder
- support adding attributes (that aren't otherwise bound) to a tag helper dictionary
- use two `TagHelperAttributeDescriptor`s for dictionary and indexer
- most exising descriptor properties have two meanings depending on new `IsIndexer`
- add `TagHelperAttributeDescriptor.IsNameMatch()`
- create no `TagHelperAttributeDescriptor`s if property name or `HtmlAttributeNameAttribute`
is invalid
- avoid corner case misfeatures where invalidity removes just one descriptor
- extend handling of invalid attribute names to include `[HtmlAttributeName]`
- handle prefix matches in `TagHelperBlockRewriter`
- add parse error when resolved dictionary key is `string.Empty`
- generate code for indexer property assignments
- add code generation for runtime error if using indexer when property is `null`
- use new `GeneratedTagHelperContext.FormatInvalidIndexerAssignmentMethodName` for message
- code generation now handles attributes in source order; thus above errors occur only when
expected if dictionary is also initialized in the Razor source
- surprisingly generation order change did not break existing tests!
nits:
- improve `TagHelperDescriptorFactory_InvalidBoundAttributeName` wording
- rename resource to `TagHelperDescriptorFactory_InvalidAttributeNameOrPrefixStart`
- correct order of arguments to `FormatTagHelperDescriptorFactory_InvalidBoundAttributeName`
- correct `TagHelperBlockRewriter_TagHelperAttributeListMustBeWellFormed` resource
- correct `TagHelperDescriptorFactoryTest` test names
- remove a few unnecessary `ToArray()` calls
- update `TagHelperAttributeDescriptorComparer` comments
- Added special cases to the using statement parser to understand `@using static Foo`.
- Added several unit tests to validate the static using structure.
- Modified existing import code generation tests to validate several static usings.
#44
- Added case in ImplicitExpression handling to understand question marks.
- text?. is special compared to text. because with text. we currently validate content after text. to determine if it's an expression or if it's a period. Now with ?. we always treat it as an expression because ?. is not a useful sentance of any kind.
- Added unit tests to validate new implicit expression handling
- Added runtime and design time code generation tests to validate null conditional operators.
#44
- Involved updating the HtmlMarkupParser to properly separate data- attributes. Prior to this change `data-foo="abc @DateTime.Now def"` would involve 1 Span for `data-foo="abc` 1 Span for `@DateTime.Now` and 1 Span for `def"`. This was very unique behavior from an attribute standpoint (as far as Razor is concerned) and made it difficult for the TagHelper rewriting system to rewrite attributes. With this change it gets broken out as follows: `|data-foo="|abc| @DateTime.Now| def|"|`.
- Added unit tests to validate the various ways you can write unbound data- attributes.
- Updated the BasicTagHelpers codegeneration test to intermix some unbound data- attributes.
#342
- relates to #89 because that changes `string` property checks and needs this refactor
- determine `string`-ness when creating `TagHelperAttributeDescriptor`s
- add `TagHelperAttributeDescriptor.IsStringProperty` (set in constructor)
- avoid repeated `string` comparisons and be more explicit
- change `TagHelperBlockRewriter` to centralize more of the `string`-ness determination
- also add `TryParseResult` DTO, avoiding multiple `out` parameters
- refactor `CSharpTagHelperCodeRenderer` to allow reuse of core attribute value rendering
- test all of it
- add `TagHelperDescriptorTest` to confirm serialization / deserialization
minor:
- fix `TagHelperBlockRewriter.TryParseBlock()` end quote removal when tag is malformed
nits:
- remove dangling mention of fixed bug #220
- make recently-added `TagHelperBlockRewriterTest` tests realistic
- multiple `TagHelperDescriptor`s for same tag helper have identical `Attributes`
- Added parse level rewriting tests to validate new TagHelper rewritten structures for minimized attributes.
- Updated existing parser tests to understand minimized attributes.
- Added codegen test to validate understanding of minimized attributes.
- Added TagHelperExecutionContext tests to validate maintaining of runtime TagHelperOutput tests.
- Refactored part of the TagHelperParseTreeRewriterTest file into a base class file so we can make better rewriting tests.
#220
- tests failing
- root cause is likely similar to reason MVC Core has same dependency
- something must have changed in the framework packages without manifest fixes
- related to #89 because we need more descriptor comparers in more places
- separate `TagHelperAttributeDescriptorComparer` and `TypeBasedTagHelperDescriptorComparer`
- encourages reuse and most will soon be used in multiple classes
- add `null` checks to `EquivalenceComparer`
- also give parameters better names
nits:
- use `<inheritdoc/>` in `TagHelperDescriptorComparer`
- also give it an explicit constructor
- make product comparers easier to subclass
- base test `CaseSensitiveTagHelperAttributeDescriptorComparer` on product code
- add `[NotNull]` in some `public` or `protected` callers as well
- add `[NotNull]` in `SeekableTextReader` constructors
- add `where TSymbolType : struct` to replace incorrect `null` checks
- remove `T` type parameters in changed files e.g. change to `TWriter`
- remove tests of removed code
nits:
- change `TextReaderExtensions` to consistently call other extensions as statics
- wrap some long doc comments
- `resources` -> `resource`
Example warning during `dnu build --quiet`:
```
...\test\Microsoft.AspNet.Razor.Test\project.json(3,34): warning: Property "resources" is deprecated. It is replaced by "resource".
```
Primarily resulted in VS Error List noise. Above does not normally show up in
`build.cmd` runs because `dnx . test` does not show build warnings.
- #362 and more
- make a few more properties immutable
- in a few cases, just remove `private` setters
- in others, adjust consuming code to handle the changes
- make `Equals()` commutative
- use `GetType() == obj.GetType()` if necessary
- use only immutable values in `GetHashCode()` calculations
- avoid `object.GetHashCode()`; that calculates hash of reference
- add warnings about `RazorError` property setters but use properties
- BUT lack of immutable values leads to some static `GetHashCode()` calculations
- correct important typo in `TagHelperDescriptorComparer`
- ensure `Equals()` does not `throw` an NRE e.g. in `LineMapping`
- add `SyntaxTreeNode.GetEquivalenceHash()`
- make `SourceLocation.Equals()` and `SourceLocation.CompareTo()` consistent
Update affected tests
- code generators and edit handlers less likely to be equal; adjust expectations
Add lots of tests
- not for all updated classes but enough to see impact of odd choices
nits:
- remove some `Equals()` and `GetHashCode()` overrides in `SpanCodeGenerator` subclasses
- no longer unique
- remove redundant null checks e.g. when also done in `base.Equals()`
- add `StringComparer.Ordinal` if `StringComparison.Ordinal` used in `Equals()`
- make some `CSharpLineMappingWriter` fields `readonly`
- remove unused `LineMapping` constructor
- #182
- ignore otherwise-bound (i.e. `public`) properties in tag helpers
nits:
- add more `TagHelperDescriptorFactory` tests e.g. of `internal` properties
- remove `private` setter from `HtmlAttributeNameAttribute`
- use `null` propagation to shorten `IsAccessibleProperty` expression
- clean up some trailing whitespace