mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Parse] Handle #if in brace skipping logic
Previously we would strictly match `{` + `}`, but
that ignored the fact that when parsing we consider
`#if` + `#endif` to be a stronger delimiter than
`{` + `}`, so can ignore a stray `}` in a `#if`.
Update the logic to also track opening and closing
`#if` decls, ignoring any braces that happen within
them.
rdar://129195380
This commit is contained in:
@@ -5658,10 +5658,11 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
|
||||
HasPotentialRegexLiteral = false;
|
||||
|
||||
unsigned OpenBraces = 1;
|
||||
unsigned OpenPoundIf = 0;
|
||||
|
||||
bool LastTokenWasFunc = false;
|
||||
|
||||
while (OpenBraces != 0 && P.Tok.isNot(tok::eof)) {
|
||||
while ((OpenBraces != 0 || OpenPoundIf != 0) && P.Tok.isNot(tok::eof)) {
|
||||
// Detect 'func' followed by an operator identifier.
|
||||
if (LastTokenWasFunc) {
|
||||
LastTokenWasFunc = false;
|
||||
@@ -5692,6 +5693,24 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
|
||||
return OpenBraces;
|
||||
}
|
||||
|
||||
// Match opening `#if` with closing `#endif` to match what the parser does,
|
||||
// `#if` + `#endif` are considered stronger delimiters than `{` + `}`.
|
||||
if (P.consumeIf(tok::pound_if)) {
|
||||
OpenPoundIf += 1;
|
||||
continue;
|
||||
}
|
||||
if (OpenPoundIf != 0) {
|
||||
// We're in a `#if`, check to see if we've reached the end.
|
||||
if (P.consumeIf(tok::pound_endif)) {
|
||||
OpenPoundIf -= 1;
|
||||
continue;
|
||||
}
|
||||
// Consume the next token and continue iterating. We can swallow any
|
||||
// amount of '{' and '}' while in the `#if`.
|
||||
P.consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (P.consumeIf(tok::l_brace)) {
|
||||
++OpenBraces;
|
||||
continue;
|
||||
|
||||
36
test/Parse/rdar129195380.swift
Normal file
36
test/Parse/rdar129195380.swift
Normal file
@@ -0,0 +1,36 @@
|
||||
// RUN: not %target-swift-frontend -experimental-skip-all-function-bodies -dump-parse %s | %FileCheck %s
|
||||
|
||||
// rdar://129195380 - Make sure the skipping logic can handle #if.
|
||||
struct S {
|
||||
// CHECK: func_decl{{.*}}:[[@LINE+1]]:3 - line:[[@LINE+11]]:3{{.*}}"foo()"
|
||||
func foo() {
|
||||
#if true
|
||||
}
|
||||
#if true
|
||||
func bar() {
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// CHECK: func_decl{{.*}}:[[@LINE+1]]:3 - line:[[@LINE+1]]:15{{.*}}"baz()"
|
||||
func baz() {}
|
||||
}
|
||||
|
||||
// The '#if' is unterminated here, so swallows the rest of the file.
|
||||
// CHECK: struct_decl{{.*}}:[[@LINE+1]]:1 - line:[[@LINE+14]]:14{{.*}}"R"
|
||||
struct R {
|
||||
#if false
|
||||
}
|
||||
#if true
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
}
|
||||
// CHECK-NOT: qux
|
||||
func qux() {}
|
||||
}
|
||||
|
||||
func flim() {}
|
||||
13
test/SourceKit/CursorInfo/rdar129195380.swift
Normal file
13
test/SourceKit/CursorInfo/rdar129195380.swift
Normal file
@@ -0,0 +1,13 @@
|
||||
// rdar://129195380 - Make sure we correctly handle '#if' when skipping function
|
||||
// bodies.
|
||||
class C {
|
||||
func test1() {
|
||||
#if FOOBAR
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 2):5 %s -- %s -DFOOBAR
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):5 %s -- %s
|
||||
abc
|
||||
}
|
||||
|
||||
func test2() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user