-
Notifications
You must be signed in to change notification settings - Fork 805
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
Toggles for outlining and structured guidelines #4227
Toggles for outlining and structured guidelines #4227
Conversation
Code is cleaned up and there isn't a need to modify tests, as the unit tests for block structure just test that So, weird behavior: With outlining enabled...
As far as I can tell, there is nothing in I cannot toggle settings in debug mode - is this due to recent changes in how resources are generated @brettfo? I noticed that I'd need to I also cannot debug, period. No breakpoints can be hit. 😕 |
@olegtk or @CyrusNajmabadi - do you remember how this works? |
Outlining/BlockStructure are all the same thing nowadays. It's all done through the StructureTaggerProvider, BlockSpans and IBlockTags. As far as the language (i.e. F#) is concerned, it should just make BlockSpans with the appropriate bits on it saying what span it is for, and if it is collapsible or not. Then, these are converted to IBlockTags (by Roslyn), basically passing along the data without doing anything interesting with it (except making a parent/child relationship between IBlockTags). It's then up to the Editor (IIRC) to make the decisions about what to do with with all of this. |
I'm probably missing something. But i don't see anything in your code that actually hooks up your user facing options to actually changing these settings. Can you point out where you do it? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CyrusNajmabadi See below for explanations
@@ -42,6 +41,11 @@ type LanguageServicePerformanceOptions = | |||
{ EnableInMemoryCrossProjectReferences: bool | |||
ProjectCheckCacheSize: int } | |||
|
|||
[<CLIMutable>] | |||
type AdvancedOptions = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the backing data for the new page I added
type AdvancedOptions = | ||
{ IsBlockStructureEnabled: bool | ||
IsOutliningEnabled: bool } | ||
|
||
[<Export(typeof<ISettings>)>] | ||
type internal Settings [<ImportingConstructor>](store: SettingsStore) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where you access the data in our settings store, with default values listed below
|
||
[<Guid(Guids.advancedSettingsPageIdSring)>] | ||
type internal AdvancedSettingsOptionPage() = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the wireup
@@ -148,6 +148,8 @@ type internal FSharpBlockStructureService(checker: FSharpChecker, projectInfoMan | |||
|
|||
override __.GetBlockStructureAsync(document, cancellationToken) : Task<BlockStructure> = | |||
asyncMaybe { | |||
do! Option.guard Settings.Advanced.IsBlockStructureEnabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code basically means "only proceed to get the info for block structure if that setting has a value of true
"
And w.r.t this:
That's what we do: https://github.com/Microsoft/visualfsharp/blob/master/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs#L136 |
Basically, what I'm looking for here is the ability to make the guidelines disappear but keep the collapsing nodes, like you can do in C# (just with one less degree of configurability), from the F# settings |
Hey Phillip! Is there a reason you're not using these built in Roslyn options for outlining/structure-guides?
If you use these then making any changes will automatically cause the file to refresh if you change them. Also, it will give you parity with how VB and C# expose these options: |
Note: if you use these options, you'll still have to have the following code somewhere (unless Roslyn moved it to a core location): |
@CyrusNajmabadi IIRC there was a problem that we coulnd't easily provide UI for built-in Roslyn options. All of the persistence infrastructure was internal. |
@majocha is correct; all of the options defined in Roslyn are unavailable to us (as are the providers). That would all have to move for us to take advantage of them. I see your PR on Roslyn would allow us to basically add our own duplicate options and then get the same functionality. Would we have to change anything w.r.t how we construct a |
Sorry, can you explain this to me? It's unclear to me why the options would be unavailable. They're at the Feature layer, and don't seem to have any C# or VB specific code AFAICT.
I don't quite understand this. To persist, all you'd have to do is: workspace.Options = workspace.Options.WithChangedOption(TheOption, theNewValue); |
If you used our options, you wouldn't have to contruct blockspans differently. If you didn't use our options, you'd have to duplicate that logic, setting NonStructural and IsCollapsible in a similar manner to how my code does it. |
@CyrusNajmabadi I don't quite grasp how options are done in Roslyn. To do it "right" and get access to everything we need from Roslyn, would we need to export a provider like this? If so, we can't do that - |
Understood. They can be a bit difficult to understand. And we haven't made them fully functional for use outside of C#/VB. That said, they are still very usable for some purposes, including this one (i think).
Nope. That's only if you're defining new options. I'm not asking you to do that. Instead, i'm just saying: Use the options we've already defined in Roslyn for this feature. i.e. the 6 options i listed above. You can expose these options in your UI however you want (for example, having 6 fine-grained checkboxes, or maybe just 2 coarse grained checkboxes). You can populate your checkboxes by reading these options. When the user interacts with your UI, just set these options on the workspace accordingly. To read the value of the option all you need to do is: var optionVal = workspace.Options.GetOption(BlockStructureOptions.TheOption, FSharpLanguageName); To set the value, all you need to do is: workspace.Options = workspace.Options.WithChangedOption(BlockStructureOptions.TheOption, FSharpLanguageName, newVal); Once you do that (and #24362 goes in), you can just make BlockSpans simply for all your language constructs. Roslyn will then check the options against those BlockSpans and will do the right thing vis-as-vis collapsing and the structure type. Roslyn should also take care of persisting these options for you (including working with roaming profiles). |
Ok. So this should def work (once my PR goes in). Here's an example of where you're interacting with Roslyn options already today: And: As you can see, you can read and change existing Roslyn options without any problems :) |
BTW: i would def open an issue (if it isn't already there) for options to be fully usable by all roslyn-languages. They're great. An easy way to represent user configuration, abstracting away from pesky things like "is the option in VS, the registry, .editorconfig, or somewhere else?" They're tied tightly into the workspace model, so they're easy to check from any service that has access to a They're also normally very easy to create and export. ideally they could be how you do all your options yourself. |
@cartermp I forgot and @CyrusNajmabadi is absolutely right. It were the custom defined options that were the problem. @CyrusNajmabadi that would be so awesome to have. |
@CyrusNajmabadi Thanks! That makes sense. I'll create a tracking issue here to address Structure options once your PR is on and remove the code I wrote here to set the I'll also open an issue on Roslyn (if it's not already there) for opening up those APIs. There are a few things we do that are F#-specific. Say we were to use this Roslyn mechanism, and they don't have a corresponding |
Depends on the option. If it's something you want the core rolsyn code to do something differently for (i.e. you want to customize core completion behavior), then you'd have to put inside Roslyn. But if it's about an option that only you F# wants to set and only F# code will read, then you can just define and export that option from your own dlls. If you have questions, it might be helpful to have specific examples you're thinking about. |
For example:
Does that make sense? |
Makes sense! |
@KevinRansom rebased and tested in VS again; still works so this is good to merge for now. @CyrusNajmabadi Once this is merged, I'll file a tracking issue to replace code here with what you've opened up here. Since 15.7 is starting to get close, it's unclear if we could do this with your work in time for the release, hence the strategy to merge now. |
Arg FCS build failed: |
@dotnet-bot test Ubuntu16.04 Release_fcs Build |
* Toggles for outlining and structured guidelines * Cleanup * Don't remove outlining alongside block structure lines and better names * fix up rebase;
I think this is just how we handle things in our language service, but you will need to close and re-open documents to see the changes take effect.
Addresses #3681.
There's a global option for structured guidelines as well, and it's controlled at the workspace level. I'm a bit on the fence about having a toggle for them in the F# settings, but I'd think people would look for them there first, then get confused when they're unable to find them. This also allows you to turn it off for F# code, but keep it on for C# code, so I don't think it's horrible to have it here.