Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update visibility of component parameters #8825

Closed
10 tasks done
rynowak opened this issue Mar 26, 2019 · 15 comments
Closed
10 tasks done

Update visibility of component parameters #8825

rynowak opened this issue Mar 26, 2019 · 15 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components Done This issue has been fixed

Comments

@rynowak
Copy link
Member

rynowak commented Mar 26, 2019

Summary

We have to make a final decision about the visibility of component parameters. We've run into many issues trying to use non-public properties, and I don't think these are going to stop.

Problems and Goals

  • We want to make it hard or impossible to set a component parameter property directly. This is never correct when done in application code
  • We've tried using non-public properties and found a bunch of things that don't work
    • Reference docs require public
    • Reference assemblies require public
    • Our metadata analysis has (possibly fragile) workarounds in place that we use to look at non-public properties
  • We want whatever we choose to work with AOT, but we don't exactly know the requirements. It's generally assumed in AOT that unused non-public code is dead code and can be removed.
  • We want whatever we choose to work with testing, but we don't know the requirements of that yet

TLDR we have given non-public properties a try and the results aren't great. We got here because we now have to maintain ref assembly code for our components manually. It would be great if the guidance for users worked for us as well.

Some options

We could recommend that users use public get properties, and we will call the setter regardless of its visibility.

We could recommend that users use public get/set properties and we will write an analyzer to tell you not to set component parameter properties.

I don't like the option that we'd keep on doing analysis over non-public properties. We don't do this anywhere else I can think of, and I don't have confidence that this will play out in our favor wrt tooling.

Conclusion

We have a conclusion here!

Preview 8

  • Reference the component analyzer package from .Components
  • Add analyzer to warn if a parameter is set in code outside of the inheritance hierarchy or a nested class
  • Update our samples
  • Verify [CascadingParameter]s do not get Analyzesr warnings impacted
  • Don't pass analyzers to the declaration compilation target
  • Add our component analyzer package to the SDK
  • Add a .targets file to our analyzer package to avoid duplicates when included by both the SDK and package
  • Make parameters public get/set
  • Add analyzer to warn if a property is not public get/set and has [Parameter]
  • Update our tests

Before final release

We can leave [CascadingParameter] properties alone. They don't interact with tooling, don't want documentation, and don't represent a public contract.

@rynowak rynowak added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates area-blazor Includes: Blazor, Razor Components labels Mar 26, 2019
@mkArtakMSFT mkArtakMSFT added this to the 3.0.0-preview6 milestone Mar 26, 2019
@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@rynowak rynowak changed the title Decide if we want to manually maintain ref-assemblies for built-in components Make a decision about the visibility of component parameters May 30, 2019
@rynowak rynowak added Needs: Design This issue requires design work before implementating. and removed task labels May 30, 2019
@egil
Copy link
Contributor

egil commented May 30, 2019

I am not sure if this is a valid scenario, but moving to virtual protected/virtual public parameters might make component inheritance easier. I.e. one could make a specialized version of the NavLink component by inheriting from LavLink instead of wrapping it.

@rynowak
Copy link
Member Author

rynowak commented May 30, 2019

Right you are. We have examples of this in the framework like InputText that are designed for inheritance.

@vertonghenb
Copy link
Contributor

vertonghenb commented Jun 3, 2019

Isn't there a guideline that we should consider using the "Composition over inheritance strategy" when using components? I think it's also used in React etc.

@SteveSandersonMS
Copy link
Member

We have to make a final decision about the visibility of component parameters. We've run into many issues trying to use non-public properties, and I don't think these are going to stop.

Overall, very much agreed. C# doesn't have a modifier that really matches the scenario perfectly.

We could recommend that users use public get/set properties and we will write an analyzer to tell you not to set component parameter properties.

Sounds like the best option if such an analyzer is feasible. I don't know the perf characteristics of analyzers in the IDE, but of course this means our analyzer has to inspect every property-set call in every method in every opened project while you're typing. If it scales to that then great.

We could still allow developers to have private set on their own components if they want (either way, the framework is using reflection to set, so it doesn't matter to us). We would have public set on framework components to avoid all the tooling/docs/etc issues. I don't feel strongly about this though.

We want whatever we choose to work with AOT, but we don't exactly know the requirements. It's generally assumed in AOT that unused non-public code is dead code and can be removed.

It's also generally assumed that unused public code is dead code that can be removed, given that AOT operates on applications not on libraries. So I don't expect changing the visibility is going to make anything better for us here.

@rynowak
Copy link
Member Author

rynowak commented Jun 5, 2019

Sounds like the best option if such an analyzer is feasible. I don't know the perf characteristics of analyzers in the IDE, but of course this means our analyzer has to inspect every property-set call in every method in every opened project while you're typing. If it scales to that then great.

This kind of thing actually works really well. You can to inspect every property when running a full build. When you're editing, you get to look at the class being worked on. The analyzer infrastructure just does this for you, it's pretty neat.

@rynowak
Copy link
Member Author

rynowak commented Jun 5, 2019

The only concern that I have here is that we have people different guidance than we have been - but I think it's worth changing what we're doing, and in that case we can't avoid telling people to change their code.

IMO we would want to roll this out in preview 7 along with an analyzer that tells you to conform to our guidlelines. Then in preview 8 (or later) we remove supports for non-public properties.

@vertonghenb
Copy link
Contributor

@rynowak I don't mind the breaking change, it's for the better and we're still in preview, so break it! 😄

@xclud
Copy link

xclud commented Jun 6, 2019

I vote for the breaking change.

@rynowak
Copy link
Member Author

rynowak commented Jun 7, 2019

@pranavkm @SteveSandersonMS - please give this a look over and make sure it all makes sense.

@pranavkm pranavkm removed the Needs: Design This issue requires design work before implementating. label Jun 7, 2019
@mkArtakMSFT mkArtakMSFT changed the title Make a decision about the visibility of component parameters Update visibility of component parameters Jun 7, 2019
NTaylorMullen added a commit that referenced this issue Jul 16, 2019
- Updated all `[Parameter]` references in .cs, .razor and .cshtml files to be `public`.

#8825
NTaylorMullen added a commit that referenced this issue Jul 17, 2019
- Updated all `[Parameter]` references in .cs, .razor and .cshtml files to be `public`.

#8825
NTaylorMullen added a commit that referenced this issue Jul 17, 2019
- The newly added analyzer warns users if they try to assign another components parameter.It does sanity checks to ensure that
  1. The property reference is indeed a component parameter
  2. The property reference is from a component
  3. The assignment is outside of the parameters type hierarchy. Aka, we don't warn users for setting a components parameter if it's in the same class.

- Updated existing `ComponentsFacts` to add additional utility methods to properly interact with components.
- Added tests to ensure we're analyzing all the goods properly.

#8825
NTaylorMullen added a commit that referenced this issue Jul 17, 2019
- Updated all `[Parameter]` references in .cs, .razor and .cshtml files to be `public`.

#8825
NTaylorMullen added a commit that referenced this issue Jul 17, 2019
- The newly added analyzer warns users if they try to assign another components parameter.It does sanity checks to ensure that
  1. The property reference is indeed a component parameter
  2. The property reference is from a component
  3. The assignment is outside of the parameters type hierarchy. Aka, we don't warn users for setting a components parameter if it's in the same class.

- Updated existing `ComponentsFacts` to add additional utility methods to properly interact with components.
- Added tests to ensure we're analyzing all the goods properly.

#8825
@NTaylorMullen NTaylorMullen added Done This issue has been fixed and removed Working labels Jul 18, 2019
@NTaylorMullen
Copy link
Contributor

All required items for this have been completed.

NTaylorMullen added a commit to dotnet/razor that referenced this issue Jul 30, 2019
- Prior to this a user could have private, protected or public parameters. We now require public and plan to update analyzers to enforce good usage of public component parameters.
- Removed private `ComponentTagHelperDescriptorProvider` workaround. meta data workaround since we no longer operate on private parameters.
- Updated existing tests to not have private parameter setters. I missed these in my last pass.
- Added two new tests to validate parameters which are private or have private setters are ignored.

dotnet/aspnetcore#8825
@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components Done This issue has been fixed
Projects
None yet
Development

No branches or pull requests

9 participants