-
Notifications
You must be signed in to change notification settings - Fork 0
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
Rebased to nn-swift-4.1 #2
Conversation
``` opt_in_rules: - modifiers_order modifiers_order: before_acl: ["override"] after_acl: ["class"] ```
> warning: initializer 'init(configuration:)' nearly matches defaulted requirement 'init(configuration:)' of protocol 'Rule' > note: candidate has non-matching type '(configuration: SeverityLevelsConfiguration)' > note: move 'init(configuration:)' to an extension to silence this warning > SwiftLintFramework.Rule:5:12: note: requirement 'init(configuration:)' declared here > public init(configuration: Any) throws
``` opt_in_rules: - modifiers_order modifiers_order: before_acl: ["override"] after_acl: ["class"] ```
Yeah, lets rebase. If the rebase goes well, go ahead a force push this to my branch. I made a back up on github. Then we can see the changes on the swiftlints PR. |
We can also point the PR on swift lint to the 4.1 PR |
2bd6923
to
d02a650
Compare
I have rebased + fixed tests. Force pushed to origin. Could you retarget the PR on SwiftLint? |
retargeted |
My basic idea on how to solve this rule would be something like the following using this example:
Will produce this:
We have: @objc -> "key.attribute": "source.decl.attribute.objc"
public -> "key.accessibility": "source.lang.swift.accessibility.public"
override -> "key.attribute": "source.decl.attribute.override"
private(set) -> "key.setter_accessibility": "source.lang.swift.accessibility.private"
weak -> "key.attribute": "source.decl.attribute.weak"
var -> "key.kind": "source.lang.swift.decl.var.global" Using the info above and switching to In
If i understand you approach correctly, you are doing something similar. What i can not understand, what does the
|
for token in tokens { | ||
// static & class are not builtin attibutes so we check every keyword for static || class | ||
if token.type == keyword, | ||
token.length == "static".bridge().length || token.length == "class".bridge().length, |
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 part here is fragile because “static” is hard coded.
case "static": | ||
tokenSection.append(token) | ||
// filter out `class` when used as a declaration | ||
case "class" : |
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.
hard coded here too which makes it fragile.
] | ||
) | ||
|
||
private func extractContinuousSections(from tokens: [SyntaxToken], in file: File) -> [[SyntaxToken]] { |
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 I can remember right this will give you have arrays where builtins, keywords happen. As in weak override
perhaps is one continuous sub array of same type of keywords.
private func extractContinuousSections(from tokens: [SyntaxToken], in file: File) -> [[SyntaxToken]] { | ||
var builtInTokenSections = [[SyntaxToken]]() | ||
var tokenSection = [SyntaxToken]() | ||
let builtIn = "source.lang.swift.syntaxtype.attribute.builtin" |
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 think there are facilities to get this information from source kit. Pretty much I think everything hard coded like this needs to go.
return builtInTokenSections.filter({ $0.count > 1 }) | ||
} | ||
|
||
private func isAccessControlLabel(_ input: String) -> Bool { |
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.
another part that may be fragile. I could not find the facilities to get this information from the source kit.
sounds good. I am not sure about the groupings. Naming is hard. I opted for the config to pivot around ACL (including setters) so you would just need to specify which “keywords” should go before or after ACL. If you only specify before_acl then everything else is assumed it goes after the ACL. Not sure if that is the best way though. Perhaps if you want to tackle getting it to depend on the new 4.1 functionality first? Then we can ask the community upstream what would be best. |
I see your point with the grouping, yeah, it could be trouble. Lets ask then the community, what do they think, or how to approach that part. Looking at the PRs from Marcelo, ACL is added to the
🎉I get this structure with 4.1 🎉 [
"key.attributes": [
[
"key.attribute": "source.decl.attribute.weak",
"key.offset": 37,
"key.length": 4
],
[
"key.attribute": "source.decl.attribute.setter_access.private",
"key.offset": 24,
"key.length": 12
],
["key.attribute": "source.decl.attribute.public",
"key.offset": 17,
"key.length": 6
],
[
"key.attribute": "source.decl.attribute.override",
"key.offset": 8,
"key.length": 8],
[
"key.attribute": "source.decl.attribute.objc",
"key.offset": 0,
"key.length": 5
]
],
"key.nameoffset": 46,
"key.accessibility": "source.lang.swift.accessibility.public",
"key.length": 13,
"key.typename": "Bar?",
"key.name": "foo",
"key.kind": "source.lang.swift.decl.var.global",
"key.offset": 42,
"key.namelength": 3,
"key.setter_accessibility": "source.lang.swift.accessibility.private"
] This means, we can drop the idea of having to search for the |
…d/SwiftLint into dm/attribute_and_modifier_order
Added an initial version of the modified modifiers rule. I am seeing the need to introduce some enum for the declaration kinds ( Somehow working with the groups seems very natural, but i can stick with Let me know what do you think about the approach. |
The implementation detail can use groups. I think this is great. The part that I am not sure is exposing that as a configuration? Perhaps you are able to expose them with some sort of different naming? The exposed “api” is what I am thinking about. |
case `override` = "source.decl.attribute.override" | ||
case `weak` = "source.decl.attribute.weak" | ||
case `testable` = "source.decl.attribute.testable" | ||
case privateSetter = "source.decl.attribute.setter_access.private" |
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 there more options like public and internal open etc
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 must be, but yesterday i was not able to grep the values from SwiftDeclarationAttribute
. I only have the 9.3 beta, and i can not install it as my default, i still need 9.2 for work. And as far i have seen SourceKitService
framework is only available with your default Xcode. I will try to figure something out...
import Foundation | ||
import SourceKittenFramework | ||
|
||
// TODO: Get somehow `SwiftDeclarationAttribute` for Swift 4.1 |
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.
class and static? class can be an attribute or a keyword
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.
added TODO
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 issue is painful. I will push an update in the following days, but static
and class
is not recognised as attributes by SourceKitten
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 You file a radar?
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 have added a workaround in my latest commit, but its an ugly hack. Please let me know what do you think, or we should wait until a further release.
I will open a radar meanwhile.
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.
Actually, now that i am just about to open the radar, i can already see, add them as source.lang.swift.decl.var.static
or source.lang.swift.decl.function.method.class
. They might just answer it is not a declaration attribute, but a declaration. Maybe i could work out something based on that, rather than this regex search i am doing now. However, somehow i should still fake them i am affraid..
For example:
class Foo {
static public let bar = 3
}
will give
{
"key.diagnostic_stage": "source.diagnostic.stage.swift.parse",
"key.substructure": [
{
"key.bodylength": 31,
"key.nameoffset": 6,
"key.accessibility": "source.lang.swift.accessibility.internal",
"key.length": 43,
"key.substructure": [
{
"key.nameoffset": 32,
"key.accessibility": "source.lang.swift.accessibility.public",
"key.length": 25,
"key.name": "bar",
"key.kind": "source.lang.swift.decl.var.static",
"key.namelength": 3,
"key.offset": 14,
"key.attributes": [
{
"key.attribute": "source.decl.attribute.public",
"key.offset": 21,
"key.length": 6}]
}
],
"key.runtime_name": "_TtC8__main__3Foo",
"key.name": "Foo",
"key.kind": "source.lang.swift.decl.class",
"key.namelength": 3,
"key.offset": 0,
"key.bodyoffset": 11
}
],
"key.offset": 0,
"key.length": 43
}
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.
Meanwhile, i decided to raise the issue, lets see what they say.
https://bugs.swift.org/browse/SR-7252
case `required` = "source.decl.attribute.required" | ||
case `optional` = "source.decl.attribute.optional" | ||
case noreturn = "source.decl.attribute.noreturn" | ||
case `NSManaged` = "source.decl.attribute.NSManaged" |
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.
These start with @ should we make the distinction?
83f292d
to
1b09fd7
Compare
case `iboutlet` = "source.decl.attribute.iboutlet" | ||
case `ibdesignable` = "source.decl.attribute.ibdesignable" | ||
case `ibinspectable` = "source.decl.attribute.ibinspectable" | ||
case `objc` = "source.decl.attribute.objc" // TODO: This always has to be first. How to handle this case? |
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.
We can relay on the compiler to make sure that’s happens. We don’t have to worry about it. If somebody gives the wrong configuration we are not able to check it.
] | ||
) | ||
|
||
private let observedDeclarationKinds: [SwiftDeclarationKind] = [.class, |
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 do we need to specify this?
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 was thinking this might speeds up things, since we skip a few cases. It might makes no diff at all.
Is there a way to know from source kit if an attribute is a modifier? As in it starts with @? Then all you have worry about is modifiers, ACL, other. |
Maybe we could filter out all these |
@masters3d I have pushed a much simpler solution, no fake cases, using I think i am getting close to the final solution, i will start expending the possible test cases. If you would have time for a review, maybe suggest a few test cases, it would be great! |
.nonmutating] | ||
case .override: | ||
return [.override] | ||
case .memoryReference: |
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.
owned
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.
changed.
.public, | ||
.open] | ||
case .setterACL: | ||
return [.privateSetter, |
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 open setter a thing?
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.
fileprivate?
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.
added these cases too.
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 think this would be hard to keep in sync with new "keywords" being added. I believe there is already some code to deal with ACL and attributes that start with @ .
There is Also, The attributes of the |
I dont have more ideas on how to do the spitting of the groups other than what I already said. The compiler already enforces attributes that start with @ to go at the beginning of the declaration. I think swift lint even has a rule to make sure these attributes go on a separate line. |
Declaration attribute has been merged to SourceKitten, and increased the Swift version to 4.1 🎉. Things starting to get together for this PR. I will be keeping the groups approach and extending it with further tests, and try to see how to utilise on the |
I retargeted the other branch to go back to master. Let me know if you need anything from me. |
89ad548
to
0e1c782
Compare
0e1c782
to
664ce7b
Compare
# Conflicts: # Cartfile.private # Carthage/Checkouts/SourceKitten # Rules.md # Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift # SwiftLint.xcodeproj/project.pbxproj
so it was merged. Thanks for the cooperation! |
Thank you for pushing this forward. |
As we discussed, i have rebased to
nn-swift-4.1
.I would have a couple of questions regarding your implementation. I thought this PR could be a good place to discuss it.
First question: Shall i rather rebase you original branch
attibute_and_modifier_order
tonn-swift-4.1
, than open this PR? 😜