Skip to content
Draft
Show file tree
Hide file tree
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
15 changes: 12 additions & 3 deletions unified/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,24 @@ codeql_pkg_files(
otherwise = ["//unified/extractor"],
win64 = ["//unified/extractor-unsupported-os:extractor"],
),
prefix = "tools/{CODEQL_PLATFORM}",
prefix = "{CODEQL_PLATFORM}",
)

pkg_filegroup(
name = "tools",
srcs = [
":extractor-arch",
"//unified/tools",
"//unified/tools/builtins",
],
prefix = "tools",
)

codeql_pack(
name = "unified",
srcs = [
":codeql-extractor-yml",
":dbscheme-group",
":extractor-arch",
"//unified/tools",
":tools",
],
)
26 changes: 22 additions & 4 deletions unified/extractor/src/extractor.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use clap::Args;
use std::path::PathBuf;

use crate::languages;
use clap::Args;
use codeql_extractor::extractor::desugaring;
use codeql_extractor::trap;

use std::path::Path;
use std::path::PathBuf;
use std::{env, fs};
#[derive(Args)]
pub struct Options {
/// Sets a custom source archive folder
Expand All @@ -31,6 +31,24 @@ pub fn run(options: Options) -> std::io::Result<()> {
lang.prefix = "unified";
}

let builtins_path = env::var("CODEQL_EXTRACTOR_UNIFIED_ROOT")
.map(|path| Path::new(&path).join("tools").join("builtins"))
.expect("failed to read CODEQL_EXTRACTOR_UNIFIED_ROOT environment variable");
let builtins_dir = fs::read_dir(builtins_path).expect("failed to read builtins directory");
let mut file_list = fs::OpenOptions::new()
.append(true)
.open(&options.file_list)
.expect("failed to open file list");
Comment on lines +38 to +41
for entry in builtins_dir {
let entry = entry.expect("failed to read builtins directory");
let path = entry.path();
if path.extension().is_some_and(|ext| ext == "swift") {
use std::io::Write;
writeln!(file_list, "{}", path.display()).expect("failed to write to file list");
}
}
drop(file_list);

let extractor = desugaring::Extractor {
prefix: "unified".to_string(),
languages,
Expand Down
2 changes: 1 addition & 1 deletion unified/ql/lib/codeql/files/FileSystem.qll
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module Folder = Impl::Folder;
/** A file. */
class File extends Container, Impl::File {
/** Holds if this file was extracted from ordinary source code. */
predicate fromSource() { any() }
predicate fromSource() { exists(this.getRelativePath()) }

/**
* Gets the number of lines containing code in this file. This value
Expand Down
29 changes: 29 additions & 0 deletions unified/ql/lib/codeql/unified/internal/Builtins.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Provides classes for builtins.
*/

private import unified

/** The folder containing builtins. */
class BuiltinsFolder extends Folder {
BuiltinsFolder() {
this.getBaseName() = "builtins" and
this.getParentContainer().getBaseName() = "tools"
}
}

private class BuiltinsTypesFile extends File {
BuiltinsTypesFile() {
this.getBaseName() = "types.swift" and
this.getParentContainer() instanceof BuiltinsFolder
}
}

/**
* A builtin type, such as `Bool` and `String`.
*
* Builtin types are represented as structs.
*/
class BuiltinClassLikeDeclaration extends ClassLikeDeclaration {
BuiltinClassLikeDeclaration() { this.getFile() instanceof BuiltinsTypesFile }
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ private module Ast implements AstSig<Location> {

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

class Callable = U::Callable;
class Callable extends U::Callable {
Callable() { this.fromSource() }
}

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

Expand Down
3 changes: 3 additions & 0 deletions unified/ql/lib/codeql/unified/internal/FacadeAst.qll
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ module Unified {
/** Gets the file containing this AST node. */
File getFile() { result = this.getLocation().getFile() }

/** Holds if this AST node comes from ordinary source code. */
predicate fromSource() { this.getFile().fromSource() }

/** Holds if this AST node has a modifier with the given text. */
predicate hasModifier(string text) {
exists(Modifier mod |
Expand Down
4 changes: 3 additions & 1 deletion unified/ql/test/library-tests/BasicTest/test.ql
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import unified

query predicate identifier(Identifier node, string value) { value = node.getValue() }
query predicate identifier(Identifier node, string value) {
node.fromSource() and value = node.getValue()
}

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

Expand Down
2 changes: 1 addition & 1 deletion unified/ql/test/library-tests/comments/comments.ql
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import unified

query predicate comments(Comment c, string text) { text = c.getCommentText() }
query predicate comments(Comment c, string text) { c.fromSource() and text = c.getCommentText() }
4 changes: 2 additions & 2 deletions unified/ql/test/library-tests/definitions/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ func test() {
let local = 2 // name=local2
local // $ definition=local2
Derived.member // $ definition=Derived definition=Base.member
let _: Derived.Nested? // $ definition=Derived definition=Base.Nested
let _: Derived.Nested? // $ definition=Derived definition=Base.Nested definition=Optional
}

typealias Alias = Derived // $ definition=Derived
let _: Alias.Nested? // $ definition=Alias definition=Base.Nested
let _: Alias.Nested? // $ definition=Alias definition=Base.Nested definition=Optional
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private class A {
return self.y // $ not handled by static name binding
}

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

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

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

Expand Down
1 change: 0 additions & 1 deletion unified/tools/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ codeql_pkg_files(
"BUILD.bazel",
],
exes = glob(["**/*"]),
prefix = "tools",
visibility = ["//unified:__pkg__"],
)
8 changes: 8 additions & 0 deletions unified/tools/builtins/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("//misc/bazel:pkg.bzl", "codeql_pkg_files")

codeql_pkg_files(
name = "builtins",
srcs = glob(["*.swift"]),
prefix = "builtins",
visibility = ["//unified:__subpackages__"],
)
207 changes: 207 additions & 0 deletions unified/tools/builtins/types.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Provides built-in Swift types

struct Bool { }

struct Int { }

struct String { }

struct Character { }

struct Substring { }

struct Int8 { }

struct Int16 { }

struct Int32 { }

struct Int64 { }

struct UInt { }

struct UInt8 { }

struct UInt16 { }

struct UInt32 { }

struct UInt64 { }

struct Float16 { }

struct Float { }

struct Double { }

struct Float80 { }

struct Array<T> { }

struct Dictionary<Key, Value> { }

struct Set<Element> { }

enum Optional<Wrapped> {
case none
case some(Wrapped)
}

enum Result<Success, Failure> {
case success(Success)
case failure(Failure)
}

struct Range<Bound> { }

struct ClosedRange<Bound> { }

struct PartialRangeFrom<Bound> { }

struct PartialRangeThrough<Bound> { }

struct PartialRangeUpTo<Bound> { }

enum Never { }

struct UnsafePointer<Pointee> { }

struct UnsafeMutablePointer<Pointee> { }

struct UnsafeRawPointer { }

struct UnsafeMutableRawPointer { }

struct UnsafeBufferPointer<Element> { }

struct UnsafeMutableBufferPointer<Element> { }

struct UnsafeRawBufferPointer { }

struct UnsafeMutableRawBufferPointer { }

struct AutoreleasingUnsafeMutablePointer<Pointee> { }

struct OpaquePointer { }

struct Unmanaged<Instance> { }

struct Function<Args, Return> { } // `Args` is always instantiated as a tuple type

typealias Void = Tuple0

struct Tuple0 {}

struct Tuple1<T0> {
var _0: T0
}

struct Tuple2<T0, T1> {
var _0: T0
var _1: T1
}

struct Tuple3<T0, T1, T2> {
var _0: T0
var _1: T1
var _2: T2
}

struct Tuple4<T0, T1, T2, T3> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
}

struct Tuple5<T0, T1, T2, T3, T4> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
}

struct Tuple6<T0, T1, T2, T3, T4, T5> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
}

struct Tuple7<T0, T1, T2, T3, T4, T5, T6> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
}

struct Tuple8<T0, T1, T2, T3, T4, T5, T6, T7> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
var _7: T7
}

struct Tuple9<T0, T1, T2, T3, T4, T5, T6, T7, T8> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
var _7: T7
var _8: T8
}

struct Tuple10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
var _7: T7
var _8: T8
var _9: T9
}

struct Tuple11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
var _7: T7
var _8: T8
var _9: T9
var _10: T10
}

struct Tuple12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> {
var _0: T0
var _1: T1
var _2: T2
var _3: T3
var _4: T4
var _5: T5
var _6: T6
var _7: T7
var _8: T8
var _9: T9
var _10: T10
var _11: T11
}
Loading