Tweaks to how dot syntax is highlighted (#78)

- Don’t highlight what *could* be a static method call using
  the `dotAccess` style, only highlight tokens that are either
  value-less enum cases or static properties.

- The exception to the above rule is within `switch` statements,
  in which even call-like tokens are assumed to be enum cases.

- Highlight calls to `.init()` as keywords, for consistency
  with other `init` usages.
This commit is contained in:
John Sundell 2019-08-06 15:50:23 +02:00 committed by GitHub
parent e107609b00
commit 367b8408b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 16 deletions

View File

@ -186,6 +186,7 @@ private extension SwiftGrammar {
var callLikeKeywords = accessControlKeywords
callLikeKeywords.insert("subscript")
callLikeKeywords.insert("init")
self.callLikeKeywords = callLikeKeywords
}
@ -213,8 +214,22 @@ private extension SwiftGrammar {
}
// Don't treat enums with associated values as function calls
guard !segment.prefixedByDotAccess else {
return false
// when they appear within a switch statement
if previousToken == "." {
let previousTokens = segment.tokens.onSameLine
if previousTokens.count > 1 {
let lastToken = previousTokens[previousTokens.count - 2]
guard lastToken != "case" else {
return false
}
// Multiple expressions can be matched within a single case
guard !lastToken.hasSuffix(",") else {
return false
}
}
}
}
@ -231,13 +246,6 @@ private extension SwiftGrammar {
return !segment.tokens.onSameLine.contains(anyOf: controlFlowTokens)
}
// Check so that this is an initializer call, not the declaration
if segment.tokens.current == "init" {
guard segment.tokens.previous == "." else {
return false
}
}
return segment.tokens.next?.starts(with: "(") ?? false
}
}
@ -417,6 +425,12 @@ private extension SwiftGrammar {
return false
}
if let next = segment.tokens.next {
guard !next.hasPrefix("(") else {
return false
}
}
return segment.tokens.onSameLine.first != "import"
}
}

View File

@ -452,7 +452,7 @@ final class DeclarationTests: SyntaxHighlighterTestCase {
.whitespace(" "),
.token("self", .keyword),
.plainText("."),
.token("init", .call),
.token("init", .keyword),
.plainText("()"),
.whitespace(" "),
.plainText("}"),

View File

@ -37,13 +37,13 @@ final class EnumTests: SyntaxHighlighterTestCase {
])
}
func testEnumDotSyntaxWithAssociatedValue() {
func testEnumDotSyntaxWithAssociatedValueTreatedAsCall() {
let components = highlighter.highlight("call(.error(error))")
XCTAssertEqual(components, [
.token("call", .call),
.plainText("(."),
.token("error", .dotAccess),
.token("error", .call),
.plainText("(error))")
])
}
@ -68,7 +68,7 @@ extension EnumTests {
return [
("testEnumDotSyntaxInAssignment", testEnumDotSyntaxInAssignment),
("testEnumDotSyntaxAsArgument", testEnumDotSyntaxAsArgument),
("testEnumDotSyntaxWithAssociatedValue", testEnumDotSyntaxWithAssociatedValue),
("testEnumDotSyntaxWithAssociatedValueTreatedAsCall", testEnumDotSyntaxWithAssociatedValueTreatedAsCall),
("testUsingEnumInSubscript", testUsingEnumInSubscript)
]
}

View File

@ -50,7 +50,7 @@ final class FunctionCallTests: SyntaxHighlighterTestCase {
.whitespace(" "),
.token("String", .type),
.plainText("."),
.token("init", .call),
.token("init", .keyword),
.plainText("()")
])
}

View File

@ -106,7 +106,7 @@ final class StatementTests: SyntaxHighlighterTestCase {
])
}
func testSwitchStatementWithAssociatedValues() {
func testSwitchStatementWithSingleAssociatedValue() {
let components = highlighter.highlight("""
switch value {
case .one(let a): break
@ -135,6 +135,42 @@ final class StatementTests: SyntaxHighlighterTestCase {
])
}
func testSwitchStatementWithMultipleAssociatedValues() {
let components = highlighter.highlight("""
switch value {
case .one(let a), .two(let b): break
}
""")
XCTAssertEqual(components, [
.token("switch", .keyword),
.whitespace(" "),
.plainText("value"),
.whitespace(" "),
.plainText("{"),
.whitespace("\n"),
.token("case", .keyword),
.whitespace(" "),
.plainText("."),
.token("one", .dotAccess),
.plainText("("),
.token("let", .keyword),
.whitespace(" "),
.plainText("a),"),
.whitespace(" "),
.plainText("."),
.token("two", .dotAccess),
.plainText("("),
.token("let", .keyword),
.whitespace(" "),
.plainText("b):"),
.whitespace(" "),
.token("break", .keyword),
.whitespace("\n"),
.plainText("}")
])
}
func testSwitchStatementWithFallthrough() {
let components = highlighter.highlight("""
switch variable {
@ -360,7 +396,8 @@ extension StatementTests {
("testImportStatementWithSubmodule", testImportStatementWithSubmodule),
("testChainedIfElseStatements", testChainedIfElseStatements),
("testSwitchStatement", testSwitchStatement),
("testSwitchStatementWithAssociatedValues", testSwitchStatementWithAssociatedValues),
("testSwitchStatementWithSingleAssociatedValue", testSwitchStatementWithSingleAssociatedValue),
("testSwitchStatementWithMultipleAssociatedValues", testSwitchStatementWithMultipleAssociatedValues),
("testSwitchStatementWithFallthrough", testSwitchStatementWithFallthrough),
("testSwitchStatementWithTypePatternMatching", testSwitchStatementWithTypePatternMatching),
("testSwitchStatementWithOptional", testSwitchStatementWithOptional),