Skip to content

Commit a58ba53

Browse files
committed
Unified: Extract built-in Swift types
1 parent c7f49f2 commit a58ba53

13 files changed

Lines changed: 303 additions & 17 deletions

File tree

unified/BUILD.bazel

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,24 @@ codeql_pkg_files(
4545
otherwise = ["//unified/extractor"],
4646
win64 = ["//unified/extractor-unsupported-os:extractor"],
4747
),
48-
prefix = "tools/{CODEQL_PLATFORM}",
48+
prefix = "{CODEQL_PLATFORM}",
49+
)
50+
51+
pkg_filegroup(
52+
name = "tools",
53+
srcs = [
54+
":extractor-arch",
55+
"//unified/tools",
56+
"//unified/tools/builtins",
57+
],
58+
prefix = "tools",
4959
)
5060

5161
codeql_pack(
5262
name = "unified",
5363
srcs = [
5464
":codeql-extractor-yml",
5565
":dbscheme-group",
56-
":extractor-arch",
57-
"//unified/tools",
66+
":tools",
5867
],
5968
)

unified/extractor/src/extractor.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use clap::Args;
2-
use std::path::PathBuf;
3-
41
use crate::languages;
2+
use clap::Args;
53
use codeql_extractor::extractor::desugaring;
64
use codeql_extractor::trap;
7-
5+
use std::path::Path;
6+
use std::path::PathBuf;
7+
use std::{env, fs};
88
#[derive(Args)]
99
pub struct Options {
1010
/// Sets a custom source archive folder
@@ -31,6 +31,33 @@ pub fn run(options: Options) -> std::io::Result<()> {
3131
lang.prefix = "unified";
3232
}
3333

34+
let scratch_dir = std::env::var("CODEQL_EXTRACTOR_UNIFIED_SCRATCH_DIR")
35+
.expect("failed to read CODEQL_EXTRACTOR_UNIFIED_SCRATCH_DIR environment variable");
36+
let builtins_path = env::var("CODEQL_EXTRACTOR_UNIFIED_ROOT")
37+
.map(|path| Path::new(&path).join("tools").join("builtins"))
38+
.expect("failed to read CODEQL_EXTRACTOR_UNIFIED_ROOT environment variable");
39+
let builtins_dir = fs::read_dir(builtins_path).expect("failed to read builtins directory");
40+
let mut builtins_list = PathBuf::new();
41+
builtins_list.push(scratch_dir.clone());
42+
builtins_list.push("builtins");
43+
builtins_list.set_extension("list");
44+
45+
let mut builtins_list_file = fs::OpenOptions::new()
46+
.create_new(true)
47+
.write(true)
48+
.open(&builtins_list)
49+
.expect("failed to open file list");
50+
for entry in builtins_dir {
51+
let entry = entry.expect("failed to read builtins directory");
52+
let path = entry.path();
53+
if path.extension().is_some_and(|ext| ext == "swift") {
54+
use std::io::Write;
55+
writeln!(builtins_list_file, "{}", path.display())
56+
.expect("failed to write to file list");
57+
}
58+
}
59+
drop(builtins_list_file);
60+
3461
let extractor = desugaring::Extractor {
3562
prefix: "unified".to_string(),
3663
languages,
@@ -39,7 +66,7 @@ pub fn run(options: Options) -> std::io::Result<()> {
3966
"CODEQL_EXTRACTOR_UNIFIED_OPTION_TRAP_COMPRESSION",
4067
),
4168
source_archive_dir: options.source_archive_dir,
42-
file_lists: vec![options.file_list],
69+
file_lists: vec![options.file_list, builtins_list],
4370
};
4471

4572
extractor.run()

unified/ql/lib/codeql/files/FileSystem.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module Folder = Impl::Folder;
3737
/** A file. */
3838
class File extends Container, Impl::File {
3939
/** Holds if this file was extracted from ordinary source code. */
40-
predicate fromSource() { any() }
40+
predicate fromSource() { exists(this.getRelativePath()) }
4141

4242
/**
4343
* Gets the number of lines containing code in this file. This value
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Provides classes for builtins.
3+
*/
4+
5+
private import unified
6+
7+
/** The folder containing builtins. */
8+
class BuiltinsFolder extends Folder {
9+
BuiltinsFolder() {
10+
this.getBaseName() = "builtins" and
11+
this.getParentContainer().getBaseName() = "tools"
12+
}
13+
}
14+
15+
private class BuiltinsTypesFile extends File {
16+
BuiltinsTypesFile() {
17+
this.getBaseName() = "types.swift" and
18+
this.getParentContainer() instanceof BuiltinsFolder
19+
}
20+
}
21+
22+
/**
23+
* A builtin type, such as `Bool` and `String`.
24+
*
25+
* Builtin types are represented as class-like declarations.
26+
*/
27+
class BuiltinClassLikeDeclaration extends ClassLikeDeclaration {
28+
BuiltinClassLikeDeclaration() { this.getFile() instanceof BuiltinsTypesFile }
29+
}

unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ private module Ast implements AstSig<Location> {
4242

4343
Callable getEnclosingCallable(AstNode node) { result = node.getEnclosingCallable() }
4444

45-
class Callable = U::Callable;
45+
class Callable extends U::Callable {
46+
Callable() { this.fromSource() }
47+
}
4648

4749
AstNode callableGetBody(Callable c) { result = c.getBody() }
4850

unified/ql/lib/codeql/unified/internal/FacadeAst.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ module Unified {
1515
/** Gets the file containing this AST node. */
1616
File getFile() { result = this.getLocation().getFile() }
1717

18+
/** Holds if this AST node comes from ordinary source code. */
19+
predicate fromSource() { this.getFile().fromSource() }
20+
1821
/** Holds if this AST node has a modifier with the given text. */
1922
predicate hasModifier(string text) {
2023
exists(Modifier mod |

unified/ql/test/library-tests/BasicTest/test.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import unified
22

3-
query predicate identifier(Identifier node, string value) { value = node.getValue() }
3+
query predicate identifier(Identifier node, string value) {
4+
node.fromSource() and value = node.getValue()
5+
}
46

57
query predicate namedPattern(NamedPattern node, string value) { value = node.getName() }
68

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import unified
22

3-
query predicate comments(Comment c, string text) { text = c.getCommentText() }
3+
query predicate comments(Comment c, string text) { c.fromSource() and text = c.getCommentText() }

unified/ql/test/library-tests/definitions/test.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ func test() {
1111
let local = 2 // name=local2
1212
local // $ definition=local2
1313
Derived.member // $ definition=Derived definition=Base.member
14-
let _: Derived.Nested? // $ definition=Derived definition=Base.Nested
14+
let _: Derived.Nested? // $ definition=Derived definition=Base.Nested definition=Optional
1515
}
1616

1717
typealias Alias = Derived // $ definition=Derived
18-
let _: Alias.Nested? // $ definition=Alias definition=Base.Nested
18+
let _: Alias.Nested? // $ definition=Alias definition=Base.Nested definition=Optional

unified/ql/test/library-tests/static-name-binding/explicit-instance-field-access.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ private class A {
1515
return self.y // $ not handled by static name binding
1616
}
1717

18-
class func z() -> Int { // name=A.type.z
18+
class func z() -> Int { // $ access=Int // name=A.type.z
1919
return 789
2020
}
2121

@@ -37,7 +37,7 @@ private class B : A { // $ access=A
3737
return self.y // $ not handled by static name binding
3838
}
3939

40-
class func z() -> Int { // name=B.type.z
40+
class func z() -> Int { // $ access=Int // name=B.type.z
4141
return 789
4242
}
4343

0 commit comments

Comments
 (0)