- Removed all design time descriptors and put their API surface into their corresponding descriptor. Part of removing the design time API surface was removing the tracking of `<Remarks>`, it wasn't used so there's on need to track it until we need it.
- Removed the Type requirement from `TagHelperDescriptor`. With this separation we'll be able to have abstract `TagHelper`s that aren't based on a class implementation.
- Removed Prefix from the `TagHelperDescriptor` API surface. It was a legacy requirement based on how the Razor parser was put together. We can work around this now.
- Stripped correlation information from the immediate `TagHelperDescriptor` API surface. Instead this information is now tracked in `TagMatchingRule`s. This change means that you will not have multiple `TagHelperDescriptor`s per `TagHelper`; instead it's all tracked in a single descriptor. A side effect of this change was the transformation of `IsIndexer` => 3 new properties.
- Renamed many descriptor types and property names.
- Added builder APIs to construct TagHelpers since they're inherently immutable in their API surface.
- Added `ITagHelperDescriptorBuilder` to represent `TagHelper`s that are built from an `ITagHelper` implementing class. It re-introduces the `TypeName` association of a `TagHelper`.
- Added `ITagHelperBoundAttributeDescriptorBuilder` to represent that an attribute was associated with a property.
- Added validation methods to the descriptor builders to enable consumers to validate the current state of the builder and add diagnostics as necessary.
- Moved descriptors away from RazorError.
- Updated the various comparers to understand the descriptors new API.
- Added a new `RazorDiagnosticFactory` abstraction to handle `RazorDiagnostic`s and their corresponding errors/ids etc. This new API should allow for easy addition of new `RazorDiagnostic` errors.
- Updated the `DefaultTagHelperDescriptorFactory` to construct `TagHelperDescriptor`s using the new builder APIs and in the new descriptor format (1 descriptor per type).
- Updated `ViewComponentTagHelperDescriptorFactory` to construct `TagHelperDescriptor`s with the builder API.
- With both factory implementations code was duplicated because the ViewComponent work will be moving outside of Razor once we have the proper hooks.
- Updated `TagHelper` binding bits to capture a binding result in order to query which rules appy to a given tag name.
Addressed feedback
- Update tests to react to new `TagHelperDescriptor` API.
- Remove case sensitive comparers and some cleanup
- Added TagHelperDescriptorJsonConverter, RazorDiagnosticJsonConverter and added serialization tests
VS has gone RTM so, updating to the RTM versions of those dependencies.
Roslyn does not publish our shim packages on NuGet.org, so updating those
to a non-ancient version for projects that use 2.0.0. The projects that
use 1.3.x are staying put for now.
The code change is dealing with something that was obsoleted.
This will make is much easier to investigate failures that bubble up to
the codegen level. You'll be able to see if there was a change to the IR
rather than just the final code.
Deletes CSharpIRToken to use the more general RazorIRToken class.
Rather than using the visitor to visit tokens, now writing a
CSharpExpresionIRNode is an 'atom', and will write its tokens itself.
This IR node will be part of the new token model for IR. It will be used
by all nodes that contain user content. Going forward, tokens will be the
thing that contains text and produces line mappings.
This commit just introduces the class.
This change fixes a bug where DefaultRazorIRLoweringPhase is too
aggressive in merging HTML spans. You can hit the bug by delimiting two
html spans with a metacode character like:
<foo>@{ <bar/> }</foo>
The lowering phase will combine these HTML nodes, which is invalid as they
don't have contiguous spans.
The change here is to merge spans only when they both have an invalid
location or are contiguous.
Introducing ExtensionIRNode and an implementation of templates based on
the new feature set.
Now TemplateIRNode is-a ExtensionIRNode. It's implemented using just
extensibility and isn't part of the standard razor codegen. I'm adding it
to the RazorEngine so that it's still there by default.
I've also included a pattern for visitors to special case
ExtensionIRNode-derived classes that they know about. This requires a
little bit of boilerplate but makes it easy to traverse just the nodes you
care about while keeping the set of nodes open.
For now the general codegen feature still hasn't had a refactor, but this
opens things up for us to start finishing things like MVC's @inject
directive.
- Added DirectiveRemovalIRPass
- Added IRazorDocumentClassifierPhase, IRazorDirectiveClassifierPhase and
IRazorIROptimizationPhase
- Added all the related passes and default implementations
- Refactored DefaultDirectiveIRPass to do the right thing
- Execute method in IR passes now return void
- Added tests for the new phases
This is a new abstraction that represents the api surface available for
codegen to target. Every kind of document should have an associated
RuntimeTarget or just use the default.
To prevent breakage, our DocumentClassifierBase class will provide a
default API set to implementors (like MVC).
I haven't fundamentally changed how codegen is done yet, I've just hidden
it behind a new abstraction. The RuntimeTarget now is also responsible for
selecting between design time and runtime.
The bulk of the noise here is from splitting a lot of the codegen stuff
into its own files.
- Literal directive tokens acted as a way for a user to provide markup bits to be required when parsing a directive.
- Removed source implementations.
- Removed tests validating the feature.
#969
- Roslyn swapped the way they performed dotless commit insertions. They went from:
date => date. => DateTime. to
date => date. => date => DateTime => DateTime.
The problem with the new approach is that date => DateTime would be rejected and therefore force the editor to reparse and reclassify any dots as HTML giving improper IntelliSense.
- Updated Razor implicit expression edit handling to allow identifier => identifier replacements as long as the identifiers didn't result in keyword or directives.
- Added tests to verify the scenarios impacted.
This is a replacement for RazorError, is conceptually equivalent with
Diagnostic from Roslyn.
The next PR will start exposing this through our public API rather than
the legacy type.
The issue here is that when a taghelper prefix is in use it will be
including in the HTML output, when it should be chopped off.
See the diff in the codegen for examples.
This change does deduplication of taghelpers during the binding/rewriting
phase. This is needed when a taghelper has multiple sets of html
attributes that are required (behaves like an OR). This is used lots in
MVC.
The old codebase used to do this in the codegen phase, but it seems
beneficial to do as early as possible.
The IR lowering phase was attaching the 'tag helper fields' node to the
builder instead of to the top-level node (document). This meant that
things wouldn't be where we expect when the first tag helper occurrence is
inside a directive block (section).
Found this porting MVC to use the new Razor codebase.
We're close to hooking up new Razor to MVC. This is a set of enabling
'quick fix' changes to resolve some blockers to using Razor.Evolution in
the product.
Main issues:
- Types not public enough - anything in the .Legacy namespace is still
slated from 'improvement'
- Wrong references. We don't want .Workspaces in MVC, so moving the heavy
lifting of TagHelper discovery to CodeAnalysis.Razor.
This commit adds support to the TagHelperBinderSyntaxTreePass to interpret
@addTagHelper, @removeTagHelper, and @tagHelperPrefix.
I also ported all the original tests for this feature and updated them to
call new APIs.
The bulk of the changes here were updates to baseline tests that weren't
correctly using @addTagHelper
This change adds support for 'imports' - extra source files which contain
directives that can merged with 'main' source files. The purpose of course
is to support things like global usings or addTagHelpers, like
_ViewImports in MVC does today.
Instead of a one-off this is now a feature of the Razor langugage since
things like addTagHelper have an impact on the parsing behavior. Also,
having a standard imports concept keeps out feature creep, for instance
the 'global' usings we have today could really just be an import.
Imports allow single-line directives including the fundamental directives
like addTagHelper, using, and other friends. Code, content, and block
directives are not merged and will be ignored. We can consider making
these kinds of things warnings in the future.
- Hardcoded `ViewComponent` discovery.
- Hardcoded `ViewComponentTagHelperDescriptor` creation.
- Added test to validate that ViewComponents are discovered and transitioned into TagHelpers properly.
- Avoided adding a reference to MVC to prevent circular references. This resulted in custom marker attributes to represent `ViewComponent`s. Also made a lot of use of `ViewComponent` conventions (ending in "ViewComponent").
#932
Also adds the source document to the RazorSyntaxTree and does some cleanup
related to this. This lets us verify which tree goes to which document and
that seems important.
Added basic tests to verify that parsing happens, though it's not being
used for anything right now.
- Ported the existing descriptor factory tests and fixed issues with the current implementation.
- Ported documentation tests with the exception of the localization variants.
- Updated the DefaultTagHelperResolver to filter TagHelper types based on accessibility.
- Added DefaultTagHelperResolver tests.
#851
This change defines stages for IR processing. The comments in RazorIRPass
really explain the details. I've also made the preliminary changes to the
stuff we've built so far to follow the new conventions.
This is building towards multitargeting for Razor, being able to target
both Razor Pages and Razor MVC Views from the same engine, being able to
target different codegen and methods from within the same engine.
This change ensures that spans are contiguous and that all source is part
of a span. This means that a character can't be 'lost' and not a member of
any span.
And guess what? We have a bug like that. So now a few tests are skipped
due to that bug.
Also made some changes to tests that construct invalid spans or spans
without correct locations as their expected input. This allows us to add
the above verification to all parser tests.
- Added a common csharp rendering phase base to put shared assets of runtime and design time code gen.
- Added a new `DesignTimeIRPass` to setup the IR bits to provide accurate intellisense.
- Added a `CodeGenerationIntegrationTest` and moved the RuntimeCodeGenerationTests into it. This way we can re-use the cshtml files and it makes searching/running the tests easy..
- Updated how line mappings are calculated for some nodes.
#848
- Previously we'd special case `@section` at code generation time; now we transform the directive into an IR node.
- Changed the expectations of `DefineSection` to not take in a section writer. It's now expected to modify what `Write`, `WriteLiteral` etc. write to when inside of the lambda. This is done today in TagHelpers via `StartTagHelperWritingScope`.
- Updated baseline files to reflect new `DefineSection` expectations.
- Updated IR tests since we no longer leave around `DirectiveIRNode`s.
#901
- Source ranges currently aren't normalized when they're input into the system. Due to how we serialize pieces of the code this breaks cross plat because of newline differences.
- This is a temporary work around to get the build passing cross plat.
- If needed, a phase/feature can always retrieve the syntax tree to lookup whether the parse tree was made in a "design time" fashion.
- Future DesignTime / Runtime specific bits will be added to their corresponding `AddRuntimeDefaults`/`AddDesignTimeDefaults` methods.
- Added TabSize,IsIndentingWithTabs and NamespaceImports to the RazorParser options. These are replacements for the existing RazorEngineHost abstraction.
- Added RazorParserOptions consumption pattern to more than just the parsing phase.
- Added a ChecksumIRNode to ensure Debugging can work.
- Updated tests to to react to new Checksum and Namespace nodes in the IR tree.
- Removed existing type names used to track `@functions`, `@section` and `@inherits`.
- Updated parsing logic to reflect existing directive behaviors.
- Added additional IR and syntax tree pass in order to fulfill the default directive expectations.
- Updated tests to to expect new extensible directives parse structure.
#894
- Prior to this the platform that the newlines were escaped on would be the platform the baselines would pass on.
- Updated baselines to reflect new newline escaping.
#888
- Also modified the property name from `SourceLocation` => `SourceRange` to avoid ambiguity.
- Updated IR baselines
- Updated IR baseline infrastructure to conditionally render the document location.
#884
This change adds a basic framework for doing baselined integration tests.
This is very similar to what we do elsewhere with generated files and
tests that read them from resources.
What's here now is the support to do this kind of baselining with IR in a
pretty readable serialization format.
This is a building block and the intent is that we'd do something similar
in the future for syntax nodes and C# source.
Looking at the code of the tests in particular, we'll also build the
ability to capture the documents at key points (such as before/after a
targeted phase) and then verify them in the same manner.
This change adds a way to actually configure the RazorEngine to use
extensible directives (previously buried behind legacy API). As part of
this feature adds the RazorParserOptions class to encapsulate anything
else that becomes a parser options (ahem taghelpers).
Now we have a pattern for this when we get there.
Options are propagated as part of the RazorSyntaxTree for
testability/sanity and this was actually responsible for the bulk of the
changes.
Also added some extension methods for adding directives to the
IRazorEngineBuilder and an end to end integration test.
This change adds a phase which runs IR passes. Design and code are almost
exactly the same as the existing SyntaxTree phase. However all of this is
public because the IR is public API.
- Based generic directive implementation off of descriptors.
- Added parsing logic to consume descriptors and parse content that's expected.
- Added parsing errors to automagically detect unexpected directive pieces.
- Updated visitor implementations to understand the directive bits.
- Added a builder abstraction to easily create descriptors. Had to maintain the ability to manually construct a descriptor to enable convenient serialization/deserialization.
- Added tests/comparers to verify correctness of parsing.
#853
- Add an `HtmlNodeOptimizationPass` that does all of the `RazorSyntaxTreeRewriting` that legacy used to achieve outside of `TagHelper`s.
- Add tests for `HtmlNodeOptimizationPass` to verify it's executing appropriate bits.
#849
- Added conditional attribute test.
- Reacted to Html optimization pass in tests.
- Removed directive IR bits since they'll be handled by the extensible directive system.
#844
- Added a TagHelperFeature to hold TagHelper specific pieces that can be replaced.
- Built a syntax tree pass that applies the ported TagHelper bits.
- Updated tests that expected different RazorEngine defaults.
- Added new tests to verify binder pass.
- Modified how tests are run to reflect our new test infrastructure.
- Added TagHelper assertion bits.
- Moved all classes to the Evolution.Legacy namespace.
- Copied Test.Sources bits to the Evolution.Test project.
#845
- Removed the `CreateReader` API in favor of a `CopyTo`, `Length`, `[index]` and `Encoding`.
- Updated existing APIs to react to the change.
- Added tests.
This is an API skeleton for the IR data model that we'll be using as a
spiritual continuation of the 'chunks' API. Currently missing a lot of
detail which will be filled in as needed.
- Prior to this change any query for ownership within a TagHelper would never succeed.
- TagHelpers structure can be influenced greatly by changes to the tags start/end body; therefore, only allowed modifications to TagHelper attribute values to avoid complexity and enable the more widespread scenario of a user typing C# code in an attribute value.
- Updated existing tests to reflect the new edit handlers that were added to TagHelper attributes.
- Added partial parsing tests to verify partial parses succeed/fail when expected.
#792
- Several classes are legacy and left over from many changes in the Razor code base. This changeset removes those classes.
- Also moved several corresponding test cases
#778
- #760
- using a `NullHtmlEncoder` improves `TagHelperContent.IsEmptyOrWhiteSpace` semantics
- e.g. a tab is still a tab after encoding
- also avoids `NotImplementedException`
- implement `Write(char)` for char-by-char `IHtmlContent` corner case
- Removed `Minimized` from `TagHelperAttribute` and replaced it with `HtmlAttributeValueStyle`.
- Removed `AddMinimizedTagHelperAttribute` method from `TagHelperExecutionContext` since we always provide a `HtmlAttributeValueStyle` now.
- Stopped manually escaping double quotes because we now know how an attribute was originally written.
- Updated tests to account for new attribute format (from kvp).
#705
- Today `TagHelperContent`s always allocate their underlying buffer even though they typically only ever have a single entry. Added a field to enable us to only allocate the backing buffer when we absolutely need to.
- Removed `IsEmpty` from `TagHelperContent` since it was not used in any of our `TagHelper`s for simplification. Changed `IsWhiteSpace` naming to be `IsEmptyOrWhiteSpace` since it can be used to indicate either state.
- Updated tests.
#621
- Previously we'd do `executionContext.Output.Content = await executionContext.Output.GetChildContentAsync()`. The problem with this approach is that it returned a `Task<TagHelperContent>` which could not be optimized when building in release.
- Added test to validate `SetOutputContentAsync` does the appropriate thing.
#721
- `TagHelperOutput` and `TagHelperContext` lifetimes now mach `TagHelperExecutionContext`s. This means once a set of `TagHelper`s have run on a tag the `TagHelperOutput`/`TagHelperContext` will be re-used.
- Added tests to validate the various `Reset`/`Reinitialize` methods behaved correctly.
- Updated codegen to no longer set `TagHelperExecutionContext.Output`.
#719
- was missing when writing out full name of an `enum` value
- was missing in one case when writing out `TagHelperAttribute` type name
nit: updated `CSharpTagHelperFieldDeclarationVisitor.WritePrivateField()` to always include the prefix
- no change in generated code but centralizes the prefix addition and reduces intermediate `string`s
- After discussion offline to maintain consistency we decided to also remove `CodeBase` fallback in the net451 scenario. This will keep CoreCLR and net451 scenarios more consistent.
- Removed `CodeBase` validation tests.
- Added `GetAssemblyLocation` extensibility point to enable proper testing of the `TagHelperDesignTimeDescriptorFactory`.
#709
- Added the ability for users to opt into CSS `TagHelper` selectors in their required attributes by surrounding the value with `[` and `]`. Added operators `^`, `$` and `=`.
- Added tests to cover code paths used when determining CSS selectors.
#684
This change implements the new API for flattening content in Razor.
Also, some optimizations to avoid allocations on paths where we need
to encode HTML attribute values.
- aspnet/Coherence-Signed#187
- remove `<RootNamespace>` settings but maintain other unique aspects e.g. `<DnxInvisibleContent ... />`
- in a few cases, standardize on VS version `14.0` and not something more specific
- Hoist `TagHelperAttribute` creation into `private static readonly` fields to avoid allocations on every request. With the recent `TagHelperAttribute` change that made them immutable we can now pre-allocate them without worry of them being modified.
- Added two extra class configuration pieces to enable pre-allocation.
- Updated test files to showcase new pre-allocations.
#600
- Currently the `TagHelperScopeManager` creates a new `TagHelperExecutionContext` per `TagHelper` on a given page. With this change the max number of `TagHelperExecutionContext`s per page is the number of nested levels that exist.
- Added two tests validating that specific pieces of `TagHelperExecutionContext` are updated as expected.
#674
- Changed the variable used to render templates (`HelperResult`s) so they can be used inside of sections.
- Updated section test file to showcase nested scenario. Also Regenerated existing test files.
#572
- Not all `TagHelper`s have unbound HTML attributes or any attributes at all. A great example of this is MVC's input `TagHelper` which usually takes the format of `<input asp-for="..." />`. By lazily initializing we don't build extra attribute lists where not needed.
- Moved `TagHelperContext` and `TagHelperOutput` creation to CreateX methods on `TagHelperExecutionContext`.
#604
- Remove a lot of the ugly generic work done in `TagHelperAttributeList`/`ReadOnlyTagHelperAttributeList`.
- Removed error cases where we'd check on addition of `TagHelperAttribute`s that their `name` was not `null`. This was due to the pre-existing `string` indexer for `TagHelperAttributeList`. It no longer sets `TagHelperAttribute`s directly, instead it's `[key] = value` (instead of `[key] = new TagHelperAttribute(...))`.
- Updated tests to account for new immutability/string indexer format.
- Removed copy ctor from `TagHelperAttribute` since its immutability kills the value.
- Changed `ReadOnlyTagHelperAttributeList` to inherit from `ReadOnlyCollection`
#604