-
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
Handle more stack frames #58769
Handle more stack frames #58769
Conversation
} | ||
|
||
[Fact] | ||
public Task TestSymbolFound_ExceptionLine_NestedLocalFunctions() |
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 test currently will fail. I haven't figured out the best way to go from the symbols for LocalFunctions to the generated slots.
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.
what's the issue 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.
oh, is it that the outer and inner local function names are teh same? yeah, we may not be able to support hat. do you have tests where the names are different?
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'll add a test with different names. The issue will always be if there is something with the same name in the containing member. We could try to reverse engineer it but likely it would be wrong.
I wonder if just going to the containing method in those cases would be a good compromise.
@@ -93,7 +93,7 @@ public string ToFullString() | |||
/// <param name="trailing">If false, trailing trivia will not be added</param> | |||
public void WriteTo(StringBuilder sb, bool leading, bool trailing) | |||
{ | |||
if (leading) | |||
if (leading && !LeadingTrivia.IsDefault) |
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.
Without this check, optional children would throw on ToFullString
because everything is the default for an EmbeddedSyntaxToken
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.
interesting... LeadingTrivia should probably be non-default... but that can be a change in another PR.
Compilation compilation, | ||
CancellationToken cancellationToken) | ||
{ | ||
if (typeSymbol is null || compilation.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.
❓ is it worth avoiding enumeration of members gated on the compilation language 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.
yes. this check seems totally reasonable to me :)
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.
oh... this is a generic helper now? hrmm... we can always keep this here, and remove later if a problem. but add comment for now that VB doesn't have local functions.
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.
alternatively, move this to ISemanticFactsService. then teh VB impl can no-op with an appropriate comment.
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 like this. I forgot about ISemanticFactsService.
src/EditorFeatures/Core/StackTraceExplorer/AbstractStackTraceSymbolResolver.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/StackTraceExplorer/StackFrameLocalMethodResolver.cs
Outdated
Show resolved
Hide resolved
|
||
var candidateFunctions = localFunctions | ||
.Where(m => m.ContainingSymbol.Name == containingMethodName) | ||
.ToImmutableArray(); |
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: this is a lot of work trying to get all the local functions, tehn filtering down to those that match the containing symbol name. consider inverting. get the containing symbol, and then look for local functions within it.
consider doc'ing how this works for nested local functions as well.
src/EditorFeatures/Core/StackTraceExplorer/StackFrameMethodSymbolResolver.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/StackTraceExplorer/StackFramePropertyMethodResolver.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/StackTraceExplorer/StackFramePropertyMethodResolver.cs
Outdated
Show resolved
Hide resolved
{ | ||
if (parameters.Length != stackFrameParameters.Parameters.Length) | ||
var compilation = await project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); | ||
var type = compilation.GetTypeByMetadataName(fullyQualifiedTypeName); |
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.
var type = compilation.GetTypeByMetadataName(fullyQualifiedTypeName); | |
var type = compilation.GetBestTypeByMetadataName(fullyQualifiedTypeName); |
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 would be great if we could avoid getting the compilation if the final part of the type-name is not found in the index for this project. getting a compilation is expensive.
@@ -86,6 +86,13 @@ private static void FuzzyTest(string input) | |||
|
|||
private static void VerifyCharacterSpans(string originalText, StackFrameTree tree) | |||
{ | |||
// Use the ToFullString to verify |
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 really tell me anything.
public Result<StackFrameToken> TryScanRequiredGeneratedNameSeparator() | ||
{ | ||
var start = Position; | ||
if (IsCharacter(CurrentChar)) |
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.
so it's ok that it's not necessary g
?
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.
In this case I wanted the lexer to know that generated name separators are just {letter}__
, and the parser determines whether the letter accounts for something that is supported.
src/Features/Core/Portable/EmbeddedLanguages/StackFrame/StackFrameLexer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/EmbeddedLanguages/StackFrame/StackFrameLexer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/EmbeddedLanguages/StackFrame/StackFrameNodeDefinitions.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/EmbeddedLanguages/StackFrame/StackFrameNodeDefinitions.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/EmbeddedLanguages/StackFrame/StackFrameNodeDefinitions.cs
Outdated
Show resolved
Hide resolved
/// ^---^----------- "|0_0" is suffix information such as slot | ||
/// ^--------^- "(String s)" identifiers the method paramters | ||
/// </code> | ||
/// </summary> |
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.
awesome!
var semanticModel = compilation.GetSemanticModel(syntaxReference.SyntaxTree); | ||
var node = syntaxReference.GetSyntax(cancellationToken); | ||
|
||
foreach (var localFunction in node.DescendantNodes().Where(syntaxFacts.IsLocalFunctionStatement)) |
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 feel ike this might double count local functions found inside accessors. because we'll hit the prop and the accessor.
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.
tentative signoff. there are some things worth looking into.
Co-authored-by: CyrusNajmabadi <[email protected]>
This adds support for local functions and generated main in the parser.
Symbol resolution now is broken up into resolvers and has special logic for local functions, getters/setters, and ordinary functions.