-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Treat decompiled sources separately from metadata sources #27940
Treat decompiled sources separately from metadata sources #27940
Conversation
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.
I believe we're now losing Mutexes which might cause files to be deleted under the process which might end badly. Everything else looks reasonable than that bit though.
{ | ||
var guidString = Guid.NewGuid().ToString("N"); | ||
_rootTemporaryPathWithGuid = Path.Combine(_rootTemporaryPath, guidString); | ||
rootTemporaryPathWithGuid = Path.Combine(_rootTemporaryPath, guidString); | ||
_mutex = new Mutex(initiallyOwned: true, name: CreateMutexName(guidString)); |
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 now may be overwriting a previous Mutex created by our process; I'm guessing if the Mutex GCs then another process might clean up things under us? I believe the right fix here is to preserve a single folder, and just maybe add another layer of folders inside of it, i.e. MetadataAsSource-{guid}\Decompiled vs. MetadataAsSource-{guid}\Metadata. Or, hold onto two mutexes, but I think going back to a single directory is easier, and also scales if/when we create a third type of something to go in 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.
Two mutexes is easy with the current pattern. Yay ref locals!
this.Workspace = sourceProject.Solution.Workspace; | ||
this.LanguageName = sourceProject.Language; | ||
if (allowDecompilation && sourceProject.Language != LanguageNames.CSharp) |
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.
If you just move this after this.LanguageName =, then I think you can reduce this all back to _parseOptions = Workspace.Services.GetLanguageServices(this.LanguageName).GetRequriedService().ParseOptions;. Basically, you've already figured out once that if it's decompiled it's always C#; no reason to do it twice.
dcaa384
to
f1ed8a7
Compare
@jasonmalinowski Updated based on review feedback. Planning to rebase this back to 2 commits once the review completes. |
{ | ||
if (_rootTemporaryPathWithGuid == null) | ||
ref string rootTemporaryPathWithGuid = ref (allowDecompilation ? ref _rootDecompiledTemporaryPathWithGuid : ref _rootMetadataTemporaryPathWithGuid); | ||
ref Mutex mutex = ref (allowDecompilation ? ref _decompiledMutex : ref _metadataMutex); |
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.
i personally hate this :) but i guess i will have to grow to live with these sorts of patterns :)
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 admire your desire to play with new things, but if we just went back to a single mutex/folder and generated the paths differently, it's just two lines with no fancy tricks whatsoever.
"If you write your code as cleverly as possible..."
else | ||
{ | ||
_parseOptions = Workspace.Services.GetLanguageServices(LanguageName).GetRequiredService<ISyntaxTreeFactoryService>().GetDefaultParseOptionsWithLatestLanguageVersion(); | ||
} |
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.
nit: consider ?:
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.
Opted against it here. The two branches seem different enough that I like to keep it obvious.
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.
Why still having the branches at all? When would the source project's parse options be different than the default parse options for the language in an observable way?
I'm not saying there's not a reason for this....I just can't tell what it is. I can't read your mind (not sure if good thing or bad thing?) but do we need a comment 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.
Would really like us to stop doing the fancy ref tricks when simpler code would do.
else | ||
{ | ||
_parseOptions = Workspace.Services.GetLanguageServices(LanguageName).GetRequiredService<ISyntaxTreeFactoryService>().GetDefaultParseOptionsWithLatestLanguageVersion(); | ||
} |
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.
Why still having the branches at all? When would the source project's parse options be different than the default parse options for the language in an observable way?
I'm not saying there's not a reason for this....I just can't tell what it is. I can't read your mind (not sure if good thing or bad thing?) but do we need a comment here?
@jasonmalinowski main feedback should be addressed now. |
this.References = sourceProject.MetadataReferences.ToImmutableArray(); | ||
this.AssemblyIdentity = topLevelNamedType.ContainingAssembly.Identity; | ||
|
||
var extension = sourceProject.Language == LanguageNames.CSharp ? ".cs" : ".vb"; | ||
var extension = LanguageName == LanguageNames.CSharp ? ".cs" : ".vb"; | ||
|
||
var directoryName = Guid.NewGuid().ToString("N"); | ||
this.TemporaryFilePath = Path.Combine(rootPath, directoryName, topLevelNamedType.Name + extension); |
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.
Doesn't this still need to have some differentiation for the decompiled vs. not?
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.
It does. Two levels of directory names are used when the keys don't match; this one will still get one unique GUID in the path where before it was getting two.
@jinujoseph I see this is assigned to me now, who is doing the work to take this for QB approval? |
approved to merge for 15.8.Preview5 (once green) |
Fixes #25244
Fixes #25255
Fixes #25731
Fixes #26329
Fixes #27187
Ask Mode template not completed
Customer scenario
What does the customer do to get into this situation, and why do we think this
is common enough to address for this release. (Granted, sometimes this will be
obvious "Open project, VS crashes" but in general, I need to understand how
common a scenario is)
Bugs this fixes
(either VSO or GitHub links)
Workarounds, if any
Also, why we think they are insufficient for RC vs. RC2, RC3, or RTW
Risk
This is generally a measure our how central the affected code is to adjacent
scenarios and thus how likely your fix is to destabilize a broader area of code
Performance impact
(with a brief justification for that assessment (e.g. "Low perf impact because no extra allocations/no complexity changes" vs. "Low")
Is this a regression from a previous update?
Root cause analysis
How did we miss it? What tests are we adding to guard against it in the future?
How was the bug found?
(E.g. customer reported it vs. ad hoc testing)
Test documentation updated?
If this is a new non-compiler feature or a significant improvement to an existing feature, update https://github.com/dotnet/roslyn/wiki/Manual-Testing once you know which release it is targeting.