mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Creating a new CodeBlockItem meant that when doing an edit in the error nodes, the prefix gets reused and thus the code is parsed as invalid although it is not.
160 lines
5.3 KiB
Swift
160 lines
5.3 KiB
Swift
// RUN: %target-run-simple-swift
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: OS=macosx
|
|
// REQUIRES: objc_interop
|
|
|
|
import StdlibUnittest
|
|
import Foundation
|
|
import SwiftSyntax
|
|
import SwiftLang
|
|
|
|
func getInput(_ file: String) -> URL {
|
|
var result = URL(fileURLWithPath: #file)
|
|
result.deleteLastPathComponent()
|
|
result.appendPathComponent("Inputs")
|
|
result.appendPathComponent(file)
|
|
return result
|
|
}
|
|
|
|
|
|
class FuncRenamer: SyntaxRewriter {
|
|
override func visit(_ node: FunctionDeclSyntax) ->DeclSyntax {
|
|
return (super.visit(node) as! FunctionDeclSyntax).withIdentifier(
|
|
SyntaxFactory.makeIdentifier("anotherName"))
|
|
}
|
|
}
|
|
|
|
var PositionTests = TestSuite("AbsolutePositionTests")
|
|
|
|
PositionTests.test("Visitor") {
|
|
expectDoesNotThrow({
|
|
let content = try SwiftLang.parse(getInput("visitor.swift"))
|
|
let source = try String(contentsOf: getInput("visitor.swift"))
|
|
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(content)
|
|
expectEqual(0, parsed.position.utf8Offset)
|
|
expectEqual(source.count,
|
|
parsed.eofToken.positionAfterSkippingLeadingTrivia.utf8Offset)
|
|
expectEqual(0, parsed.position.utf8Offset)
|
|
expectEqual(source.count, parsed.byteSize)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("Closure") {
|
|
expectDoesNotThrow({
|
|
let content = try SwiftLang.parse(getInput("closure.swift"))
|
|
let source = try String(contentsOf: getInput("closure.swift"))
|
|
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(content)
|
|
expectEqual(source.count,
|
|
parsed.eofToken.positionAfterSkippingLeadingTrivia.utf8Offset)
|
|
expectEqual(0, parsed.position.utf8Offset)
|
|
expectEqual(source.count, parsed.byteSize)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("Rename") {
|
|
expectDoesNotThrow({
|
|
let content = try SwiftLang.parse(getInput("visitor.swift"))
|
|
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(content)
|
|
let renamed = FuncRenamer().visit(parsed) as! SourceFileSyntax
|
|
let renamedSource = renamed.description
|
|
expectEqual(renamedSource.count,
|
|
renamed.eofToken.positionAfterSkippingLeadingTrivia.utf8Offset)
|
|
expectEqual(renamedSource.count, renamed.byteSize)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("CurrentFile") {
|
|
expectDoesNotThrow({
|
|
let content = try SwiftLang.parse(URL(fileURLWithPath: #file))
|
|
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(content)
|
|
class Visitor: SyntaxVisitor {
|
|
override func visitPre(_ node: Syntax) {
|
|
_ = node.position
|
|
_ = node.byteSize
|
|
_ = node.positionAfterSkippingLeadingTrivia
|
|
}
|
|
override func visit(_ node: TokenSyntax) {
|
|
expectEqual(node.positionAfterSkippingLeadingTrivia.utf8Offset,
|
|
node.position.utf8Offset + node.leadingTrivia.byteSize)
|
|
}
|
|
}
|
|
Visitor().visit(parsed)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("Recursion") {
|
|
expectDoesNotThrow({
|
|
var l = [CodeBlockItemSyntax]()
|
|
let idx = 2000
|
|
for _ in 0...idx {
|
|
l.append(SyntaxFactory.makeCodeBlockItem(
|
|
item: SyntaxFactory.makeReturnStmt(
|
|
returnKeyword: SyntaxFactory.makeToken(.returnKeyword, presence: .present)
|
|
.withTrailingTrivia(.newlines(1)), expression: nil), semicolon: nil, errorTokens: nil))
|
|
}
|
|
let root = SyntaxFactory.makeSourceFile(
|
|
statements: SyntaxFactory.makeCodeBlockItemList(l),
|
|
eofToken: SyntaxFactory.makeToken(.eof, presence: .present))
|
|
_ = root.statements[idx].position
|
|
_ = root.statements[idx].byteSize
|
|
_ = root.statements[idx].positionAfterSkippingLeadingTrivia
|
|
})
|
|
}
|
|
|
|
func createSourceFile(_ count: Int) -> SourceFileSyntax {
|
|
let leading = Trivia(pieces: [
|
|
.newlines(1),
|
|
.backticks(1),
|
|
.docLineComment("/// some comment")
|
|
])
|
|
let trailing = Trivia.docLineComment("/// This is comment\n")
|
|
let items : [CodeBlockItemSyntax] =
|
|
[CodeBlockItemSyntax](repeating: CodeBlockItemSyntax {
|
|
$0.useItem(ReturnStmtSyntax {
|
|
$0.useReturnKeyword(
|
|
SyntaxFactory.makeReturnKeyword(
|
|
leadingTrivia: leading,
|
|
trailingTrivia: trailing))
|
|
})}, count: count)
|
|
return SyntaxFactory.makeSourceFile(
|
|
statements: SyntaxFactory.makeCodeBlockItemList(items),
|
|
eofToken: SyntaxFactory.makeToken(.eof, presence: .present))
|
|
}
|
|
|
|
PositionTests.test("Trivias") {
|
|
expectDoesNotThrow({
|
|
let idx = 5
|
|
let root = createSourceFile(idx + 1)
|
|
expectEqual(3, root.leadingTrivia!.count)
|
|
expectEqual(0, root.trailingTrivia!.count)
|
|
let state = root.statements[idx]
|
|
expectEqual(3, state.leadingTrivia!.count)
|
|
expectEqual(1, state.trailingTrivia!.count)
|
|
expectEqual(state.byteSize,
|
|
state.leadingTrivia!.byteSize + state.trailingTrivia!.byteSize
|
|
+ state.byteSizeAfterTrimmingTrivia)
|
|
expectFalse(root.statements.isImplicit)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("Implicit") {
|
|
expectDoesNotThrow({
|
|
let root = createSourceFile(0)
|
|
expectTrue(root.statements.isImplicit)
|
|
})
|
|
}
|
|
|
|
PositionTests.test("WithoutSourceFileRoot") {
|
|
expectDoesNotThrow({
|
|
let item = SyntaxFactory.makeCodeBlockItem(
|
|
item: SyntaxFactory.makeReturnStmt(
|
|
returnKeyword: SyntaxFactory.makeToken(.returnKeyword, presence: .present)
|
|
.withLeadingTrivia(.newlines(1)).withTrailingTrivia(.newlines(1)),
|
|
expression: nil), semicolon: nil, errorTokens: nil)
|
|
expectEqual(0, item.position.utf8Offset)
|
|
expectEqual(1, item.positionAfterSkippingLeadingTrivia.utf8Offset)
|
|
})
|
|
}
|
|
|
|
runAllTests()
|