Add support for parameter names #136
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -56,17 +56,21 @@ fileprivate final class FunctionSignatureVisitor: SyntaxVisitor { | |||||||||||||||||||
let type = node.type?.typeDescription | ||||||||||||||||||||
else { return .skipChildren } | ||||||||||||||||||||
|
||||||||||||||||||||
appendArgument(argumentLabelName: argumentLabelName, type: type) | ||||||||||||||||||||
let parameterName = node.secondName?.text | ||||||||||||||||||||
|
||||||||||||||||||||
appendArgument(argumentLabelName: argumentLabelName, parameterName: parameterName, type: type) | ||||||||||||||||||||
return .skipChildren | ||||||||||||||||||||
} | ||||||||||||||||||||
override func visit(_ node: ReturnClauseSyntax) -> SyntaxVisitorContinueKind { | ||||||||||||||||||||
returnType = node.returnType.typeDescription | ||||||||||||||||||||
return .skipChildren | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
fileprivate func appendArgument(argumentLabelName: String, type: TypeDescription) { | ||||||||||||||||||||
fileprivate func appendArgument(argumentLabelName: String, parameterName: String?, type: TypeDescription) { | ||||||||||||||||||||
var arguments = self.arguments ?? [] | ||||||||||||||||||||
arguments.append(.init(argumentLabelName: argumentLabelName, type: type)) | ||||||||||||||||||||
// By default, parameters use their parameter name as their argument label | ||||||||||||||||||||
let param = parameterName ?? argumentLabelName | ||||||||||||||||||||
arguments.append(.init(argumentLabelName: argumentLabelName, parameterName: param, type: type)) | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love the name
Suggested change
As an aside, the comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do think the comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's helpful context! Within that context, the comment makes sense. Putting that comment on top of the assignment of Maybe what's confusing me more is the fact that we're setting the This code would create identical output for the following scanned methods:
Ideally the output of our scans could be used to re-create the original code (or at least the method signatures on the scanned types). This implementation doesn't let us do that with confidence There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I thought about doing that but wanted to take it out into its own line so I could add the code comment above. Since this is in the implementation and I think param pretty clearly refers to "parameter" I think this is fine? But lemme know if you disagree! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the meaning of the I would recommend updating the comment though, and possibly updating the API here to ensure that the output types would be different for the following two methods:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't see a problem with scanning those 2 equally since they are, in fact, equal. I think we've decided to be opinionated here in terms of style (e.g. using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. they're equal from a "how would you call the code" POV, but not from a "how would you generate a protocol for this method" POV. Though I just tried it out and the following code does compile:
as does
So I withdraw the objection, since this API is not limiting a consumer's ability to generate compiling code. |
||||||||||||||||||||
self.arguments = arguments | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -87,6 +91,7 @@ public struct FunctionDeclarationInfo: Codable, Hashable { | |||||||||||||||||||
|
||||||||||||||||||||
public struct ArgumentInfo: Codable, Hashable { | ||||||||||||||||||||
public let argumentLabelName: String | ||||||||||||||||||||
public let parameterName: String | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Per my realization at the end of #136 (comment) I think making the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just pushed a new commit that hopefully will help clarify a bit f4c285d |
||||||||||||||||||||
public let type: TypeDescription | ||||||||||||||||||||
} | ||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -175,9 +175,12 @@ final class FunctionDeclarationVisitorSpec: QuickSpec { | |
try? self.sut.walkContent(content) | ||
} | ||
|
||
it("finds the parameter label") { | ||
it("finds the argument label") { | ||
expect(self.sut.functionDeclarations.first?.arguments?.first?.argumentLabelName) == "_" | ||
} | ||
it("finds the parameter name") { | ||
expect(self.sut.functionDeclarations.first?.arguments?.first?.parameterName) == "string" | ||
} | ||
it("calculates the selectorName") { | ||
expect(self.sut.functionDeclarations.first?.selectorName) == "print(_:)" | ||
} | ||
|
@@ -200,12 +203,15 @@ final class FunctionDeclarationVisitorSpec: QuickSpec { | |
it("calculates the selectorName") { | ||
expect(self.sut.functionDeclarations.first?.selectorName) == "append(argumentLabelName:)" | ||
} | ||
it("finds the parameter name") { | ||
expect(self.sut.functionDeclarations.first?.arguments?.first?.parameterName) == "parameterName" | ||
} | ||
} | ||
|
||
context("function with multiple parameters") { | ||
beforeEach { | ||
let content = """ | ||
func append(argumentLabelName parameterName: String, type: TypeDescription) { | ||
func append(argumentLabelName parameterName: String, type secondParameterName: TypeDescription) { | ||
// ... | ||
} | ||
""" | ||
|
@@ -216,10 +222,14 @@ final class FunctionDeclarationVisitorSpec: QuickSpec { | |
it("finds the correct number of parameters") { | ||
expect(self.sut.functionDeclarations.first?.arguments?.count) == 2 | ||
} | ||
it("finds the parameter labels") { | ||
it("finds the argument labels") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a test somewhere for a case where there is no argument label and only a parameter name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that's possible, the argument label is always present IIUC?
I think you're referring to having the argument label be the same as the parameter name, which I think we already have tests for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just pushed a new commit that hopefully will help clarify a bit f4c285d |
||
expect(self.sut.functionDeclarations.first?.arguments?.first?.argumentLabelName) == "argumentLabelName" | ||
expect(self.sut.functionDeclarations.first?.arguments?.last?.argumentLabelName) == "type" | ||
} | ||
it("finds the parameter names") { | ||
expect(self.sut.functionDeclarations.first?.arguments?.first?.parameterName) == "parameterName" | ||
expect(self.sut.functionDeclarations.first?.arguments?.last?.parameterName) == "secondParameterName" | ||
} | ||
it("calculates the selectorName") { | ||
expect(self.sut.functionDeclarations.first?.selectorName) == "append(argumentLabelName:type:)" | ||
} | ||
|
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.
Technically speaking if a function argument only has a parameter name and no argument label then the single name is the parameter name. The way we've written this function though the single name would be the argument label.
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.
Can we rework this function so that the argument label name is optional and the parameter name is required?
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 yeah, I think I got this the other way around. I disagree with making these optional though, that seems incorrect since we'd never really have a nil argument label.
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 went back and re-read this.
Based on:
I'm again confused.
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 I don't think
Is correct?
How I understand this is that:
So I think making either of these nil is just incorrect, since they can never technically be nil.
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.
Ok, this is what I ended up with f4c285d