Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
391 changes: 391 additions & 0 deletions Tests/SwiftParserTest/IncrementalParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,395 @@ public class IncrementalParsingTests: XCTestCase {
]
)
}

public func testAddElse() {
assertIncrementalParse(
"""
#if false
⏩️⏸️#else⏪️
"""
)
}

public func testInsertSpace() {
assertIncrementalParse(
"""
class AnimationType {
func foo(x: Blah) {
switch x {
case (.

extension AnimationType {
public⏩️⏸️ ⏪️
"""
)
}

public func testAddFuncParens() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func parensAdded⏩️⏸️()⏪️ {
}
}
"""
)
}

public func testAddOpeningBrace() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func openingBraceAdded() ⏩️⏸️{⏪️
}
"""
)
}

public func testAddClosingBrace() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func closingBraceAdded() {

⏩️⏸️}⏪️
}
"""
)
}

public func testRemoveFuncKeyword() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
⏩️func⏸️⏪️ funcKeywordRemoved() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertIncrementalParse will apply all of these edits concurrently, while lit_tests/incrParse/funcs.swift specified multiple independent test cases where only a single edit was applied. I would split this case up into multiple assertIncrementalParse calls where each one only has a single edit.

Same for most of the test cases below. NESTED_INITIALIZERS performs a multi-edit but I think none of the others do, but please double-check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we split these up, do you think should we maintain all other text in in that file? I'm not quite sure how much these context will affect our test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just keep the immediate parent contexts. E.g. here, I would just keep class InvalidFuncDecls {


}
}
"""
)
}

public func testAddParamName() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func addingParamName(⏩️⏸️arg⏪️) {

}
}
"""
)
}

public func testAddParamColon() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func addingParamColon(arg⏩️⏸️:⏪️) {
}
}
"""
)
}

public func testAddingParamType() {
assertIncrementalParse(
"""
class InvalidFuncDecls {
func addingParamType(arg:⏩️⏸️ String⏪️) {
}
}
"""
)
}

public func testInsertTextIdentifier() {
assertIncrementalParse(
"""
self = ⏩️⏸️_ _⏪️foo(1)[object1, object2] + o bar(1)
"""
)
}

public func testNestedInitializers() {
assertIncrementalParse(
"""
class NestedInitializers {
⏩️⏸️init() {⏪️
init() {

}
⏩️⏸️}⏪️
}
"""
)
}

public func testMultiEditMapping() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
let one: Int;let two: Int; let three: Int; ⏩️⏸️ ⏪️⏩️⏸️ ⏪️let found: Int;let five: Int;
""",
reusedNodes: [
ReusedNodeSpec("let one: Int;", kind: .codeBlockItem),
ReusedNodeSpec("let two: Int;", kind: .codeBlockItem),
ReusedNodeSpec("let five: Int;", kind: .codeBlockItem),
]
)
}

public func testAddProperty() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
struct Foo {
let a: Int
let b: Int
let c: Int
let d: String
⏩️⏸️let e_newProp: String⏪️
let f: Int
let g: Int
}
""",
reusedNodes: [
ReusedNodeSpec("let a: Int", kind: .memberDeclListItem),
ReusedNodeSpec("let b: Int", kind: .memberDeclListItem),
ReusedNodeSpec("let c: Int", kind: .memberDeclListItem),
ReusedNodeSpec("let g: Int", kind: .memberDeclListItem),
]
)
}

public func testWarpInClass() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
⏩️⏸️class Foo {⏪️
func foo1() {
print("Hello Foo!")
}

func foo2() {
print("Hello again")
}
""",
reusedNodes: [
ReusedNodeSpec(
"""
func foo1() {
print("Hello Foo!")
}
""",
kind: .functionDecl
),
ReusedNodeSpec(
"""
func foo2() {
print("Hello again!")
}
""",
kind: .functionDecl
),
]
)
}

public func testUnwarpClass() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
⏩️class Bar {⏸️⏪️
func bar1() {
let pi = 3.1415
print("Pi is (approximately) \\(pi)")
}

func bar2() {
print("I can compute Pi as well:")
bar1()
}
}
""",
reusedNodes: [
ReusedNodeSpec(
"""
func bar1() {
let pi = 3.1415
print("Pi is (approximately) \\(pi)")
}
""",
kind: .functionDecl
),
ReusedNodeSpec(
"""
func bar2() {
print("I can compute Pi as well:")
bar1()
}
""",
kind: .functionDecl
),
]
)
}

public func testNextTokenCalculation() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
let a = "hello"
let c = "⏩️ ⏸️⏪️world"
""",
reusedNodes: [
ReusedNodeSpec("let a = \"hello\"", kind: .codeBlockItem)
]
)
}

public func testReplace() throws {
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
assertIncrementalParse(
"""
func foo() {
}

_ = ⏩️6⏸️7⏪️
""",
reusedNodes: [
ReusedNodeSpec(
"""
func foo() {
}
""",
kind: .codeBlockItem
)
]
)
}

public func testReplaceByLonger() {
assertIncrementalParse(
"""
_ = ⏩️6⏸️"Hello World"⏪️
"""
)
}

public func testReplaceByShorter() {
assertIncrementalParse(
"""
_ = ⏩️"Hello again"⏸️"a"⏪️
"""
)
}

public func testInsert() {
assertIncrementalParse(
"""
⏩️⏸️foo()⏪️
"""
)
}

public func testRemove() {
assertIncrementalParse(
"""
⏩️print("abc")⏸️⏪️
"""
)
}

public func testAttachToPrevNode() {
assertIncrementalParse(
"""
foo()
⏩️⏸️{}⏪️
_ = 1
"""
)
}

public func testClassSurrounding() {
assertIncrementalParse(
"""
⏩️⏸️class C {⏪️
func method1() {}
"""
)
}

public func testMultiEdit() {
assertIncrementalParse(
"""
⏩️⏸️class C {⏪️
func method1() {}
⏩️⏸️}⏪️
"""
)
}

public func testMultiEditSameLine() {
assertIncrementalParse(
"""
⏩️_⏸️let x⏪️ = ⏩️1⏸️"hi"⏪️
"""
)
}

public func testReplaceWithMultiByteChar() {
assertIncrementalParse(
"""
let x = "⏩️a⏸️👨‍👩‍👧‍👦⏪️"
"""
)
}

public func testReplaceMultiByteCharWithShorter() {
assertIncrementalParse(
"""
let x = "⏩️👨‍👩‍👧‍👦⏸️🎉⏪️"
"""
)
}

public func testLastCharOfStruct() {
assertIncrementalParse(
"""
private struc⏩️⏸️t⏪️ MyStruct {
}
"""
)
}

public func testAddArrayCloseBracket() {
assertIncrementalParse(
"""
var computedVar: [Int] {
return [1
⏩️⏸️]⏪️
}
"""
)
}

public func testAddIfOpenBrace() {
assertIncrementalParse(
"""
if true ⏩️⏸️{⏪️
_ = 5
}
"""
)
}

public func testExtendIdentifier() {
assertIncrementalParse(
"""
let y⏩️⏸️ou⏪️ = 42
"""
)
}
}