-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Cache the unescaped form of globalconfig section names #59301
Cache the unescaped form of globalconfig section names #59301
Conversation
src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs
Show resolved
Hide resolved
public GlobalAnalyzerConfig(AnalyzerConfig.Section globalSection, ImmutableArray<AnalyzerConfig.Section> namedSections) | ||
{ | ||
GlobalSection = globalSection; | ||
NamedSections = namedSections; | ||
|
||
var unescapedSectionNames = ArrayBuilder<string?>.GetInstance(); |
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.
Do we actually use the unescaped section name anywhere? Consider just updating the namedSections
in place with the unescaped name.
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.
Hmm thinking about it, maybe we can just do the escaping as we build the global config. I don't think the unescaped name is ever used anywhere, so we can probably just do it once upfront instead.
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.
@chsienki I was somewhat worried whether that might introduce new bugs since it means some section names are escaped and some aren't and it's more or less up to you to know what's what. Now that said, there's other code here:
roslyn/src/Compilers/Core/Portable/CommandLine/AnalyzerConfigSet.cs
Lines 572 to 578 in cc888b2
if (!_values.TryGetValue(section.Name, out var sectionDict)) | |
{ | |
sectionDict = ImmutableDictionary.CreateBuilder<string, (string, string, int)>(Section.PropertiesKeyComparer); | |
_values.Add(section.Name, sectionDict); | |
} | |
_duplicates.TryGetValue(section.Name, out var duplicateDict); |
That's using the escaped string when trying to merge sections. Looking at our lexer \ is used to escape and character, even if it otherwise doesn't require escaping, so it would mean Foo and F\oo will convert to the same string, but we won't merge the properties because we're dealing with escaped and not unescaped strings.
I can't tell if that's a bug in our lexer that we even allow such a construct (the .editorconfig specification says "Special characters can be escaped with a backslash so they won't be interpreted as wildcard patterns.", which isn't "all characters can be escaped..."), but in general this is arguing for doing the escaping earlier, I think.
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.
@jasonmalinowski Yeah, the specification is annoyingly vague on that front. I'm not sure where I land on which way we should interpret it, but think the current behavior is probably fine. If you want a backslash you can escape it, so its at least consistent and keeps the lexer simpler.
That being said global configs are already not editor configs, so I think as long as we decide on the explicit set of rules there (and document them) we're probably ok.
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.
@chsienki Yeah, I'm OK keeping the lexer behavior. Does that then mean we have a bug for the Foo
and Fo\o
example? Because if we're calling that a bug then that absolutely motivates me to redo this PR to do the unescape process earlier and just update the section name directly since the more look the more I'm finding problems here otherwise.
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.
Yeah, I think doing it earlier is the right approach here.
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.
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.
Alright, time to rewrite this PR then!
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.
Ah, my bad we don't have the bug. Once we're actually looping through global configs we don't break on the first one but keep searching regardless. Still going to simplify this though that way.
src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs
Outdated
Show resolved
Hide resolved
We were unescaping section names each time we were trying to find the applicable config rules for a file; if we were computing options for each file in a compilation this resulted in a huge amount of duplicate work. Fixes AB#1472298
a82ada0
to
761400f
Compare
Fundamentally different approach taken, so resetting approval.
We were unescaping section names each time we were trying to find the applicable config rules for a file; if we were computing options for each file in a compilation this resulted in a huge amount of duplicate work.
Fixes AB#1472298