8000 Merge pull request #52 from apple/master · swiftlang/swift-syntax@70d2c64 · GitHub
[go: up one dir, main page]

Skip to content

Commit 70d2c64

Browse files
authored
Merge pull request #52 from apple/master
Even master and swift-5.0-branch
2 parents a07481f + aee69f4 commit 70d2c64

File tree

9 files changed

+86
-80
lines changed

9 files changed

+86
-80
lines changed

Sources/SwiftSyntax/AtomicCache.swift

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===--------------------- LazyNonThreadSafeCache.swift -------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
/// LazyNonThreadSafeCache is a wrapper class around an uninitialized value.
16+
/// It takes a closure that will be used to create the value when needed.
17+
///
18+
/// FIXME: the cache is no longer thread-safe. We need stdlib to provide proper
19+
/// APIs to ensure thread safety
20+
class LazyNonThreadSafeCache<Value: AnyObject> {
21+
/// The cached pointer that will be filled in the first time `value` is
22+
/// accessed.
23+
private var _cachedValue: AnyObject?
24+
25+
/// The value inside this cache. If the value has not been initialized when
26+
/// this value is requested, then the closure will be called and its resulting
27+
/// value will be stored in the cache.
28+
/// - Parameter create: The closure that will return the fully realized value
29+
/// inside the cache.
30+
func value(_ create: () -> Value) -> Value {
31+
if _cachedValue == nil {
32+
_cachedValue = create()
33+
}
34+
return _cachedValue as! Value
35+
}
36+
37+
/// Get the raw cache with the right type for debugging purposes.
38+
/// - note: Only for use in the debugger!
39+
@available(*, deprecated, message: "Only for use in the debugger.")
40+
var unsafeValue: Value? {
41+
return _cachedValue as? Value
42+
}
43+
}

Sources/SwiftSyntax/RawSyntax.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ final class RawSyntax {
9393
/// incremental parses
9494
let id: SyntaxNodeId
9595

96-
var _contentLength = AtomicCache<Box<SourceLength>>()
96+
var _contentLength = LazyNonThreadSafeCache<Box<SourceLength>>()
9797

9898
/// The length of this node excluding its leading and trailing trivia
9999
var contentLength: SourceLength {

Sources/SwiftSyntax/SyntaxData.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ final class SyntaxData: Equatable {
3636
let indexInParent: Int
3737
weak var parent: SyntaxData?
3838

39-
let childCaches: [AtomicCache<SyntaxData>]
39+
let childCaches: [LazyNonThreadSafeCache<SyntaxData>]
4040

41-
private let positionCache: AtomicCache<Box<AbsolutePosition>>
41+
private let positionCache: LazyNonThreadSafeCache<Box<AbsolutePosition>>
4242

4343
fileprivate func calculatePosition() -> AbsolutePosition {
4444
guard let parent = parent else {
@@ -92,8 +92,8 @@ final class SyntaxData: Equatable {
9292
self.raw = raw
9393
self.indexInParent = indexInParent
9494
self.parent = parent
95-
self.childCaches = raw.layout.map { _ in AtomicCache<SyntaxData>() }
96-
self.positionCache = AtomicCache<Box<AbsolutePosition>>()
95+
self.childCaches = raw.layout.map { _ in LazyNonThreadSafeCache<SyntaxData>() }
96+
self.positionCache = LazyNonThreadSafeCache<Box<AbsolutePosition>>()
9797
}
9898

9999
/// The index path from this node to the root. This can be used to uniquely

Sources/SwiftSyntax/SyntaxNodes.swift.gyb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public protocol ${node.name}: Syntax {}
6666
% for line in dedented_lines(node.description):
6767
/// ${line}
6868
% end
69+
/// Syntax nodes are not thread-safe.
6970
public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
7071
% if node.children:
7172
enum Cursor: Int {
@@ -145,9 +146,9 @@ public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
145146
return lhs._data === rhs._data
146147
}
147148

148-
/// A unique hash value for this node.
149-
public var hashValue: Int {
150-
return ObjectIdentifier(_data).hashValue
149+
/// Feed the essential parts of this node to the supplied hasher.
150+
public func hash(into hasher: inout Hasher) {
151+
hasher.combine(ObjectIdentifier(_data))
151152
}
152153
}
153154

Sources/lit-test-helper/main.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,27 @@ func performClassifySyntax(args: CommandLineArguments) throws {
124124
}
125125
}
126126

127+
class NodePrinter: SyntaxVisitor {
128+
override func visitPre(_ node: Syntax) {
129+
assert(!node.isUnknown)
130+
print("<\(type(of: node))>", terminator: "")
131+
}
132+
override func visitPost(_ node: Syntax) {
133+
print("</\(type(of: node))>", terminator: "")
134+
}
135+
override func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
136+
print(token, terminator:"")
137+
return .visitChildren
138+
}
139+
}
140+
141+
func printSyntaxTree(args: CommandLineArguments) throws {
142+
let treeURL = URL(fileURLWithPath: try args.getRequired("-source-file"))
143+
let swiftcURL = args["-swiftc"].map(URL.init(fileURLWithPath:))
144+
let tree = try SyntaxTreeParser.parse(treeURL, swiftcURL: swiftcURL)
145+
tree.walk(NodePrinter())
146+
}
147+
127148
do {
128149
let args = try CommandLineArguments.parse(CommandLine.arguments.dropFirst())
129150

@@ -133,6 +154,8 @@ do {
133154
try performClassifySyntax(args: args)
134155
} else if args.has("-deserialize") {
135156
try performDeserialize(args: args)
157+
} else if args.has("-print-source") {
158+
try printSyntaxTree(args: args)
136159
} else if args.has("-help") {
137160
printHelp()
138161
} else {

Tests/LinuxMain.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ XCTMain({ () -> [XCTestCaseEntry] in
66
testCase(AbsolutePositionTestCase.allTests),
77
testCase(DecodeSyntaxTestCase.allTests),
88
testCase(DiagnosticTestCase.allTests),
9-
testCase(LazyCachingTestCase.allTests),
9+
// We need to make syntax node thread safe to enable these tests
10+
// testCase(LazyCachingTestCase.allTests),
1011
testCase(ParseFileTestCase.allTests),
1112
testCase(SyntaxChildrenAPITestCase.allTests),
1213
testCase(SyntaxCollectionsAPITestCase.allTests),

Tests/SwiftSyntaxTest/LazyCaching.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import SwiftSyntax
44
public class LazyCachingTestCase: XCTestCase {
55

66
public static let allTests = [
7-
("testPathological", testPathological),
8-
("testTwoAccesses", testTwoAccesses),
7+
("testPathological", disabledtestPathological),
8+
("testTwoAccesses", disabledtestTwoAccesses),
99
]
1010

11-
public func testPathological() {
11+
// FIXME: re-enable this test when syntax nodes are thread safe
12+
public func disabledtestPathological() {
1213
let tuple = SyntaxFactory.makeVoidTupleType()
1314

1415
DispatchQueue.concurrentPerform(iterations: 100) { _ in
1516
XCTAssertEqual(tuple.leftParen, tuple.leftParen)
1617
}
1718
}
1819

19-
public func testTwoAccesses() {
20+
// FIXME: re-enable this test when syntax nodes are thread safe
21+
public func disabledtestTwoAccesses() {
2022
let tuple = SyntaxFactory.makeVoidTupleType()
2123

2224
let queue1 = DispatchQueue(label: "queue1")

build-script.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def run_lit_tests(swift_build_exec, build_dir, release, swiftc_exec,
264264
lit_call.extend([PACKAGE_DIR + '/lit_tests'])
265265

266266
if swiftc_exec:
267-
lit_call.extend(['--param', 'SWIFTC=' + swiftc_exec])
267+
lit_call.extend(['--param', 'SWIFTC=' + realpath(swiftc_exec)])
268268
if filecheck_exec:
269269
lit_call.extend(['--param', 'FILECHECK=' + filecheck_exec])
270270
if lit_test_helper_exec:
@@ -280,7 +280,6 @@ def run_lit_tests(swift_build_exec, build_dir, release, swiftc_exec,
280280
# Don't show all commands if verbose is not enabled
281281
if not verbose:
282282
lit_call.extend(['--succinct'])
283-
284283
return call(lit_call, verbose=verbose) == 0
285284

286285

@@ -299,7 +298,7 @@ def run_xctests(swift_test_exec, build_dir, release, swiftc_exec, verbose):
299298
if swiftc_exec:
300299
# Add the swiftc exec to PATH so that SwiftSyntax finds it
301300
subenv['PATH'] = realpath(swiftc_exec + '/..') + ':' + subenv['PATH']
302-
301+
subenv['SWIFT_EXEC'] = swiftc_exec
303302
return call(swiftpm_call, env=subenv, verbose=verbose) == 0
304303

305304
def delete_rpath(rpath, binary):
@@ -478,7 +477,7 @@ def main():
478477
release=args.release,
479478
swift_build_exec=args.swift_build_exec,
480479
filecheck_exec=realpath(args.filecheck_exec),
481-
swiftc_exec=realpath(args.swiftc_exec),
480+
swiftc_exec=args.swiftc_exec,
482481
swift_syntax_test_exec=
483482
realpath(args.swift_syntax_test_exec),
484483
verbose=args.verbose)

0 commit comments

Comments
 (0)
0