mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
With the binding of configurations to their associated rule types "unknown configuration" errors can be made more specific mentioning also the rule's identifier in the printed message.
76 lines
2.6 KiB
Swift
76 lines
2.6 KiB
Swift
import SwiftIDEUtils
|
|
|
|
struct OrphanedDocCommentRule: SourceKitFreeRule, ConfigurationProviderRule {
|
|
var configuration = SeverityConfiguration<Self>(.warning)
|
|
|
|
static let description = RuleDescription(
|
|
identifier: "orphaned_doc_comment",
|
|
name: "Orphaned Doc Comment",
|
|
description: "A doc comment should be attached to a declaration",
|
|
kind: .lint,
|
|
nonTriggeringExamples: [
|
|
Example("""
|
|
/// My great property
|
|
var myGreatProperty: String!
|
|
"""),
|
|
Example("""
|
|
//////////////////////////////////////
|
|
//
|
|
// Copyright header.
|
|
//
|
|
//////////////////////////////////////
|
|
"""),
|
|
Example("""
|
|
/// Look here for more info: https://github.com.
|
|
var myGreatProperty: String!
|
|
"""),
|
|
Example("""
|
|
/// Look here for more info:
|
|
/// https://github.com.
|
|
var myGreatProperty: String!
|
|
""")
|
|
],
|
|
triggeringExamples: [
|
|
Example("""
|
|
↓/// My great property
|
|
// Not a doc string
|
|
var myGreatProperty: String!
|
|
"""),
|
|
Example("""
|
|
↓/// Look here for more info: https://github.com.
|
|
// Not a doc string
|
|
var myGreatProperty: String!
|
|
""")
|
|
]
|
|
)
|
|
|
|
func validate(file: SwiftLintFile) -> [StyleViolation] {
|
|
file.syntaxClassifications
|
|
.filter { $0.kind != .none }
|
|
.pairs()
|
|
.compactMap { first, second in
|
|
let firstByteRange = first.range.toSourceKittenByteRange()
|
|
guard
|
|
let second,
|
|
first.kind == .docLineComment || first.kind == .docBlockComment,
|
|
second.kind == .lineComment || second.kind == .blockComment,
|
|
let firstString = file.stringView.substringWithByteRange(firstByteRange),
|
|
// These patterns are often used for "file header" style comments
|
|
!firstString.starts(with: "////") && !firstString.starts(with: "/***")
|
|
else {
|
|
return nil
|
|
}
|
|
|
|
return StyleViolation(ruleDescription: Self.description,
|
|
severity: configuration.severity,
|
|
location: Location(file: file, byteOffset: firstByteRange.location))
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension Sequence {
|
|
func pairs() -> Zip2Sequence<Self, [Element?]> {
|
|
return zip(self, Array(dropFirst()) + [nil])
|
|
}
|
|
}
|