diff --git a/.github/workflows/ffigenpad.yml b/.github/workflows/ffigenpad.yml new file mode 100644 index 0000000000..b8fe761839 --- /dev/null +++ b/.github/workflows/ffigenpad.yml @@ -0,0 +1,73 @@ +name: ffigenpad + +on: + pull_request: + branches: [main] + paths: + - ".github/workflows/ffigenpad.yaml" + - "pkgs/ffigenpad/**" + push: + branches: [main] + paths: + - ".github/workflows/ffigenpad.yaml" + - "pkgs/ffigenpad/**" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9a9194f87191a7e9055e3e9b95b8cfb13023bb08 + + - uses: dart-lang/setup-dart@e9a814f39d5452701455a47847735e0f482026c8 + with: + sdk: dev + + - run: dart pub get + working-directory: pkgs/ffigenpad + + - uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 + with: + version: 3.1.61 + + - name: setup ffigenpad + working-directory: pkgs/ffigenpad + run: dart run tool/setup.dart + + - name: build libclang.wasm + working-directory: pkgs/ffigenpad + run: dart run tool/build_libclang.dart --optimize + + - name: build ffigenpad + working-directory: pkgs/ffigenpad + run: | + dart compile wasm ./lib/ffigenpad.dart -o ./bin/ffigenpad.wasm -O3 \ + --extra-compiler-option=--enable-experimental-ffi \ + --extra-compiler-option=--enable-experimental-wasm-interop + + - uses: pnpm/action-setup@ac5bf11548bf5e19b8aadb8182072616590fa4a6 + with: + version: 9.7.0 + run_install: | + - cwd: pkgs/ffigenpad/web + + - uses: actions/configure-pages@aabcbc432d6b06d1fd5e8bf3cf756880c35e014d + + - name: build website + working-directory: pkgs/ffigenpad/web + run: pnpm build + + - uses: actions/upload-pages-artifact@1780dfc2cece65a782cc86fa133f96aef8ad0345 + with: + path: pkgs/ffigenpad/web/dist + + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/deploy-pages@b74272834adc04f971da4b0b055c49fa8d7f90c9 diff --git a/pkgs/ffigenpad/CHANGELOG.md b/pkgs/ffigenpad/CHANGELOG.md new file mode 100644 index 0000000000..a0712a79e7 --- /dev/null +++ b/pkgs/ffigenpad/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 + +- Initial version. diff --git a/pkgs/ffigenpad/README.md b/pkgs/ffigenpad/README.md new file mode 100644 index 0000000000..dfa9869a1b --- /dev/null +++ b/pkgs/ffigenpad/README.md @@ -0,0 +1,62 @@ +# FFIgenPad + +A web interface in which you paste a C header in a textbox on the left, and it outputs `dart:ffi` bindings generated by `package:ffigen` in a textbox on the right. (Inspiration is https://godbolt.org/ which does this for a C file on the left and assembly on the right.) + +It doesn't need a server cause it compiles the Dart code in `package:ffigen` and libclang to WASM. That way everything can run in the browser. + +------ + +## Project Structure + +Most of the files in `lib/src/` are copied from the source of *ffigen* with modifications to make it compatible with dart2wasm (many of the workarounds are listed in [this blog article](https://thecomputerm.hashnode.dev/dirty-deeds-done-dart-cheap-experiments-with-dart2wasm)). + +However the files listed do not have an ffigen counterpart: +- [./lib/ffigenpad.dart](./lib/ffigenpad.dart) +- [./lib/memfs.dart](./lib/memfs.dart) +- [./lib/src/header_parser/calloc.dart](./lib/src/header_parser/calloc.dart) +- [./lib/src/header_parser/clang_bindings/clang_types.dart](./lib/src/header_parser/clang_bindings/clang_types.dart) +- [./lib/src/header_parser/clang_bindings/clang_wrapper.dart](./lib/src/header_parser/clang_bindings/clang_wrapper.dart) + +## Building + +### Prerequisites + +- dart +- emscripten (>= 3.1.61) +- for website + - bunjs (>= ^1.2.0) + +### Steps + +- Run `tool/setup.dart` to download LLVM archive files to build *libclang.wasm* + +```sh +# in project root +dart run tool/setup.dart +``` + +- Run `tool/build_libclang.dart` to build *libclang.wasm* using functions exported from *third_party/libclang/libclang.exports* + +```sh +# in project root +dart run tool/build_libclang.dart +``` + +- Build FFIgenPad using the experimental dart2wasm compiler + +```sh +# in project root +dart compile wasm ./lib/ffigenpad.dart -o ./bin/ffigenpad.wasm \ + --extra-compiler-option=--enable-experimental-ffi \ + --extra-compiler-option=--enable-experimental-wasm-interop +``` + +- To build the website + +```sh +# in project root +cd web +bun i # install dependencies +bun run build +# preview with: npm run preview +``` diff --git a/pkgs/ffigenpad/analysis_options.yaml b/pkgs/ffigenpad/analysis_options.yaml new file mode 100644 index 0000000000..558786eefd --- /dev/null +++ b/pkgs/ffigenpad/analysis_options.yaml @@ -0,0 +1,33 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:dart_flutter_team_lints/analysis_options.yaml + +# Uncomment the following section to specify additional rules. + +linter: + rules: + implementation_imports: false + +analyzer: + errors: + todo: ignore + language: + strict-casts: true + strict-inference: true + strict-raw-types: true +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/pkgs/ffigenpad/bin/.gitignore b/pkgs/ffigenpad/bin/.gitignore new file mode 100644 index 0000000000..dcc2bd5c07 --- /dev/null +++ b/pkgs/ffigenpad/bin/.gitignore @@ -0,0 +1,3 @@ +*.wasm +*.mjs +*.wasm.map diff --git a/pkgs/ffigenpad/bin/README.md b/pkgs/ffigenpad/bin/README.md new file mode 100644 index 0000000000..e7686af554 --- /dev/null +++ b/pkgs/ffigenpad/bin/README.md @@ -0,0 +1,3 @@ +# Overview + +Contains build outputs for *libclang.wasm* and *ffigenpad.wasm*. diff --git a/pkgs/ffigenpad/lib/ffigenpad.dart b/pkgs/ffigenpad/lib/ffigenpad.dart new file mode 100644 index 0000000000..8f0a6c5482 --- /dev/null +++ b/pkgs/ffigenpad/lib/ffigenpad.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; + +import 'package:logging/logging.dart'; +import 'package:yaml/yaml.dart'; + +import 'memfs.dart'; +import 'src/config_provider.dart'; +import 'src/ffigen.dart'; + +@JS() +external void setLogs(JSObject logs); + +void generate(String yaml) { + final ffigen = FfiGen(logLevel: Level.ALL); + final config = YamlConfig.fromYaml(loadYaml(yaml) as YamlMap); + ffigen.run(config); +} + +void main(List args) { + final logs = []; + Logger.root.onRecord.listen((record) { + final log = JSObject(); + log.setProperty('level'.toJS, (record.level.value / 100).toJS); + log.setProperty('message'.toJS, record.message.toJS); + + logs.add(log); + }); + IOOverrides.runWithIOOverrides(() { + generate(args.first); + }, MemFSIOOverrides()); + setLogs(logs.toJS); +} diff --git a/pkgs/ffigenpad/lib/memfs.dart b/pkgs/ffigenpad/lib/memfs.dart new file mode 100644 index 0000000000..8b876aeaa9 --- /dev/null +++ b/pkgs/ffigenpad/lib/memfs.dart @@ -0,0 +1,122 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' as convert; +import 'dart:io'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import 'dart:typed_data'; + +// adapted functions from https://emscripten.org/docs/api_reference/Filesystem-API.html#id2 +extension type MemFS(JSObject _) implements JSObject { + external JSArray readdir(String path); + external JSUint8Array readFile(String path, [JSObject? opts]); + external void writeFile(String path, String data); + external void unlink(String path); + external void mkdir(String path); + external void rmdir(String path); + external void rename(String oldpath, String newpath); + external String cwd(); + external void chdir(String path); + external JSObject analyzePath(String path, bool dontResolveLastLink); +} + +@JS('FS') +external MemFS get memfs; + +class MemFSDirectory implements Directory { + @override + String path; + + MemFSDirectory(this.path); + + @override + void createSync({bool recursive = false}) { + memfs.mkdir(path); + } + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +class MemFSFile implements File { + @override + String path; + + MemFSFile(this.path); + + @override + MemFSFile get absolute => MemFSFile(path); + + @override + void createSync({bool recursive = false, bool exclusive = false}) { + memfs.writeFile(path, ''); + } + + @override + void deleteSync({bool recursive = false}) { + memfs.unlink(path); + } + + @override + bool existsSync() { + return memfs + .analyzePath(path, false) + .getProperty('exists'.toJS) + .toDart; + } + + @override + void writeAsStringSync(String contents, + {FileMode mode = FileMode.write, + convert.Encoding encoding = convert.utf8, + bool flush = false}) { + memfs.writeFile(path, contents); + } + + @override + Uint8List readAsBytesSync() { + return memfs.readFile(path).toDart; + } + + @override + String readAsStringSync({convert.Encoding encoding = convert.utf8}) { + return encoding.decode(readAsBytesSync()); + } + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +class MemFSIOOverrides extends IOOverrides { + @override + MemFSDirectory createDirectory(String path) { + return MemFSDirectory(path); + } + + @override + MemFSFile createFile(String path) { + return MemFSFile(path); + } + + @override + bool fsWatchIsSupported() { + return false; + } + + @override + void setCurrentDirectory(String path) { + memfs.chdir(path); + } + + @override + MemFSDirectory getCurrentDirectory() { + return MemFSDirectory(memfs.cwd()); + } + + @override + MemFSDirectory getSystemTempDirectory() { + return MemFSDirectory('/tmp'); + } +} diff --git a/pkgs/ffigenpad/lib/src/code_generator.dart b/pkgs/ffigenpad/lib/src/code_generator.dart new file mode 100644 index 0000000000..033c0ef336 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Generates FFI bindings for a given Library. +library; + +export 'code_generator/binding.dart'; +export 'code_generator/compound.dart'; +export 'code_generator/constant.dart'; +export 'code_generator/enum_class.dart'; +export 'code_generator/func.dart'; +export 'code_generator/func_type.dart'; +export 'code_generator/global.dart'; +export 'code_generator/handle.dart'; +export 'code_generator/imports.dart'; +export 'code_generator/library.dart'; +export 'code_generator/native_type.dart'; +export 'code_generator/objc_block.dart'; +export 'code_generator/objc_built_in_functions.dart'; +export 'code_generator/objc_interface.dart'; +export 'code_generator/objc_methods.dart'; +export 'code_generator/objc_nullable.dart'; +export 'code_generator/objc_protocol.dart'; +export 'code_generator/pointer.dart'; +export 'code_generator/struct.dart'; +export 'code_generator/type.dart'; +export 'code_generator/typealias.dart'; +export 'code_generator/union.dart'; diff --git a/pkgs/ffigenpad/lib/src/code_generator/binding.dart b/pkgs/ffigenpad/lib/src/code_generator/binding.dart new file mode 100644 index 0000000000..810ba1251d --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/binding.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'binding_string.dart'; +import 'writer.dart'; + +/// Base class for all Bindings. +/// +/// Do not extend directly, use [LookUpBinding] or [NoLookUpBinding]. +abstract class Binding { + /// Holds the Unified Symbol Resolution string obtained from libclang. + final String usr; + + /// The name as it was in C. + final String originalName; + + /// Binding name to generate, may get changed to resolve name conflicts. + String name; + + final String? dartDoc; + final bool isInternal; + + Binding({ + required this.usr, + required this.originalName, + required this.name, + this.dartDoc, + this.isInternal = false, + }); + + /// Get all dependencies, including itself and save them in [dependencies]. + void addDependencies(Set dependencies); + + /// Converts a Binding to its actual string representation. + /// + /// Note: This does not print the typedef dependencies. + /// Must call getTypedefDependencies first. + BindingString toBindingString(Writer w); + + /// Returns the Objective C bindings, if any. + BindingString? toObjCBindingString(Writer w) => null; +} + +/// Base class for bindings which look up symbols in dynamic library. +abstract class LookUpBinding extends Binding { + LookUpBinding({ + String? usr, + String? originalName, + required super.name, + super.dartDoc, + super.isInternal, + }) : super( + usr: usr ?? name, + originalName: originalName ?? name, + ); +} + +/// Base class for bindings which don't look up symbols in dynamic library. +abstract class NoLookUpBinding extends Binding { + NoLookUpBinding({ + String? usr, + String? originalName, + required super.name, + super.dartDoc, + super.isInternal, + }) : super( + usr: usr ?? name, + originalName: originalName ?? name, + ); +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/binding_string.dart b/pkgs/ffigenpad/lib/src/code_generator/binding_string.dart new file mode 100644 index 0000000000..58b2b276a6 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/binding_string.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'package:ffigen/src/code_generator/binding_string.dart'; diff --git a/pkgs/ffigenpad/lib/src/code_generator/compound.dart b/pkgs/ffigenpad/lib/src/code_generator/compound.dart new file mode 100644 index 0000000000..7eda0281de --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/compound.dart @@ -0,0 +1,201 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +enum CompoundType { struct, union } + +/// A binding for Compound type - Struct/Union. +abstract class Compound extends BindingType { + /// Marker for if a struct definition is complete. + /// + /// A function can be safely pass this struct by value if it's complete. + bool isIncomplete; + + List members; + + bool get isOpaque => members.isEmpty; + + /// Value for `@Packed(X)` annotation. Can be null (no packing), 1, 2, 4, 8, + /// or 16. + /// + /// Only supported for [CompoundType.struct]. + int? pack; + + /// Marker for checking if the dependencies are parsed. + bool parsedDependencies = false; + + CompoundType compoundType; + bool get isStruct => compoundType == CompoundType.struct; + bool get isUnion => compoundType == CompoundType.union; + + ObjCBuiltInFunctions? objCBuiltInFunctions; + + /// The way the native type is written in C source code. This isn't always the + /// same as the originalName, because the type may need to be prefixed with + /// `struct` or `union`, depending on whether the declaration is a typedef. + final String nativeType; + + Compound({ + super.usr, + super.originalName, + required super.name, + required this.compoundType, + this.isIncomplete = false, + this.pack, + super.dartDoc, + List? members, + super.isInternal, + this.objCBuiltInFunctions, + String? nativeType, + }) : members = members ?? [], + nativeType = nativeType ?? originalName ?? name; + + factory Compound.fromType({ + required CompoundType type, + String? usr, + String? originalName, + required String name, + bool isIncomplete = false, + int? pack, + String? dartDoc, + List? members, + ObjCBuiltInFunctions? objCBuiltInFunctions, + String? nativeType, + }) { + switch (type) { + case CompoundType.struct: + return Struct( + usr: usr, + originalName: originalName, + name: name, + isIncomplete: isIncomplete, + pack: pack, + dartDoc: dartDoc, + members: members, + objCBuiltInFunctions: objCBuiltInFunctions, + nativeType: nativeType, + ); + case CompoundType.union: + return Union( + usr: usr, + originalName: originalName, + name: name, + isIncomplete: isIncomplete, + pack: pack, + dartDoc: dartDoc, + members: members, + objCBuiltInFunctions: objCBuiltInFunctions, + nativeType: nativeType, + ); + } + } + + String _getInlineArrayTypeString(Type type, Writer w) { + if (type is ConstantArray) { + return '${w.ffiLibraryPrefix}.Array<' + '${_getInlineArrayTypeString(type.child, w)}>'; + } + return type.getCType(w); + } + + bool get _isBuiltIn => + objCBuiltInFunctions?.isBuiltInCompound(originalName) ?? false; + + @override + BindingString toBindingString(Writer w) { + final bindingType = + isStruct ? BindingStringType.struct : BindingStringType.union; + if (_isBuiltIn) { + return BindingString(type: bindingType, string: ''); + } + + final s = StringBuffer(); + final enclosingClassName = name; + if (dartDoc != null) { + s.write(makeDartDoc(dartDoc!)); + } + + /// Adding [enclosingClassName] because dart doesn't allow class member + /// to have the same name as the class. + final localUniqueNamer = UniqueNamer({enclosingClassName}); + + /// Marking type names because dart doesn't allow class member to have the + /// same name as a type name used internally. + for (final m in members) { + localUniqueNamer.markUsed(m.type.getFfiDartType(w)); + } + + /// Write @Packed(X) annotation if struct is packed. + if (isStruct && pack != null) { + s.write('@${w.ffiLibraryPrefix}.Packed($pack)\n'); + } + final dartClassName = isStruct ? 'Struct' : 'Union'; + // Write class declaration. + s.write('final class $enclosingClassName extends '); + s.write('${w.ffiLibraryPrefix}.${isOpaque ? 'Opaque' : dartClassName}{\n'); + const depth = ' '; + for (final m in members) { + m.name = localUniqueNamer.makeUnique(m.name); + if (m.dartDoc != null) { + s.write('$depth/// '); + s.writeAll(m.dartDoc!.split('\n'), '\n$depth/// '); + s.write('\n'); + } + if (m.type case final ConstantArray arrayType) { + s.writeln(makeArrayAnnotation(w, arrayType)); + s.write('${depth}external ${_getInlineArrayTypeString(m.type, w)} '); + s.write('${m.name};\n\n'); + } else { + if (!m.type.sameFfiDartAndCType) { + s.write('$depth@${m.type.getCType(w)}()\n'); + } + s.write('${depth}external ${m.type.getFfiDartType(w)} ${m.name};\n\n'); + } + } + s.write('}\n\n'); + + return BindingString(type: bindingType, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this) || _isBuiltIn) return; + + dependencies.add(this); + for (final m in members) { + m.type.addDependencies(dependencies); + } + } + + @override + bool get isIncompleteCompound => isIncomplete; + + @override + String getCType(Writer w) => _isBuiltIn ? '${w.objcPkgPrefix}.$name' : name; + + @override + String getNativeType({String varName = ''}) => '$nativeType $varName'; + + @override + bool get sameFfiDartAndCType => true; +} + +class Member { + final String? dartDoc; + final String originalName; + String name; + final Type type; + + Member({ + String? originalName, + required this.name, + required this.type, + this.dartDoc, + }) : originalName = originalName ?? name; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/constant.dart b/pkgs/ffigenpad/lib/src/code_generator/constant.dart new file mode 100644 index 0000000000..0bef022491 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/constant.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'binding.dart'; +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +/// A simple Constant. +/// +/// Expands to - +/// ```dart +/// const = ; +/// ``` +/// +/// Example - +/// ```dart +/// const int name = 10; +/// ``` +class Constant extends NoLookUpBinding { + /// The rawType is pasted as it is. E.g 'int', 'String', 'double' + final String rawType; + + /// The rawValue is pasted as it is. + /// + /// Put quotes if type is a string. + final String rawValue; + + Constant({ + super.usr, + super.originalName, + required super.name, + super.dartDoc, + required this.rawType, + required this.rawValue, + }); + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + final constantName = name; + + if (dartDoc != null) { + s.write(makeDartDoc(dartDoc!)); + } + + s.write('\nconst $rawType $constantName = $rawValue;\n\n'); + + return BindingString( + type: BindingStringType.constant, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + + dependencies.add(this); + } +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/dart_keywords.dart b/pkgs/ffigenpad/lib/src/code_generator/dart_keywords.dart new file mode 100644 index 0000000000..ff778c178a --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/dart_keywords.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'package:ffigen/src/code_generator/dart_keywords.dart'; diff --git a/pkgs/ffigenpad/lib/src/code_generator/enum_class.dart b/pkgs/ffigenpad/lib/src/code_generator/enum_class.dart new file mode 100644 index 0000000000..105c15f395 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/enum_class.dart @@ -0,0 +1,332 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; + +import 'binding.dart'; +import 'binding_string.dart'; +import 'imports.dart'; +import 'objc_built_in_functions.dart'; +import 'type.dart'; +import 'utils.dart'; +import 'writer.dart'; + +/// A binding for enums in C. +/// +/// For a C enum - +/// ```c +/// enum Fruits {apple, banana = 10, yellow_fruit = 10}; +/// ``` +/// The generated dart code is +/// +/// ```dart +/// enum Fruits { +/// apple(0), +/// banana(10); +/// +/// static const yellow_fruit = banana; +/// +/// final int value; +/// const Fruit(this.value); +/// +/// @override +/// String toString() { +/// if (this == banana) return "Fruits.banana, Fruits.yellow_fruit"; +/// return super.toString(); +/// } +/// } +/// ``` +class EnumClass extends BindingType { + /// Backing integer type for this enum. + Type nativeType; + + /// The amount of indentation in every line. + static const depth = ' '; + + /// A list of all the members of the native enum. + final List enumConstants; + + /// Generates new names for all members that don't equal [name]. + final UniqueNamer namer; + + ObjCBuiltInFunctions? objCBuiltInFunctions; + + /// Whether this enum should be generated as a collection of integers. + bool generateAsInt; + + EnumClass({ + super.usr, + super.originalName, + required super.name, + super.dartDoc, + Type? nativeType, + List? enumConstants, + this.objCBuiltInFunctions, + this.generateAsInt = false, + }) : nativeType = nativeType ?? intType, + enumConstants = enumConstants ?? [], + namer = UniqueNamer({name}); + + /// The names of all the enum members generated by [namer]. + final Map enumNames = {}; + + /// Maps all unique enum values to a list of their duplicates or aliases. + /// + /// See [scanForDuplicates] and [writeToStringOverride]. + final Map> uniqueToDuplicates = {}; + + /// Maps all duplicate enum members to the member who first had that value. + /// + /// See [scanForDuplicates] and [writeDuplicateMembers]. + final Map duplicateToOriginal = {}; + + /// A collection of all the enum members with unique values. + /// + /// See [scanForDuplicates] and [writeUniqueMembers]. + final Set uniqueMembers = {}; + + /// Returns a string to declare the enum member and any documentation it may + /// have had. + String formatValue(EnumConstant ec, {bool asInt = false}) { + final buffer = StringBuffer(); + final enumValueName = namer.makeUnique(ec.name); + enumNames[ec] = enumValueName; + if (ec.dartDoc != null) { + buffer.write('$depth/// '); + buffer.writeAll(ec.dartDoc!.split('\n'), '\n$depth/// '); + buffer.write('\n'); + } + if (asInt) { + buffer.write('${depth}static const $enumValueName = ${ec.value};'); + } else { + buffer.write('$depth$enumValueName(${ec.value})'); + } + return buffer.toString(); + } + + /// Finds enum values that are duplicates of previous enum values. + /// + /// Since all enum values in Dart are distinct, these duplicates do not + /// get their own values in Dart. Rather, they are aliases of the original + /// value. For example, if a native enum has 2 constants with a value of 10, + /// only one enum value will be generated in Dart, and the other will be set + /// equal to it. + void scanForDuplicates() { + uniqueMembers.clear(); + uniqueToDuplicates.clear(); + duplicateToOriginal.clear(); + for (final ec in enumConstants) { + final original = uniqueMembers.firstWhereOrNull( + (other) => other.value == ec.value, + ); + if (original == null) { + // This is a unique entry + uniqueMembers.add(ec); + uniqueToDuplicates[ec] = []; + } else { + // This is a duplicate of a previous entry + duplicateToOriginal[ec] = original; + uniqueToDuplicates[original]!.add(ec); + } + } + } + + void writeIntegerConstants(StringBuffer s) { + s.writeAll(enumConstants.map((c) => formatValue(c, asInt: true)), '\n'); + } + + /// Writes the enum declarations for all unique members. + /// + /// Eg, C: `apple = 1`, Dart: `apple(1)` + void writeUniqueMembers(StringBuffer s) { + s.writeAll(uniqueMembers.map(formatValue), ',\n'); + if (uniqueMembers.isNotEmpty) s.write(';\n'); + } + + /// Writes alias declarations for all members with duplicate values. + /// + /// Eg, C: `banana = 10, yellow_fruit = 10`. + /// Dart: `static const yellow_fruit = banana`. + void writeDuplicateMembers(StringBuffer s) { + if (duplicateToOriginal.isEmpty) return; + for (final entry in duplicateToOriginal.entries) { + final duplicate = entry.key; + final original = entry.value; + final duplicateName = namer.makeUnique(duplicate.name); + // [!] Each original enum value was given a name in [writeUniqueMembers]. + final originalName = enumNames[original]!; + enumNames[duplicate] = duplicateName; + if (duplicate.dartDoc != null) { + s.write('$depth/// '); + s.writeAll(duplicate.dartDoc!.split('\n'), '\n$depth/// '); + s.write('\n'); + } + s.write('${depth}static const $duplicateName = $originalName;\n'); + } + } + + /// Writes the constructor for the enum. + /// + /// Always accepts an integer value to match the native value. + void writeConstructor(StringBuffer s) { + s.write('${depth}final int value;\n'); + s.write('${depth}const $name(this.value);\n'); + } + + /// Overrides [Enum.toString] so all aliases are included, if any. + /// + /// If a native enum has two members with the same value, they are + /// functionally identical, and should be represented as such. This method + /// overrides [toString] to include all duplicate members in the same message. + void writeToStringOverride(StringBuffer s) { + if (duplicateToOriginal.isEmpty) return; + s.write('$depth@override\n'); + s.write('${depth}String toString() {\n'); + for (final entry in uniqueToDuplicates.entries) { + // [!] All enum values were given a name when their declarations were + // generated. + final unique = entry.key; + final originalName = enumNames[unique]!; + final duplicates = entry.value; + if (duplicates.isEmpty) continue; + final allDuplicates = [ + for (final duplicate in [unique] + duplicates) + '$name.${enumNames[duplicate]!}', + ].join(', '); + s.write( + '$depth$depth' + 'if (this == $originalName) return "$allDuplicates";\n', + ); + } + s.write('${depth * 2}return super.toString();\n'); + s.write('$depth}'); + } + + /// Writes the DartDoc string for this enum. + void writeDartDoc(StringBuffer s) { + if (dartDoc != null) { + s.write(makeDartDoc(dartDoc!)); + } + } + + /// Writes a sealed class when no members exist, because Dart enums cannot be + /// empty. + void writeEmptyEnum(StringBuffer s) { + s.write('sealed class $name { }\n'); + } + + /// Writes a static function that maps integers to enum values. + void writeFromValue(StringBuffer s) { + s.write('${depth}static $name fromValue(int value) => switch (value) {\n'); + for (final member in uniqueMembers) { + final memberName = enumNames[member]!; + s.write('$depth$depth${member.value} => $memberName,\n'); + } + s.write( + '$depth${depth}_ => ' + 'throw ArgumentError("Unknown value for $name: \$value"),\n', + ); + s.write('$depth};\n'); + } + + bool get _isBuiltIn => + objCBuiltInFunctions?.isBuiltInEnum(originalName) ?? false; + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + if (_isBuiltIn) { + return const BindingString(type: BindingStringType.enum_, string: ''); + } + scanForDuplicates(); + + writeDartDoc(s); + if (enumConstants.isEmpty) { + writeEmptyEnum(s); + } else if (generateAsInt) { + s.write('abstract class $name {\n'); + writeIntegerConstants(s); + s.write('}\n\n'); + } else { + s.write('enum $name {\n'); + writeUniqueMembers(s); + s.write('\n'); + writeDuplicateMembers(s); + s.write('\n'); + writeConstructor(s); + s.write('\n'); + writeFromValue(s); + s.write('\n'); + writeToStringOverride(s); + s.write('}\n\n'); + } + + return BindingString( + type: BindingStringType.enum_, + string: s.toString(), + ); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this) || _isBuiltIn) return; + dependencies.add(this); + } + + @override + String getCType(Writer w) { + w.usedEnumCType = true; + return nativeType.getCType(w); + } + + @override + String getFfiDartType(Writer w) => nativeType.getFfiDartType(w); + + @override + String getDartType(Writer w) => + _isBuiltIn ? '${w.objcPkgPrefix}.$name' : name; + + @override + String getNativeType({String varName = ''}) => '$originalName $varName'; + + @override + bool get sameFfiDartAndCType => nativeType.sameFfiDartAndCType; + + @override + bool get sameDartAndFfiDartType => generateAsInt; + + @override + String? getDefaultValue(Writer w) => '0'; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + '$value.value'; + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + '${getDartType(w)}.fromValue($value)'; +} + +/// Represents a single value in an enum. +class EnumConstant { + final String? originalName; + final String? dartDoc; + final String name; + final int value; + const EnumConstant({ + String? originalName, + required this.name, + required this.value, + this.dartDoc, + }) : originalName = originalName ?? name; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/func.dart b/pkgs/ffigenpad/lib/src/code_generator/func.dart new file mode 100644 index 0000000000..3f5fcce1a4 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/func.dart @@ -0,0 +1,237 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; +import '../config_provider/config_types.dart'; + +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +/// A binding for C function. +/// +/// For example, take the following C function. +/// +/// ```c +/// int sum(int a, int b); +/// ``` +/// +/// The generated Dart code for this function (without `FfiNative`) is as +/// follows. +/// +/// ```dart +/// int sum(int a, int b) { +/// return _sum(a, b); +/// } +/// +/// final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum'); +/// +/// typedef _c_sum = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b); +/// +/// typedef _dart_sum = int Function(int a, int b); +/// ``` +/// +/// When using `Native`, the code is as follows. +/// +/// ```dart +/// @ffi.Native('sum') +/// external int sum(int a, int b); +/// ``` +class Func extends LookUpBinding { + final FunctionType functionType; + final bool exposeSymbolAddress; + final bool exposeFunctionTypedefs; + final bool isLeaf; + final bool objCReturnsRetained; + final bool useNameForLookup; + final FfiNativeConfig ffiNativeConfig; + late final String funcPointerName; + + /// Contains typealias for function type if [exposeFunctionTypedefs] is true. + Typealias? _exposedFunctionTypealias; + + /// [originalName] is looked up in dynamic library, if not + /// provided, takes the value of [name]. + Func({ + super.usr, + required String name, + super.originalName, + super.dartDoc, + required Type returnType, + List? parameters, + List? varArgParameters, + this.exposeSymbolAddress = false, + this.exposeFunctionTypedefs = false, + this.isLeaf = false, + this.objCReturnsRetained = false, + this.useNameForLookup = false, + super.isInternal, + this.ffiNativeConfig = const FfiNativeConfig(enabled: false), + }) : functionType = FunctionType( + returnType: returnType, + parameters: parameters ?? const [], + varArgParameters: varArgParameters ?? const [], + ), + super( + name: name, + ) { + for (var i = 0; i < functionType.parameters.length; i++) { + if (functionType.parameters[i].name.trim() == '') { + functionType.parameters[i].name = 'arg$i'; + } + } + + // Get function name with first letter in upper case. + final upperCaseName = name[0].toUpperCase() + name.substring(1); + if (exposeFunctionTypedefs) { + _exposedFunctionTypealias = Typealias( + name: upperCaseName, + type: functionType, + genFfiDartType: true, + isInternal: true, + ); + } + } + + String get _lookupName => useNameForLookup ? name : originalName; + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + final enclosingFuncName = name; + + if (dartDoc != null) { + s.write(makeDartDoc(dartDoc!)); + } + // Resolve name conflicts in function parameter names. + final paramNamer = UniqueNamer({}); + for (final p in functionType.dartTypeParameters) { + p.name = paramNamer.makeUnique(p.name); + } + + final cType = _exposedFunctionTypealias?.getCType(w) ?? + functionType.getCType(w, writeArgumentNames: false); + final dartType = _exposedFunctionTypealias?.getFfiDartType(w) ?? + functionType.getFfiDartType(w, writeArgumentNames: false); + final needsWrapper = !functionType.sameDartAndFfiDartType && !isInternal; + + final funcVarName = w.wrapperLevelUniqueNamer.makeUnique('_$name'); + final ffiReturnType = functionType.returnType.getFfiDartType(w); + final ffiArgDeclString = functionType.dartTypeParameters + .map((p) => '${p.type.getFfiDartType(w)} ${p.name},\n') + .join(''); + + late final String dartReturnType; + late final String dartArgDeclString; + late final String funcImplCall; + if (needsWrapper) { + dartReturnType = functionType.returnType.getDartType(w); + dartArgDeclString = functionType.dartTypeParameters + .map((p) => '${p.type.getDartType(w)} ${p.name},\n') + .join(''); + + final argString = functionType.dartTypeParameters.map((p) { + final type = + p.type.convertDartTypeToFfiDartType(w, p.name, objCRetain: false); + return '$type,\n'; + }).join(''); + funcImplCall = functionType.returnType.convertFfiDartTypeToDartType( + w, + '$funcVarName($argString)', + objCRetain: !objCReturnsRetained, + ); + } else { + dartReturnType = ffiReturnType; + dartArgDeclString = ffiArgDeclString; + final argString = + functionType.dartTypeParameters.map((p) => '${p.name},\n').join(''); + funcImplCall = '$funcVarName($argString)'; + } + + if (ffiNativeConfig.enabled) { + final nativeFuncName = needsWrapper ? funcVarName : enclosingFuncName; + s.write(''' +${makeNativeAnnotation( + w, + nativeType: cType, + dartName: nativeFuncName, + nativeSymbolName: _lookupName, + isLeaf: isLeaf, + )} +external $ffiReturnType $nativeFuncName($ffiArgDeclString); + +'''); + if (needsWrapper) { + s.write(''' +$dartReturnType $enclosingFuncName($dartArgDeclString) => $funcImplCall; + +'''); + } + + if (exposeSymbolAddress) { + // Add to SymbolAddress in writer. + w.symbolAddressWriter.addNativeSymbol( + type: '${w.ffiLibraryPrefix}.Pointer<' + '${w.ffiLibraryPrefix}.NativeFunction<$cType>>', + name: name, + ); + } + } else { + funcPointerName = w.wrapperLevelUniqueNamer.makeUnique('_${name}Ptr'); + final isLeafString = isLeaf ? 'isLeaf:true' : ''; + + // Write enclosing function. + s.write(''' +$dartReturnType $enclosingFuncName($dartArgDeclString) { + return $funcImplCall; +} + +'''); + + if (exposeSymbolAddress) { + // Add to SymbolAddress in writer. + w.symbolAddressWriter.addSymbol( + type: '${w.ffiLibraryPrefix}.Pointer<' + '${w.ffiLibraryPrefix}.NativeFunction<$cType>>', + name: name, + ptrName: funcPointerName, + ); + } + + // Write function pointer. + s.write(''' +late final $funcPointerName = ${w.lookupFuncIdentifier}< + ${w.ffiLibraryPrefix}.NativeFunction<$cType>>('$_lookupName'); +late final $funcVarName = $funcPointerName.asFunction<$dartType>($isLeafString); + +'''); + } + + return BindingString(type: BindingStringType.func, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + + dependencies.add(this); + functionType.addDependencies(dependencies); + if (exposeFunctionTypedefs) { + _exposedFunctionTypealias!.addDependencies(dependencies); + } + } +} + +/// Represents a Parameter, used in [Func] and [Typealias]. +class Parameter { + final String? originalName; + String name; + final Type type; + + Parameter({String? originalName, this.name = '', required Type type}) + : originalName = originalName ?? name, + // A [NativeFunc] is wrapped with a pointer because this is a shorthand + // used in C for Pointer to function. + type = type.typealiasType is NativeFunc ? PointerType(type) : type; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/func_type.dart b/pkgs/ffigenpad/lib/src/code_generator/func_type.dart new file mode 100644 index 0000000000..a7f00e5354 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/func_type.dart @@ -0,0 +1,160 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; +import 'utils.dart'; + +import 'writer.dart'; + +/// Represents a function type. +class FunctionType extends Type { + final Type returnType; + final List parameters; + final List varArgParameters; + + /// Get all the parameters for generating the dart type. This includes both + /// [parameters] and [varArgParameters]. + List get dartTypeParameters => parameters + varArgParameters; + + FunctionType({ + required this.returnType, + required this.parameters, + this.varArgParameters = const [], + }); + + String _getTypeImpl( + bool writeArgumentNames, String Function(Type) typeToString, + {String? varArgWrapper}) { + final params = varArgWrapper != null ? parameters : dartTypeParameters; + String? varArgPack; + if (varArgWrapper != null && varArgParameters.isNotEmpty) { + final varArgPackBuf = StringBuffer(); + varArgPackBuf.write('$varArgWrapper<('); + varArgPackBuf.write(varArgParameters.map((p) { + return '${typeToString(p.type)} ${writeArgumentNames ? p.name : ""}'; + }).join(', ')); + varArgPackBuf.write(',)>'); + varArgPack = varArgPackBuf.toString(); + } + + // Write return Type. + final sb = StringBuffer(); + sb.write(typeToString(returnType)); + + // Write Function. + sb.write(' Function('); + sb.write([ + ...params.map((p) { + return '${typeToString(p.type)} ${writeArgumentNames ? p.name : ""}'; + }), + if (varArgPack != null) varArgPack, + ].join(', ')); + sb.write(')'); + + return sb.toString(); + } + + @override + String getCType(Writer w, {bool writeArgumentNames = true}) => + _getTypeImpl(writeArgumentNames, (Type t) => t.getCType(w), + varArgWrapper: '${w.ffiLibraryPrefix}.VarArgs'); + + @override + String getFfiDartType(Writer w, {bool writeArgumentNames = true}) => + _getTypeImpl(writeArgumentNames, (Type t) => t.getFfiDartType(w)); + + @override + String getDartType(Writer w, {bool writeArgumentNames = true}) => + _getTypeImpl(writeArgumentNames, (Type t) => t.getDartType(w)); + + @override + String getNativeType({String varName = ''}) { + final arg = dartTypeParameters.map((p) => p.type.getNativeType()); + return '${returnType.getNativeType()} (*$varName)(${arg.join(', ')})'; + } + + @override + bool get sameFfiDartAndCType => + returnType.sameFfiDartAndCType && + dartTypeParameters.every((p) => p.type.sameFfiDartAndCType); + + @override + bool get sameDartAndCType => + returnType.sameDartAndCType && + dartTypeParameters.every((p) => p.type.sameDartAndCType); + + @override + bool get sameDartAndFfiDartType => + returnType.sameDartAndFfiDartType && + dartTypeParameters.every((p) => p.type.sameDartAndFfiDartType); + + @override + String toString() => _getTypeImpl(false, (Type t) => t.toString()); + + @override + String cacheKey() => _getTypeImpl(false, (Type t) => t.cacheKey()); + + @override + void addDependencies(Set dependencies) { + returnType.addDependencies(dependencies); + for (final p in parameters) { + p.type.addDependencies(dependencies); + } + } + + void addParameterNames(List names) { + if (names.length != parameters.length) { + return; + } + final paramNamer = UniqueNamer({}); + for (var i = 0; i < parameters.length; i++) { + final finalName = paramNamer.makeUnique(names[i]); + parameters[i] = Parameter( + type: parameters[i].type, + originalName: names[i], + name: finalName, + ); + } + } +} + +/// Represents a NativeFunction<Function>. +class NativeFunc extends Type { + // Either a FunctionType or a Typealias of a FunctionType. + final Type _type; + + NativeFunc(this._type) : assert(_type is FunctionType || _type is Typealias); + + FunctionType get type { + if (_type is Typealias) { + return _type.typealiasType as FunctionType; + } + return _type as FunctionType; + } + + @override + void addDependencies(Set dependencies) { + _type.addDependencies(dependencies); + } + + @override + String getCType(Writer w) => + '${w.ffiLibraryPrefix}.NativeFunction<${_type.getCType(w)}>'; + + @override + String getFfiDartType(Writer w) => getCType(w); + + @override + String getNativeType({String varName = ''}) => + _type.getNativeType(varName: varName); + + @override + bool get sameFfiDartAndCType => true; + + @override + String toString() => 'NativeFunction<${_type.toString()}>'; + + @override + String cacheKey() => 'NatFn(${_type.cacheKey()})'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/global.dart b/pkgs/ffigenpad/lib/src/code_generator/global.dart new file mode 100644 index 0000000000..6bb1504010 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/global.dart @@ -0,0 +1,117 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../config_provider/config_types.dart'; +import 'binding.dart'; +import 'binding_string.dart'; +import 'compound.dart'; +import 'pointer.dart'; +import 'type.dart'; +import 'utils.dart'; +import 'writer.dart'; + +/// A binding to a global variable +/// +/// For a C global variable - +/// ```c +/// int a; +/// ``` +/// The generated dart code is - +/// ```dart +/// final int a = _dylib.lookup('a').value; +/// ``` +class Global extends LookUpBinding { + final Type type; + final bool exposeSymbolAddress; + final FfiNativeConfig nativeConfig; + final bool constant; + + Global({ + super.usr, + super.originalName, + required super.name, + required this.type, + super.dartDoc, + this.exposeSymbolAddress = false, + this.constant = false, + this.nativeConfig = const FfiNativeConfig(enabled: false), + }); + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + final globalVarName = name; + if (dartDoc != null) { + s.write(makeDartDoc(dartDoc!)); + } + final dartType = type.getFfiDartType(w); + final cType = type.getCType(w); + + if (nativeConfig.enabled) { + if (type case final ConstantArray arr) { + s.writeln(makeArrayAnnotation(w, arr)); + } + + s + ..writeln(makeNativeAnnotation( + w, + nativeType: cType, + dartName: globalVarName, + nativeSymbolName: originalName, + isLeaf: false, + )) + ..write('external '); + if (constant) { + s.write('final '); + } + + s.writeln('$dartType $globalVarName;\n'); + + if (exposeSymbolAddress) { + w.symbolAddressWriter.addNativeSymbol( + type: '${w.ffiLibraryPrefix}.Pointer<$cType>', name: name); + } + } else { + final pointerName = + w.wrapperLevelUniqueNamer.makeUnique('_$globalVarName'); + + s.write('late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ' + "${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n"); + final baseTypealiasType = type.typealiasType; + if (baseTypealiasType is Compound) { + if (baseTypealiasType.isOpaque) { + s.write('${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName =>' + ' $pointerName;\n\n'); + } else { + s.write('$dartType get $globalVarName => $pointerName.ref;\n\n'); + } + } else { + s.write('$dartType get $globalVarName => $pointerName.value;\n\n'); + if (!constant) { + s.write('set $globalVarName($dartType value) =>' + '$pointerName.value = value;\n\n'); + } + } + + if (exposeSymbolAddress) { + // Add to SymbolAddress in writer. + w.symbolAddressWriter.addSymbol( + type: '${w.ffiLibraryPrefix}.Pointer<$cType>', + name: name, + ptrName: pointerName, + ); + } + } + + return BindingString(type: BindingStringType.global, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + + dependencies.add(this); + type.addDependencies(dependencies); + } +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/handle.dart b/pkgs/ffigenpad/lib/src/code_generator/handle.dart new file mode 100644 index 0000000000..de4f30c831 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/handle.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'writer.dart'; + +/// Represents a Dart_Handle. +class HandleType extends Type { + const HandleType._(); + static const _handle = HandleType._(); + factory HandleType() => _handle; + + @override + String getCType(Writer w) => '${w.ffiLibraryPrefix}.Handle'; + + @override + String getFfiDartType(Writer w) => 'Object'; + + // The real native type is Dart_Handle, but that would mean importing + // dart_api.h into the generated native code. + @override + String getNativeType({String varName = ''}) => 'void* $varName'; + + @override + bool get sameFfiDartAndCType => false; + + @override + String toString() => 'Handle'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/imports.dart b/pkgs/ffigenpad/lib/src/code_generator/imports.dart new file mode 100644 index 0000000000..9ea3936f38 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/imports.dart @@ -0,0 +1,106 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:ffigen/src/code_generator/imports.dart' show LibraryImport; + +import 'type.dart'; +import 'writer.dart'; + +export 'package:ffigen/src/code_generator/imports.dart' show LibraryImport; + +/// An imported type which will be used in the generated code. +class ImportedType extends Type { + final LibraryImport libraryImport; + final String cType; + final String dartType; + final String nativeType; + final String? defaultValue; + + ImportedType(this.libraryImport, this.cType, this.dartType, this.nativeType, + [this.defaultValue]); + + @override + String getCType(Writer w) { + w.markImportUsed(libraryImport); + return '${libraryImport.prefix}.$cType'; + } + + @override + String getFfiDartType(Writer w) => cType == dartType ? getCType(w) : dartType; + + @override + String getNativeType({String varName = ''}) => '$nativeType $varName'; + + @override + bool get sameFfiDartAndCType => cType == dartType; + + @override + String toString() => '${libraryImport.name}.$cType'; + + @override + String? getDefaultValue(Writer w) => defaultValue; +} + +/// An unchecked type similar to [ImportedType] which exists in the generated +/// binding itself. +class SelfImportedType extends Type { + final String cType; + final String dartType; + final String? defaultValue; + + SelfImportedType(this.cType, this.dartType, [this.defaultValue]); + + @override + String getCType(Writer w) => cType; + + @override + String getFfiDartType(Writer w) => dartType; + + @override + bool get sameFfiDartAndCType => cType == dartType; + + @override + String toString() => cType; +} + +final ffiImport = LibraryImport('ffi', 'dart:ffi'); +final ffiPkgImport = LibraryImport('pkg_ffi', 'package:ffi/ffi.dart'); +final objcPkgImport = LibraryImport( + 'objc', 'package:objective_c/objective_c.dart', + importPathWhenImportedByPackageObjC: '../objective_c.dart'); +final self = LibraryImport('self', ''); + +final voidType = ImportedType(ffiImport, 'Void', 'void', 'void'); + +final unsignedCharType = + ImportedType(ffiImport, 'UnsignedChar', 'int', 'unsigned char', '0'); +final signedCharType = + ImportedType(ffiImport, 'SignedChar', 'int', 'char', '0'); +final charType = ImportedType(ffiImport, 'Char', 'int', 'char', '0'); +final unsignedShortType = + ImportedType(ffiImport, 'UnsignedShort', 'int', 'unsigned short', '0'); +final shortType = ImportedType(ffiImport, 'Short', 'int', 'short', '0'); +final unsignedIntType = + ImportedType(ffiImport, 'UnsignedInt', 'int', 'unsigned', '0'); +final intType = ImportedType(ffiImport, 'Int', 'int', 'int', '0'); +final unsignedLongType = + ImportedType(ffiImport, 'UnsignedLong', 'int', 'unsigned long', '0'); +final longType = ImportedType(ffiImport, 'Long', 'int', 'long', '0'); +final unsignedLongLongType = ImportedType( + ffiImport, 'UnsignedLongLong', 'int', 'unsigned long long', '0'); +final longLongType = + ImportedType(ffiImport, 'LongLong', 'int', 'long long', '0'); + +final floatType = ImportedType(ffiImport, 'Float', 'double', 'float', '0.0'); +final doubleType = ImportedType(ffiImport, 'Double', 'double', 'double', '0.0'); + +final sizeType = ImportedType(ffiImport, 'Size', 'int', 'size_t', '0'); +final wCharType = ImportedType(ffiImport, 'WChar', 'int', 'wchar_t', '0'); + +final objCObjectType = + ImportedType(objcPkgImport, 'ObjCObject', 'ObjCObject', 'void'); +final objCSelType = + ImportedType(objcPkgImport, 'ObjCSelector', 'ObjCSelector', 'void'); +final objCBlockType = + ImportedType(objcPkgImport, 'ObjCBlock', 'ObjCBlock', 'id'); diff --git a/pkgs/ffigenpad/lib/src/code_generator/library.dart b/pkgs/ffigenpad/lib/src/code_generator/library.dart new file mode 100644 index 0000000000..226dbcede2 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/library.dart @@ -0,0 +1,193 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:dart_style/dart_style.dart'; +import 'package:logging/logging.dart'; +import 'package:yaml_edit/yaml_edit.dart'; + +import '../code_generator.dart'; +import '../config_provider/config_types.dart'; +import 'utils.dart'; +import 'writer.dart'; + +final _logger = Logger('ffigen.code_generator.library'); +final _formatter = DartFormatter( + languageVersion: DartFormatter.latestLanguageVersion, +); + +/// Container for all Bindings. +class Library { + /// List of bindings in this library. + late List bindings; + + late Writer _writer; + Writer get writer => _writer; + + Library({ + required String name, + String? description, + required List bindings, + String? header, + bool sort = false, + bool generateForPackageObjectiveC = false, + PackingValue? Function(Declaration)? packingOverride, + List? libraryImports, + bool silenceEnumWarning = false, + List nativeEntryPoints = const [], + }) { + _findBindings(bindings, sort); + + /// Handle any declaration-declaration name conflicts and emit warnings. + final declConflictHandler = UniqueNamer({}); + for (final b in this.bindings) { + _warnIfPrivateDeclaration(b); + _resolveIfNameConflicts(declConflictHandler, b); + } + + // Override pack values according to config. We do this after declaration + // conflicts have been handled so that users can target the generated names. + if (packingOverride != null) { + for (final b in this.bindings) { + if (b is Struct) { + final pack = packingOverride(Declaration( + usr: b.usr, + originalName: b.originalName, + )); + if (pack != null) { + b.pack = pack.value; + } + } + } + } + + // Seperate bindings which require lookup. + final lookupBindings = []; + final nativeBindings = []; + FfiNativeConfig? nativeConfig; + + for (final binding in this.bindings.whereType()) { + final nativeConfigForBinding = switch (binding) { + Func() => binding.ffiNativeConfig, + Global() => binding.nativeConfig, + _ => null, + }; + + // At the moment, all bindings share their native config. + nativeConfig ??= nativeConfigForBinding; + + final usesLookup = + nativeConfigForBinding == null || !nativeConfigForBinding.enabled; + (usesLookup ? lookupBindings : nativeBindings).add(binding); + } + final noLookUpBindings = + this.bindings.whereType().toList(); + + _writer = Writer( + lookUpBindings: lookupBindings, + ffiNativeBindings: nativeBindings, + nativeAssetId: nativeConfig?.assetId, + noLookUpBindings: noLookUpBindings, + className: name, + classDocComment: description, + header: header, + additionalImports: libraryImports, + generateForPackageObjectiveC: generateForPackageObjectiveC, + silenceEnumWarning: silenceEnumWarning, + nativeEntryPoints: nativeEntryPoints, + ); + } + + void _findBindings(List original, bool sort) { + /// Get all dependencies (includes itself). + final dependencies = {}; + for (final b in original) { + b.addDependencies(dependencies); + } + + /// Save bindings. + bindings = dependencies.toList(); + if (sort) { + bindings.sortBy((b) => b.name); + } + } + + /// Logs a warning if generated declaration will be private. + void _warnIfPrivateDeclaration(Binding b) { + if (b.name.startsWith('_') && !b.isInternal) { + _logger.warning("Generated declaration '${b.name}' starts with '_' " + 'and therefore will be private.'); + } + } + + /// Resolves name conflict(if any) and logs a warning. + void _resolveIfNameConflicts(UniqueNamer namer, Binding b) { + // Print warning if name was conflicting and has been changed. + if (namer.isUsed(b.name)) { + final oldName = b.name; + b.name = namer.makeUnique(b.name); + + _logger.warning("Resolved name conflict: Declaration '$oldName' " + "and has been renamed to '${b.name}'."); + } else { + namer.markUsed(b.name); + } + } + + /// Generates [file] by generating C bindings. + void generateFile(File file, {bool format = true}) { + if (!file.existsSync()) file.createSync(recursive: true); + var content = generate(); + if (format) { + content = _formatter.format(content); + } + file.writeAsStringSync(content); + } + + /// Generates [file] with the Objective C code needed for the bindings, if + /// any. + /// + /// Returns whether bindings were generated. + bool generateObjCFile(File file) { + final bindings = writer.generateObjC(file.path); + + if (bindings == null) { + // No ObjC code needed. If there's already a file (eg from an earlier + // run), delete it so it's not accidentally included in the build. + if (file.existsSync()) file.deleteSync(); + return false; + } + + if (!file.existsSync()) file.createSync(recursive: true); + file.writeAsStringSync(bindings); + return true; + } + + /// Generates [file] with symbol output yaml. + void generateSymbolOutputFile(File file, String importPath) { + if (!file.existsSync()) file.createSync(recursive: true); + final symbolFileYamlMap = writer.generateSymbolOutputYamlMap(importPath); + final yamlEditor = YamlEditor(''); + yamlEditor.update([], wrapAsYamlNode(symbolFileYamlMap)); + var yamlString = yamlEditor.toString(); + if (!yamlString.endsWith('\n')) { + yamlString += '\n'; + } + file.writeAsStringSync(yamlString); + } + + /// Generates the bindings. + String generate() { + return writer.generate(); + } + + @override + bool operator ==(Object other) => + other is Library && other.generate() == generate(); + + @override + int get hashCode => bindings.hashCode; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/native_type.dart b/pkgs/ffigenpad/lib/src/code_generator/native_type.dart new file mode 100644 index 0000000000..cb04c1a2a5 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/native_type.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'writer.dart'; + +enum SupportedNativeType { + voidType, + char, + int8, + int16, + int32, + int64, + uint8, + uint16, + uint32, + uint64, + float, + double, + intPtr, + uintPtr, +} + +/// Represents a primitive native type, such as float. +class NativeType extends Type { + static const _primitives = { + SupportedNativeType.voidType: NativeType._('Void', 'void', 'void', null), + SupportedNativeType.char: NativeType._('Uint8', 'int', 'char', '0'), + SupportedNativeType.int8: NativeType._('Int8', 'int', 'int8_t', '0'), + SupportedNativeType.int16: NativeType._('Int16', 'int', 'int16_t', '0'), + SupportedNativeType.int32: NativeType._('Int32', 'int', 'int32_t', '0'), + SupportedNativeType.int64: NativeType._('Int64', 'int', 'int64_t', '0'), + SupportedNativeType.uint8: NativeType._('Uint8', 'int', 'uint8_t', '0'), + SupportedNativeType.uint16: NativeType._('Uint16', 'int', 'uint16_t', '0'), + SupportedNativeType.uint32: NativeType._('Uint32', 'int', 'uint32_t', '0'), + SupportedNativeType.uint64: NativeType._('Uint64', 'int', 'uint64_t', '0'), + SupportedNativeType.float: NativeType._('Float', 'double', 'float', '0.0'), + SupportedNativeType.double: + NativeType._('Double', 'double', 'double', '0.0'), + SupportedNativeType.intPtr: NativeType._('IntPtr', 'int', 'intptr_t', '0'), + SupportedNativeType.uintPtr: + NativeType._('UintPtr', 'int', 'uintptr_t', '0'), + }; + + final String _cType; + final String _dartType; + final String _nativeType; + final String? _defaultValue; + + const NativeType._( + this._cType, this._dartType, this._nativeType, this._defaultValue); + + factory NativeType(SupportedNativeType type) => _primitives[type]!; + + @override + String getCType(Writer w) => '${w.ffiLibraryPrefix}.$_cType'; + + @override + String getFfiDartType(Writer w) => _dartType; + + @override + String getNativeType({String varName = ''}) => '$_nativeType $varName'; + + @override + bool get sameFfiDartAndCType => _cType == _dartType; + + @override + String toString() => _cType; + + @override + String cacheKey() => _cType; + + @override + String? getDefaultValue(Writer w) => _defaultValue; +} + +class BooleanType extends NativeType { + const BooleanType._() : super._('Bool', 'bool', 'BOOL', 'false'); + static const _boolean = BooleanType._(); + factory BooleanType() => _boolean; + + @override + String toString() => 'bool'; + + @override + String cacheKey() => 'bool'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_block.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_block.dart new file mode 100644 index 0000000000..4841297615 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_block.dart @@ -0,0 +1,327 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; +import '../config_provider/config_types.dart'; +import '../header_parser/data.dart' show bindingsIndex; + +import 'binding_string.dart'; +import 'writer.dart'; + +class ObjCBlock extends BindingType { + final Type returnType; + final List argTypes; + Func? _wrapListenerBlock; + + factory ObjCBlock({ + required Type returnType, + required List argTypes, + }) { + final usr = _getBlockUsr(returnType, argTypes); + + final oldBlock = bindingsIndex.getSeenObjCBlock(usr); + if (oldBlock != null) { + return oldBlock; + } + + final block = ObjCBlock._( + usr: usr, + name: _getBlockName(returnType, argTypes), + returnType: returnType, + argTypes: argTypes, + ); + bindingsIndex.addObjCBlockToSeen(usr, block); + + return block; + } + + ObjCBlock._({ + required String super.usr, + required super.name, + required this.returnType, + required this.argTypes, + }) : super(originalName: name); + + // Generates a human readable name for the block based on the args and return + // type. These names will be pretty verbose and unweildy, but they're at least + // sensible and stable. Users can always add their own typedef with a simpler + // name if necessary. + static String _getBlockName(Type returnType, List argTypes) => + 'ObjCBlock_${[returnType, ...argTypes].map(_typeName).join('_')}'; + static String _typeName(Type type) => + type.toString().replaceAll(_illegalNameChar, ''); + static final _illegalNameChar = RegExp(r'[^0-9a-zA-Z]'); + + static String _getBlockUsr(Type returnType, List argTypes) { + // Create a fake USR code for the block. This code is used to dedupe blocks + // with the same signature. + final usr = StringBuffer(); + usr.write('objcBlock: ${returnType.cacheKey()}'); + for (final type in argTypes) { + usr.write(' ${type.cacheKey()}'); + } + return usr.toString(); + } + + bool get hasListener => returnType == voidType; + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + + final params = []; + for (var i = 0; i < argTypes.length; ++i) { + params.add(Parameter(name: 'arg$i', type: argTypes[i])); + } + + final voidPtr = PointerType(voidType).getCType(w); + final blockPtr = PointerType(objCBlockType); + final funcType = FunctionType(returnType: returnType, parameters: params); + final natFnType = NativeFunc(funcType); + final natFnPtr = PointerType(natFnType).getCType(w); + final funcPtrTrampoline = + w.topLevelUniqueNamer.makeUnique('_${name}_fnPtrTrampoline'); + final closureTrampoline = + w.topLevelUniqueNamer.makeUnique('_${name}_closureTrampoline'); + final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(w); + final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(w); + final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(w); + final trampFuncType = FunctionType( + returnType: returnType, + parameters: [Parameter(type: blockPtr, name: 'block'), ...params]); + final trampFuncCType = trampFuncType.getCType(w, writeArgumentNames: false); + final trampFuncFfiDartType = + trampFuncType.getFfiDartType(w, writeArgumentNames: false); + final natTrampFnType = NativeFunc(trampFuncType).getCType(w); + final nativeCallableType = + '${w.ffiLibraryPrefix}.NativeCallable<$trampFuncCType>'; + final funcDartType = funcType.getDartType(w, writeArgumentNames: false); + final funcFfiDartType = + funcType.getFfiDartType(w, writeArgumentNames: false); + final returnFfiDartType = returnType.getFfiDartType(w); + final blockCType = blockPtr.getCType(w); + + final paramsNameOnly = params.map((p) => p.name).join(', '); + final paramsFfiDartType = + params.map((p) => '${p.type.getFfiDartType(w)} ${p.name}').join(', '); + final paramsDartType = + params.map((p) => '${p.type.getDartType(w)} ${p.name}').join(', '); + + // Write the function pointer based trampoline function. + s.write(''' +$returnFfiDartType $funcPtrTrampoline($blockCType block, $paramsFfiDartType) => + block.ref.target.cast<${natFnType.getFfiDartType(w)}>() + .asFunction<$funcFfiDartType>()($paramsNameOnly); +'''); + + // Write the closure based trampoline function. + s.write(''' +$returnFfiDartType $closureTrampoline($blockCType block, $paramsFfiDartType) => + ($getBlockClosure(block) as $funcFfiDartType)($paramsNameOnly); +'''); + + // Snippet that converts a Dart typed closure to FfiDart type. This snippet + // is used below. Note that the closure being converted is called `fn`. + final convertedFnArgs = params + .map((p) => + p.type.convertFfiDartTypeToDartType(w, p.name, objCRetain: true)) + .join(', '); + final convFnInvocation = returnType.convertDartTypeToFfiDartType( + w, 'fn($convertedFnArgs)', + objCRetain: true); + final convFn = '($paramsFfiDartType) => $convFnInvocation'; + + // Write the wrapper class. + final defaultValue = returnType.getDefaultValue(w); + final exceptionalReturn = defaultValue == null ? '' : ', $defaultValue'; + s.write(''' +class $name extends ${ObjCBuiltInFunctions.blockBase.gen(w)} { + $name._($blockCType pointer, + {bool retain = false, bool release = true}) : + super(pointer, retain: retain, release: release); + + /// Returns a block that wraps the given raw block pointer. + static $name castFromPointer($blockCType pointer, + {bool retain = false, bool release = false}) { + return $name._(pointer, retain: retain, release: release); + } + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + $name.fromFunctionPointer($natFnPtr ptr) : + this._($newPointerBlock( + _cFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction< + $trampFuncCType>($funcPtrTrampoline + $exceptionalReturn).cast(), ptr.cast())); + static $voidPtr? _cFuncTrampoline; + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + $name.fromFunction($funcDartType fn) : + this._($newClosureBlock( + _dartFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction< + $trampFuncCType>($closureTrampoline $exceptionalReturn).cast(), + $convFn)); + static $voidPtr? _dartFuncTrampoline; + +'''); + + // Listener block constructor is only available for void blocks. + if (hasListener) { + // This snippet is the same as the convFn above, except that the args + // don't need to be retained because they've already been retained by + // _wrapListenerBlock. + final listenerConvertedFnArgs = params + .map((p) => + p.type.convertFfiDartTypeToDartType(w, p.name, objCRetain: false)) + .join(', '); + final listenerConvFnInvocation = returnType.convertDartTypeToFfiDartType( + w, 'fn($listenerConvertedFnArgs)', + objCRetain: true); + final listenerConvFn = + '($paramsFfiDartType) => $listenerConvFnInvocation'; + + s.write(''' + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// Note that unlike the default behavior of NativeCallable.listener, listener + /// blocks do not keep the isolate alive. + $name.listener($funcDartType fn) : + this._(${_wrapListenerBlock?.name ?? ''}($newClosureBlock( + (_dartFuncListenerTrampoline ??= $nativeCallableType.listener( + $closureTrampoline $exceptionalReturn)..keepIsolateAlive = + false).nativeFunction.cast(), $listenerConvFn))); + static $nativeCallableType? _dartFuncListenerTrampoline; + +'''); + } + + // Call method. + s.write(' ${returnType.getDartType(w)} call($paramsDartType) =>'); + final callMethodArgs = params + .map((p) => + p.type.convertDartTypeToFfiDartType(w, p.name, objCRetain: false)) + .join(', '); + final callMethodInvocation = ''' +pointer.ref.invoke.cast<$natTrampFnType>().asFunction<$trampFuncFfiDartType>()( + pointer, $callMethodArgs)'''; + s.write(returnType.convertFfiDartTypeToDartType(w, callMethodInvocation, + objCRetain: false)); + s.write(';\n'); + + s.write('}\n'); + return BindingString( + type: BindingStringType.objcBlock, string: s.toString()); + } + + @override + BindingString? toObjCBindingString(Writer w) { + if (_wrapListenerBlock == null) return null; + + final argsReceived = []; + final retains = []; + for (var i = 0; i < argTypes.length; ++i) { + final t = argTypes[i]; + final argName = 'arg$i'; + argsReceived.add(t.getNativeType(varName: argName)); + retains.add(t.generateRetain(argName) ?? argName); + } + final fnName = _wrapListenerBlock!.name; + final blockTypedef = w.objCLevelUniqueNamer.makeUnique('ListenerBlock'); + + final s = StringBuffer(); + s.write(''' + +typedef ${getNativeType(varName: blockTypedef)}; +$blockTypedef $fnName($blockTypedef block) { + $blockTypedef wrapper = [^void(${argsReceived.join(', ')}) { + block(${retains.join(', ')}); + } copy]; + [block release]; + return wrapper; +} +'''); + return BindingString( + type: BindingStringType.objcBlock, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + dependencies.add(this); + + returnType.addDependencies(dependencies); + for (final t in argTypes) { + t.addDependencies(dependencies); + } + + if (hasListener && argTypes.any((t) => t.generateRetain('') != null)) { + _wrapListenerBlock = Func( + name: 'wrapListenerBlock_$name', + returnType: this, + parameters: [Parameter(name: 'block', type: this)], + objCReturnsRetained: true, + isLeaf: true, + isInternal: true, + useNameForLookup: true, + ffiNativeConfig: const FfiNativeConfig(enabled: true), + )..addDependencies(dependencies); + } + } + + @override + String getCType(Writer w) => PointerType(objCBlockType).getCType(w); + + @override + String getDartType(Writer w) => name; + + @override + String getNativeType({String varName = ''}) { + final args = argTypes.map((t) => t.getNativeType()); + return '${returnType.getNativeType()} (^$varName)(${args.join(', ')})'; + } + + @override + bool get sameFfiDartAndCType => true; + + @override + bool get sameDartAndCType => false; + + @override + bool get sameDartAndFfiDartType => false; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + ObjCInterface.generateGetId(value, objCRetain); + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + ObjCInterface.generateConstructor(name, value, objCRetain); + + @override + String? generateRetain(String value) => '[$value copy]'; + + @override + String toString() => '($returnType (^)(${argTypes.join(', ')}))'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_built_in_functions.dart new file mode 100644 index 0000000000..6245d670d3 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_built_in_functions.dart @@ -0,0 +1,334 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'binding_string.dart'; +import 'writer.dart'; + +/// Built in functions used by the Objective C bindings. +class ObjCBuiltInFunctions { + ObjCBuiltInFunctions(this.generateForPackageObjectiveC); + + final bool generateForPackageObjectiveC; + + static const registerName = ObjCImport('registerName'); + static const getClass = ObjCImport('getClass'); + static const msgSendPointer = ObjCImport('msgSendPointer'); + static const msgSendFpretPointer = ObjCImport('msgSendFpretPointer'); + static const msgSendStretPointer = ObjCImport('msgSendStretPointer'); + static const useMsgSendVariants = ObjCImport('useMsgSendVariants'); + static const newPointerBlock = ObjCImport('newPointerBlock'); + static const newClosureBlock = ObjCImport('newClosureBlock'); + static const getBlockClosure = ObjCImport('getBlockClosure'); + static const getProtocolMethodSignature = + ObjCImport('getProtocolMethodSignature'); + static const getProtocol = ObjCImport('getProtocol'); + static const objectBase = ObjCImport('ObjCObjectBase'); + static const blockBase = ObjCImport('ObjCBlockBase'); + static const protocolMethod = ObjCImport('ObjCProtocolMethod'); + static const protocolListenableMethod = + ObjCImport('ObjCProtocolListenableMethod'); + static const protocolBuilder = ObjCImport('ObjCProtocolBuilder'); + static const dartProxy = ObjCImport('DartProxy'); + + // Keep in sync with pkgs/objective_c/ffigen_objc.yaml. + static const builtInInterfaces = { + 'DartProxy', + 'DartProxyBuilder', + 'NSArray', + 'NSCharacterSet', + 'NSCoder', + 'NSData', + 'NSDate', + 'NSDictionary', + 'NSEnumerator', + 'NSError', + 'NSIndexSet', + 'NSInvocation', + 'NSItemProvider', + 'NSLocale', + 'NSMethodSignature', + 'NSMutableArray', + 'NSMutableData', + 'NSMutableDictionary', + 'NSMutableIndexSet', + 'NSMutableOrderedSet', + 'NSMutableSet', + 'NSMutableString', + 'NSNotification', + 'NSNumber', + 'NSObject', + 'NSOrderedSet', + 'NSProxy', + 'NSSet', + 'NSString', + 'NSURL', + 'NSURLHandle', + 'NSValue', + 'Protocol', + }; + static const builtInCompounds = { + 'NSFastEnumerationState', + 'NSRange', + }; + static const builtInEnums = { + 'NSBinarySearchingOptions', + 'NSComparisonResult', + 'NSDataBase64DecodingOptions', + 'NSDataBase64EncodingOptions', + 'NSDataCompressionAlgorithm', + 'NSDataReadingOptions', + 'NSDataSearchOptions', + 'NSDataWritingOptions', + 'NSEnumerationOptions', + 'NSItemProviderFileOptions', + 'NSItemProviderRepresentationVisibility', + 'NSKeyValueChange', + 'NSKeyValueObservingOptions', + 'NSKeyValueSetMutationKind', + 'NSOrderedCollectionDifferenceCalculationOptions', + 'NSSortOptions', + 'NSStringCompareOptions', + 'NSStringEncodingConversionOptions', + 'NSStringEnumerationOptions', + 'NSURLBookmarkCreationOptions', + 'NSURLBookmarkResolutionOptions', + 'NSURLHandleStatus', + }; + + // TODO(https://github.com/dart-lang/native/issues/1173): Ideally this check + // would be based on more than just the name. + bool isBuiltInInterface(String name) => + !generateForPackageObjectiveC && builtInInterfaces.contains(name); + bool isBuiltInCompound(String name) => + !generateForPackageObjectiveC && builtInCompounds.contains(name); + bool isBuiltInEnum(String name) => + !generateForPackageObjectiveC && builtInEnums.contains(name); + bool isNSObject(String name) => name == 'NSObject'; + + // We need to load a separate instance of objc_msgSend for each signature. If + // the return type is a struct, we need to use objc_msgSend_stret instead, and + // for float return types we need objc_msgSend_fpret. + final _msgSendFuncs = {}; + ObjCMsgSendFunc getMsgSendFunc( + Type returnType, List params) { + var key = returnType.cacheKey(); + for (final p in params) { + key += ' ${p.type.cacheKey()}'; + } + return _msgSendFuncs[key] ??= ObjCMsgSendFunc( + '_objc_msgSend_${_msgSendFuncs.length}', + returnType, + params, + useMsgSendVariants); + } + + final _selObjects = {}; + ObjCInternalGlobal getSelObject(String methodName) { + return _selObjects[methodName] ??= ObjCInternalGlobal( + '_sel_${methodName.replaceAll(":", "_")}', + (Writer w) => '${registerName.gen(w)}("$methodName")', + ); + } + + void addDependencies(Set dependencies) { + for (final msgSendFunc in _msgSendFuncs.values) { + msgSendFunc.addDependencies(dependencies); + } + for (final sel in _selObjects.values) { + sel.addDependencies(dependencies); + } + } + + static bool isInstanceType(Type type) { + if (type is ObjCInstanceType) return true; + final baseType = type.typealiasType; + return baseType is ObjCNullable && baseType.child is ObjCInstanceType; + } +} + +/// A function, global variable, or helper type defined in package:objective_c. +class ObjCImport { + final String name; + + const ObjCImport(this.name); + + String gen(Writer w) => '${w.objcPkgPrefix}.$name'; +} + +/// Globals only used internally by ObjC bindings, such as classes and SELs. +class ObjCInternalGlobal extends NoLookUpBinding { + final String Function(Writer) makeValue; + + ObjCInternalGlobal(String name, this.makeValue) + : super(originalName: name, name: name, isInternal: true); + + @override + BindingString toBindingString(Writer w) { + final s = StringBuffer(); + name = w.wrapperLevelUniqueNamer.makeUnique(name); + s.write('late final $name = ${makeValue(w)};\n'); + return BindingString(type: BindingStringType.global, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + dependencies.add(this); + } +} + +enum ObjCMsgSendVariant { + normal(ObjCBuiltInFunctions.msgSendPointer), + stret(ObjCBuiltInFunctions.msgSendStretPointer), + fpret(ObjCBuiltInFunctions.msgSendFpretPointer); + + final ObjCImport pointer; + const ObjCMsgSendVariant(this.pointer); + + static ObjCMsgSendVariant fromReturnType(Type returnType) { + if (returnType is Compound && returnType.isStruct) { + return ObjCMsgSendVariant.stret; + } else if (returnType == floatType || returnType == doubleType) { + return ObjCMsgSendVariant.fpret; + } + return ObjCMsgSendVariant.normal; + } +} + +class ObjCMsgSendVariantFunc extends NoLookUpBinding { + ObjCMsgSendVariant variant; + FunctionType type; + + ObjCMsgSendVariantFunc( + {required super.name, + required this.variant, + required Type returnType, + required List parameters}) + : type = FunctionType(returnType: returnType, parameters: parameters), + super(isInternal: true); + + @override + BindingString toBindingString(Writer w) { + final cType = NativeFunc(type).getCType(w); + final dartType = type.getFfiDartType(w, writeArgumentNames: false); + final pointer = variant.pointer.gen(w); + + final bindingString = ''' +final $name = $pointer.cast<$cType>().asFunction<$dartType>(); +'''; + + return BindingString(type: BindingStringType.func, string: bindingString); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + dependencies.add(this); + type.addDependencies(dependencies); + } +} + +/// A wrapper around the objc_msgSend function, or the stret or fpret variants. +/// +/// The [variant] is based purely on the return type of the method. +/// +/// For the stret and fpret variants, we may need to fall back to the normal +/// objc_msgSend function at runtime, depending on the ABI. So we emit both the +/// variant function and the normal function, and decide which to use at runtime +/// based on the ABI. The result of the ABI check is stored in [useVariants]. +/// +/// This runtime check is complicated by the fact that objc_msgSend_stret has +/// a different signature than objc_msgSend has for the same method. This is +/// because objc_msgSend_stret takes a pointer to the return type as its first +/// arg. +class ObjCMsgSendFunc { + final ObjCMsgSendVariant variant; + final ObjCImport useVariants; + + // [normalFunc] is always a reference to the normal objc_msgSend function. If + // the [variant] is fpret or stret, then [variantFunc] is a reference to the + // corresponding variant of the objc_msgSend function, otherwise it's null. + late final ObjCMsgSendVariantFunc normalFunc; + late final ObjCMsgSendVariantFunc? variantFunc; + + ObjCMsgSendFunc(String name, Type returnType, List params, + this.useVariants) + : variant = ObjCMsgSendVariant.fromReturnType(returnType) { + normalFunc = ObjCMsgSendVariantFunc( + name: name, + variant: ObjCMsgSendVariant.normal, + returnType: returnType, + parameters: _params(params), + ); + switch (variant) { + case ObjCMsgSendVariant.normal: + variantFunc = null; + case ObjCMsgSendVariant.fpret: + variantFunc = ObjCMsgSendVariantFunc( + name: '${name}Fpret', + variant: variant, + returnType: returnType, + parameters: _params(params), + ); + case ObjCMsgSendVariant.stret: + variantFunc = ObjCMsgSendVariantFunc( + name: '${name}Stret', + variant: variant, + returnType: voidType, + parameters: _params(params, structRetPtr: PointerType(returnType)), + ); + } + } + + static List _params(List params, + {Type? structRetPtr}) { + return [ + if (structRetPtr != null) Parameter(type: structRetPtr), + Parameter(type: PointerType(objCObjectType)), + Parameter(type: PointerType(objCSelType)), + for (final p in params) Parameter(type: p.type), + ]; + } + + bool get isStret => variant == ObjCMsgSendVariant.stret; + + void addDependencies(Set dependencies) { + normalFunc.addDependencies(dependencies); + variantFunc?.addDependencies(dependencies); + } + + String invoke(Writer w, String target, String sel, Iterable params, + {String? structRetPtr}) { + final normalCall = _invoke(normalFunc.name, target, sel, params); + switch (variant) { + case ObjCMsgSendVariant.normal: + return normalCall; + case ObjCMsgSendVariant.fpret: + final fpretCall = _invoke(variantFunc!.name, target, sel, params); + return '${useVariants.gen(w)} ? $fpretCall : $normalCall'; + case ObjCMsgSendVariant.stret: + final stretCall = _invoke(variantFunc!.name, target, sel, params, + structRetPtr: structRetPtr); + return '${useVariants.gen(w)} ? $stretCall : ' + '$structRetPtr.ref = $normalCall'; + } + } + + static String _invoke( + String name, + String target, + String sel, + Iterable params, { + String? structRetPtr, + }) { + return '''$name(${[ + if (structRetPtr != null) structRetPtr, + target, + sel, + ...params, + ].join(', ')})'''; + } +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_interface.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_interface.dart new file mode 100644 index 0000000000..47c711a036 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_interface.dart @@ -0,0 +1,350 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +// Class methods defined on NSObject that we don't want to copy to child objects +// by default. +const _excludedNSObjectClassMethods = { + 'allocWithZone:', + 'class', + 'conformsToProtocol:', + 'copyWithZone:', + 'debugDescription', + 'description', + 'hash', + 'initialize', + 'instanceMethodForSelector:', + 'instanceMethodSignatureForSelector:', + 'instancesRespondToSelector:', + 'isSubclassOfClass:', + 'load', + 'mutableCopyWithZone:', + 'poseAsClass:', + 'resolveClassMethod:', + 'resolveInstanceMethod:', + 'setVersion:', + 'superclass', + 'version', +}; + +class ObjCInterface extends BindingType with ObjCMethods { + ObjCInterface? superType; + bool filled = false; + + final String lookupName; + late final ObjCInternalGlobal _classObject; + late final ObjCInternalGlobal _isKindOfClass; + late final ObjCMsgSendFunc _isKindOfClassMsgSend; + + @override + final ObjCBuiltInFunctions builtInFunctions; + + ObjCInterface({ + super.usr, + required String super.originalName, + String? name, + String? lookupName, + super.dartDoc, + required this.builtInFunctions, + }) : lookupName = lookupName ?? originalName, + super(name: name ?? originalName); + + bool get _isBuiltIn => builtInFunctions.isBuiltInInterface(originalName); + + @override + BindingString toBindingString(Writer w) { + if (_isBuiltIn) { + return const BindingString( + type: BindingStringType.objcInterface, string: ''); + } + + String paramsToString(List params, + {required bool isStatic}) { + final stringParams = []; + + stringParams.addAll( + params.map((p) => '${_getConvertedType(p.type, w, name)} ${p.name}')); + return '(${stringParams.join(", ")})'; + } + + final s = StringBuffer(); + s.write(makeDartDoc(dartDoc ?? originalName)); + + final methodNamer = createMethodRenamer(w); + + final rawObjType = PointerType(objCObjectType).getCType(w); + final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); + + final superTypeIsInPkgObjc = superType == null; + + // Class declaration. + s.write('''class $name extends ${superType?.getDartType(w) ?? wrapObjType} { + $name._($rawObjType pointer, + {bool retain = false, bool release = false}) : + ${superTypeIsInPkgObjc ? 'super' : 'super.castFromPointer'} + (pointer, retain: retain, release: release); + + /// Constructs a [$name] that points to the same underlying object as [other]. + $name.castFrom($wrapObjType other) : + this._(other.pointer, retain: true, release: true); + + /// Constructs a [$name] that wraps the given raw object pointer. + $name.castFromPointer($rawObjType other, + {bool retain = false, bool release = false}) : + this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [$name]. + static bool isInstance($wrapObjType obj) { + return ${_isKindOfClassMsgSend.invoke( + w, + 'obj.pointer', + _isKindOfClass.name, + [_classObject.name], + )}; + } + +'''); + + // Methods. + for (final m in methods) { + final methodName = m.getDartMethodName(methodNamer); + final isStatic = m.isClassMethod; + final isStret = m.msgSend!.isStret; + + var returnType = m.returnType; + var params = m.params; + if (isStret) { + params = [ObjCMethodParam(PointerType(returnType), 'stret'), ...params]; + returnType = voidType; + } + + // The method declaration. + s.write(makeDartDoc(m.dartDoc ?? m.originalName)); + s.write(' '); + if (isStatic) { + s.write('static '); + s.write(_getConvertedType(returnType, w, name)); + + switch (m.kind) { + case ObjCMethodKind.method: + // static returnType methodName(...) + s.write(' $methodName'); + break; + case ObjCMethodKind.propertyGetter: + // static returnType getMethodName() + s.write(' get'); + s.write(methodName[0].toUpperCase() + methodName.substring(1)); + break; + case ObjCMethodKind.propertySetter: + // static void setMethodName(...) + s.write(' set'); + s.write(methodName[0].toUpperCase() + methodName.substring(1)); + break; + } + s.write(paramsToString(params, isStatic: true)); + } else { + switch (m.kind) { + case ObjCMethodKind.method: + // returnType methodName(...) + s.write(_getConvertedType(returnType, w, name)); + s.write(' $methodName'); + s.write(paramsToString(params, isStatic: false)); + break; + case ObjCMethodKind.propertyGetter: + s.write(_getConvertedType(returnType, w, name)); + if (isStret) { + // void getMethodName(Pointer stret) + s.write(' get'); + s.write(methodName[0].toUpperCase() + methodName.substring(1)); + s.write(paramsToString(params, isStatic: false)); + } else { + // returnType get methodName + s.write(' get $methodName'); + } + break; + case ObjCMethodKind.propertySetter: + // set methodName(...) + s.write(' set $methodName'); + s.write(paramsToString(params, isStatic: false)); + break; + } + } + + s.write(' {\n'); + + // Implementation. + final convertReturn = m.kind != ObjCMethodKind.propertySetter && + !returnType.sameDartAndFfiDartType; + + if (returnType != voidType) { + s.write(' ${convertReturn ? 'final _ret = ' : 'return '}'); + } + s.write(m.msgSend!.invoke( + w, + isStatic ? _classObject.name : 'this.pointer', + m.selObject!.name, + m.params.map((p) => p.type + .convertDartTypeToFfiDartType(w, p.name, objCRetain: false)), + structRetPtr: 'stret')); + s.write(';\n'); + if (convertReturn) { + final result = returnType.convertFfiDartTypeToDartType( + w, + '_ret', + objCRetain: !m.isOwnedReturn, + objCEnclosingClass: name, + ); + s.write(' return $result;'); + } + + s.write(' }\n\n'); + } + + s.write('}\n\n'); + + return BindingString( + type: BindingStringType.objcInterface, string: s.toString()); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this) || _isBuiltIn) return; + dependencies.add(this); + + _classObject = ObjCInternalGlobal('_class_$originalName', + (Writer w) => '${ObjCBuiltInFunctions.getClass.gen(w)}("$lookupName")') + ..addDependencies(dependencies); + _isKindOfClass = builtInFunctions.getSelObject('isKindOfClass:'); + _isKindOfClassMsgSend = builtInFunctions.getMsgSendFunc( + BooleanType(), [ObjCMethodParam(PointerType(objCObjectType), 'clazz')]); + + addMethodDependencies(dependencies, needMsgSend: true); + + if (superType != null) { + superType!.addDependencies(dependencies); + _copyMethodsFromSuperType(); + _fixNullabilityOfOverriddenMethods(); + + // Add dependencies for any methods that were added. + addMethodDependencies(dependencies, needMsgSend: true); + } + + builtInFunctions.addDependencies(dependencies); + } + + void _copyMethodsFromSuperType() { + // We need to copy certain methods from the super type: + // - Class methods, because Dart classes don't inherit static methods. + // - Methods that return instancetype, because the subclass's copy of the + // method needs to return the subclass, not the super class. + // Note: instancetype is only allowed as a return type, not an arg type. + for (final m in superType!.methods) { + if (m.isClassMethod && + !_excludedNSObjectClassMethods.contains(m.originalName)) { + addMethod(m); + } else if (ObjCBuiltInFunctions.isInstanceType(m.returnType)) { + addMethod(m); + } + } + } + + void _fixNullabilityOfOverriddenMethods() { + // ObjC ignores nullability when deciding if an override for an inherited + // method is valid. But in Dart it's invalid to override a method and change + // it's return type from non-null to nullable, or its arg type from nullable + // to non-null. So in these cases we have to make the non-null type + // nullable, to avoid Dart compile errors. + var superType_ = superType; + while (superType_ != null) { + for (final method in methods) { + final superMethod = superType_.getMethod(method.originalName); + if (superMethod != null && + !superMethod.isClassMethod && + !method.isClassMethod) { + if (superMethod.returnType.typealiasType is! ObjCNullable && + method.returnType.typealiasType is ObjCNullable) { + superMethod.returnType = ObjCNullable(superMethod.returnType); + } + final numArgs = method.params.length < superMethod.params.length + ? method.params.length + : superMethod.params.length; + for (var i = 0; i < numArgs; ++i) { + final param = method.params[i]; + final superParam = superMethod.params[i]; + if (superParam.type.typealiasType is ObjCNullable && + param.type.typealiasType is! ObjCNullable) { + param.type = ObjCNullable(param.type); + } + } + } + } + superType_ = superType_.superType; + } + } + + @override + String getCType(Writer w) => PointerType(objCObjectType).getCType(w); + + @override + String getDartType(Writer w) => + _isBuiltIn ? '${w.objcPkgPrefix}.$name' : name; + + @override + String getNativeType({String varName = ''}) => '$originalName* $varName'; + + @override + bool get sameFfiDartAndCType => true; + + @override + bool get sameDartAndCType => false; + + @override + bool get sameDartAndFfiDartType => false; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + ObjCInterface.generateGetId(value, objCRetain); + + static String generateGetId(String value, bool objCRetain) => + objCRetain ? '$value.retainAndReturnPointer()' : '$value.pointer'; + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + ObjCInterface.generateConstructor(getDartType(w), value, objCRetain); + + static String generateConstructor( + String className, + String value, + bool objCRetain, + ) { + final ownershipFlags = 'retain: $objCRetain, release: true'; + return '$className.castFromPointer($value, $ownershipFlags)'; + } + + @override + String? generateRetain(String value) => '[$value retain]'; + + String _getConvertedType(Type type, Writer w, String enclosingClass) { + if (type is ObjCInstanceType) return enclosingClass; + final baseType = type.typealiasType; + if (baseType is ObjCNullable && baseType.child is ObjCInstanceType) { + return '$enclosingClass?'; + } + return type.getDartType(w); + } +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_methods.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_methods.dart new file mode 100644 index 0000000000..19e9fd030b --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_methods.dart @@ -0,0 +1,230 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../code_generator.dart'; +import 'utils.dart'; +import 'writer.dart'; + +final _logger = Logger('ffigen.code_generator.objc_methods'); + +mixin ObjCMethods { + final _methods = {}; + + Iterable get methods => _methods.values; + ObjCMethod? getMethod(String name) => _methods[name]; + + String get originalName; + String get name; + ObjCBuiltInFunctions get builtInFunctions; + + void addMethod(ObjCMethod method) { + if (_shouldIncludeMethod(method)) { + _methods[method.originalName] = + _maybeReplaceMethod(getMethod(method.originalName), method); + } + } + + void addMethodDependencies( + Set dependencies, { + bool needMsgSend = false, + bool needProtocolBlock = false, + }) { + for (final m in methods) { + m.addDependencies(dependencies, builtInFunctions, + needMsgSend: needMsgSend, needProtocolBlock: needProtocolBlock); + } + } + + ObjCMethod _maybeReplaceMethod(ObjCMethod? oldMethod, ObjCMethod newMethod) { + if (oldMethod == null) return newMethod; + + // Typically we ignore duplicate methods. However, property setters and + // getters are duplicated in the AST. One copy is marked with + // ObjCMethodKind.propertyGetter/Setter. The other copy is missing + // important information, and is a plain old instanceMethod. So if the + // existing method is an instanceMethod, and the new one is a property, + // override it. + if (newMethod.isProperty && !oldMethod.isProperty) { + return newMethod; + } else if (!newMethod.isProperty && oldMethod.isProperty) { + // Don't override, but also skip the same method check below. + return oldMethod; + } + + // Check the duplicate is the same method. + if (!newMethod.sameAs(oldMethod)) { + _logger.severe('Duplicate methods with different signatures: ' + '$originalName.${newMethod.originalName}'); + return newMethod; + } + + // There's a bug in some Apple APIs where an init method that should return + // instancetype has a duplicate definition that instead returns id. In that + // case, use the one that returns instancetype. Note that since instancetype + // is an alias of id, the sameAs check above passes. + if (ObjCBuiltInFunctions.isInstanceType(newMethod.returnType) && + !ObjCBuiltInFunctions.isInstanceType(oldMethod.returnType)) { + return newMethod; + } else if (!ObjCBuiltInFunctions.isInstanceType(newMethod.returnType) && + ObjCBuiltInFunctions.isInstanceType(oldMethod.returnType)) { + return oldMethod; + } + + return newMethod; + } + + bool _shouldIncludeMethod(ObjCMethod method) => + method.childTypes.every((Type t) { + t = t.typealiasType.baseType; + + // Ignore methods with variadic args. + // TODO(https://github.com/dart-lang/native/issues/1192): Remove this. + if (t is Struct && t.originalName == '__va_list_tag') { + return false; + } + + // Ignore methods with block args or rets when we're generating in + // package:objective_c. + // TODO(https://github.com/dart-lang/native/issues/1180): Remove this. + if (builtInFunctions.generateForPackageObjectiveC && t is ObjCBlock) { + return false; + } + + return true; + }); + + UniqueNamer createMethodRenamer(Writer w) => UniqueNamer( + {name, 'pointer', 'toString', 'hashCode', 'runtimeType', 'noSuchMethod'}, + parent: w.topLevelUniqueNamer); +} + +enum ObjCMethodKind { + method, + propertyGetter, + propertySetter, +} + +class ObjCProperty { + final String originalName; + String? dartName; + + ObjCProperty(this.originalName); +} + +class ObjCMethod { + final String? dartDoc; + final String originalName; + final ObjCProperty? property; + Type returnType; + final List params; + final ObjCMethodKind kind; + final bool isClassMethod; + final bool isOptional; + bool returnsRetained = false; + ObjCInternalGlobal? selObject; + ObjCMsgSendFunc? msgSend; + late ObjCBlock protocolBlock; + + ObjCMethod({ + required this.originalName, + this.property, + this.dartDoc, + required this.kind, + required this.isClassMethod, + required this.isOptional, + required this.returnType, + List? params_, + }) : params = params_ ?? []; + + bool get isProperty => + kind == ObjCMethodKind.propertyGetter || + kind == ObjCMethodKind.propertySetter; + bool get isRequired => !isOptional; + bool get isInstanceMethod => !isClassMethod; + + void addDependencies( + Set dependencies, + ObjCBuiltInFunctions builtInFunctions, { + bool needMsgSend = false, + bool needProtocolBlock = false, + }) { + returnType.addDependencies(dependencies); + for (final p in params) { + p.type.addDependencies(dependencies); + } + selObject = builtInFunctions.getSelObject(originalName) + ..addDependencies(dependencies); + if (needMsgSend) { + msgSend = builtInFunctions.getMsgSendFunc(returnType, params) + ..addDependencies(dependencies); + } + if (needProtocolBlock) { + final argTypes = [ + // First arg of the protocol block is a void pointer that we ignore. + PointerType(voidType), + ...params.map((p) => p.type), + ]; + protocolBlock = ObjCBlock( + returnType: returnType, + argTypes: argTypes, + )..addDependencies(dependencies); + } + } + + String getDartMethodName(UniqueNamer uniqueNamer) { + if (property != null) { + // A getter and a setter are allowed to have the same name, so we can't + // just run the name through uniqueNamer. Instead they need to share + // the dartName, which is run through uniqueNamer. + if (property!.dartName == null) { + property!.dartName = uniqueNamer.makeUnique(property!.originalName); + } + return property!.dartName!; + } + // Objective C methods can look like: + // foo + // foo: + // foo:someArgName: + // So replace all ':' with '_'. + return uniqueNamer.makeUnique(originalName.replaceAll(':', '_')); + } + + bool sameAs(ObjCMethod other) { + if (originalName != other.originalName) return false; + if (kind != other.kind) return false; + if (isClassMethod != other.isClassMethod) return false; + if (isOptional != other.isOptional) return false; + // msgSend is deduped by signature, so this check covers the signature. + return msgSend == other.msgSend; + } + + static final _copyRegExp = RegExp('[cC]opy'); + bool get isOwnedReturn => + returnsRetained || + originalName.startsWith('new') || + originalName.startsWith('alloc') || + originalName.contains(_copyRegExp); + + Iterable get childTypes sync* { + yield returnType; + for (final p in params) { + yield p.type; + } + } + + @override + String toString() => '${isOptional ? "@optional " : ""}$returnType ' + '$originalName(${params.join(', ')})'; +} + +class ObjCMethodParam { + Type type; + final String name; + ObjCMethodParam(this.type, this.name); + + @override + String toString() => '$type $name'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_nullable.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_nullable.dart new file mode 100644 index 0000000000..42b7fe3e60 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_nullable.dart @@ -0,0 +1,91 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'writer.dart'; + +/// An ObjC type annotated with nullable. Eg: +/// +(nullable NSObject*) methodWithNullableResult; +class ObjCNullable extends Type { + Type child; + + ObjCNullable(this.child) : assert(isSupported(child)); + + static bool isSupported(Type type) => + type is ObjCInterface || + type is ObjCBlock || + type is ObjCObjectPointer || + type is ObjCInstanceType; + + @override + void addDependencies(Set dependencies) { + child.addDependencies(dependencies); + } + + @override + Type get baseType => child.baseType; + + @override + String getCType(Writer w) => child.getCType(w); + + @override + String getFfiDartType(Writer w) => child.getFfiDartType(w); + + @override + String getDartType(Writer w) => '${child.getDartType(w)}?'; + + @override + String getNativeType({String varName = ''}) => + child.getNativeType(varName: varName); + + @override + bool get sameFfiDartAndCType => child.sameFfiDartAndCType; + + @override + bool get sameDartAndCType => false; + + @override + bool get sameDartAndFfiDartType => false; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) { + // This is a bit of a hack, but works for all the types that are allowed to + // be a child type. If we add more allowed child types, we may have to start + // special casing each type. Turns value._id into value?._id ?? nullptr. + final convertedValue = child.convertDartTypeToFfiDartType(w, '$value?', + objCRetain: objCRetain); + return '$convertedValue ?? ${w.ffiLibraryPrefix}.nullptr'; + } + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) { + // All currently supported child types have a Pointer as their FfiDartType. + final convertedValue = child.convertFfiDartTypeToDartType( + w, + value, + objCRetain: objCRetain, + objCEnclosingClass: objCEnclosingClass, + ); + return '$value.address == 0 ? null : $convertedValue'; + } + + @override + String? generateRetain(String value) => child.generateRetain(value); + + @override + String toString() => '$child?'; + + @override + String cacheKey() => '${child.cacheKey()}?'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigenpad/lib/src/code_generator/objc_protocol.dart new file mode 100644 index 0000000000..d1caa135e6 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/objc_protocol.dart @@ -0,0 +1,198 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +class ObjCProtocol extends NoLookUpBinding with ObjCMethods { + final superProtocols = []; + final String lookupName; + late final ObjCInternalGlobal _protocolPointer; + + @override + final ObjCBuiltInFunctions builtInFunctions; + + ObjCProtocol({ + super.usr, + required String super.originalName, + String? name, + String? lookupName, + super.dartDoc, + required this.builtInFunctions, + }) : lookupName = lookupName ?? originalName, + super(name: name ?? originalName); + + @override + BindingString toBindingString(Writer w) { + final protocolMethod = ObjCBuiltInFunctions.protocolMethod.gen(w); + final protocolListenableMethod = + ObjCBuiltInFunctions.protocolListenableMethod.gen(w); + final protocolBuilder = ObjCBuiltInFunctions.protocolBuilder.gen(w); + final objectBase = ObjCBuiltInFunctions.objectBase.gen(w); + final getSignature = ObjCBuiltInFunctions.getProtocolMethodSignature.gen(w); + + final buildArgs = []; + final buildImplementations = StringBuffer(); + final buildListenerImplementations = StringBuffer(); + final methodFields = StringBuffer(); + + final methodNamer = createMethodRenamer(w); + + var anyListeners = false; + for (final method in methods) { + final methodName = method.getDartMethodName(methodNamer); + final fieldName = methodName; + final argName = methodName; + final block = method.protocolBlock; + final blockType = block.getDartType(w); + final methodClass = + block.hasListener ? protocolListenableMethod : protocolMethod; + + // The function type omits the first arg of the block, which is unused. + final func = FunctionType(returnType: block.returnType, parameters: [ + for (int i = 1; i < block.argTypes.length; ++i) + Parameter(name: 'arg$i', type: block.argTypes[i]), + ]); + final funcType = func.getDartType(w, writeArgumentNames: false); + + if (method.isOptional) { + buildArgs.add('$funcType? $argName'); + } else { + buildArgs.add('required $funcType $argName'); + } + + final blockFirstArg = block.argTypes[0].getDartType(w); + final argsReceived = func.parameters + .map((p) => '${p.type.getDartType(w)} ${p.name}') + .join(', '); + final argsPassed = func.parameters.map((p) => p.name).join(', '); + final wrapper = '($blockFirstArg _, $argsReceived) => func($argsPassed)'; + + var listenerBuilder = ''; + var maybeImplementAsListener = 'implement'; + if (block.hasListener) { + listenerBuilder = '($funcType func) => $blockType.listener($wrapper),'; + maybeImplementAsListener = 'implementAsListener'; + anyListeners = true; + } + + buildImplementations.write(''' + $name.$fieldName.implement(builder, $argName);'''); + buildListenerImplementations.write(''' + $name.$fieldName.$maybeImplementAsListener(builder, $argName);'''); + + methodFields.write(makeDartDoc(method.dartDoc ?? method.originalName)); + methodFields.write('''static final $fieldName = $methodClass<$funcType>( + ${method.selObject!.name}, + $getSignature( + ${_protocolPointer.name}, + ${method.selObject!.name}, + isRequired: ${method.isRequired}, + isInstanceMethod: ${method.isInstanceMethod}, + ), + ($funcType func) => $blockType.fromFunction($wrapper), + $listenerBuilder + ); +'''); + } + + final args = buildArgs.isEmpty ? '' : '{${buildArgs.join(', ')}}'; + final builders = ''' + /// Builds an object that implements the $originalName protocol. To implement + /// multiple protocols, use [addToBuilder] or [$protocolBuilder] directly. + static $objectBase implement($args) { + final builder = $protocolBuilder(); + $buildImplementations + return builder.build(); + } + + /// Adds the implementation of the $originalName protocol to an existing + /// [$protocolBuilder]. + static void addToBuilder($protocolBuilder builder, $args) { + $buildImplementations + } +'''; + + var listenerBuilders = ''; + if (anyListeners) { + listenerBuilders = ''' + /// Builds an object that implements the $originalName protocol. To implement + /// multiple protocols, use [addToBuilder] or [$protocolBuilder] directly. All + /// methods that can be implemented as listeners will be. + static $objectBase implementAsListener($args) { + final builder = $protocolBuilder(); + $buildListenerImplementations + return builder.build(); + } + + /// Adds the implementation of the $originalName protocol to an existing + /// [$protocolBuilder]. All methods that can be implemented as listeners will + /// be. + static void addToBuilderAsListener($protocolBuilder builder, $args) { + $buildListenerImplementations + } +'''; + } + + final mainString = ''' +${makeDartDoc(dartDoc ?? originalName)}abstract final class $name { + $builders + $listenerBuilders + $methodFields +} +'''; + + return BindingString( + type: BindingStringType.objcProtocol, string: mainString); + } + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + dependencies.add(this); + + _protocolPointer = ObjCInternalGlobal( + '_protocol_$originalName', + (Writer w) => + '${ObjCBuiltInFunctions.getProtocol.gen(w)}("$lookupName")') + ..addDependencies(dependencies); + + for (final superProtocol in superProtocols) { + superProtocol.addDependencies(dependencies); + } + + addMethodDependencies(dependencies, needProtocolBlock: true); + + for (final superProtocol in superProtocols) { + _copyMethodsFromSuperType(superProtocol); + } + + // Add dependencies for any methods that were added. + addMethodDependencies(dependencies, needProtocolBlock: true); + } + + void _copyMethodsFromSuperType(ObjCProtocol superProtocol) { + if (builtInFunctions.isNSObject(superProtocol.originalName)) { + // When writing a protocol that doesn't inherit from any other protocols, + // it's typical to have it inherit from NSObject instead. But NSObject has + // heaps of methods that users are very unlikely to want to implement, so + // ignore it. If the user really wants to implement them they can use the + // ObjCProtocolBuilder. + return; + } + + // Protocols have very different inheritance semantics than Dart classes. + // So copy across all the methods explicitly, rather than trying to use Dart + // inheritance to get them implicitly. + for (final method in superProtocol.methods) { + addMethod(method); + } + } + + @override + String toString() => originalName; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/pointer.dart b/pkgs/ffigenpad/lib/src/code_generator/pointer.dart new file mode 100644 index 0000000000..177bcab41e --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/pointer.dart @@ -0,0 +1,139 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'writer.dart'; + +/// Represents a pointer. +class PointerType extends Type { + final Type child; + + PointerType._(this.child); + + factory PointerType(Type child) { + if (child == objCObjectType) { + return ObjCObjectPointer(); + } + return PointerType._(child); + } + + @override + void addDependencies(Set dependencies) { + child.addDependencies(dependencies); + } + + @override + Type get baseType => child.baseType; + + @override + String getCType(Writer w) => + '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>'; + + @override + String getNativeType({String varName = ''}) => + '${child.getNativeType()}* $varName'; + + // Both the C type and the FFI Dart type are 'Pointer<$cType>'. + @override + bool get sameFfiDartAndCType => true; + + @override + String toString() => '$child*'; + + @override + String cacheKey() => '${child.cacheKey()}*'; +} + +/// Represents a constant array, which has a fixed size. +class ConstantArray extends PointerType { + final int length; + final bool useArrayType; + + ConstantArray(this.length, Type child, {required this.useArrayType}) + : super._(child); + + @override + Type get baseArrayType => child.baseArrayType; + + @override + bool get isIncompleteCompound => baseArrayType.isIncompleteCompound; + + @override + String getNativeType({String varName = ''}) => + '${child.getNativeType()} $varName[$length]'; + + @override + String toString() => '$child[$length]'; + + @override + String cacheKey() => '${child.cacheKey()}[$length]'; + + @override + String getCType(Writer w) { + if (useArrayType) { + return '${w.ffiLibraryPrefix}.Array<${child.getCType(w)}>'; + } + + return super.getCType(w); + } +} + +/// Represents an incomplete array, which has an unknown size. +class IncompleteArray extends PointerType { + IncompleteArray(super.child) : super._(); + + @override + Type get baseArrayType => child.baseArrayType; + + @override + String getNativeType({String varName = ''}) => + '${child.getNativeType()} $varName[]'; + + @override + String toString() => '$child[]'; + + @override + String cacheKey() => '${child.cacheKey()}[]'; +} + +/// A pointer to an Objective C object. +class ObjCObjectPointer extends PointerType { + factory ObjCObjectPointer() => _inst; + + static final _inst = ObjCObjectPointer._(); + ObjCObjectPointer._() : super._(objCObjectType); + + @override + String getDartType(Writer w) => '${w.objcPkgPrefix}.ObjCObjectBase'; + + @override + String getNativeType({String varName = ''}) => 'id $varName'; + + @override + bool get sameDartAndCType => false; + + @override + bool get sameDartAndFfiDartType => false; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + ObjCInterface.generateGetId(value, objCRetain); + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + '${getDartType(w)}($value, retain: $objCRetain, release: true)'; + + @override + String? generateRetain(String value) => '[$value retain]'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/struct.dart b/pkgs/ffigenpad/lib/src/code_generator/struct.dart new file mode 100644 index 0000000000..945261a676 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/struct.dart @@ -0,0 +1,44 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'compound.dart'; + +/// A binding for C Struct. +/// +/// For a C structure - +/// ```c +/// struct C { +/// int a; +/// double b; +/// int c; +/// }; +/// ``` +/// The generated dart code is - +/// ```dart +/// final class Struct extends ffi.Struct { +/// @ffi.Int32() +/// int a; +/// +/// @ffi.Double() +/// double b; +/// +/// @ffi.Uint8() +/// int c; +/// +/// } +/// ``` +class Struct extends Compound { + Struct({ + super.usr, + super.originalName, + required super.name, + super.isIncomplete, + super.pack, + super.dartDoc, + super.members, + super.isInternal, + super.objCBuiltInFunctions, + super.nativeType, + }) : super(compoundType: CompoundType.struct); +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/type.dart b/pkgs/ffigenpad/lib/src/code_generator/type.dart new file mode 100644 index 0000000000..be4a97fb37 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/type.dart @@ -0,0 +1,204 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import 'writer.dart'; + +/// Type class for return types, variable types, etc. +/// +/// Implementers should extend either Type, or BindingType if the type is also a +/// binding, and override at least getCType and toString. +abstract class Type { + const Type(); + + /// Get all dependencies of this type and save them in [dependencies]. + void addDependencies(Set dependencies) {} + + /// Get base type for any type. + /// + /// E.g int** has base [Type] of int. + /// double[2][3] has base [Type] of double. + Type get baseType => this; + + /// Get base Array type. + /// + /// Returns itself if it's not an Array Type. + Type get baseArrayType => this; + + /// Get base typealias type. + /// + /// Returns itself if it's not a Typealias. + Type get typealiasType => this; + + /// Returns true if the type is a [Compound] and is incomplete. + bool get isIncompleteCompound => false; + + /// Returns the C type of the Type. This is the FFI compatible type that is + /// passed to native code. + String getCType(Writer w) => + throw UnsupportedError('No mapping for type: $this'); + + /// Returns the Dart type of the Type. This is the type that is passed from + /// FFI to Dart code. + String getFfiDartType(Writer w) => getCType(w); + + /// Returns the user type of the Type. This is the type that is presented to + /// users by the ffigened API to users. For C bindings this is always the same + /// as getFfiDartType. For ObjC bindings this refers to the wrapper object. + String getDartType(Writer w) => getFfiDartType(w); + + /// Returns the C/ObjC type of the Type. This is the type as it appears in + /// C/ObjC source code. It should not be used in Dart source code. + /// + /// This method takes a [varName] arg because some C/ObjC types embed the + /// variable name inside the type. Eg, to pass an ObjC block as a function + /// argument, the syntax is `int (^arg)(int)`, where arg is the [varName]. + String getNativeType({String varName = ''}) => + throw UnsupportedError('No native mapping for type: $this'); + + /// Returns whether the FFI dart type and C type string are same. + bool get sameFfiDartAndCType; + + /// Returns whether the dart type and C type string are same. + bool get sameDartAndCType => sameFfiDartAndCType; + + /// Returns whether the dart type and FFI dart type string are same. + bool get sameDartAndFfiDartType => true; + + /// Returns generated Dart code that converts the given value from its + /// DartType to its FfiDartType. + /// + /// [value] is the value to be converted. If [objCRetain] is true, the ObjC + /// object will be reained (ref count incremented) during conversion. + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + value; + + /// Returns generated Dart code that converts the given value from its + /// FfiDartType to its DartType. + /// + /// [value] is the value to be converted. If [objCRetain] is true, the ObjC + /// wrapper object will retain (ref count increment) the wrapped object + /// pointer. If this conversion is occuring in the context of an ObjC class, + /// then [objCEnclosingClass] should be the name of the Dart wrapper class + /// (this is used by instancetype). + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + value; + + /// Returns generated ObjC code that retains a reference to the given value. + /// Returns null if the Type does not need to be retained. + String? generateRetain(String value) => null; + + /// Returns a human readable string representation of the Type. This is mostly + /// just for debugging, but it may also be used for non-functional code (eg to + /// name a variable or type in generated code). + @override + String toString(); + + /// Cache key used in various places to dedupe Types. By default this is just + /// the hash of the Type, but in many cases this does not dedupe sufficiently. + /// So Types that may be duplicated should override this to return a more + /// specific key. Types that are already deduped don't need to override this. + /// toString() is not a valid cache key as there may be name collisions. + String cacheKey() => hashCode.toRadixString(36); + + /// Returns a string of code that creates a default value for this type. For + /// example, for int types this returns the string '0'. A null return means + /// that default values aren't supported for this type, eg void. + String? getDefaultValue(Writer w) => null; +} + +/// Base class for all Type bindings. +/// +/// Since Dart doesn't have multiple inheritance, this type exists so that we +/// don't have to reimplement the default methods in all the classes that want +/// to extend both NoLookUpBinding and Type. +abstract class BindingType extends NoLookUpBinding implements Type { + BindingType({ + super.usr, + super.originalName, + required super.name, + super.dartDoc, + super.isInternal, + }); + + @override + Type get baseType => this; + + @override + Type get baseArrayType => this; + + @override + Type get typealiasType => this; + + @override + bool get isIncompleteCompound => false; + + @override + String getFfiDartType(Writer w) => getCType(w); + + @override + String getDartType(Writer w) => getFfiDartType(w); + + @override + String getNativeType({String varName = ''}) => + throw UnsupportedError('No native mapping for type: $this'); + + @override + bool get sameDartAndCType => sameFfiDartAndCType; + + @override + bool get sameDartAndFfiDartType => true; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + value; + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + value; + + @override + String? generateRetain(String value) => null; + + @override + String toString() => originalName; + + @override + String cacheKey() => hashCode.toRadixString(36); + + @override + String? getDefaultValue(Writer w) => null; +} + +/// Represents an unimplemented type. Used as a marker, so that declarations +/// having these can exclude them. +class UnimplementedType extends Type { + String reason; + UnimplementedType(this.reason); + + @override + String toString() => '(Unimplemented: $reason)'; + + @override + bool get sameFfiDartAndCType => true; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/typealias.dart b/pkgs/ffigenpad/lib/src/code_generator/typealias.dart new file mode 100644 index 0000000000..2be2a2ec94 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/typealias.dart @@ -0,0 +1,256 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; + +import '../strings.dart' as strings; +import 'binding_string.dart'; +import 'utils.dart'; +import 'writer.dart'; + +/// A simple Typealias, Expands to - +/// +/// ```dart +/// typedef $name = $type; +/// ); +/// ``` +class Typealias extends BindingType { + final Type type; + String? _ffiDartAliasName; + String? _dartAliasName; + + /// Creates a Typealias. + /// + /// If [genFfiDartType] is true, a binding is generated for the Ffi Dart type + /// in addition to the C type. See [Type.getFfiDartType]. + factory Typealias({ + String? usr, + String? originalName, + String? dartDoc, + required String name, + required Type type, + bool genFfiDartType = false, + bool isInternal = false, + }) { + final funcType = _getFunctionTypeFromPointer(type); + if (funcType != null) { + type = PointerType(NativeFunc(Typealias._( + name: '${name}Function', + type: funcType, + genFfiDartType: genFfiDartType, + isInternal: isInternal, + ))); + } + if ((originalName ?? name) == strings.objcInstanceType && + type is ObjCObjectPointer) { + return ObjCInstanceType._( + usr: usr, + originalName: originalName, + dartDoc: dartDoc, + name: name, + type: type, + genFfiDartType: genFfiDartType, + isInternal: isInternal, + ); + } + return Typealias._( + usr: usr, + originalName: originalName, + dartDoc: dartDoc, + name: name, + type: type, + genFfiDartType: genFfiDartType, + isInternal: isInternal, + ); + } + + Typealias._({ + super.usr, + super.originalName, + super.dartDoc, + required String name, + required this.type, + bool genFfiDartType = false, + super.isInternal, + }) : _ffiDartAliasName = genFfiDartType ? 'Dart$name' : null, + _dartAliasName = + (!genFfiDartType && type is! Typealias && !type.sameDartAndCType) + ? 'Dart$name' + : null, + super( + name: genFfiDartType ? 'Native$name' : name, + ); + + @override + void addDependencies(Set dependencies) { + if (dependencies.contains(this)) return; + + dependencies.add(this); + type.addDependencies(dependencies); + } + + static FunctionType? _getFunctionTypeFromPointer(Type type) { + if (type is! PointerType) return null; + final pointee = type.child; + if (pointee is! NativeFunc) return null; + return pointee.type; + } + + @override + BindingString toBindingString(Writer w) { + if (_ffiDartAliasName != null) { + _ffiDartAliasName = w.topLevelUniqueNamer.makeUnique(_ffiDartAliasName!); + } + if (_dartAliasName != null) { + _dartAliasName = w.topLevelUniqueNamer.makeUnique(_dartAliasName!); + } + + final sb = StringBuffer(); + if (dartDoc != null) { + sb.write(makeDartDoc(dartDoc!)); + } + sb.write('typedef $name = ${type.getCType(w)};\n'); + if (_ffiDartAliasName != null) { + sb.write('typedef $_ffiDartAliasName = ${type.getFfiDartType(w)};\n'); + } + if (_dartAliasName != null) { + sb.write('typedef $_dartAliasName = ${type.getDartType(w)};\n'); + } + return BindingString( + type: BindingStringType.typeDef, string: sb.toString()); + } + + @override + Type get typealiasType => type.typealiasType; + + @override + bool get isIncompleteCompound => type.isIncompleteCompound; + + @override + String getCType(Writer w) => name; + + @override + String getNativeType({String varName = ''}) => + type.getNativeType(varName: varName); + + @override + String getFfiDartType(Writer w) { + if (_ffiDartAliasName != null) { + return _ffiDartAliasName!; + } else if (type.sameFfiDartAndCType) { + return name; + } else { + return type.getFfiDartType(w); + } + } + + @override + String getDartType(Writer w) { + if (_dartAliasName != null) { + return _dartAliasName!; + } else if (type.sameDartAndCType) { + return getFfiDartType(w); + } else { + return type.getDartType(w); + } + } + + @override + bool get sameFfiDartAndCType => type.sameFfiDartAndCType; + + @override + bool get sameDartAndCType => type.sameDartAndCType; + + @override + bool get sameDartAndFfiDartType => type.sameDartAndFfiDartType; + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + type.convertDartTypeToFfiDartType(w, value, objCRetain: objCRetain); + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + type.convertFfiDartTypeToDartType( + w, + value, + objCRetain: objCRetain, + objCEnclosingClass: objCEnclosingClass, + ); + + @override + String? generateRetain(String value) => type.generateRetain(value); + + @override + String cacheKey() => type.cacheKey(); + + @override + String? getDefaultValue(Writer w) => type.getDefaultValue(w); + + // Used to compare whether two Typealias are same symbols and ensure that they + // are unique when adding to a [Set]. + @override + bool operator ==(Object other) { + if (other is! Typealias) return false; + if (identical(this, other)) return true; + return other.usr == usr; + } + + // [usr] is unique for specific symbols. + @override + int get hashCode => usr.hashCode; +} + +/// Objective C's instancetype. +/// +/// This is an alias for an ObjC object pointer that is special cased in code +/// generation. It's only valid as the return type of a method, and always +/// appears as the enclosing class's type, even in inherited methods. +class ObjCInstanceType extends Typealias { + ObjCInstanceType._({ + super.usr, + super.originalName, + super.dartDoc, + required super.name, + required super.type, + super.genFfiDartType, + super.isInternal, + }) : super._(); + + @override + String convertDartTypeToFfiDartType( + Writer w, + String value, { + required bool objCRetain, + }) => + ObjCInterface.generateGetId(value, objCRetain); + + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + objCEnclosingClass == null + ? super.convertFfiDartTypeToDartType( + w, + value, + objCRetain: objCRetain, + objCEnclosingClass: objCEnclosingClass, + ) + : ObjCInterface.generateConstructor( + objCEnclosingClass, value, objCRetain); + + @override + String getNativeType({String varName = ''}) => 'id $varName'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/union.dart b/pkgs/ffigenpad/lib/src/code_generator/union.dart new file mode 100644 index 0000000000..3675023d74 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/union.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'compound.dart'; + +/// A binding for a C union - +/// +/// ```c +/// union C { +/// int a; +/// double b; +/// float c; +/// }; +/// ``` +/// The generated dart code is - +/// ```dart +/// final class Union extends ffi.Union{ +/// @ffi.Int32() +/// int a; +/// +/// @ffi.Double() +/// double b; +/// +/// @ffi.Float() +/// float c; +/// +/// } +/// ``` +class Union extends Compound { + Union({ + super.usr, + super.originalName, + required super.name, + super.isIncomplete, + super.pack, + super.dartDoc, + super.members, + super.objCBuiltInFunctions, + super.nativeType, + }) : super(compoundType: CompoundType.union); +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/utils.dart b/pkgs/ffigenpad/lib/src/code_generator/utils.dart new file mode 100644 index 0000000000..020a0cdb20 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/utils.dart @@ -0,0 +1,98 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart_keywords.dart'; +import 'pointer.dart'; +import 'type.dart'; +import 'writer.dart'; + +export 'package:ffigen/src/code_generator/utils.dart' + show makeDartDoc, makeDoc, parseObjCFrameworkHeader; + +class UniqueNamer { + final Set _usedUpNames; + + /// Creates a UniqueNamer with given [usedUpNames] and Dart reserved keywords. + /// + /// If [parent] is provided, also includes all the parent's names. + UniqueNamer(Set usedUpNames, {UniqueNamer? parent}) + : _usedUpNames = { + ...keywords, + ...usedUpNames, + ...parent?._usedUpNames ?? {}, + }; + + /// Creates a UniqueNamer with given [_usedUpNames] only. + UniqueNamer._raw(this._usedUpNames); + + /// Returns a unique name by appending `` to it if necessary. + /// + /// Adds the resulting name to the used names by default. + String makeUnique(String name, [bool addToUsedUpNames = true]) { + // For example, nested structures/unions may not have a name + if (name.isEmpty) { + name = 'unnamed'; + } + + var crName = name; + var i = 1; + while (_usedUpNames.contains(crName)) { + crName = '$name$i'; + i++; + } + if (addToUsedUpNames) { + _usedUpNames.add(crName); + } + return crName; + } + + /// Adds a name to used names. + /// + /// Note: [makeUnique] also adds the name by default. + void markUsed(String name) { + _usedUpNames.add(name); + } + + /// Returns true if a name has been used before. + bool isUsed(String name) { + return _usedUpNames.contains(name); + } + + /// Returns true if a name has not been used before. + bool isUnique(String name) { + return !_usedUpNames.contains(name); + } + + UniqueNamer clone() => UniqueNamer._raw({..._usedUpNames}); +} + +String makeNativeAnnotation( + Writer w, { + required String? nativeType, + required String dartName, + required String nativeSymbolName, + bool isLeaf = false, +}) { + final args = <(String, String)>[]; + if (dartName != nativeSymbolName) { + args.add(('symbol', '"$nativeSymbolName"')); + } + if (isLeaf) { + args.add(('isLeaf', 'true')); + } + + final combinedArgs = args.map((e) => '${e.$1}: ${e.$2}').join(', '); + return '@${w.ffiLibraryPrefix}.Native<$nativeType>($combinedArgs)'; +} + +String makeArrayAnnotation(Writer w, ConstantArray arrayType) { + final dimensions = []; + Type type = arrayType; + while (type is ConstantArray) { + dimensions.add(type.length); + type = type.child; + } + + return '@${w.ffiLibraryPrefix}.Array.multi([${dimensions.join(', ')}])'; +} diff --git a/pkgs/ffigenpad/lib/src/code_generator/writer.dart b/pkgs/ffigenpad/lib/src/code_generator/writer.dart new file mode 100644 index 0000000000..ff8e8e6d8f --- /dev/null +++ b/pkgs/ffigenpad/lib/src/code_generator/writer.dart @@ -0,0 +1,516 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as p; + +import '../code_generator.dart'; +import '../strings.dart' as strings; +import 'utils.dart'; + +final _logger = Logger('ffigen.code_generator.writer'); + +/// To store generated String bindings. +class Writer { + final String? header; + + /// Holds bindings, which lookup symbols. + final List lookUpBindings; + + /// Holds bindings, which lookup symbols through `FfiNative`. + final List ffiNativeBindings; + + /// Holds bindings which don't lookup symbols. + final List noLookUpBindings; + + /// The default asset id to use for [ffiNativeBindings]. + final String? nativeAssetId; + + /// Manages the `_SymbolAddress` class. + final symbolAddressWriter = SymbolAddressWriter(); + + late String _className; + String get className => _className; + + final String? classDocComment; + + final bool generateForPackageObjectiveC; + + final List nativeEntryPoints; + + /// Tracks where enumType.getCType is called. Reset everytime [generate] is + /// called. + bool usedEnumCType = false; + + String? _ffiLibraryPrefix; + String get ffiLibraryPrefix { + if (_ffiLibraryPrefix != null) { + return _ffiLibraryPrefix!; + } + + final import = _usedImports.firstWhere( + (element) => element.name == ffiImport.name, + orElse: () => ffiImport); + _usedImports.add(import); + return _ffiLibraryPrefix = import.prefix; + } + + String? _ffiPkgLibraryPrefix; + String get ffiPkgLibraryPrefix { + if (_ffiPkgLibraryPrefix != null) { + return _ffiPkgLibraryPrefix!; + } + + final import = _usedImports.firstWhere( + (element) => element.name == ffiPkgImport.name, + orElse: () => ffiPkgImport); + _usedImports.add(import); + return _ffiPkgLibraryPrefix = import.prefix; + } + + String? _objcPkgPrefix; + String get objcPkgPrefix { + if (_objcPkgPrefix != null) { + return _objcPkgPrefix!; + } + + final import = _usedImports.firstWhere( + (element) => element.name == objcPkgImport.name, + orElse: () => objcPkgImport); + _usedImports.add(import); + return _objcPkgPrefix = import.prefix; + } + + late String selfImportPrefix = () { + final import = _usedImports + .firstWhere((element) => element.name == self.name, orElse: () => self); + _usedImports.add(import); + return import.prefix; + }(); + + final Set _usedImports = {}; + + late String _lookupFuncIdentifier; + String get lookupFuncIdentifier => _lookupFuncIdentifier; + + late String _symbolAddressClassName; + late String _symbolAddressVariableName; + late String _symbolAddressLibraryVarName; + + /// Initial namers set after running constructor. Namers are reset to this + /// initial state everytime [generate] is called. + late UniqueNamer _initialTopLevelUniqueNamer, _initialWrapperLevelUniqueNamer; + + /// Used by [Binding]s for generating required code. + late UniqueNamer _topLevelUniqueNamer; + UniqueNamer get topLevelUniqueNamer => _topLevelUniqueNamer; + late UniqueNamer _wrapperLevelUniqueNamer; + UniqueNamer get wrapperLevelUniqueNamer => _wrapperLevelUniqueNamer; + late UniqueNamer _objCLevelUniqueNamer; + UniqueNamer get objCLevelUniqueNamer => _objCLevelUniqueNamer; + + late String _arrayHelperClassPrefix; + + /// Guaranteed to be a unique prefix. + String get arrayHelperClassPrefix => _arrayHelperClassPrefix; + + /// Set true after calling [generate]. Indicates if + /// [generateSymbolOutputYamlMap] can be called. + bool get canGenerateSymbolOutput => _canGenerateSymbolOutput; + bool _canGenerateSymbolOutput = false; + + final bool silenceEnumWarning; + + Writer({ + required this.lookUpBindings, + required this.ffiNativeBindings, + required this.noLookUpBindings, + required String className, + required this.nativeAssetId, + List? additionalImports, + this.classDocComment, + this.header, + required this.generateForPackageObjectiveC, + required this.silenceEnumWarning, + required this.nativeEntryPoints, + }) { + final globalLevelNameSet = noLookUpBindings.map((e) => e.name).toSet(); + final wrapperLevelNameSet = lookUpBindings.map((e) => e.name).toSet(); + final allNameSet = {} + ..addAll(globalLevelNameSet) + ..addAll(wrapperLevelNameSet); + + _initialTopLevelUniqueNamer = UniqueNamer(globalLevelNameSet); + _initialWrapperLevelUniqueNamer = UniqueNamer(wrapperLevelNameSet); + final allLevelsUniqueNamer = UniqueNamer(allNameSet); + + /// Wrapper class name must be unique among all names. + _className = _resolveNameConflict( + name: className, + makeUnique: allLevelsUniqueNamer, + markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer], + ); + + /// Library imports prefix should be unique unique among all names. + if (additionalImports != null) { + for (final lib in additionalImports) { + lib.prefix = _resolveNameConflict( + name: lib.prefix, + makeUnique: allLevelsUniqueNamer, + markUsed: [ + _initialWrapperLevelUniqueNamer, + _initialTopLevelUniqueNamer + ], + ); + } + } + + /// [_lookupFuncIdentifier] should be unique in top level. + _lookupFuncIdentifier = _resolveNameConflict( + name: '_lookup', + makeUnique: _initialTopLevelUniqueNamer, + markUsed: [_initialTopLevelUniqueNamer], + ); + + /// Resolve name conflicts of identifiers used for SymbolAddresses. + _symbolAddressClassName = _resolveNameConflict( + name: '_SymbolAddresses', + makeUnique: allLevelsUniqueNamer, + markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer], + ); + _symbolAddressVariableName = _resolveNameConflict( + name: 'addresses', + makeUnique: _initialWrapperLevelUniqueNamer, + markUsed: [_initialWrapperLevelUniqueNamer], + ); + _symbolAddressLibraryVarName = _resolveNameConflict( + name: '_library', + makeUnique: _initialWrapperLevelUniqueNamer, + markUsed: [_initialWrapperLevelUniqueNamer], + ); + + /// Finding a unique prefix for Array Helper Classes and store into + /// [_arrayHelperClassPrefix]. + final base = 'ArrayHelper'; + _arrayHelperClassPrefix = base; + var suffixInt = 0; + for (var i = 0; i < allNameSet.length; i++) { + if (allNameSet.elementAt(i).startsWith(_arrayHelperClassPrefix)) { + // Not a unique prefix, start over with a new suffix. + i = -1; + suffixInt++; + _arrayHelperClassPrefix = '$base$suffixInt'; + } + } + + _resetUniqueNamersNamers(); + } + + /// Resolved name conflict using [makeUnique] and marks the result as used in + /// all [markUsed]. + String _resolveNameConflict({ + required String name, + required UniqueNamer makeUnique, + List markUsed = const [], + }) { + final s = makeUnique.makeUnique(name); + for (final un in markUsed) { + un.markUsed(s); + } + return s; + } + + /// Resets the namers to initial state. Namers are reset before generating. + void _resetUniqueNamersNamers() { + _topLevelUniqueNamer = _initialTopLevelUniqueNamer.clone(); + _wrapperLevelUniqueNamer = _initialWrapperLevelUniqueNamer.clone(); + _objCLevelUniqueNamer = UniqueNamer({}); + } + + void markImportUsed(LibraryImport import) { + _usedImports.add(import); + } + + /// Writes all bindings to a String. + String generate() { + final s = StringBuffer(); + + // We write the source first to determine which imports are actually + // referenced. Headers and [s] are then combined into the final result. + final result = StringBuffer(); + + // Reset unique namers to initial state. + _resetUniqueNamersNamers(); + + // Reset [usedEnumCType]. + usedEnumCType = false; + + // Write file header (if any). + if (header != null) { + result.writeln(header); + } + + // Write auto generated declaration. + result.write(makeDoc( + 'AUTO GENERATED FILE, DO NOT EDIT.\n\nGenerated by `package:ffigen`.')); + + // Write lint ignore if not specified by user already. + if (!RegExp(r'ignore_for_file:\s*type\s*=\s*lint').hasMatch(header ?? '')) { + result.write(makeDoc('ignore_for_file: type=lint')); + } + + // If there are any @Native bindings, the file needs to have an + // `@DefaultAsset` annotation for the symbols to resolve properly. This + // avoids duplicating the asset on every element. + // Since the annotation goes on a `library;` directive, it needs to appear + // before other definitions in the file. + if (ffiNativeBindings.isNotEmpty && nativeAssetId != null) { + result + ..writeln("@$ffiLibraryPrefix.DefaultAsset('$nativeAssetId')") + ..writeln('library;\n'); + } + + /// Write [lookUpBindings]. + if (lookUpBindings.isNotEmpty) { + // Write doc comment for wrapper class. + if (classDocComment != null) { + s.write(makeDartDoc(classDocComment!)); + } + // Write wrapper classs. + s.write('class $_className{\n'); + // Write dylib. + s.write('/// Holds the symbol lookup function.\n'); + s.write('final $ffiLibraryPrefix.Pointer Function(String symbolName) ' + '$lookupFuncIdentifier;\n'); + s.write('\n'); + //Write doc comment for wrapper class constructor. + s.write(makeDartDoc('The symbols are looked up in [dynamicLibrary].')); + // Write wrapper class constructor. + s.write('$_className($ffiLibraryPrefix.DynamicLibrary dynamicLibrary): ' + '$lookupFuncIdentifier = dynamicLibrary.lookup;\n\n'); + //Write doc comment for wrapper class named constructor. + s.write(makeDartDoc('The symbols are looked up with [lookup].')); + // Write wrapper class named constructor. + s.write('$_className.fromLookup($ffiLibraryPrefix.Pointer ' + 'Function(' + 'String symbolName) lookup): $lookupFuncIdentifier = lookup;\n\n'); + for (final b in lookUpBindings) { + s.write(b.toBindingString(this).string); + } + if (symbolAddressWriter.shouldGenerate) { + s.write(symbolAddressWriter.writeObject(this)); + } + + s.write('}\n\n'); + } + + if (ffiNativeBindings.isNotEmpty) { + for (final b in ffiNativeBindings) { + s.write(b.toBindingString(this).string); + } + + if (symbolAddressWriter.shouldGenerate) { + s.write(symbolAddressWriter.writeObject(this)); + } + } + + if (symbolAddressWriter.shouldGenerate) { + s.write(symbolAddressWriter.writeClass(this)); + } + + /// Write [noLookUpBindings]. + for (final b in noLookUpBindings) { + s.write(b.toBindingString(this).string); + } + + // Write neccesary imports. + for (final lib in _usedImports) { + final path = lib.importPath(generateForPackageObjectiveC); + result.write("import '$path' as ${lib.prefix};\n"); + } + result.write(s); + + // Warn about Enum usage in API surface. + if (!silenceEnumWarning && usedEnumCType) { + _logger.severe('The integer type used for enums is ' + 'implementation-defined. FFIgen tries to mimic the integer sizes ' + 'chosen by the most common compilers for the various OS and ' + 'architecture combinations. To prevent any crashes, remove the ' + 'enums from your API surface. To rely on the (unsafe!) mimicking, ' + 'you can silence this warning by adding silence-enum-warning: true ' + 'to the FFIgen config.'); + } + + _canGenerateSymbolOutput = true; + return result.toString(); + } + + List get _allBindings => [ + ...noLookUpBindings, + ...ffiNativeBindings, + ...lookUpBindings, + ]; + + Map generateSymbolOutputYamlMap(String importFilePath) { + final bindings = _allBindings; + if (!canGenerateSymbolOutput) { + throw Exception('Invalid state: generateSymbolOutputYamlMap() ' + 'called before generate()'); + } + + // Warn for macros. + final hasMacroBindings = bindings.any( + (element) => element is Constant && element.usr.contains('@macro@')); + if (hasMacroBindings) { + _logger.info('Removing all Macros from symbol file since they cannot ' + 'be cross referenced reliably.'); + } + + // Remove internal bindings and macros. + bindings.removeWhere((element) { + return element.isInternal || + (element is Constant && element.usr.contains('@macro@')); + }); + + // Sort bindings alphabetically by USR. + bindings.sort((a, b) => a.usr.compareTo(b.usr)); + + final usesFfiNative = bindings + .whereType() + .any((element) => element.ffiNativeConfig.enabled); + + return { + strings.formatVersion: strings.symbolFileFormatVersion, + strings.files: { + importFilePath: { + strings.usedConfig: { + strings.ffiNative: usesFfiNative, + }, + strings.symbols: { + for (final b in bindings) b.usr: {strings.name: b.name}, + }, + }, + }, + }; + } + + static String _objcImport(String entryPoint, String outDir) { + final frameworkHeader = parseObjCFrameworkHeader(entryPoint); + + if (frameworkHeader == null) { + // If it's not a framework header, use a relative import. + return '#import "${p.relative(entryPoint, from: outDir)}"\n'; + } + + // If it's a framework header, use a <> style import. + return '#import <$frameworkHeader>'; + } + + /// Writes the Objective C code needed for the bindings, if any. Returns null + /// if there are no bindings that need generated ObjC code. This function does + /// not generate the output file, but the [outFilename] does affect the + /// generated code. + String? generateObjC(String outFilename) { + final outDir = p.dirname(outFilename); + + final s = StringBuffer(); + s.write(''' +#include + +'''); + + for (final entryPoint in nativeEntryPoints) { + s.write(_objcImport(entryPoint, outDir)); + } + + var empty = true; + for (final binding in _allBindings) { + final bindingString = binding.toObjCBindingString(this); + if (bindingString != null) { + empty = false; + s.write(bindingString.string); + } + } + return empty ? null : s.toString(); + } +} + +/// Manages the generated `_SymbolAddress` class. +class SymbolAddressWriter { + final List<_SymbolAddressUnit> _addresses = []; + + /// Used to check if we need to generate `_SymbolAddress` class. + bool get shouldGenerate => _addresses.isNotEmpty; + + bool get hasNonNativeAddress => _addresses.any((e) => !e.native); + + void addSymbol({ + required String type, + required String name, + required String ptrName, + }) { + _addresses.add(_SymbolAddressUnit(type, name, ptrName, false)); + } + + void addNativeSymbol({required String type, required String name}) { + _addresses.add(_SymbolAddressUnit(type, name, '', true)); + } + + String writeObject(Writer w) { + final className = w._symbolAddressClassName; + final fieldName = w._symbolAddressVariableName; + + if (hasNonNativeAddress) { + return 'late final $fieldName = $className(this);'; + } else { + return 'const $fieldName = $className();'; + } + } + + String writeClass(Writer w) { + final sb = StringBuffer(); + sb.write('class ${w._symbolAddressClassName} {\n'); + + if (hasNonNativeAddress) { + // Write Library object. + sb.write('final ${w._className} ${w._symbolAddressLibraryVarName};\n'); + // Write Constructor. + sb.write('${w._symbolAddressClassName}(' + 'this.${w._symbolAddressLibraryVarName});\n'); + } else { + // Native bindings are top-level, so we don't need a field here. + sb.write('const ${w._symbolAddressClassName}();'); + } + + for (final address in _addresses) { + sb.write('${address.type} get ${address.name} => '); + + if (address.native) { + // For native fields and functions, we can use Native.addressOf to look + // up their address. + // The name of address getter shadows the actual element in the library, + // so we need to use a self-import. + final arg = '${w.selfImportPrefix}.${address.name}'; + sb.writeln('${w.ffiLibraryPrefix}.Native.addressOf($arg);'); + } else { + // For other elements, the generator will write a private field of type + // Pointer which we can reference here. + sb.writeln('${w._symbolAddressLibraryVarName}.${address.ptrName};'); + } + } + sb.write('}\n'); + return sb.toString(); + } +} + +/// Holds the data for a single symbol address. +class _SymbolAddressUnit { + final String type, name, ptrName; + + /// Whether the symbol we're looking up has been declared with `@Native`. + final bool native; + + _SymbolAddressUnit(this.type, this.name, this.ptrName, this.native); +} diff --git a/pkgs/ffigenpad/lib/src/config_provider.dart b/pkgs/ffigenpad/lib/src/config_provider.dart new file mode 100644 index 0000000000..1194762728 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Creates config object used by other sub_modules. +library; + +export 'config_provider/config.dart'; +export 'config_provider/yaml_config.dart'; diff --git a/pkgs/ffigenpad/lib/src/config_provider/config.dart b/pkgs/ffigenpad/lib/src/config_provider/config.dart new file mode 100644 index 0000000000..2daa0d7ef4 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/config.dart @@ -0,0 +1,309 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; +import 'config_impl.dart'; +import 'config_types.dart'; +// import 'spec_utils.dart'; + +/// Provides configurations to other modules. +abstract interface class Config { + /// Input config filename, if any. + Uri? get filename; + + /// Output file name. + Uri get output; + + /// Output ObjC file name. + Uri get outputObjC; + + /// Symbol file config. + SymbolFile? get symbolFile; + + /// Language that ffigen is consuming. + Language get language; + + /// Path to headers. May not contain globs. + List get entryPoints; + + /// Whether to include a specific header. This exists in addition to + /// [entryPoints] to allow filtering of transitively included headers. + bool shouldIncludeHeader(Uri header); + + /// CommandLine Arguments to pass to clang_compiler. + List get compilerOpts; + + /// VarArg function handling. + Map> get varArgFunctions; + + /// Declaration filters for Functions. + DeclarationFilters get functionDecl; + + /// Declaration filters for Structs. + DeclarationFilters get structDecl; + + /// Declaration filters for Unions. + DeclarationFilters get unionDecl; + + /// Declaration filters for Enums. + DeclarationFilters get enumClassDecl; + + /// Declaration filters for Unnamed enum constants. + DeclarationFilters get unnamedEnumConstants; + + /// Declaration filters for Globals. + DeclarationFilters get globals; + + /// Declaration filters for Macro constants. + DeclarationFilters get macroDecl; + + /// Declaration filters for Typedefs. + DeclarationFilters get typedefs; + + /// Declaration filters for Objective C interfaces. + DeclarationFilters get objcInterfaces; + + /// Declaration filters for Objective C protocols. + DeclarationFilters get objcProtocols; + + /// If enabled, unused typedefs will also be generated. + bool get includeUnusedTypedefs; + + /// Undocumented option that changes code generation for package:objective_c. + /// The main difference is whether NSObject etc are imported from + /// package:objective_c (the default) or code genned like any other class. + /// This is necessary because package:objective_c can't import NSObject from + /// itself. + bool get generateForPackageObjectiveC; + + /// If generated bindings should be sorted alphabetically. + bool get sort; + + /// If typedef of supported types(int8_t) should be directly used. + bool get useSupportedTypedefs; + + /// Stores all the library imports specified by user including those for ffi + /// and pkg_ffi. + Map get libraryImports; + + /// Stores all the symbol file maps name to ImportedType mappings specified by + /// user. + Map get usrTypeMappings; + + /// Stores typedef name to ImportedType mappings specified by user. + Map get typedefTypeMappings; + + /// Stores struct name to ImportedType mappings specified by user. + Map get structTypeMappings; + + /// Stores union name to ImportedType mappings specified by user. + Map get unionTypeMappings; + + /// Stores native int name to ImportedType mappings specified by user. + Map get nativeTypeMappings; + + /// Extracted Doc comment type. + CommentType get commentType; + + /// Whether structs that are dependencies should be included. + CompoundDependencies get structDependencies; + + /// Whether unions that are dependencies should be included. + CompoundDependencies get unionDependencies; + + /// Whether, and how, to override struct packing for the given struct. + PackingValue? structPackingOverride(Declaration declaration); + + /// The module that the ObjC interface belongs to. + String? interfaceModule(Declaration declaration); + + /// The module that the ObjC protocol belongs to. + String? protocolModule(Declaration declaration); + + /// Name of the wrapper class. + String get wrapperName; + + /// Doc comment for the wrapper class. + String? get wrapperDocComment; + + /// Header of the generated bindings. + String? get preamble; + + /// If `Dart_Handle` should be mapped with Handle/Object. + bool get useDartHandle; + + /// Whether to silence warning for enum integer type mimicking. + bool get silenceEnumWarning; + + /// Whether to expose the function typedef for a given function. + bool shouldExposeFunctionTypedef(Declaration declaration); + + /// Whether the given function is a leaf function. + bool isLeafFunction(Declaration declaration); + + /// Whether to generate the given enum as a series of int constants, rather + /// than a real Dart enum. + bool enumShouldBeInt(Declaration declaration); + + /// Whether to generate the given unnamed enum as a series of int constants, + /// rather than a real Dart enum. + bool unnamedEnumsShouldBeInt(Declaration declaration); + + /// Config options for @Native annotations. + FfiNativeConfig get ffiNativeConfig; + + /// Where to ignore compiler warnings/errors in source header files. + bool get ignoreSourceErrors; + + /// Whether to format the output file. + bool get formatOutput; + + factory Config({ + Uri? filename, + Uri? libclangDylib, + required Uri output, + Uri? outputObjC, + SymbolFile? symbolFile, + Language language = Language.c, + required List entryPoints, + bool Function(Uri header)? shouldIncludeHeaderFunc, + List compilerOpts = const [], + Map> varArgFunctions = + const >{}, + DeclarationFilters? functionDecl, + DeclarationFilters? structDecl, + DeclarationFilters? unionDecl, + DeclarationFilters? enumClassDecl, + DeclarationFilters? unnamedEnumConstants, + DeclarationFilters? globals, + DeclarationFilters? macroDecl, + DeclarationFilters? typedefs, + DeclarationFilters? objcInterfaces, + DeclarationFilters? objcProtocols, + bool includeUnusedTypedefs = false, + bool generateForPackageObjectiveC = false, + bool sort = false, + bool useSupportedTypedefs = true, + List libraryImports = const [], + List usrTypeMappings = const [], + List typedefTypeMappings = const [], + List structTypeMappings = const [], + List unionTypeMappings = const [], + List nativeTypeMappings = const [], + CommentType? commentType, + CompoundDependencies structDependencies = CompoundDependencies.full, + CompoundDependencies unionDependencies = CompoundDependencies.full, + PackingValue? Function(Declaration declaration)? structPackingOverrideFunc, + String? Function(Declaration declaration)? interfaceModuleFunc, + String? Function(Declaration declaration)? protocolModuleFunc, + String wrapperName = 'NativeLibrary', + String? wrapperDocComment, + String? preamble, + bool useDartHandle = true, + bool silenceEnumWarning = false, + bool Function(Declaration declaration)? shouldExposeFunctionTypedefFunc, + bool Function(Declaration declaration)? isLeafFunctionFunc, + bool Function(Declaration declaration)? enumShouldBeIntFunc, + bool Function(Declaration declaration)? unnamedEnumsShouldBeIntFunc, + FfiNativeConfig ffiNativeConfig = const FfiNativeConfig(enabled: false), + bool ignoreSourceErrors = false, + bool formatOutput = true, + }) => + ConfigImpl( + filename: filename == null ? null : Uri.file(filename.toFilePath()), + output: Uri.file(output.toFilePath()), + outputObjC: + Uri.file(outputObjC?.toFilePath() ?? '${output.toFilePath()}.m'), + symbolFile: symbolFile, + language: language, + entryPoints: entryPoints, + shouldIncludeHeaderFunc: shouldIncludeHeaderFunc ?? (_) => true, + compilerOpts: compilerOpts, + varArgFunctions: varArgFunctions, + functionDecl: functionDecl ?? DeclarationFilters.excludeAll, + structDecl: structDecl ?? DeclarationFilters.excludeAll, + unionDecl: unionDecl ?? DeclarationFilters.excludeAll, + enumClassDecl: enumClassDecl ?? DeclarationFilters.excludeAll, + unnamedEnumConstants: + unnamedEnumConstants ?? DeclarationFilters.excludeAll, + globals: globals ?? DeclarationFilters.excludeAll, + macroDecl: macroDecl ?? DeclarationFilters.excludeAll, + typedefs: typedefs ?? DeclarationFilters.excludeAll, + objcInterfaces: objcInterfaces ?? DeclarationFilters.excludeAll, + objcProtocols: objcProtocols ?? DeclarationFilters.excludeAll, + includeUnusedTypedefs: includeUnusedTypedefs, + generateForPackageObjectiveC: generateForPackageObjectiveC, + sort: sort, + useSupportedTypedefs: useSupportedTypedefs, + libraryImports: Map.fromEntries( + libraryImports.map((import) => + MapEntry(import.name, import))), + usrTypeMappings: Map.fromEntries( + usrTypeMappings.map((import) => + MapEntry(import.nativeType, import))), + typedefTypeMappings: Map.fromEntries( + typedefTypeMappings.map((import) => + MapEntry(import.nativeType, import))), + structTypeMappings: Map.fromEntries( + structTypeMappings.map((import) => + MapEntry(import.nativeType, import))), + unionTypeMappings: Map.fromEntries( + unionTypeMappings.map((import) => + MapEntry(import.nativeType, import))), + nativeTypeMappings: Map.fromEntries( + nativeTypeMappings.map((import) => + MapEntry(import.nativeType, import))), + commentType: commentType ?? CommentType.def(), + structDependencies: structDependencies, + unionDependencies: unionDependencies, + structPackingOverrideFunc: structPackingOverrideFunc ?? (_) => null, + interfaceModuleFunc: interfaceModuleFunc ?? (_) => null, + protocolModuleFunc: protocolModuleFunc ?? (_) => null, + wrapperName: wrapperName, + wrapperDocComment: wrapperDocComment, + preamble: preamble, + useDartHandle: useDartHandle, + silenceEnumWarning: silenceEnumWarning, + shouldExposeFunctionTypedefFunc: + shouldExposeFunctionTypedefFunc ?? (_) => false, + isLeafFunctionFunc: isLeafFunctionFunc ?? (_) => false, + enumShouldBeIntFunc: enumShouldBeIntFunc ?? (_) => false, + unnamedEnumsShouldBeIntFunc: + unnamedEnumsShouldBeIntFunc ?? (_) => false, + ffiNativeConfig: ffiNativeConfig, + ignoreSourceErrors: ignoreSourceErrors, + formatOutput: formatOutput, + ); +} + +abstract interface class DeclarationFilters { + /// Checks if a name is allowed by a filter. + bool shouldInclude(Declaration declaration); + + /// Checks if the symbol address should be included for this name. + bool shouldIncludeSymbolAddress(Declaration declaration); + + /// Applies renaming and returns the result. + String rename(Declaration declaration); + + /// Applies member renaming and returns the result. + String renameMember(Declaration declaration, String member); + + factory DeclarationFilters({ + bool Function(Declaration declaration)? shouldInclude, + bool Function(Declaration declaration)? shouldIncludeSymbolAddress, + String Function(Declaration declaration)? rename, + String Function(Declaration declaration, String member)? renameMember, + }) => + DeclarationFiltersImpl( + shouldIncludeFunc: shouldInclude ?? (_) => false, + shouldIncludeSymbolAddressFunc: + shouldIncludeSymbolAddress ?? (_) => false, + renameFunc: rename ?? (declaration) => declaration.originalName, + renameMemberFunc: renameMember ?? (_, member) => member, + ); + + static final excludeAll = DeclarationFilters(); + static final includeAll = DeclarationFilters(shouldInclude: (_) => true); +} diff --git a/pkgs/ffigenpad/lib/src/config_provider/config_impl.dart b/pkgs/ffigenpad/lib/src/config_provider/config_impl.dart new file mode 100644 index 0000000000..0098715771 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/config_impl.dart @@ -0,0 +1,244 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart'; +import 'config.dart'; +import 'config_types.dart'; + +class ConfigImpl implements Config { + @override + final Uri? filename; + + @override + final Uri output; + + @override + final Uri outputObjC; + + @override + final SymbolFile? symbolFile; + + @override + final Language language; + + @override + final List entryPoints; + + @override + bool shouldIncludeHeader(Uri header) => shouldIncludeHeaderFunc(header); + final bool Function(Uri header) shouldIncludeHeaderFunc; + + @override + final List compilerOpts; + + @override + final Map> varArgFunctions; + + @override + final DeclarationFilters functionDecl; + + @override + final DeclarationFilters structDecl; + + @override + final DeclarationFilters unionDecl; + + @override + final DeclarationFilters enumClassDecl; + + @override + final DeclarationFilters unnamedEnumConstants; + + @override + final DeclarationFilters globals; + + @override + final DeclarationFilters macroDecl; + + @override + final DeclarationFilters typedefs; + + @override + final DeclarationFilters objcInterfaces; + + @override + final DeclarationFilters objcProtocols; + + @override + final bool includeUnusedTypedefs; + + @override + final bool generateForPackageObjectiveC; + + @override + final bool sort; + + @override + final bool useSupportedTypedefs; + + @override + final Map libraryImports; + + @override + final Map usrTypeMappings; + + @override + final Map typedefTypeMappings; + + @override + final Map structTypeMappings; + + @override + final Map unionTypeMappings; + + @override + final Map nativeTypeMappings; + + @override + final CommentType commentType; + + @override + final CompoundDependencies structDependencies; + + @override + final CompoundDependencies unionDependencies; + + @override + PackingValue? structPackingOverride(Declaration declaration) => + structPackingOverrideFunc(declaration); + final PackingValue? Function(Declaration declaration) + structPackingOverrideFunc; + + @override + String? interfaceModule(Declaration declaration) => + interfaceModuleFunc(declaration); + final String? Function(Declaration declaration) interfaceModuleFunc; + + @override + String? protocolModule(Declaration declaration) => + protocolModuleFunc(declaration); + final String? Function(Declaration declaration) protocolModuleFunc; + + @override + final String wrapperName; + + @override + final String? wrapperDocComment; + + @override + final String? preamble; + + @override + final bool useDartHandle; + + @override + final bool silenceEnumWarning; + + @override + bool shouldExposeFunctionTypedef(Declaration declaration) => + shouldExposeFunctionTypedefFunc(declaration); + final bool Function(Declaration declaration) shouldExposeFunctionTypedefFunc; + + @override + bool isLeafFunction(Declaration declaration) => + isLeafFunctionFunc(declaration); + final bool Function(Declaration declaration) isLeafFunctionFunc; + + @override + bool enumShouldBeInt(Declaration declaration) => + enumShouldBeIntFunc(declaration); + final bool Function(Declaration declaration) enumShouldBeIntFunc; + + @override + bool unnamedEnumsShouldBeInt(Declaration declaration) => + unnamedEnumsShouldBeIntFunc(declaration); + final bool Function(Declaration declaration) unnamedEnumsShouldBeIntFunc; + + @override + final FfiNativeConfig ffiNativeConfig; + + @override + final bool ignoreSourceErrors; + + @override + final bool formatOutput; + + ConfigImpl({ + required this.filename, + required this.output, + required this.outputObjC, + required this.symbolFile, + required this.language, + required this.entryPoints, + required this.shouldIncludeHeaderFunc, + required this.compilerOpts, + required this.varArgFunctions, + required this.functionDecl, + required this.structDecl, + required this.unionDecl, + required this.enumClassDecl, + required this.unnamedEnumConstants, + required this.globals, + required this.macroDecl, + required this.typedefs, + required this.objcInterfaces, + required this.objcProtocols, + required this.includeUnusedTypedefs, + required this.generateForPackageObjectiveC, + required this.sort, + required this.useSupportedTypedefs, + required this.libraryImports, + required this.usrTypeMappings, + required this.typedefTypeMappings, + required this.structTypeMappings, + required this.unionTypeMappings, + required this.nativeTypeMappings, + required this.commentType, + required this.structDependencies, + required this.unionDependencies, + required this.structPackingOverrideFunc, + required this.interfaceModuleFunc, + required this.protocolModuleFunc, + required this.wrapperName, + required this.wrapperDocComment, + required this.preamble, + required this.useDartHandle, + required this.silenceEnumWarning, + required this.shouldExposeFunctionTypedefFunc, + required this.isLeafFunctionFunc, + required this.enumShouldBeIntFunc, + required this.unnamedEnumsShouldBeIntFunc, + required this.ffiNativeConfig, + required this.ignoreSourceErrors, + required this.formatOutput, + }); +} + +class DeclarationFiltersImpl implements DeclarationFilters { + @override + String rename(Declaration declaration) => renameFunc(declaration); + final String Function(Declaration declaration) renameFunc; + + @override + String renameMember(Declaration declaration, String member) => + renameMemberFunc(declaration, member); + final String Function(Declaration declaration, String member) + renameMemberFunc; + + @override + bool shouldInclude(Declaration declaration) => shouldIncludeFunc(declaration); + final bool Function(Declaration declaration) shouldIncludeFunc; + + @override + bool shouldIncludeSymbolAddress(Declaration declaration) => + shouldIncludeSymbolAddressFunc(declaration); + final bool Function(Declaration declaration) shouldIncludeSymbolAddressFunc; + + DeclarationFiltersImpl({ + required this.renameFunc, + required this.renameMemberFunc, + required this.shouldIncludeFunc, + required this.shouldIncludeSymbolAddressFunc, + }); +} diff --git a/pkgs/ffigenpad/lib/src/config_provider/config_spec.dart b/pkgs/ffigenpad/lib/src/config_provider/config_spec.dart new file mode 100644 index 0000000000..4486b61d09 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/config_spec.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'package:ffigen/src/config_provider/config_spec.dart'; diff --git a/pkgs/ffigenpad/lib/src/config_provider/config_types.dart b/pkgs/ffigenpad/lib/src/config_provider/config_types.dart new file mode 100644 index 0000000000..c5e0a91f5f --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/config_types.dart @@ -0,0 +1,427 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Contains all the neccesary classes required by config. +library; + +import 'package:quiver/pattern.dart' as quiver; + +import '../code_generator.dart'; +import 'config.dart'; + +enum Language { c, objc } + +class CommentType { + CommentStyle style; + CommentLength length; + CommentType(this.style, this.length); + + /// Sets default style as [CommentStyle.doxygen], default length as + /// [CommentLength.full]. + CommentType.def() + : style = CommentStyle.doxygen, + length = CommentLength.full; + + /// Disables any comments. + CommentType.none() + : style = CommentStyle.doxygen, + length = CommentLength.none; +} + +enum CommentStyle { doxygen, any } + +enum CommentLength { none, brief, full } + +enum CompoundDependencies { full, opaque } + +/// Holds config for how Structs Packing will be overriden. +class StructPackingOverride { + final List<(RegExp, int?)> _matchers; + + StructPackingOverride(this._matchers); + + /// Returns pack value for [name]. + PackingValue? getOverridenPackValue(String name) { + for (final (regex, value) in _matchers) { + if (quiver.matchesFull(regex, name)) { + return PackingValue(value); + } + } + return null; + } +} + +// Holds headers and filters for header. +class YamlHeaders { + /// Path to headers. + /// + /// This contains all the headers, after extraction from Globs. + final List entryPoints; + + /// Include filter for headers. + final HeaderIncludeFilter includeFilter; + + YamlHeaders({List? entryPoints, HeaderIncludeFilter? includeFilter}) + : entryPoints = entryPoints?.map(Uri.file).toList() ?? [], + includeFilter = includeFilter ?? GlobHeaderFilter(); +} + +abstract class HeaderIncludeFilter { + bool shouldInclude(Uri headerSourceFile); +} + +class GlobHeaderFilter extends HeaderIncludeFilter { + List? includeGlobs = []; + + GlobHeaderFilter({ + this.includeGlobs, + }); + + @override + bool shouldInclude(Uri headerSourceFile) { + // Return true if header was included. + for (final globPattern in includeGlobs!) { + if (quiver.matchesFull(globPattern, headerSourceFile.toFilePath())) { + return true; + } + } + + // If any includedInclusionHeaders is provided, return false. + if (includeGlobs!.isNotEmpty) { + return false; + } else { + return true; + } + } +} + +/// A generic declaration config, used for Functions, Structs, Enums, Macros, +/// unnamed Enums and Globals. +class YamlDeclarationFilters implements DeclarationFilters { + final YamlIncluder _includer; + final YamlRenamer _renamer; + final YamlMemberRenamer _memberRenamer; + final YamlIncluder _symbolAddressIncluder; + final bool excludeAllByDefault; + + YamlDeclarationFilters({ + YamlIncluder? includer, + YamlRenamer? renamer, + YamlMemberRenamer? memberRenamer, + YamlIncluder? symbolAddressIncluder, + required this.excludeAllByDefault, + }) : _includer = includer ?? YamlIncluder(), + _renamer = renamer ?? YamlRenamer(), + _memberRenamer = memberRenamer ?? YamlMemberRenamer(), + _symbolAddressIncluder = + symbolAddressIncluder ?? YamlIncluder.excludeByDefault(); + + /// Applies renaming and returns the result. + @override + String rename(Declaration declaration) => + _renamer.rename(declaration.originalName); + + /// Applies member renaming and returns the result. + @override + String renameMember(Declaration declaration, String member) => + _memberRenamer.rename(declaration.originalName, member); + + /// Checks if a name is allowed by a filter. + @override + bool shouldInclude(Declaration declaration) => + _includer.shouldInclude(declaration.originalName, excludeAllByDefault); + + /// Checks if the symbol address should be included for this name. + @override + bool shouldIncludeSymbolAddress(Declaration declaration) => + _symbolAddressIncluder.shouldInclude(declaration.originalName); +} + +/// Matches `$`, value can be accessed in group 1 of match. +final replaceGroupRegexp = RegExp(r'\$([0-9])'); + +/// Match/rename using [regExp]. +class RegExpRenamer { + final RegExp regExp; + final String replacementPattern; + + RegExpRenamer(this.regExp, this.replacementPattern); + + /// Returns true if [str] has a full match with [regExp]. + bool matches(String str) => quiver.matchesFull(regExp, str); + + /// Renames [str] according to [replacementPattern]. + /// + /// Returns [str] if [regExp] doesn't have a full match. + String rename(String str) { + if (matches(str)) { + // Get match. + final regExpMatch = regExp.firstMatch(str)!; + + /// Get group values. + /// E.g for `str`: `clang_dispose` and `regExp`: `clang_(.*)` + /// groups will be `0`: `clang_disponse`, `1`: `dispose`. + final groups = regExpMatch.groups( + List.generate(regExpMatch.groupCount, (index) => index) + + [regExpMatch.groupCount]); + + /// Replace all `$` symbols with respective groups (if any). + final result = + replacementPattern.replaceAllMapped(replaceGroupRegexp, (match) { + final groupInt = int.parse(match.group(1)!); + return groups[groupInt]!; + }); + return result; + } else { + return str; + } + } + + @override + String toString() { + return 'Regexp: $regExp, ReplacementPattern: $replacementPattern'; + } +} + +/// Handles `include/exclude` logic for a declaration. +class YamlIncluder { + final List _includeMatchers; + final Set _includeFull; + final List _excludeMatchers; + final Set _excludeFull; + + YamlIncluder({ + List? includeMatchers, + Set? includeFull, + List? excludeMatchers, + Set? excludeFull, + }) : _includeMatchers = includeMatchers ?? [], + _includeFull = includeFull ?? {}, + _excludeMatchers = excludeMatchers ?? [], + _excludeFull = excludeFull ?? {}; + + YamlIncluder.excludeByDefault() + : _includeMatchers = [], + _includeFull = {}, + _excludeMatchers = [RegExp('.*', dotAll: true)], + _excludeFull = {}; + + /// Returns true if [name] is allowed. + /// + /// Exclude overrides include. + bool shouldInclude(String name, [bool excludeAllByDefault = false]) { + if (_excludeFull.contains(name)) { + return false; + } + + for (final em in _excludeMatchers) { + if (quiver.matchesFull(em, name)) { + return false; + } + } + + if (_includeFull.contains(name)) { + return true; + } + + for (final im in _includeMatchers) { + if (quiver.matchesFull(im, name)) { + return true; + } + } + + // If user has provided 'include' field in the filter, then default + // matching is false. + if (_includeMatchers.isNotEmpty || _includeFull.isNotEmpty) { + return false; + } else { + // Otherwise, fall back to the default behavior for empty filters. + return !excludeAllByDefault; + } + } +} + +/// Handles `full/regexp` renaming logic. +class YamlRenamer { + final Map _renameFull; + final List _renameMatchers; + + YamlRenamer({ + List? renamePatterns, + Map? renameFull, + }) : _renameMatchers = renamePatterns ?? [], + _renameFull = renameFull ?? {}; + + YamlRenamer.noRename() + : _renameMatchers = [], + _renameFull = {}; + + String rename(String name) { + // Apply full rename (if any). + if (_renameFull.containsKey(name)) { + return _renameFull[name]!; + } + + // Apply rename regexp (if matches). + for (final renamer in _renameMatchers) { + if (renamer.matches(name)) { + return renamer.rename(name); + } + } + + // No renaming is provided for this declaration, return unchanged. + return name; + } +} + +/// Match declaration name using [declarationRegExp]. +class RegExpMemberRenamer { + final RegExp declarationRegExp; + final YamlRenamer memberRenamer; + + RegExpMemberRenamer(this.declarationRegExp, this.memberRenamer); + + /// Returns true if [declaration] has a full match with [declarationRegExp]. + bool matchesDeclarationName(String declaration) => + quiver.matchesFull(declarationRegExp, declaration); + + @override + String toString() { + return 'DeclarationRegExp: $declarationRegExp, ' + 'YamlMemberRenamer: $memberRenamer'; + } +} + +/// Handles `full/regexp` member renaming. +class YamlMemberRenamer { + final Map _memberRenameFull; + final List _memberRenameMatchers; + + final Map _cache = {}; + + YamlMemberRenamer({ + Map? memberRenameFull, + List? memberRenamePattern, + }) : _memberRenameFull = memberRenameFull ?? {}, + _memberRenameMatchers = memberRenamePattern ?? []; + + String rename(String declaration, String member) { + if (_cache.containsKey(declaration)) { + return _cache[declaration]!.rename(member); + } + + // Apply full rename (if any). + if (_memberRenameFull.containsKey(declaration)) { + // Add to cache. + _cache[declaration] = _memberRenameFull[declaration]!; + return _cache[declaration]!.rename(member); + } + + // Apply rename regexp (if matches). + for (final renamer in _memberRenameMatchers) { + if (renamer.matchesDeclarationName(declaration)) { + // Add to cache. + _cache[declaration] = renamer.memberRenamer; + return _cache[declaration]!.rename(member); + } + } + + // No renaming is provided for this declaration, return unchanged. + return member; + } +} + +List defaultCompilerOpts({bool macIncludeStdLib = true}) => []; + +/// Handles config for automatically added compiler options. +class CompilerOptsAuto { + final bool macIncludeStdLib; + + CompilerOptsAuto({bool? macIncludeStdLib}) + : macIncludeStdLib = macIncludeStdLib ?? true; + + /// Extracts compiler options based on OS and config. + List extractCompilerOpts() { + return defaultCompilerOpts(macIncludeStdLib: macIncludeStdLib); + } +} + +class _ObjCModuleEntry { + final RegExp pattern; + final String moduleName; + + _ObjCModuleEntry(this.pattern, this.moduleName); +} + +/// Handles applying module prefixes to ObjC classes. +class ObjCModules { + final _prefixes = <_ObjCModuleEntry>[]; + + ObjCModules(Map prefixes) { + for (final entry in prefixes.entries) { + _prefixes.add(_ObjCModuleEntry(RegExp(entry.key), entry.value)); + } + } + + /// If any of the prefixing patterns match, returns the corresponding module. + /// Otherwise returns null. + String? getModule(String className) { + for (final entry in _prefixes) { + if (quiver.matchesFull(entry.pattern, className)) { + return entry.moduleName; + } + } + return null; + } +} + +class FfiNativeConfig { + final bool enabled; + final String? assetId; + + const FfiNativeConfig({required this.enabled, this.assetId}); +} + +class SymbolFile { + final Uri importPath; + final Uri output; + + SymbolFile(this.importPath, this.output); +} + +class OutputConfig { + final String output; + final String? outputObjC; + final SymbolFile? symbolFile; + + OutputConfig(this.output, this.outputObjC, this.symbolFile); +} + +class RawVarArgFunction { + String? postfix; + final List rawTypeStrings; + + RawVarArgFunction(this.postfix, this.rawTypeStrings); +} + +class VarArgFunction { + final String postfix; + final List types; + + VarArgFunction(this.postfix, this.types); +} + +class PackingValue { + int? value; + PackingValue(this.value); +} + +class Declaration { + String usr; + String originalName; + Declaration({ + required this.usr, + required this.originalName, + }); +} diff --git a/pkgs/ffigenpad/lib/src/config_provider/spec_utils.dart b/pkgs/ffigenpad/lib/src/config_provider/spec_utils.dart new file mode 100644 index 0000000000..c9a83e56de --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/spec_utils.dart @@ -0,0 +1,629 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:file/local.dart'; +import 'package:glob/glob.dart'; +import 'package:logging/logging.dart'; +import 'package:package_config/package_config.dart'; +import 'package:path/path.dart' as p; +import 'package:quiver/pattern.dart' as quiver; +import 'package:yaml/yaml.dart'; + +import '../code_generator.dart'; +import '../code_generator/utils.dart'; +import '../header_parser/type_extractor/cxtypekindmap.dart'; +import '../strings.dart' as strings; +import 'config_types.dart'; + +final _logger = Logger('ffigen.config_provider.spec_utils'); + +/// Replaces the path separators according to current platform. +String _replaceSeparators(String path) { + return path.replaceAll(p.windows.separator, p.posix.separator); +} + +/// Replaces the path separators according to current platform. If a relative +/// path is passed in, it is resolved relative to the config path, and the +/// absolute path is returned. +String _normalizePath(String path, String? configFilename) { + final skipNormalization = + (configFilename == null) || p.isAbsolute(path) || path.startsWith('**'); + return _replaceSeparators(skipNormalization + ? path + : p.absolute(p.join(p.dirname(configFilename), path))); +} + +Map libraryImportsExtractor( + Map? typeMap) { + final resultMap = {}; + if (typeMap != null) { + for (final kv in typeMap.entries) { + resultMap[kv.key] = LibraryImport(kv.key, kv.value); + } + } + return resultMap; +} + +void loadImportedTypes(YamlMap fileConfig, + Map usrTypeMappings, LibraryImport libraryImport) { + final symbols = fileConfig['symbols'] as YamlMap; + for (final key in symbols.keys) { + final usr = key as String; + final value = symbols[usr]! as YamlMap; + final name = value['name'] as String; + usrTypeMappings[usr] = ImportedType(libraryImport, name, name, name); + } +} + +YamlMap loadSymbolFile(String symbolFilePath, String? configFileName, + PackageConfig? packageConfig) { + final path = symbolFilePath.startsWith('package:') + ? packageConfig!.resolve(Uri.parse(symbolFilePath))!.toFilePath() + : _normalizePath(symbolFilePath, configFileName); + + return loadYaml(File(path).readAsStringSync()) as YamlMap; +} + +Map symbolFileImportExtractor( + List yamlConfig, + Map libraryImports, + String? configFileName, + PackageConfig? packageConfig) { + final resultMap = {}; + for (final item in yamlConfig) { + String symbolFilePath; + symbolFilePath = item; + final symbolFile = + loadSymbolFile(symbolFilePath, configFileName, packageConfig); + final formatVersion = symbolFile[strings.formatVersion] as String; + if (formatVersion.split('.')[0] != + strings.symbolFileFormatVersion.split('.')[0]) { + _logger.severe('Incompatible format versions for file $symbolFilePath: ' + '${strings.symbolFileFormatVersion}(ours), $formatVersion(theirs).'); + exit(1); + } + final uniqueNamer = UniqueNamer(libraryImports.keys + .followedBy([strings.defaultSymbolFileImportPrefix]).toSet()); + final files = symbolFile[strings.files] as YamlMap; + for (final file in files.keys) { + final existingImports = libraryImports.values + .where((element) => element.importPath(false) == file); + if (existingImports.isEmpty) { + final name = + uniqueNamer.makeUnique(strings.defaultSymbolFileImportPrefix); + libraryImports[name] = LibraryImport(name, file as String); + } + final libraryImport = libraryImports.values.firstWhere( + (element) => element.importPath(false) == file, + ); + loadImportedTypes(files[file] as YamlMap, resultMap, libraryImport); + } + } + return resultMap; +} + +Map> typeMapExtractor(Map? yamlConfig) { + // Key - type_name, Value - [lib, cType, dartType]. + final resultMap = >{}; + final typeMap = yamlConfig; + if (typeMap != null) { + for (final typeName in typeMap.keys) { + final typeConfigItem = typeMap[typeName] as Map; + resultMap[typeName as String] = [ + typeConfigItem[strings.lib] as String, + typeConfigItem[strings.cType] as String, + typeConfigItem[strings.dartType] as String, + ]; + } + } + return resultMap; +} + +Map makeImportTypeMapping( + Map> rawTypeMappings, + Map libraryImportsMap) { + final typeMappings = {}; + for (final key in rawTypeMappings.keys) { + final lib = rawTypeMappings[key]![0]; + final cType = rawTypeMappings[key]![1]; + final dartType = rawTypeMappings[key]![2]; + final nativeType = key; + if (strings.predefinedLibraryImports.containsKey(lib)) { + typeMappings[key] = ImportedType( + strings.predefinedLibraryImports[lib]!, cType, dartType, nativeType); + } else if (libraryImportsMap.containsKey(lib)) { + typeMappings[key] = + ImportedType(libraryImportsMap[lib]!, cType, dartType, nativeType); + } else { + throw Exception('Please declare $lib under library-imports.'); + } + } + return typeMappings; +} + +Type makePointerToType(Type type, int pointerCount) { + for (var i = 0; i < pointerCount; i++) { + type = PointerType(type); + } + return type; +} + +String makePostfixFromRawVarArgType(List rawVarArgType) { + return rawVarArgType + .map((e) => e + .replaceAll('*', 'Ptr') + .replaceAll(RegExp(r'_t$'), '') + .replaceAll(' ', '') + .replaceAll(RegExp('[^A-Za-z0-9_]'), '')) + .map((e) => e.length > 1 ? '${e[0].toUpperCase()}${e.substring(1)}' : e) + .join(''); +} + +Type makeTypeFromRawVarArgType( + String rawVarArgType, Map libraryImportsMap) { + Type baseType; + var rawBaseType = rawVarArgType.trim(); + // Split the raw type based on pointer usage. E.g - + // int => [int] + // char* => [char,*] + // ffi.Hello ** => [ffi.Hello,**] + final typeStringRegexp = RegExp(r'([a-zA-Z0-9_\s\.]+)(\**)$'); + if (!typeStringRegexp.hasMatch(rawBaseType)) { + throw Exception('Cannot parse variadic argument type - $rawVarArgType.'); + } + final regExpMatch = typeStringRegexp.firstMatch(rawBaseType)!; + final groups = regExpMatch.groups([1, 2]); + rawBaseType = groups[0]!; + // Handle basic supported types. + if (cxTypeKindToImportedTypes.containsKey(rawBaseType)) { + baseType = cxTypeKindToImportedTypes[rawBaseType]!; + } else if (supportedTypedefToImportedType.containsKey(rawBaseType)) { + baseType = supportedTypedefToImportedType[rawBaseType]!; + } else if (suportedTypedefToSuportedNativeType.containsKey(rawBaseType)) { + baseType = NativeType(suportedTypedefToSuportedNativeType[rawBaseType]!); + } else { + // Use library import if specified (E.g - ffi.UintPtr or custom.MyStruct) + final rawVarArgTypeSplit = rawBaseType.split('.'); + if (rawVarArgTypeSplit.length == 1) { + final typeName = rawVarArgTypeSplit[0].replaceAll(' ', ''); + baseType = SelfImportedType(typeName, typeName); + } else if (rawVarArgTypeSplit.length == 2) { + final lib = rawVarArgTypeSplit[0]; + final libraryImport = strings.predefinedLibraryImports[lib] ?? + libraryImportsMap[rawVarArgTypeSplit[0]]; + if (libraryImport == null) { + throw Exception('Please declare $lib in library-imports.'); + } + final typeName = rawVarArgTypeSplit[1].replaceAll(' ', ''); + baseType = ImportedType(libraryImport, typeName, typeName, typeName); + } else { + throw Exception( + 'Invalid type $rawVarArgType : Expected 0 or 1 .(dot) separators.'); + } + } + + // Handle pointers + final pointerCount = groups[1]!.length; + return makePointerToType(baseType, pointerCount); +} + +Map> makeVarArgFunctionsMapping( + Map> rawVarArgMappings, + Map libraryImportsMap) { + final mappings = >{}; + for (final key in rawVarArgMappings.keys) { + final varArgList = []; + for (final rawVarArg in rawVarArgMappings[key]!) { + var postfix = rawVarArg.postfix ?? ''; + final types = []; + for (final rva in rawVarArg.rawTypeStrings) { + types.add(makeTypeFromRawVarArgType(rva, libraryImportsMap)); + } + if (postfix.isEmpty) { + if (rawVarArgMappings[key]!.length == 1) { + postfix = ''; + } else { + postfix = makePostfixFromRawVarArgType(rawVarArg.rawTypeStrings); + } + } + // Extract postfix from config and/or deduce from var names. + varArgList.add(VarArgFunction(postfix, types)); + } + mappings[key] = varArgList; + } + return mappings; +} + +final _quoteMatcher = RegExp(r'''^["'](.*)["']$''', dotAll: true); +final _cmdlineArgMatcher = RegExp(r'''['"](\\"|[^"])*?['"]|[^ ]+'''); +List compilerOptsToList(String compilerOpts) { + final list = []; + _cmdlineArgMatcher.allMatches(compilerOpts).forEach((element) { + var match = element.group(0); + if (match != null) { + if (quiver.matchesFull(_quoteMatcher, match)) { + match = _quoteMatcher.allMatches(match).first.group(1)!; + } + list.add(match); + } + }); + + return list; +} + +List compilerOptsExtractor(List value) { + final list = []; + for (final el in value) { + list.addAll(compilerOptsToList(el)); + } + return list; +} + +YamlHeaders headersExtractor( + Map> yamlConfig, String? configFilename) { + final entryPoints = []; + final includeGlobs = []; + for (final key in yamlConfig.keys) { + if (key == strings.entryPoints) { + for (final h in yamlConfig[key]!) { + final headerGlob = _normalizePath(h, configFilename); + // Add file directly to header if it's not a Glob but a File. + if (File(headerGlob).existsSync()) { + final osSpecificPath = headerGlob; + entryPoints.add(osSpecificPath); + _logger.fine('Adding header/file: $headerGlob'); + } else { + final glob = Glob(headerGlob); + for (final file in glob.listFileSystemSync(const LocalFileSystem(), + followLinks: true)) { + final fixedPath = file.path; + entryPoints.add(fixedPath); + _logger.fine('Adding header/file: $fixedPath'); + } + } + } + } + if (key == strings.includeDirectives) { + for (final h in yamlConfig[key]!) { + final headerGlob = h; + final fixedGlob = _normalizePath(headerGlob, configFilename); + includeGlobs.add(quiver.Glob(fixedGlob)); + } + } + } + return YamlHeaders( + entryPoints: entryPoints, + includeFilter: GlobHeaderFilter( + includeGlobs: includeGlobs, + ), + ); +} + +String? _findLibInConda() { + final condaEnvPath = Platform.environment['CONDA_PREFIX'] ?? ''; + if (condaEnvPath.isNotEmpty) { + final locations = [ + p.join(condaEnvPath, 'lib'), + p.join(p.dirname(p.dirname(condaEnvPath)), 'lib'), + ]; + for (final l in locations) { + final k = findLibclangDylib(l); + if (k != null) return k; + } + } + return null; +} + +/// Returns location of dynamic library by searching default locations. Logs +/// error and throws an Exception if not found. +String findDylibAtDefaultLocations() { + // Assume clang in conda has a higher priority. + var k = _findLibInConda(); + if (k != null) return k; + if (Platform.isLinux) { + for (final l in strings.linuxDylibLocations) { + k = findLibclangDylib(l); + if (k != null) return k; + } + Process.runSync('ldconfig', ['-p']); + final ldConfigResult = Process.runSync('ldconfig', ['-p']); + if (ldConfigResult.exitCode == 0) { + final lines = (ldConfigResult.stdout as String).split('\n'); + final paths = [ + for (final line in lines) + if (line.contains('libclang')) line.split(' => ')[1], + ]; + for (final location in paths) { + if (File(location).existsSync()) { + return location; + } + } + } + } else if (Platform.isWindows) { + final dylibLocations = strings.windowsDylibLocations.toList(); + final userHome = Platform.environment['USERPROFILE']; + if (userHome != null) { + dylibLocations + .add(p.join(userHome, 'scoop', 'apps', 'llvm', 'current', 'bin')); + } + for (final l in dylibLocations) { + k = findLibclangDylib(l); + if (k != null) return k; + } + } else if (Platform.isMacOS) { + for (final l in strings.macOsDylibLocations) { + k = findLibclangDylib(l); + if (k != null) return k; + } + final findLibraryResult = + Process.runSync('xcodebuild', ['-find-library', 'libclang.dylib']); + if (findLibraryResult.exitCode == 0) { + final location = (findLibraryResult.stdout as String).split('\n').first; + if (File(location).existsSync()) { + return location; + } + } + final xcodePathResult = Process.runSync('xcode-select', ['-print-path']); + if (xcodePathResult.exitCode == 0) { + final xcodePath = (xcodePathResult.stdout as String).split('\n').first; + final location = + p.join(xcodePath, strings.xcodeDylibLocation, strings.dylibFileName); + if (File(location).existsSync()) { + return location; + } + } + } else { + throw Exception('Unsupported Platform.'); + } + + _logger.severe("Couldn't find dynamic library in default locations."); + _logger.severe( + "Please supply one or more path/to/llvm in ffigen's config under the key '${strings.llvmPath}'."); + throw Exception("Couldn't find dynamic library in default locations."); +} + +String? findLibclangDylib(String parentFolder) { + final location = p.join(parentFolder, strings.dylibFileName); + if (File(location).existsSync()) { + return location; + } else { + return null; + } +} + +String llvmPathExtractor(List value) { + // Extract libclang's dylib from user specified paths. + for (final path in value) { + final dylibPath = + findLibclangDylib(p.join(path, strings.dynamicLibParentName)); + if (dylibPath != null) { + _logger.fine('Found dynamic library at: $dylibPath'); + return dylibPath; + } + // Check if user has specified complete path to dylib. + final completeDylibPath = path; + if (p.extension(completeDylibPath).isNotEmpty && + File(completeDylibPath).existsSync()) { + _logger.info( + 'Using complete dylib path: $completeDylibPath from llvm-path.'); + return completeDylibPath; + } + } + _logger.fine("Couldn't find dynamic library under paths specified by " + '${strings.llvmPath}.'); + // Extract path from default locations. + try { + final res = findDylibAtDefaultLocations(); + return res; + } catch (e) { + final path = p.join(strings.dynamicLibParentName, strings.dylibFileName); + _logger.severe("Couldn't find $path in specified locations."); + exit(1); + } +} + +OutputConfig outputExtractor( + dynamic value, String? configFilename, PackageConfig? packageConfig) { + if (value is String) { + return OutputConfig(_normalizePath(value, configFilename), null, null); + } + value = value as Map; + return OutputConfig( + _normalizePath(value[strings.bindings] as String, configFilename), + value.containsKey(strings.objCBindings) + ? _normalizePath(value[strings.objCBindings] as String, configFilename) + : null, + value.containsKey(strings.symbolFile) + ? symbolFileOutputExtractor( + value[strings.symbolFile], configFilename, packageConfig) + : null, + ); +} + +SymbolFile symbolFileOutputExtractor( + dynamic value, String? configFilename, PackageConfig? packageConfig) { + value = value as Map; + var output = Uri.parse(value[strings.output] as String); + if (output.scheme != 'package') { + _logger.warning('Consider using a Package Uri for ${strings.symbolFile} -> ' + '${strings.output}: $output so that external packages can use it.'); + output = Uri.file(_normalizePath(output.toFilePath(), configFilename)); + } else { + output = packageConfig!.resolve(output)!; + } + final importPath = Uri.parse(value[strings.importPath] as String); + if (importPath.scheme != 'package') { + _logger.warning('Consider using a Package Uri for ${strings.symbolFile} -> ' + '${strings.importPath}: $importPath so that external packages ' + 'can use it.'); + } + return SymbolFile(importPath, output); +} + +/// Returns true if [str] is not a full name. +/// +/// E.g `abc` is a full name, `abc.*` is not. +bool isFullDeclarationName(String str) => + quiver.matchesFull(RegExp('[a-zA-Z_0-9]*'), str); + +YamlIncluder extractIncluderFromYaml(Map yamlMap) { + final includeMatchers = [], + includeFull = {}, + excludeMatchers = [], + excludeFull = {}; + + final include = yamlMap[strings.include] as List?; + if (include != null) { + if (include.isEmpty) { + return YamlIncluder.excludeByDefault(); + } + for (final str in include) { + if (isFullDeclarationName(str)) { + includeFull.add(str); + } else { + includeMatchers.add(RegExp(str, dotAll: true)); + } + } + } + + final exclude = yamlMap[strings.exclude] as List?; + if (exclude != null) { + for (final str in exclude) { + if (isFullDeclarationName(str)) { + excludeFull.add(str); + } else { + excludeMatchers.add(RegExp(str, dotAll: true)); + } + } + } + + return YamlIncluder( + includeMatchers: includeMatchers, + includeFull: includeFull, + excludeMatchers: excludeMatchers, + excludeFull: excludeFull, + ); +} + +Map> varArgFunctionConfigExtractor( + Map yamlMap) { + final result = >{}; + final configMap = yamlMap; + for (final key in configMap.keys) { + final vafuncs = []; + for (final rawVaFunc in configMap[key] as List) { + if (rawVaFunc is List) { + vafuncs.add(RawVarArgFunction(null, rawVaFunc.cast())); + } else if (rawVaFunc is Map) { + vafuncs.add(RawVarArgFunction(rawVaFunc[strings.postfix] as String?, + (rawVaFunc[strings.types] as List).cast())); + } else { + throw Exception('Unexpected type in variadic-argument config.'); + } + } + result[key as String] = vafuncs; + } + + return result; +} + +YamlDeclarationFilters declarationConfigExtractor( + Map yamlMap, bool excludeAllByDefault) { + final renamePatterns = []; + final renameFull = {}; + final memberRenamePatterns = []; + final memberRenamerFull = {}; + + final includer = extractIncluderFromYaml(yamlMap); + + final symbolIncluder = yamlMap[strings.symbolAddress] as YamlIncluder?; + + final rename = yamlMap[strings.rename] as Map?; + + if (rename != null) { + for (final key in rename.keys) { + final str = key.toString(); + if (isFullDeclarationName(str)) { + renameFull[str] = rename[str]!; + } else { + renamePatterns + .add(RegExpRenamer(RegExp(str, dotAll: true), rename[str]!)); + } + } + } + + final memberRename = + yamlMap[strings.memberRename] as Map>?; + + if (memberRename != null) { + for (final key in memberRename.keys) { + final decl = key.toString(); + final renamePatterns = []; + final renameFull = {}; + + final memberRenameMap = memberRename[decl]!; + for (final member in memberRenameMap.keys) { + final memberStr = member.toString(); + if (isFullDeclarationName(memberStr)) { + renameFull[memberStr] = memberRenameMap[member]!; + } else { + renamePatterns.add(RegExpRenamer( + RegExp(memberStr, dotAll: true), memberRenameMap[member]!)); + } + } + if (isFullDeclarationName(decl)) { + memberRenamerFull[decl] = YamlRenamer( + renameFull: renameFull, + renamePatterns: renamePatterns, + ); + } else { + memberRenamePatterns.add( + RegExpMemberRenamer( + RegExp(decl, dotAll: true), + YamlRenamer( + renameFull: renameFull, + renamePatterns: renamePatterns, + ), + ), + ); + } + } + } + + return YamlDeclarationFilters( + includer: includer, + renamer: YamlRenamer( + renameFull: renameFull, + renamePatterns: renamePatterns, + ), + memberRenamer: YamlMemberRenamer( + memberRenameFull: memberRenamerFull, + memberRenamePattern: memberRenamePatterns, + ), + symbolAddressIncluder: symbolIncluder, + excludeAllByDefault: excludeAllByDefault, + ); +} + +StructPackingOverride structPackingOverrideExtractor( + Map value) { + final matcherMap = <(RegExp, int?)>[]; + for (final key in value.keys) { + matcherMap.add(( + RegExp(key as String, dotAll: true), + strings.packingValuesMap[value[key]] + )); + } + return StructPackingOverride(matcherMap); +} + +FfiNativeConfig ffiNativeExtractor(dynamic yamlConfig) { + final yamlMap = yamlConfig as Map?; + return FfiNativeConfig( + enabled: true, + assetId: yamlMap?[strings.ffiNativeAsset] as String?, + ); +} diff --git a/pkgs/ffigenpad/lib/src/config_provider/yaml_config.dart b/pkgs/ffigenpad/lib/src/config_provider/yaml_config.dart new file mode 100644 index 0000000000..3ee1416233 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/config_provider/yaml_config.dart @@ -0,0 +1,1083 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Validates the yaml input by the user, prints useful info for the user. +library; + +import 'dart:io'; + +import 'package:logging/logging.dart'; +import 'package:package_config/package_config_types.dart'; +import 'package:yaml/yaml.dart'; + +import '../code_generator.dart'; +import '../strings.dart' as strings; +import 'config.dart'; +import 'config_spec.dart'; +import 'config_types.dart'; +import 'spec_utils.dart'; + +final _logger = Logger('ffigen.config_provider.config'); + +/// Provides configurations to other modules. +/// +/// Handles validation, extraction of configurations from a yaml file. +class YamlConfig implements Config { + /// Input config filename, if any. + @override + final Uri? filename; + + /// Package config. + final PackageConfig? packageConfig; + + /// Output file name. + @override + Uri get output => Uri.file(_output); + late String _output; + + /// Output ObjC file name. + @override + Uri get outputObjC => Uri.file(_outputObjC ?? '$_output.m'); + String? _outputObjC; + + /// Symbol file config. + @override + SymbolFile? get symbolFile => _symbolFile; + late SymbolFile? _symbolFile; + + /// Language that ffigen is consuming. + @override + Language get language => _language; + late Language _language; + + /// Path to headers. May not contain globs. + @override + List get entryPoints => _headers.entryPoints; + + /// Whether to include a specific header. This exists in addition to + /// [entryPoints] to allow filtering of transitively included headers. + @override + bool shouldIncludeHeader(Uri header) => + _headers.includeFilter.shouldInclude(header); + late YamlHeaders _headers; + + /// CommandLine Arguments to pass to clang_compiler. + @override + List get compilerOpts => _compilerOpts; + late List _compilerOpts; + + /// VarArg function handling. + @override + Map> get varArgFunctions => _varArgFunctions; + late Map> _varArgFunctions = {}; + + /// Declaration config for Functions. + @override + DeclarationFilters get functionDecl => _functionDecl; + late DeclarationFilters _functionDecl; + + /// Declaration config for Structs. + @override + DeclarationFilters get structDecl => _structDecl; + late DeclarationFilters _structDecl; + + /// Declaration config for Unions. + @override + DeclarationFilters get unionDecl => _unionDecl; + late DeclarationFilters _unionDecl; + + /// Declaration config for Enums. + @override + DeclarationFilters get enumClassDecl => _enumClassDecl; + late DeclarationFilters _enumClassDecl; + + /// Declaration config for Unnamed enum constants. + @override + DeclarationFilters get unnamedEnumConstants => _unnamedEnumConstants; + late DeclarationFilters _unnamedEnumConstants; + + /// Declaration config for Globals. + @override + DeclarationFilters get globals => _globals; + late DeclarationFilters _globals; + + /// Declaration config for Macro constants. + @override + DeclarationFilters get macroDecl => _macroDecl; + late DeclarationFilters _macroDecl; + + /// Declaration config for Typedefs. + @override + DeclarationFilters get typedefs => _typedefs; + late DeclarationFilters _typedefs; + + /// Declaration config for Objective C interfaces. + @override + DeclarationFilters get objcInterfaces => _objcInterfaces; + late DeclarationFilters _objcInterfaces; + + /// Declaration config for Objective C protocols. + @override + DeclarationFilters get objcProtocols => _objcProtocols; + late DeclarationFilters _objcProtocols; + + /// If enabled, the default behavior of all declaration filters is to exclude + /// everything, rather than include everything. + late bool _excludeAllByDefault; + + /// If enabled, unused typedefs will also be generated. + @override + bool get includeUnusedTypedefs => _includeUnusedTypedefs; + late bool _includeUnusedTypedefs; + + /// Undocumented option that changes code generation for package:objective_c. + /// The main difference is whether NSObject etc are imported from + /// package:objective_c (the default) or code genned like any other class. + /// This is necessary because package:objective_c can't import NSObject from + /// itself. + @override + bool get generateForPackageObjectiveC => _generateForPackageObjectiveC; + late bool _generateForPackageObjectiveC; + + /// If generated bindings should be sorted alphabetically. + @override + bool get sort => _sort; + late bool _sort; + + /// If typedef of supported types(int8_t) should be directly used. + @override + bool get useSupportedTypedefs => _useSupportedTypedefs; + late bool _useSupportedTypedefs; + + /// Stores all the library imports specified by user including those for ffi + /// and pkg_ffi. + @override + Map get libraryImports => _libraryImports; + late Map _libraryImports; + + /// Stores all the symbol file maps name to ImportedType mappings specified by + /// user. + @override + Map get usrTypeMappings => _usrTypeMappings; + late Map _usrTypeMappings; + + /// Stores typedef name to ImportedType mappings specified by user. + @override + Map get typedefTypeMappings => _typedefTypeMappings; + late Map _typedefTypeMappings; + + /// Stores struct name to ImportedType mappings specified by user. + @override + Map get structTypeMappings => _structTypeMappings; + late Map _structTypeMappings; + + /// Stores union name to ImportedType mappings specified by user. + @override + Map get unionTypeMappings => _unionTypeMappings; + late Map _unionTypeMappings; + + /// Stores native int name to ImportedType mappings specified by user. + @override + Map get nativeTypeMappings => _nativeTypeMappings; + late Map _nativeTypeMappings; + + /// Extracted Doc comment type. + @override + CommentType get commentType => _commentType; + late CommentType _commentType; + + /// Whether structs that are dependencies should be included. + @override + CompoundDependencies get structDependencies => _structDependencies; + late CompoundDependencies _structDependencies; + + /// Whether unions that are dependencies should be included. + @override + CompoundDependencies get unionDependencies => _unionDependencies; + late CompoundDependencies _unionDependencies; + + /// Holds config for how struct packing should be overriden. + @override + PackingValue? structPackingOverride(Declaration declaration) => + _structPackingOverride.getOverridenPackValue(declaration.originalName); + late StructPackingOverride _structPackingOverride; + + /// The module that the ObjC interface belongs to. + @override + String? interfaceModule(Declaration declaration) => + _objcInterfaceModules.getModule(declaration.originalName); + late ObjCModules _objcInterfaceModules; + + /// The module that the ObjC protocols belongs to. + @override + String? protocolModule(Declaration declaration) => + _objcProtocolModules.getModule(declaration.originalName); + late ObjCModules _objcProtocolModules; + + /// Name of the wrapper class. + @override + String get wrapperName => _wrapperName; + late String _wrapperName; + + /// Doc comment for the wrapper class. + @override + String? get wrapperDocComment => _wrapperDocComment; + String? _wrapperDocComment; + + /// Header of the generated bindings. + @override + String? get preamble => _preamble; + String? _preamble; + + /// If `Dart_Handle` should be mapped with Handle/Object. + @override + bool get useDartHandle => _useDartHandle; + late bool _useDartHandle; + + /// Where to silence warning for enum integer type mimicking. + @override + bool get silenceEnumWarning => _silenceEnumWarning; + late bool _silenceEnumWarning; + + /// Whether to expose the function typedef for a given function. + @override + bool shouldExposeFunctionTypedef(Declaration declaration) => + _exposeFunctionTypedefs.shouldInclude(declaration.originalName); + late YamlIncluder _exposeFunctionTypedefs; + + /// Whether the given function is a leaf function. + @override + bool isLeafFunction(Declaration declaration) => + _leafFunctions.shouldInclude(declaration.originalName); + late YamlIncluder _leafFunctions; + + /// Whether to generate the given enum as a series of int constants, rather + /// than a real Dart enum. + @override + bool enumShouldBeInt(Declaration declaration) => + _enumsAsInt.shouldInclude(declaration.originalName); + late YamlIncluder _enumsAsInt; + + /// Whether to generate the given unnamed enum as a series of int constants, + /// rather than a real Dart enum. + @override + bool unnamedEnumsShouldBeInt(Declaration declaration) => + _unnamedEnumsAsInt.shouldInclude(declaration.originalName); + late YamlIncluder _unnamedEnumsAsInt; + + @override + FfiNativeConfig get ffiNativeConfig => _ffiNativeConfig; + late FfiNativeConfig _ffiNativeConfig; + + /// Where to ignore compiler warnings/errors in source header files. + @override + bool ignoreSourceErrors = false; + + /// Whether to format the output file. + @override + bool formatOutput = true; + + YamlConfig._({required this.filename, required this.packageConfig}); + + /// Create config from Yaml map. + factory YamlConfig.fromYaml(YamlMap map, + {String? filename, PackageConfig? packageConfig}) { + final config = YamlConfig._( + filename: filename == null ? null : Uri.file(filename), + packageConfig: packageConfig); + _logger.finest('Config Map: $map'); + + final ffigenConfigSpec = config._getRootConfigSpec(); + final result = ffigenConfigSpec.validate(map); + if (!result) { + throw const FormatException('Invalid configurations provided.'); + } + + ffigenConfigSpec.extract(map); + return config; + } + + /// Create config from a file. + factory YamlConfig.fromFile(File file, {PackageConfig? packageConfig}) { + // Throws a [YamlException] if it's unable to parse the Yaml. + final configYaml = loadYaml(file.readAsStringSync()) as YamlMap; + + return YamlConfig.fromYaml(configYaml, + filename: file.path, packageConfig: packageConfig); + } + + /// Returns the root ConfigSpec object. + static ConfigSpec getsRootConfigSpec() { + final configspecs = YamlConfig._(filename: null, packageConfig: null); + return configspecs._getRootConfigSpec(); + } + + /// Add compiler options for clang. If [highPriority] is true these are added + /// to the front of the list. + void addCompilerOpts(String compilerOpts, {bool highPriority = false}) { + if (highPriority) { + _compilerOpts.insertAll( + 0, compilerOptsToList(compilerOpts)); // Inserts at the front. + } else { + _compilerOpts.addAll(compilerOptsToList(compilerOpts)); + } + } + + ConfigSpec _getRootConfigSpec() { + return HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.excludeAllByDefault, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) => _excludeAllByDefault = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.output, + required: true, + valueConfigSpec: OneOfConfigSpec( + childConfigSpecs: [ + _filePathStringConfigSpec(), + _outputFullConfigSpec(), + ], + transform: (node) => outputExtractor( + node.value, filename?.toFilePath(), packageConfig), + result: (node) { + _output = (node.value as OutputConfig).output; + _outputObjC = (node.value as OutputConfig).outputObjC; + _symbolFile = (node.value as OutputConfig).symbolFile; + }, + )), + HeterogeneousMapEntry( + key: strings.language, + valueConfigSpec: EnumConfigSpec( + allowedValues: {strings.langC, strings.langObjC}, + transform: (node) { + if (node.value == strings.langObjC) { + _logger.severe( + 'Objective C support is EXPERIMENTAL. The API may change ' + 'in a breaking way without notice.'); + return Language.objc; + } else { + return Language.c; + } + }, + ), + defaultValue: (node) => Language.c, + resultOrDefault: (node) => _language = node.value as Language, + ), + HeterogeneousMapEntry( + key: strings.headers, + required: true, + valueConfigSpec: + HeterogeneousMapConfigSpec, YamlHeaders>( + entries: [ + HeterogeneousMapEntry( + key: strings.entryPoints, + valueConfigSpec: ListConfigSpec>( + childConfigSpec: StringConfigSpec()), + required: true, + ), + HeterogeneousMapEntry( + key: strings.includeDirectives, + valueConfigSpec: ListConfigSpec>( + childConfigSpec: StringConfigSpec()), + ), + ], + transform: (node) => + headersExtractor(node.value, filename?.toFilePath()), + result: (node) => _headers = node.value, + )), + HeterogeneousMapEntry( + key: strings.ignoreSourceErrors, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) { + // Set value to true if not already. + ignoreSourceErrors = ignoreSourceErrors || node.value as bool; + }, + ), + HeterogeneousMapEntry( + key: strings.compilerOpts, + valueConfigSpec: OneOfConfigSpec, List>( + childConfigSpecs: [ + StringConfigSpec( + transform: (node) => [node.value], + ), + ListConfigSpec>( + childConfigSpec: StringConfigSpec()) + ], + transform: (node) => compilerOptsExtractor(node.value), + ), + defaultValue: (node) => [], + resultOrDefault: (node) => _compilerOpts = node.value as List, + ), + HeterogeneousMapEntry( + key: strings.compilerOptsAuto, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.macos, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.includeCStdLib, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => true, + ) + ], + ), + ) + ], + transform: (node) => CompilerOptsAuto( + macIncludeStdLib: (node.value[strings.macos] + as Map?)?[strings.includeCStdLib] as bool, + ), + result: (node) => _compilerOpts.addAll( + (node.value as CompilerOptsAuto).extractCompilerOpts()), + )), + HeterogeneousMapEntry( + key: strings.libraryImports, + valueConfigSpec: MapConfigSpec>( + keyValueConfigSpecs: [ + (keyRegexp: '.*', valueConfigSpec: StringConfigSpec()), + ], + customValidation: _libraryImportsPredefinedValidation, + transform: (node) => libraryImportsExtractor(node.value.cast()), + ), + defaultValue: (node) => {}, + resultOrDefault: (node) => + _libraryImports = (node.value) as Map, + ), + HeterogeneousMapEntry( + key: strings.functions, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + HeterogeneousMapEntry( + key: strings.symbolAddress, + valueConfigSpec: _includeExcludeObject(), + defaultValue: (node) => YamlIncluder.excludeByDefault(), + ), + HeterogeneousMapEntry( + key: strings.exposeFunctionTypedefs, + valueConfigSpec: _includeExcludeObject(), + defaultValue: (node) => YamlIncluder.excludeByDefault(), + ), + HeterogeneousMapEntry( + key: strings.leafFunctions, + valueConfigSpec: _includeExcludeObject(), + defaultValue: (node) => YamlIncluder.excludeByDefault(), + ), + HeterogeneousMapEntry( + key: strings.varArgFunctions, + valueConfigSpec: _functionVarArgsConfigSpec(), + defaultValue: (node) => >{}, + resultOrDefault: (node) { + _varArgFunctions = makeVarArgFunctionsMapping( + node.value as Map>, + _libraryImports); + }, + ), + ], + result: (node) { + _functionDecl = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _exposeFunctionTypedefs = (node.value + as Map)[strings.exposeFunctionTypedefs] as YamlIncluder; + _leafFunctions = + (node.value as Map)[strings.leafFunctions] as YamlIncluder; + }, + )), + HeterogeneousMapEntry( + key: strings.structs, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + _dependencyOnlyHeterogeneousMapKey(), + HeterogeneousMapEntry( + key: strings.structPack, + valueConfigSpec: MapConfigSpec( + keyValueConfigSpecs: [ + ( + keyRegexp: '.*', + valueConfigSpec: EnumConfigSpec( + allowedValues: {'none', 1, 2, 4, 8, 16}, + transform: (node) => + node.value == 'none' ? null : node.value, + ), + ) + ], + transform: (node) => + structPackingOverrideExtractor(node.value), + ), + defaultValue: (node) => StructPackingOverride([]), + resultOrDefault: (node) => _structPackingOverride = + node.value as StructPackingOverride, + ), + ], + result: (node) { + _structDecl = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _structDependencies = (node.value + as Map)[strings.dependencyOnly] as CompoundDependencies; + }, + )), + HeterogeneousMapEntry( + key: strings.unions, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + _dependencyOnlyHeterogeneousMapKey(), + ], + result: (node) { + _unionDecl = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _unionDependencies = (node.value as Map)[strings.dependencyOnly] + as CompoundDependencies; + }, + )), + HeterogeneousMapEntry( + key: strings.enums, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + ..._enumIntProperties(), + ], + result: (node) { + _enumClassDecl = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _enumsAsInt = + (node.value as Map)[strings.enumAsInt] as YamlIncluder; + }, + )), + HeterogeneousMapEntry( + key: strings.unnamedEnums, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._enumIntProperties(), + ], + result: (node) { + _unnamedEnumConstants = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _unnamedEnumsAsInt = + (node.value as Map)[strings.enumAsInt] as YamlIncluder; + }, + )), + HeterogeneousMapEntry( + key: strings.globals, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + HeterogeneousMapEntry( + key: strings.symbolAddress, + valueConfigSpec: _includeExcludeObject(), + defaultValue: (node) => YamlIncluder.excludeByDefault(), + ) + ], + result: (node) { + _globals = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + }, + )), + HeterogeneousMapEntry( + key: strings.macros, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ], + result: (node) { + _macroDecl = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + }, + )), + HeterogeneousMapEntry( + key: strings.typedefs, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ], + result: (node) { + _typedefs = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + }, + )), + HeterogeneousMapEntry( + key: strings.objcInterfaces, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + HeterogeneousMapEntry( + key: strings.objcModule, + valueConfigSpec: _objcModuleObject(), + defaultValue: (node) => ObjCModules({}), + ) + ], + result: (node) { + _objcInterfaces = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _objcInterfaceModules = + (node.value as Map)[strings.objcModule] as ObjCModules; + }, + )), + HeterogeneousMapEntry( + key: strings.objcProtocols, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + ..._includeExcludeProperties(), + ..._renameProperties(), + ..._memberRenameProperties(), + HeterogeneousMapEntry( + key: strings.objcModule, + valueConfigSpec: _objcModuleObject(), + defaultValue: (node) => ObjCModules({}), + ) + ], + result: (node) { + _objcProtocols = declarationConfigExtractor( + node.value as Map, _excludeAllByDefault); + _objcProtocolModules = + (node.value as Map)[strings.objcModule] as ObjCModules; + }, + )), + HeterogeneousMapEntry( + key: strings.import, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.symbolFilesImport, + valueConfigSpec: + ListConfigSpec>( + childConfigSpec: StringConfigSpec(), + transform: (node) => symbolFileImportExtractor(node.value, + _libraryImports, filename?.toFilePath(), packageConfig), + ), + defaultValue: (node) => {}, + resultOrDefault: (node) => _usrTypeMappings = + node.value as Map, + ) + ], + )), + HeterogeneousMapEntry( + key: strings.typeMap, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.typeMapTypedefs, + valueConfigSpec: _mappedTypeObject(), + defaultValue: (node) => >{}, + ), + HeterogeneousMapEntry( + key: strings.typeMapStructs, + valueConfigSpec: _mappedTypeObject(), + defaultValue: (node) => >{}, + ), + HeterogeneousMapEntry( + key: strings.typeMapUnions, + valueConfigSpec: _mappedTypeObject(), + defaultValue: (node) => >{}, + ), + HeterogeneousMapEntry( + key: strings.typeMapNativeTypes, + valueConfigSpec: _mappedTypeObject(), + defaultValue: (node) => >{}, + ), + ], + result: (node) { + final nodeValue = node.value as Map; + _typedefTypeMappings = makeImportTypeMapping( + (nodeValue[strings.typeMapTypedefs]) + as Map>, + _libraryImports, + ); + _structTypeMappings = makeImportTypeMapping( + (nodeValue[strings.typeMapStructs]) + as Map>, + _libraryImports, + ); + _unionTypeMappings = makeImportTypeMapping( + (nodeValue[strings.typeMapUnions]) + as Map>, + _libraryImports, + ); + _nativeTypeMappings = makeImportTypeMapping( + (nodeValue[strings.typeMapNativeTypes]) + as Map>, + _libraryImports, + ); + }, + )), + HeterogeneousMapEntry( + key: strings.includeUnusedTypedefs, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) => + _includeUnusedTypedefs = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.generateForPackageObjectiveC, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) => + _generateForPackageObjectiveC = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.sort, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) => _sort = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.useSupportedTypedefs, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => true, + resultOrDefault: (node) => _useSupportedTypedefs = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.comments, + valueConfigSpec: _commentConfigSpec(), + defaultValue: (node) => CommentType.def(), + resultOrDefault: (node) => _commentType = node.value as CommentType, + ), + HeterogeneousMapEntry( + key: strings.name, + valueConfigSpec: _dartClassNameStringConfigSpec(), + defaultValue: (node) { + _logger.warning( + "Prefer adding Key '${node.pathString}' to your config."); + return 'NativeLibrary'; + }, + resultOrDefault: (node) => _wrapperName = node.value as String, + ), + HeterogeneousMapEntry( + key: strings.description, + valueConfigSpec: _nonEmptyStringConfigSpec(), + defaultValue: (node) { + _logger.warning( + "Prefer adding Key '${node.pathString}' to your config."); + return null; + }, + resultOrDefault: (node) => _wrapperDocComment = node.value as String?, + ), + HeterogeneousMapEntry( + key: strings.preamble, + valueConfigSpec: StringConfigSpec( + result: (node) => _preamble = node.value as String?, + )), + HeterogeneousMapEntry( + key: strings.useDartHandle, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => true, + resultOrDefault: (node) => _useDartHandle = node.value as bool, + ), + HeterogeneousMapEntry( + key: strings.ffiNative, + valueConfigSpec: OneOfConfigSpec( + childConfigSpecs: [ + EnumConfigSpec(allowedValues: {null}), + HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.ffiNativeAsset, + valueConfigSpec: StringConfigSpec(), + required: true, + ) + ], + ) + ], + transform: (node) => ffiNativeExtractor(node.value), + ), + defaultValue: (node) => const FfiNativeConfig(enabled: false), + resultOrDefault: (node) => + _ffiNativeConfig = (node.value) as FfiNativeConfig, + ), + HeterogeneousMapEntry( + key: strings.silenceEnumWarning, + valueConfigSpec: BoolConfigSpec(), + defaultValue: (node) => false, + resultOrDefault: (node) => _silenceEnumWarning = node.value as bool, + ), + ], + ); + } + + bool _libraryImportsPredefinedValidation(ConfigValue node) { + if (node.value is YamlMap) { + return (node.value as YamlMap).keys.where((key) { + if (strings.predefinedLibraryImports.containsKey(key)) { + _logger.severe( + '${node.pathString} -> $key should not collide with any ' + 'predefined imports - ${strings.predefinedLibraryImports.keys}.'); + return true; + } + return false; + }).isEmpty; + } + return true; + } + + OneOfConfigSpec _commentConfigSpec() { + return OneOfConfigSpec( + childConfigSpecs: [ + BoolConfigSpec( + transform: (node) => + (node.value == true) ? CommentType.def() : CommentType.none(), + ), + HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.style, + valueConfigSpec: EnumConfigSpec( + allowedValues: {strings.doxygen, strings.any}, + transform: (node) => node.value == strings.doxygen + ? CommentStyle.doxygen + : CommentStyle.any, + ), + defaultValue: (node) => CommentStyle.doxygen, + ), + HeterogeneousMapEntry( + key: strings.length, + valueConfigSpec: EnumConfigSpec( + allowedValues: {strings.brief, strings.full}, + transform: (node) => node.value == strings.brief + ? CommentLength.brief + : CommentLength.full, + ), + defaultValue: (node) => CommentLength.full, + ), + ], + transform: (node) => CommentType( + node.value[strings.style] as CommentStyle, + node.value[strings.length] as CommentLength, + ), + ), + ], + ); + } + + MapConfigSpec _functionVarArgsConfigSpec() { + return MapConfigSpec( + keyValueConfigSpecs: [ + ( + keyRegexp: '.*', + valueConfigSpec: ListConfigSpec( + childConfigSpec: OneOfConfigSpec( + childConfigSpecs: [ + ListConfigSpec(childConfigSpec: StringConfigSpec()), + HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.types, + valueConfigSpec: ListConfigSpec>( + childConfigSpec: StringConfigSpec()), + required: true, + ), + HeterogeneousMapEntry( + key: strings.postfix, + valueConfigSpec: StringConfigSpec(), + ), + ], + ) + ], + ), + ) + ) + ], + transform: (node) => varArgFunctionConfigExtractor(node.value), + ); + } + + HeterogeneousMapConfigSpec _outputFullConfigSpec() { + return HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.bindings, + valueConfigSpec: _filePathStringConfigSpec(), + required: true, + ), + HeterogeneousMapEntry( + key: strings.objCBindings, + valueConfigSpec: _filePathStringConfigSpec(), + ), + HeterogeneousMapEntry( + key: strings.symbolFile, + valueConfigSpec: HeterogeneousMapConfigSpec( + entries: [ + HeterogeneousMapEntry( + key: strings.output, + valueConfigSpec: _filePathStringConfigSpec(), + required: true, + ), + HeterogeneousMapEntry( + key: strings.importPath, + valueConfigSpec: StringConfigSpec(), + required: true, + ), + ], + ), + ), + ], + ); + } + + StringConfigSpec _filePathStringConfigSpec() { + return StringConfigSpec( + schemaDefName: 'filePath', + schemaDescription: 'A file path', + ); + } + + StringConfigSpec _nonEmptyStringConfigSpec() { + return StringConfigSpec( + schemaDefName: 'nonEmptyString', + pattern: r'.+', + ); + } + + StringConfigSpec _dartClassNameStringConfigSpec() { + return StringConfigSpec( + schemaDefName: 'publicDartClass', + schemaDescription: 'A public dart class name.', + pattern: r'^[a-zA-Z]+[_a-zA-Z0-9]*$', + ); + } + + List _includeExcludeProperties() { + return [ + HeterogeneousMapEntry( + key: strings.include, + valueConfigSpec: _fullMatchOrRegexpList(), + ), + HeterogeneousMapEntry( + key: strings.exclude, + valueConfigSpec: _fullMatchOrRegexpList(), + defaultValue: (node) => [], + ), + ]; + } + + ListConfigSpec> _fullMatchOrRegexpList() { + return ListConfigSpec( + schemaDefName: 'fullMatchOrRegexpList', + childConfigSpec: StringConfigSpec(), + ); + } + + List _renameProperties() { + return [ + HeterogeneousMapEntry( + key: strings.rename, + valueConfigSpec: MapConfigSpec( + schemaDefName: 'rename', + keyValueConfigSpecs: [ + (keyRegexp: '.*', valueConfigSpec: StringConfigSpec()), + ], + ), + ), + ]; + } + + List _memberRenameProperties() { + return [ + HeterogeneousMapEntry( + key: strings.memberRename, + valueConfigSpec: MapConfigSpec, + Map>>( + schemaDefName: 'memberRename', + keyValueConfigSpecs: [ + ( + keyRegexp: '.*', + valueConfigSpec: MapConfigSpec>( + keyValueConfigSpecs: [ + (keyRegexp: '.*', valueConfigSpec: StringConfigSpec()) + ], + ), + ), + ], + ), + ), + ]; + } + + List _enumIntProperties() => [ + HeterogeneousMapEntry( + key: strings.enumAsInt, + defaultValue: (node) => YamlIncluder.excludeByDefault(), + valueConfigSpec: _includeExcludeObject(), + ), + ]; + + HeterogeneousMapConfigSpec, YamlIncluder> + _includeExcludeObject() { + return HeterogeneousMapConfigSpec( + schemaDefName: 'includeExclude', + entries: [ + ..._includeExcludeProperties(), + ], + transform: (node) => extractIncluderFromYaml(node.value), + ); + } + + HeterogeneousMapEntry _dependencyOnlyHeterogeneousMapKey() { + return HeterogeneousMapEntry( + key: strings.dependencyOnly, + valueConfigSpec: EnumConfigSpec( + schemaDefName: 'dependencyOnly', + allowedValues: { + strings.fullCompoundDependencies, + strings.opaqueCompoundDependencies, + }, + transform: (node) => node.value == strings.opaqueCompoundDependencies + ? CompoundDependencies.opaque + : CompoundDependencies.full, + ), + defaultValue: (node) => CompoundDependencies.full, + ); + } + + MapConfigSpec _mappedTypeObject() { + return MapConfigSpec( + schemaDefName: 'mappedTypes', + keyValueConfigSpecs: [ + ( + keyRegexp: '.*', + valueConfigSpec: HeterogeneousMapConfigSpec(entries: [ + HeterogeneousMapEntry( + key: strings.lib, valueConfigSpec: StringConfigSpec()), + HeterogeneousMapEntry( + key: strings.cType, valueConfigSpec: StringConfigSpec()), + HeterogeneousMapEntry( + key: strings.dartType, valueConfigSpec: StringConfigSpec()), + ]), + ) + ], + transform: (node) => typeMapExtractor(node.value), + ); + } + + MapConfigSpec _objcModuleObject() { + return MapConfigSpec( + schemaDefName: 'objcModule', + keyValueConfigSpecs: [ + (keyRegexp: '.*', valueConfigSpec: StringConfigSpec()), + ], + transform: (node) => ObjCModules(node.value.cast()), + ); + } +} diff --git a/pkgs/ffigenpad/lib/src/ffigen.dart b/pkgs/ffigenpad/lib/src/ffigen.dart new file mode 100644 index 0000000000..ef39c360f8 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/ffigen.dart @@ -0,0 +1,61 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:logging/logging.dart'; + +import 'config_provider.dart' show Config; +import 'header_parser.dart' show parse; + +final _logger = Logger('ffigen.ffigen'); + +class FfiGen { + FfiGen({Level logLevel = Level.INFO}) { + Logger.root.level = logLevel; + Logger.root.onRecord.listen((record) { + final levelStr = '[${record.level.name}]'.padRight(9); + _printLog('$levelStr: ${record.message}', record.level); + }); + } + + /// Runs the entire generation pipeline for the given config. + void run(Config config) { + // Parse the bindings according to config object provided. + final library = parse(config); + + // Generate files for the parsed bindings. + final gen = File(config.output.toFilePath()); + library.generateFile(gen, format: config.formatOutput); + _logger.info( + _successPen('Finished, Bindings generated in ${gen.absolute.path}')); + + final objCGen = File(config.outputObjC.toFilePath()); + if (library.generateObjCFile(objCGen)) { + _logger.info(_successPen('Finished, Objective C bindings generated ' + 'in ${objCGen.absolute.path}')); + } + + if (config.symbolFile != null) { + final symbolFileGen = File(config.symbolFile!.output.toFilePath()); + library.generateSymbolOutputFile( + symbolFileGen, config.symbolFile!.importPath.toString()); + _logger.info(_successPen('Finished, Symbol Output generated in ' + '${symbolFileGen.absolute.path}')); + } + } + + static void _printLog(String log, Level level) { + // Prints text in red for Severe logs only. + if (level < Level.SEVERE) { + print(log); + } else { + print(_errorPen(log)); + } + } + + // TODO: look into better color formatting + static String _successPen(String str) => '${"SUCCESS/"}$str${"/SUCCESS"}'; + static String _errorPen(String str) => '${"ERROR/"}$str${"/ERROR"}'; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser.dart b/pkgs/ffigenpad/lib/src/header_parser.dart new file mode 100644 index 0000000000..a64b135e45 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Generates a Library (code_generator) +/// +/// Parses the header files AST using clang_bindings. +library; + +export 'header_parser/parser.dart' show parse; diff --git a/pkgs/ffigenpad/lib/src/header_parser/calloc.dart b/pkgs/ffigenpad/lib/src/header_parser/calloc.dart new file mode 100644 index 0000000000..61a99f28d6 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/calloc.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Provides an allocator for malloc and free functions exported by emscripten. +library; + +import 'dart:ffi' as ffi; +import 'dart:js_interop'; + +@ffi.Native Function(ffi.Int)>(symbol: 'malloc') +external ffi.Pointer _wasmAllocate( + int size, +); + +@ffi.Native)>(symbol: 'free') +external void _wasmDeallocate( + ffi.Pointer ptr, +); + +class _WasmAllocator implements ffi.Allocator { + @override + ffi.Pointer allocate( + int byteCount, { + int? alignment, + }) { + return _wasmAllocate(byteCount).cast(); + } + + @override + void free(ffi.Pointer pointer) { + _wasmDeallocate(pointer.cast()); + } +} + +final calloc = _WasmAllocator(); + +@JS() +external int addFunction(JSExportedDartFunction fp, String signature); + +@JS() +external void removeFunction(int index); diff --git a/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_bindings.dart new file mode 100644 index 0000000000..8bb0918a8e --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_bindings.dart @@ -0,0 +1,1860 @@ +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// ignore_for_file: camel_case_types, non_constant_identifier_names + +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint +@ffi.DefaultAsset('libclang') +library; + +import 'dart:ffi' as ffi; + +/// Destroy a diagnostic. +@ffi.Native() +external void clang_disposeDiagnostic( + CXDiagnostic Diagnostic, +); + +/// Determine the severity of the given diagnostic. +@ffi.Native() +external int clang_getDiagnosticSeverity( + CXDiagnostic arg0, +); + +/// Provides a shared context for creating translation units. +/// +/// It provides two options: +/// +/// - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" +/// declarations (when loading any new translation units). A "local" declaration +/// is one that belongs in the translation unit itself and not in a precompiled +/// header that was used by the translation unit. If zero, all declarations +/// will be enumerated. +/// +/// Here is an example: +/// +/// \code +/// // excludeDeclsFromPCH = 1, displayDiagnostics=1 +/// Idx = clang_createIndex(1, 1); +/// +/// // IndexTest.pch was produced with the following command: +/// // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" +/// TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); +/// +/// // This will load all the symbols from 'IndexTest.pch' +/// clang_visitChildren(clang_getTranslationUnitCursor(TU), +/// TranslationUnitVisitor, 0); +/// clang_disposeTranslationUnit(TU); +/// +/// // This will load all the symbols from 'IndexTest.c', excluding symbols +/// // from 'IndexTest.pch'. +/// char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" }; +/// TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args, +/// 0, 0); +/// clang_visitChildren(clang_getTranslationUnitCursor(TU), +/// TranslationUnitVisitor, 0); +/// clang_disposeTranslationUnit(TU); +/// \endcode +/// +/// This process of creating the 'pch', loading it separately, and using it (via +/// -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks +/// (which gives the indexer the same performance benefit as the compiler). +@ffi.Native() +external CXIndex clang_createIndex( + int excludeDeclarationsFromPCH, + int displayDiagnostics, +); + +/// Destroy the given index. +/// +/// The index must not be destroyed until all of the translation units created +/// within that index have been destroyed. +@ffi.Native() +external void clang_disposeIndex( + CXIndex index, +); + +/// Determine the number of diagnostics produced for the given +/// translation unit. +@ffi.Native() +external int clang_getNumDiagnostics( + CXTranslationUnit Unit, +); + +/// Retrieve a diagnostic associated with the given translation unit. +/// +/// \param Unit the translation unit to query. +/// \param Index the zero-based diagnostic number to retrieve. +/// +/// \returns the requested diagnostic. This diagnostic must be freed +/// via a call to \c clang_disposeDiagnostic(). +@ffi.Native() +external CXDiagnostic clang_getDiagnostic( + CXTranslationUnit Unit, + int Index, +); + +/// Same as \c clang_parseTranslationUnit2, but returns +/// the \c CXTranslationUnit instead of an error code. In case of an error this +/// routine returns a \c NULL \c CXTranslationUnit, without further detailed +/// error codes. +@ffi.Native< + CXTranslationUnit Function( + CXIndex, + ffi.Pointer, + ffi.Pointer>, + ffi.Int32, + ffi.Pointer, + ffi.Uint32, + ffi.Uint32)>() +external CXTranslationUnit clang_parseTranslationUnit( + CXIndex CIdx, + ffi.Pointer source_filename, + ffi.Pointer> command_line_args, + int num_command_line_args, + ffi.Pointer unsaved_files, + int num_unsaved_files, + int options, +); + +/// Destroy the specified CXTranslationUnit object. +@ffi.Native() +external void clang_disposeTranslationUnit( + CXTranslationUnit arg0, +); + +/// Returns the kind of the evaluated result. +@ffi.Native() +external int clang_EvalResult_getKind( + CXEvalResult E, +); + +/// Returns the evaluation result as a long long integer if the +/// kind is Int. This prevents overflows that may happen if the result is +/// returned with clang_EvalResult_getAsInt. +@ffi.Native() +external int clang_EvalResult_getAsLongLong( + CXEvalResult E, +); + +/// Returns the evaluation result as double if the +/// kind is double. +@ffi.Native() +external double clang_EvalResult_getAsDouble( + CXEvalResult E, +); + +/// Returns the evaluation result as a constant string if the +/// kind is other than Int or float. User must not free this pointer, +/// instead call clang_EvalResult_dispose on the CXEvalResult returned +/// by clang_Cursor_Evaluate. +@ffi.Native Function(CXEvalResult)>() +external ffi.Pointer clang_EvalResult_getAsStr( + CXEvalResult E, +); + +/// Disposes the created Eval memory. +@ffi.Native() +external void clang_EvalResult_dispose( + CXEvalResult E, +); + +@ffi.Native Function()>() +external ffi.Pointer clang_getClangVersion_wrap(); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCString_wrap( + ffi.Pointer string, +); + +@ffi.Native)>() +external void clang_disposeString_wrap( + ffi.Pointer string, +); + +@ffi.Native)>() +external int clang_getCursorKind_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorDefinition_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Uint32)>() +external ffi.Pointer clang_getCursorKindSpelling_wrap( + int kind, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorType_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getTypeSpelling_wrap( + ffi.Pointer type, +); + +@ffi.Native Function(ffi.Uint32)>() +external ffi.Pointer clang_getTypeKindSpelling_wrap( + int typeKind, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getResultType_wrap( + ffi.Pointer functionType, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getPointeeType_wrap( + ffi.Pointer pointerType, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCanonicalType_wrap( + ffi.Pointer typerefType, +); + +@ffi.Native)>() +external int getCXTypeKind( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Type_getModifiedType_wrap( + ffi.Pointer type, +); + +@ffi.Native)>() +external int clang_Type_getNullability_wrap( + ffi.Pointer type, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Type_getNamedType_wrap( + ffi.Pointer elaboratedType, +); + +@ffi.Native)>() +external int clang_Type_getAlignOf_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getTypeDeclaration_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getTypedefName_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getTypedefDeclUnderlyingType_wrap( + ffi.Pointer cxcursor, +); + +/// The name of parameter, struct, typedef. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorSpelling_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorUSR_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(CXTranslationUnit)>() +external ffi.Pointer clang_getTranslationUnitCursor_wrap( + CXTranslationUnit tu, +); + +@ffi.Native Function(CXDiagnostic, ffi.Int32)>() +external ffi.Pointer clang_formatDiagnostic_wrap( + CXDiagnostic diag, + int opts, +); + +/// Visitor is a function pointer with parameters having pointers to cxcursor +/// instead of cxcursor by default. +@ffi.Native, ffi.UintPtr)>() +external int clang_visitChildren_wrap( + ffi.Pointer parent, + int _modifiedVisitor, +); + +@ffi.Native)>() +external int clang_getNumArgTypes_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer, ffi.Uint32)>() +external ffi.Pointer clang_getArgType_wrap( + ffi.Pointer cxtype, + int i, +); + +@ffi.Native)>() +external int clang_getEnumConstantDeclValue_wrap( + ffi.Pointer cursor, +); + +/// Returns non-zero if the ranges are the same, zero if they differ. +@ffi.Native< + ffi.Uint32 Function( + ffi.Pointer, ffi.Pointer)>() +external int clang_equalRanges_wrap( + ffi.Pointer c1, + ffi.Pointer c2, +); + +@ffi.Native)>() +external CXEvalResult clang_Cursor_Evaluate_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer, ffi.Uint32)>() +external ffi.Pointer clang_Cursor_getArgument_wrap( + ffi.Pointer cursor, + int i, +); + +@ffi.Native)>() +external int clang_Cursor_getNumArguments_wrap( + ffi.Pointer cursor, +); + +/// Returns the comment range. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Cursor_getCommentRange_wrap( + ffi.Pointer cursor, +); + +/// Returns the raw comment. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Cursor_getRawCommentText_wrap( + ffi.Pointer cursor, +); + +/// Returns the first paragraph of doxygen doc comment. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Cursor_getBriefCommentText_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_getStorageClass_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_getFieldDeclBitWidth_wrap( + ffi.Pointer C, +); + +@ffi.Native)>() +external int clang_Cursor_hasAttrs_wrap( + ffi.Pointer C, +); + +@ffi.Native)>() +external int clang_Cursor_isFunctionInlined_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_isAnonymous_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_isAnonymousRecordDecl_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_isNull_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_isMacroFunctionLike_wrap( + ffi.Pointer cursor, +); + +@ffi.Native)>() +external int clang_Cursor_isMacroBuiltin_wrap( + ffi.Pointer cursor, +); + +@ffi.Native, ffi.Uint32)>() +external int clang_Cursor_getObjCPropertyAttributes_wrap( + ffi.Pointer cursor, + int reserved, +); + +@ffi.Native)>() +external int clang_Cursor_isObjCOptional_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Cursor_getObjCPropertyGetterName_wrap( + ffi.Pointer C, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_Cursor_getObjCPropertySetterName_wrap( + ffi.Pointer C, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorResultType_wrap( + ffi.Pointer C, +); + +@ffi.Native)>() +external int clang_isFunctionTypeVariadic_wrap( + ffi.Pointer type, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getCursorLocation_wrap( + ffi.Pointer cursor, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getEnumDeclIntegerType_wrap( + ffi.Pointer cursor, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>() +external void clang_getFileLocation_wrap( + ffi.Pointer location, + ffi.Pointer file, + ffi.Pointer line, + ffi.Pointer column, + ffi.Pointer offset, +); + +@ffi.Native Function(CXFile)>() +external ffi.Pointer clang_getFileName_wrap( + CXFile SFile, +); + +@ffi.Native)>() +external int clang_getNumElements_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer clang_getArrayElementType_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native)>() +external int clang_isConstQualifiedType_wrap( + ffi.Pointer cxtype, +); + +@ffi.Native)>() +external int clang_Location_isInSystemHeader_wrap( + ffi.Pointer location, +); + +/// Describes the severity of a particular diagnostic. +abstract class CXDiagnosticSeverity { + /// A diagnostic that has been suppressed, e.g., by a command-line + /// option. + static const CXDiagnostic_Ignored = 0; + + /// This diagnostic is a note that should be attached to the + /// previous (non-note) diagnostic. + static const CXDiagnostic_Note = 1; + + /// This diagnostic indicates suspicious code that may not be + /// wrong. + static const CXDiagnostic_Warning = 2; + + /// This diagnostic indicates that the code is ill-formed. + static const CXDiagnostic_Error = 3; + + /// This diagnostic indicates that the code is ill-formed such + /// that future parser recovery is unlikely to produce useful + /// results. + static const CXDiagnostic_Fatal = 4; +} + +/// A single diagnostic, containing the diagnostic's severity, +/// location, text, source ranges, and fix-it hints. +typedef CXDiagnostic = ffi.Pointer; + +/// Options to control the display of diagnostics. +/// +/// The values in this enum are meant to be combined to customize the +/// behavior of \c clang_formatDiagnostic(). +abstract class CXDiagnosticDisplayOptions { + /// Display the source-location information where the + /// diagnostic was located. + /// + /// When set, diagnostics will be prefixed by the file, line, and + /// (optionally) column to which the diagnostic refers. For example, + /// + /// \code + /// test.c:28: warning: extra tokens at end of #endif directive + /// \endcode + /// + /// This option corresponds to the clang flag \c -fshow-source-location. + static const CXDiagnostic_DisplaySourceLocation = 1; + + /// If displaying the source-location information of the + /// diagnostic, also include the column number. + /// + /// This option corresponds to the clang flag \c -fshow-column. + static const CXDiagnostic_DisplayColumn = 2; + + /// If displaying the source-location information of the + /// diagnostic, also include information about source ranges in a + /// machine-parsable format. + /// + /// This option corresponds to the clang flag + /// \c -fdiagnostics-print-source-range-info. + static const CXDiagnostic_DisplaySourceRanges = 4; + + /// Display the option name associated with this diagnostic, if any. + /// + /// The option name displayed (e.g., -Wconversion) will be placed in brackets + /// after the diagnostic text. This option corresponds to the clang flag + /// \c -fdiagnostics-show-option. + static const CXDiagnostic_DisplayOption = 8; + + /// Display the category number associated with this diagnostic, if any. + /// + /// The category number is displayed within brackets after the diagnostic text. + /// This option corresponds to the clang flag + /// \c -fdiagnostics-show-category=id. + static const CXDiagnostic_DisplayCategoryId = 16; + + /// Display the category name associated with this diagnostic, if any. + /// + /// The category name is displayed within brackets after the diagnostic text. + /// This option corresponds to the clang flag + /// \c -fdiagnostics-show-category=name. + static const CXDiagnostic_DisplayCategoryName = 32; +} + +/// An "index" that consists of a set of translation units that would +/// typically be linked together into an executable or library. +typedef CXIndex = ffi.Pointer; + +/// A single translation unit, which resides in an index. +typedef CXTranslationUnit = ffi.Pointer; + +final class CXTranslationUnitImpl extends ffi.Opaque {} + +/// Flags that control the creation of translation units. +/// +/// The enumerators in this enumeration type are meant to be bitwise +/// ORed together to specify which options should be used when +/// constructing the translation unit. +abstract class CXTranslationUnit_Flags { + /// Used to indicate that no special translation-unit options are + /// needed. + static const CXTranslationUnit_None = 0; + + /// Used to indicate that the parser should construct a "detailed" + /// preprocessing record, including all macro definitions and instantiations. + /// + /// Constructing a detailed preprocessing record requires more memory + /// and time to parse, since the information contained in the record + /// is usually not retained. However, it can be useful for + /// applications that require more detailed information about the + /// behavior of the preprocessor. + static const CXTranslationUnit_DetailedPreprocessingRecord = 1; + + /// Used to indicate that the translation unit is incomplete. + /// + /// When a translation unit is considered "incomplete", semantic + /// analysis that is typically performed at the end of the + /// translation unit will be suppressed. For example, this suppresses + /// the completion of tentative declarations in C and of + /// instantiation of implicitly-instantiation function templates in + /// C++. This option is typically used when parsing a header with the + /// intent of producing a precompiled header. + static const CXTranslationUnit_Incomplete = 2; + + /// Used to indicate that the translation unit should be built with an + /// implicit precompiled header for the preamble. + /// + /// An implicit precompiled header is used as an optimization when a + /// particular translation unit is likely to be reparsed many times + /// when the sources aren't changing that often. In this case, an + /// implicit precompiled header will be built containing all of the + /// initial includes at the top of the main file (what we refer to as + /// the "preamble" of the file). In subsequent parses, if the + /// preamble or the files in it have not changed, \c + /// clang_reparseTranslationUnit() will re-use the implicit + /// precompiled header to improve parsing performance. + static const CXTranslationUnit_PrecompiledPreamble = 4; + + /// Used to indicate that the translation unit should cache some + /// code-completion results with each reparse of the source file. + /// + /// Caching of code-completion results is a performance optimization that + /// introduces some overhead to reparsing but improves the performance of + /// code-completion operations. + static const CXTranslationUnit_CacheCompletionResults = 8; + + /// Used to indicate that the translation unit will be serialized with + /// \c clang_saveTranslationUnit. + /// + /// This option is typically used when parsing a header with the intent of + /// producing a precompiled header. + static const CXTranslationUnit_ForSerialization = 16; + + /// DEPRECATED: Enabled chained precompiled preambles in C++. + /// + /// Note: this is a *temporary* option that is available only while + /// we are testing C++ precompiled preamble support. It is deprecated. + static const CXTranslationUnit_CXXChainedPCH = 32; + + /// Used to indicate that function/method bodies should be skipped while + /// parsing. + /// + /// This option can be used to search for declarations/definitions while + /// ignoring the usages. + static const CXTranslationUnit_SkipFunctionBodies = 64; + + /// Used to indicate that brief documentation comments should be + /// included into the set of code completions returned from this translation + /// unit. + static const CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 128; + + /// Used to indicate that the precompiled preamble should be created on + /// the first parse. Otherwise it will be created on the first reparse. This + /// trades runtime on the first parse (serializing the preamble takes time) for + /// reduced runtime on the second parse (can now reuse the preamble). + static const CXTranslationUnit_CreatePreambleOnFirstParse = 256; + + /// Do not stop processing when fatal errors are encountered. + /// + /// When fatal errors are encountered while parsing a translation unit, + /// semantic analysis is typically stopped early when compiling code. A common + /// source for fatal errors are unresolvable include files. For the + /// purposes of an IDE, this is undesirable behavior and as much information + /// as possible should be reported. Use this flag to enable this behavior. + static const CXTranslationUnit_KeepGoing = 512; + + /// Sets the preprocessor in a mode for parsing a single file only. + static const CXTranslationUnit_SingleFileParse = 1024; + + /// Used in combination with CXTranslationUnit_SkipFunctionBodies to + /// constrain the skipping of function bodies to the preamble. + /// + /// The function bodies of the main file are not skipped. + static const CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 2048; + + /// Used to indicate that attributed types should be included in CXType. + static const CXTranslationUnit_IncludeAttributedTypes = 4096; + + /// Used to indicate that implicit attributes should be visited. + static const CXTranslationUnit_VisitImplicitAttributes = 8192; + + /// Used to indicate that non-errors from included files should be ignored. + /// + /// If set, clang_getDiagnosticSetFromTU() will not report e.g. warnings from + /// included files anymore. This speeds up clang_getDiagnosticSetFromTU() for + /// the case where these warnings are not of interest, as for an IDE for + /// example, which typically shows only the diagnostics in the main file. + static const CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 16384; + + /// Tells the preprocessor not to skip excluded conditional blocks. + static const CXTranslationUnit_RetainExcludedConditionalBlocks = 32768; +} + +/// Provides the contents of a file that has not yet been saved to disk. +/// +/// Each CXUnsavedFile instance provides the name of a file on the +/// system along with the current contents of that file that have not +/// yet been saved to disk. +final class CXUnsavedFile extends ffi.Opaque {} + +/// Describes the kind of entity that a cursor refers to. +abstract class CXCursorKind { + /// A declaration whose specific kind is not exposed via this + /// interface. + /// + /// Unexposed declarations have the same operations as any other kind + /// of declaration; one can extract their location information, + /// spelling, find their definitions, etc. However, the specific kind + /// of the declaration is not reported. + static const CXCursor_UnexposedDecl = 1; + + /// A C or C++ struct. + static const CXCursor_StructDecl = 2; + + /// A C or C++ union. + static const CXCursor_UnionDecl = 3; + + /// A C++ class. + static const CXCursor_ClassDecl = 4; + + /// An enumeration. + static const CXCursor_EnumDecl = 5; + + /// A field (in C) or non-static data member (in C++) in a + /// struct, union, or C++ class. + static const CXCursor_FieldDecl = 6; + + /// An enumerator constant. + static const CXCursor_EnumConstantDecl = 7; + + /// A function. + static const CXCursor_FunctionDecl = 8; + + /// A variable. + static const CXCursor_VarDecl = 9; + + /// A function or method parameter. + static const CXCursor_ParmDecl = 10; + + /// An Objective-C \@interface. + static const CXCursor_ObjCInterfaceDecl = 11; + + /// An Objective-C \@interface for a category. + static const CXCursor_ObjCCategoryDecl = 12; + + /// An Objective-C \@protocol declaration. + static const CXCursor_ObjCProtocolDecl = 13; + + /// An Objective-C \@property declaration. + static const CXCursor_ObjCPropertyDecl = 14; + + /// An Objective-C instance variable. + static const CXCursor_ObjCIvarDecl = 15; + + /// An Objective-C instance method. + static const CXCursor_ObjCInstanceMethodDecl = 16; + + /// An Objective-C class method. + static const CXCursor_ObjCClassMethodDecl = 17; + + /// An Objective-C \@implementation. + static const CXCursor_ObjCImplementationDecl = 18; + + /// An Objective-C \@implementation for a category. + static const CXCursor_ObjCCategoryImplDecl = 19; + + /// A typedef. + static const CXCursor_TypedefDecl = 20; + + /// A C++ class method. + static const CXCursor_CXXMethod = 21; + + /// A C++ namespace. + static const CXCursor_Namespace = 22; + + /// A linkage specification, e.g. 'extern "C"'. + static const CXCursor_LinkageSpec = 23; + + /// A C++ constructor. + static const CXCursor_Constructor = 24; + + /// A C++ destructor. + static const CXCursor_Destructor = 25; + + /// A C++ conversion function. + static const CXCursor_ConversionFunction = 26; + + /// A C++ template type parameter. + static const CXCursor_TemplateTypeParameter = 27; + + /// A C++ non-type template parameter. + static const CXCursor_NonTypeTemplateParameter = 28; + + /// A C++ template template parameter. + static const CXCursor_TemplateTemplateParameter = 29; + + /// A C++ function template. + static const CXCursor_FunctionTemplate = 30; + + /// A C++ class template. + static const CXCursor_ClassTemplate = 31; + + /// A C++ class template partial specialization. + static const CXCursor_ClassTemplatePartialSpecialization = 32; + + /// A C++ namespace alias declaration. + static const CXCursor_NamespaceAlias = 33; + + /// A C++ using directive. + static const CXCursor_UsingDirective = 34; + + /// A C++ using declaration. + static const CXCursor_UsingDeclaration = 35; + + /// A C++ alias declaration + static const CXCursor_TypeAliasDecl = 36; + + /// An Objective-C \@synthesize definition. + static const CXCursor_ObjCSynthesizeDecl = 37; + + /// An Objective-C \@dynamic definition. + static const CXCursor_ObjCDynamicDecl = 38; + + /// An access specifier. + static const CXCursor_CXXAccessSpecifier = 39; + static const CXCursor_FirstDecl = 1; + static const CXCursor_LastDecl = 39; + static const CXCursor_FirstRef = 40; + static const CXCursor_ObjCSuperClassRef = 40; + static const CXCursor_ObjCProtocolRef = 41; + static const CXCursor_ObjCClassRef = 42; + + /// A reference to a type declaration. + /// + /// A type reference occurs anywhere where a type is named but not + /// declared. For example, given: + /// + /// \code + /// typedef unsigned size_type; + /// size_type size; + /// \endcode + /// + /// The typedef is a declaration of size_type (CXCursor_TypedefDecl), + /// while the type of the variable "size" is referenced. The cursor + /// referenced by the type of size is the typedef for size_type. + static const CXCursor_TypeRef = 43; + static const CXCursor_CXXBaseSpecifier = 44; + + /// A reference to a class template, function template, template + /// template parameter, or class template partial specialization. + static const CXCursor_TemplateRef = 45; + + /// A reference to a namespace or namespace alias. + static const CXCursor_NamespaceRef = 46; + + /// A reference to a member of a struct, union, or class that occurs in + /// some non-expression context, e.g., a designated initializer. + static const CXCursor_MemberRef = 47; + + /// A reference to a labeled statement. + /// + /// This cursor kind is used to describe the jump to "start_over" in the + /// goto statement in the following example: + /// + /// \code + /// start_over: + /// ++counter; + /// + /// goto start_over; + /// \endcode + /// + /// A label reference cursor refers to a label statement. + static const CXCursor_LabelRef = 48; + + /// A reference to a set of overloaded functions or function templates + /// that has not yet been resolved to a specific function or function template. + /// + /// An overloaded declaration reference cursor occurs in C++ templates where + /// a dependent name refers to a function. For example: + /// + /// \code + /// template void swap(T&, T&); + /// + /// struct X { ... }; + /// void swap(X&, X&); + /// + /// template + /// void reverse(T* first, T* last) { + /// while (first < last - 1) { + /// swap(*first, *--last); + /// ++first; + /// } + /// } + /// + /// struct Y { }; + /// void swap(Y&, Y&); + /// \endcode + /// + /// Here, the identifier "swap" is associated with an overloaded declaration + /// reference. In the template definition, "swap" refers to either of the two + /// "swap" functions declared above, so both results will be available. At + /// instantiation time, "swap" may also refer to other functions found via + /// argument-dependent lookup (e.g., the "swap" function at the end of the + /// example). + /// + /// The functions \c clang_getNumOverloadedDecls() and + /// \c clang_getOverloadedDecl() can be used to retrieve the definitions + /// referenced by this cursor. + static const CXCursor_OverloadedDeclRef = 49; + + /// A reference to a variable that occurs in some non-expression + /// context, e.g., a C++ lambda capture list. + static const CXCursor_VariableRef = 50; + static const CXCursor_LastRef = 50; + static const CXCursor_FirstInvalid = 70; + static const CXCursor_InvalidFile = 70; + static const CXCursor_NoDeclFound = 71; + static const CXCursor_NotImplemented = 72; + static const CXCursor_InvalidCode = 73; + static const CXCursor_LastInvalid = 73; + static const CXCursor_FirstExpr = 100; + + /// An expression whose specific kind is not exposed via this + /// interface. + /// + /// Unexposed expressions have the same operations as any other kind + /// of expression; one can extract their location information, + /// spelling, children, etc. However, the specific kind of the + /// expression is not reported. + static const CXCursor_UnexposedExpr = 100; + + /// An expression that refers to some value declaration, such + /// as a function, variable, or enumerator. + static const CXCursor_DeclRefExpr = 101; + + /// An expression that refers to a member of a struct, union, + /// class, Objective-C class, etc. + static const CXCursor_MemberRefExpr = 102; + + /// An expression that calls a function. + static const CXCursor_CallExpr = 103; + + /// An expression that sends a message to an Objective-C + /// object or class. + static const CXCursor_ObjCMessageExpr = 104; + + /// An expression that represents a block literal. + static const CXCursor_BlockExpr = 105; + + /// An integer literal. + static const CXCursor_IntegerLiteral = 106; + + /// A floating point number literal. + static const CXCursor_FloatingLiteral = 107; + + /// An imaginary number literal. + static const CXCursor_ImaginaryLiteral = 108; + + /// A string literal. + static const CXCursor_StringLiteral = 109; + + /// A character literal. + static const CXCursor_CharacterLiteral = 110; + + /// A parenthesized expression, e.g. "(1)". + /// + /// This AST node is only formed if full location information is requested. + static const CXCursor_ParenExpr = 111; + + /// This represents the unary-expression's (except sizeof and + /// alignof). + static const CXCursor_UnaryOperator = 112; + + /// [C99 6.5.2.1] Array Subscripting. + static const CXCursor_ArraySubscriptExpr = 113; + + /// A builtin binary operation expression such as "x + y" or + /// "x <= y". + static const CXCursor_BinaryOperator = 114; + + /// Compound assignment such as "+=". + static const CXCursor_CompoundAssignOperator = 115; + + /// The ?: ternary operator. + static const CXCursor_ConditionalOperator = 116; + + /// An explicit cast in C (C99 6.5.4) or a C-style cast in C++ + /// (C++ [expr.cast]), which uses the syntax (Type)expr. + /// + /// For example: (int)f. + static const CXCursor_CStyleCastExpr = 117; + + /// [C99 6.5.2.5] + static const CXCursor_CompoundLiteralExpr = 118; + + /// Describes an C or C++ initializer list. + static const CXCursor_InitListExpr = 119; + + /// The GNU address of label extension, representing &&label. + static const CXCursor_AddrLabelExpr = 120; + + /// This is the GNU Statement Expression extension: ({int X=4; X;}) + static const CXCursor_StmtExpr = 121; + + /// Represents a C11 generic selection. + static const CXCursor_GenericSelectionExpr = 122; + + /// Implements the GNU __null extension, which is a name for a null + /// pointer constant that has integral type (e.g., int or long) and is the same + /// size and alignment as a pointer. + /// + /// The __null extension is typically only used by system headers, which define + /// NULL as __null in C++ rather than using 0 (which is an integer that may not + /// match the size of a pointer). + static const CXCursor_GNUNullExpr = 123; + + /// C++'s static_cast<> expression. + static const CXCursor_CXXStaticCastExpr = 124; + + /// C++'s dynamic_cast<> expression. + static const CXCursor_CXXDynamicCastExpr = 125; + + /// C++'s reinterpret_cast<> expression. + static const CXCursor_CXXReinterpretCastExpr = 126; + + /// C++'s const_cast<> expression. + static const CXCursor_CXXConstCastExpr = 127; + + /// Represents an explicit C++ type conversion that uses "functional" + /// notion (C++ [expr.type.conv]). + /// + /// Example: + /// \code + /// x = int(0.5); + /// \endcode + static const CXCursor_CXXFunctionalCastExpr = 128; + + /// A C++ typeid expression (C++ [expr.typeid]). + static const CXCursor_CXXTypeidExpr = 129; + + /// [C++ 2.13.5] C++ Boolean Literal. + static const CXCursor_CXXBoolLiteralExpr = 130; + + /// [C++0x 2.14.7] C++ Pointer Literal. + static const CXCursor_CXXNullPtrLiteralExpr = 131; + + /// Represents the "this" expression in C++ + static const CXCursor_CXXThisExpr = 132; + + /// [C++ 15] C++ Throw Expression. + /// + /// This handles 'throw' and 'throw' assignment-expression. When + /// assignment-expression isn't present, Op will be null. + static const CXCursor_CXXThrowExpr = 133; + + /// A new expression for memory allocation and constructor calls, e.g: + /// "new CXXNewExpr(foo)". + static const CXCursor_CXXNewExpr = 134; + + /// A delete expression for memory deallocation and destructor calls, + /// e.g. "delete[] pArray". + static const CXCursor_CXXDeleteExpr = 135; + + /// A unary expression. (noexcept, sizeof, or other traits) + static const CXCursor_UnaryExpr = 136; + + /// An Objective-C string literal i.e. @"foo". + static const CXCursor_ObjCStringLiteral = 137; + + /// An Objective-C \@encode expression. + static const CXCursor_ObjCEncodeExpr = 138; + + /// An Objective-C \@selector expression. + static const CXCursor_ObjCSelectorExpr = 139; + + /// An Objective-C \@protocol expression. + static const CXCursor_ObjCProtocolExpr = 140; + + /// An Objective-C "bridged" cast expression, which casts between + /// Objective-C pointers and C pointers, transferring ownership in the process. + /// + /// \code + /// NSString *str = (__bridge_transfer NSString *)CFCreateString(); + /// \endcode + static const CXCursor_ObjCBridgedCastExpr = 141; + + /// Represents a C++0x pack expansion that produces a sequence of + /// expressions. + /// + /// A pack expansion expression contains a pattern (which itself is an + /// expression) followed by an ellipsis. For example: + /// + /// \code + /// template + /// void forward(F f, Types &&...args) { + /// f(static_cast(args)...); + /// } + /// \endcode + static const CXCursor_PackExpansionExpr = 142; + + /// Represents an expression that computes the length of a parameter + /// pack. + /// + /// \code + /// template + /// struct count { + /// static const unsigned value = sizeof...(Types); + /// }; + /// \endcode + static const CXCursor_SizeOfPackExpr = 143; + static const CXCursor_LambdaExpr = 144; + + /// Objective-c Boolean Literal. + static const CXCursor_ObjCBoolLiteralExpr = 145; + + /// Represents the "self" expression in an Objective-C method. + static const CXCursor_ObjCSelfExpr = 146; + + /// OpenMP 5.0 [2.1.5, Array Section]. + static const CXCursor_OMPArraySectionExpr = 147; + + /// Represents an @available(...) check. + static const CXCursor_ObjCAvailabilityCheckExpr = 148; + + /// Fixed point literal + static const CXCursor_FixedPointLiteral = 149; + + /// OpenMP 5.0 [2.1.4, Array Shaping]. + static const CXCursor_OMPArrayShapingExpr = 150; + + /// OpenMP 5.0 [2.1.6 Iterators] + static const CXCursor_OMPIteratorExpr = 151; + + /// OpenCL's addrspace_cast<> expression. + static const CXCursor_CXXAddrspaceCastExpr = 152; + + /// Expression that references a C++20 concept. + static const CXCursor_ConceptSpecializationExpr = 153; + + /// Expression that references a C++20 concept. + static const CXCursor_RequiresExpr = 154; + + /// Expression that references a C++20 parenthesized list aggregate + /// initializer. + static const CXCursor_CXXParenListInitExpr = 155; + static const CXCursor_LastExpr = 155; + static const CXCursor_FirstStmt = 200; + + /// A statement whose specific kind is not exposed via this + /// interface. + /// + /// Unexposed statements have the same operations as any other kind of + /// statement; one can extract their location information, spelling, + /// children, etc. However, the specific kind of the statement is not + /// reported. + static const CXCursor_UnexposedStmt = 200; + + /// A labelled statement in a function. + /// + /// This cursor kind is used to describe the "start_over:" label statement in + /// the following example: + /// + /// \code + /// start_over: + /// ++counter; + /// \endcode + static const CXCursor_LabelStmt = 201; + + /// A group of statements like { stmt stmt }. + /// + /// This cursor kind is used to describe compound statements, e.g. function + /// bodies. + static const CXCursor_CompoundStmt = 202; + + /// A case statement. + static const CXCursor_CaseStmt = 203; + + /// A default statement. + static const CXCursor_DefaultStmt = 204; + + /// An if statement + static const CXCursor_IfStmt = 205; + + /// A switch statement. + static const CXCursor_SwitchStmt = 206; + + /// A while statement. + static const CXCursor_WhileStmt = 207; + + /// A do statement. + static const CXCursor_DoStmt = 208; + + /// A for statement. + static const CXCursor_ForStmt = 209; + + /// A goto statement. + static const CXCursor_GotoStmt = 210; + + /// An indirect goto statement. + static const CXCursor_IndirectGotoStmt = 211; + + /// A continue statement. + static const CXCursor_ContinueStmt = 212; + + /// A break statement. + static const CXCursor_BreakStmt = 213; + + /// A return statement. + static const CXCursor_ReturnStmt = 214; + + /// A GCC inline assembly statement extension. + static const CXCursor_GCCAsmStmt = 215; + static const CXCursor_AsmStmt = 215; + + /// Objective-C's overall \@try-\@catch-\@finally statement. + static const CXCursor_ObjCAtTryStmt = 216; + + /// Objective-C's \@catch statement. + static const CXCursor_ObjCAtCatchStmt = 217; + + /// Objective-C's \@finally statement. + static const CXCursor_ObjCAtFinallyStmt = 218; + + /// Objective-C's \@throw statement. + static const CXCursor_ObjCAtThrowStmt = 219; + + /// Objective-C's \@synchronized statement. + static const CXCursor_ObjCAtSynchronizedStmt = 220; + + /// Objective-C's autorelease pool statement. + static const CXCursor_ObjCAutoreleasePoolStmt = 221; + + /// Objective-C's collection statement. + static const CXCursor_ObjCForCollectionStmt = 222; + + /// C++'s catch statement. + static const CXCursor_CXXCatchStmt = 223; + + /// C++'s try statement. + static const CXCursor_CXXTryStmt = 224; + + /// C++'s for (* : *) statement. + static const CXCursor_CXXForRangeStmt = 225; + + /// Windows Structured Exception Handling's try statement. + static const CXCursor_SEHTryStmt = 226; + + /// Windows Structured Exception Handling's except statement. + static const CXCursor_SEHExceptStmt = 227; + + /// Windows Structured Exception Handling's finally statement. + static const CXCursor_SEHFinallyStmt = 228; + + /// A MS inline assembly statement extension. + static const CXCursor_MSAsmStmt = 229; + + /// The null statement ";": C99 6.8.3p3. + /// + /// This cursor kind is used to describe the null statement. + static const CXCursor_NullStmt = 230; + + /// Adaptor class for mixing declarations with statements and + /// expressions. + static const CXCursor_DeclStmt = 231; + + /// OpenMP parallel directive. + static const CXCursor_OMPParallelDirective = 232; + + /// OpenMP SIMD directive. + static const CXCursor_OMPSimdDirective = 233; + + /// OpenMP for directive. + static const CXCursor_OMPForDirective = 234; + + /// OpenMP sections directive. + static const CXCursor_OMPSectionsDirective = 235; + + /// OpenMP section directive. + static const CXCursor_OMPSectionDirective = 236; + + /// OpenMP single directive. + static const CXCursor_OMPSingleDirective = 237; + + /// OpenMP parallel for directive. + static const CXCursor_OMPParallelForDirective = 238; + + /// OpenMP parallel sections directive. + static const CXCursor_OMPParallelSectionsDirective = 239; + + /// OpenMP task directive. + static const CXCursor_OMPTaskDirective = 240; + + /// OpenMP master directive. + static const CXCursor_OMPMasterDirective = 241; + + /// OpenMP critical directive. + static const CXCursor_OMPCriticalDirective = 242; + + /// OpenMP taskyield directive. + static const CXCursor_OMPTaskyieldDirective = 243; + + /// OpenMP barrier directive. + static const CXCursor_OMPBarrierDirective = 244; + + /// OpenMP taskwait directive. + static const CXCursor_OMPTaskwaitDirective = 245; + + /// OpenMP flush directive. + static const CXCursor_OMPFlushDirective = 246; + + /// Windows Structured Exception Handling's leave statement. + static const CXCursor_SEHLeaveStmt = 247; + + /// OpenMP ordered directive. + static const CXCursor_OMPOrderedDirective = 248; + + /// OpenMP atomic directive. + static const CXCursor_OMPAtomicDirective = 249; + + /// OpenMP for SIMD directive. + static const CXCursor_OMPForSimdDirective = 250; + + /// OpenMP parallel for SIMD directive. + static const CXCursor_OMPParallelForSimdDirective = 251; + + /// OpenMP target directive. + static const CXCursor_OMPTargetDirective = 252; + + /// OpenMP teams directive. + static const CXCursor_OMPTeamsDirective = 253; + + /// OpenMP taskgroup directive. + static const CXCursor_OMPTaskgroupDirective = 254; + + /// OpenMP cancellation point directive. + static const CXCursor_OMPCancellationPointDirective = 255; + + /// OpenMP cancel directive. + static const CXCursor_OMPCancelDirective = 256; + + /// OpenMP target data directive. + static const CXCursor_OMPTargetDataDirective = 257; + + /// OpenMP taskloop directive. + static const CXCursor_OMPTaskLoopDirective = 258; + + /// OpenMP taskloop simd directive. + static const CXCursor_OMPTaskLoopSimdDirective = 259; + + /// OpenMP distribute directive. + static const CXCursor_OMPDistributeDirective = 260; + + /// OpenMP target enter data directive. + static const CXCursor_OMPTargetEnterDataDirective = 261; + + /// OpenMP target exit data directive. + static const CXCursor_OMPTargetExitDataDirective = 262; + + /// OpenMP target parallel directive. + static const CXCursor_OMPTargetParallelDirective = 263; + + /// OpenMP target parallel for directive. + static const CXCursor_OMPTargetParallelForDirective = 264; + + /// OpenMP target update directive. + static const CXCursor_OMPTargetUpdateDirective = 265; + + /// OpenMP distribute parallel for directive. + static const CXCursor_OMPDistributeParallelForDirective = 266; + + /// OpenMP distribute parallel for simd directive. + static const CXCursor_OMPDistributeParallelForSimdDirective = 267; + + /// OpenMP distribute simd directive. + static const CXCursor_OMPDistributeSimdDirective = 268; + + /// OpenMP target parallel for simd directive. + static const CXCursor_OMPTargetParallelForSimdDirective = 269; + + /// OpenMP target simd directive. + static const CXCursor_OMPTargetSimdDirective = 270; + + /// OpenMP teams distribute directive. + static const CXCursor_OMPTeamsDistributeDirective = 271; + + /// OpenMP teams distribute simd directive. + static const CXCursor_OMPTeamsDistributeSimdDirective = 272; + + /// OpenMP teams distribute parallel for simd directive. + static const CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273; + + /// OpenMP teams distribute parallel for directive. + static const CXCursor_OMPTeamsDistributeParallelForDirective = 274; + + /// OpenMP target teams directive. + static const CXCursor_OMPTargetTeamsDirective = 275; + + /// OpenMP target teams distribute directive. + static const CXCursor_OMPTargetTeamsDistributeDirective = 276; + + /// OpenMP target teams distribute parallel for directive. + static const CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277; + + /// OpenMP target teams distribute parallel for simd directive. + static const CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective = 278; + + /// OpenMP target teams distribute simd directive. + static const CXCursor_OMPTargetTeamsDistributeSimdDirective = 279; + + /// C++2a std::bit_cast expression. + static const CXCursor_BuiltinBitCastExpr = 280; + + /// OpenMP master taskloop directive. + static const CXCursor_OMPMasterTaskLoopDirective = 281; + + /// OpenMP parallel master taskloop directive. + static const CXCursor_OMPParallelMasterTaskLoopDirective = 282; + + /// OpenMP master taskloop simd directive. + static const CXCursor_OMPMasterTaskLoopSimdDirective = 283; + + /// OpenMP parallel master taskloop simd directive. + static const CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284; + + /// OpenMP parallel master directive. + static const CXCursor_OMPParallelMasterDirective = 285; + + /// OpenMP depobj directive. + static const CXCursor_OMPDepobjDirective = 286; + + /// OpenMP scan directive. + static const CXCursor_OMPScanDirective = 287; + + /// OpenMP tile directive. + static const CXCursor_OMPTileDirective = 288; + + /// OpenMP canonical loop. + static const CXCursor_OMPCanonicalLoop = 289; + + /// OpenMP interop directive. + static const CXCursor_OMPInteropDirective = 290; + + /// OpenMP dispatch directive. + static const CXCursor_OMPDispatchDirective = 291; + + /// OpenMP masked directive. + static const CXCursor_OMPMaskedDirective = 292; + + /// OpenMP unroll directive. + static const CXCursor_OMPUnrollDirective = 293; + + /// OpenMP metadirective directive. + static const CXCursor_OMPMetaDirective = 294; + + /// OpenMP loop directive. + static const CXCursor_OMPGenericLoopDirective = 295; + + /// OpenMP teams loop directive. + static const CXCursor_OMPTeamsGenericLoopDirective = 296; + + /// OpenMP target teams loop directive. + static const CXCursor_OMPTargetTeamsGenericLoopDirective = 297; + + /// OpenMP parallel loop directive. + static const CXCursor_OMPParallelGenericLoopDirective = 298; + + /// OpenMP target parallel loop directive. + static const CXCursor_OMPTargetParallelGenericLoopDirective = 299; + + /// OpenMP parallel masked directive. + static const CXCursor_OMPParallelMaskedDirective = 300; + + /// OpenMP masked taskloop directive. + static const CXCursor_OMPMaskedTaskLoopDirective = 301; + + /// OpenMP masked taskloop simd directive. + static const CXCursor_OMPMaskedTaskLoopSimdDirective = 302; + + /// OpenMP parallel masked taskloop directive. + static const CXCursor_OMPParallelMaskedTaskLoopDirective = 303; + + /// OpenMP parallel masked taskloop simd directive. + static const CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304; + + /// OpenMP error directive. + static const CXCursor_OMPErrorDirective = 305; + + /// OpenMP scope directive. + static const CXCursor_OMPScopeDirective = 306; + static const CXCursor_LastStmt = 306; + + /// Cursor that represents the translation unit itself. + /// + /// The translation unit cursor exists primarily to act as the root + /// cursor for traversing the contents of a translation unit. + static const CXCursor_TranslationUnit = 350; + static const CXCursor_FirstAttr = 400; + + /// An attribute whose specific kind is not exposed via this + /// interface. + static const CXCursor_UnexposedAttr = 400; + static const CXCursor_IBActionAttr = 401; + static const CXCursor_IBOutletAttr = 402; + static const CXCursor_IBOutletCollectionAttr = 403; + static const CXCursor_CXXFinalAttr = 404; + static const CXCursor_CXXOverrideAttr = 405; + static const CXCursor_AnnotateAttr = 406; + static const CXCursor_AsmLabelAttr = 407; + static const CXCursor_PackedAttr = 408; + static const CXCursor_PureAttr = 409; + static const CXCursor_ConstAttr = 410; + static const CXCursor_NoDuplicateAttr = 411; + static const CXCursor_CUDAConstantAttr = 412; + static const CXCursor_CUDADeviceAttr = 413; + static const CXCursor_CUDAGlobalAttr = 414; + static const CXCursor_CUDAHostAttr = 415; + static const CXCursor_CUDASharedAttr = 416; + static const CXCursor_VisibilityAttr = 417; + static const CXCursor_DLLExport = 418; + static const CXCursor_DLLImport = 419; + static const CXCursor_NSReturnsRetained = 420; + static const CXCursor_NSReturnsNotRetained = 421; + static const CXCursor_NSReturnsAutoreleased = 422; + static const CXCursor_NSConsumesSelf = 423; + static const CXCursor_NSConsumed = 424; + static const CXCursor_ObjCException = 425; + static const CXCursor_ObjCNSObject = 426; + static const CXCursor_ObjCIndependentClass = 427; + static const CXCursor_ObjCPreciseLifetime = 428; + static const CXCursor_ObjCReturnsInnerPointer = 429; + static const CXCursor_ObjCRequiresSuper = 430; + static const CXCursor_ObjCRootClass = 431; + static const CXCursor_ObjCSubclassingRestricted = 432; + static const CXCursor_ObjCExplicitProtocolImpl = 433; + static const CXCursor_ObjCDesignatedInitializer = 434; + static const CXCursor_ObjCRuntimeVisible = 435; + static const CXCursor_ObjCBoxable = 436; + static const CXCursor_FlagEnum = 437; + static const CXCursor_ConvergentAttr = 438; + static const CXCursor_WarnUnusedAttr = 439; + static const CXCursor_WarnUnusedResultAttr = 440; + static const CXCursor_AlignedAttr = 441; + static const CXCursor_LastAttr = 441; + static const CXCursor_PreprocessingDirective = 500; + static const CXCursor_MacroDefinition = 501; + static const CXCursor_MacroExpansion = 502; + static const CXCursor_MacroInstantiation = 502; + static const CXCursor_InclusionDirective = 503; + static const CXCursor_FirstPreprocessing = 500; + static const CXCursor_LastPreprocessing = 503; + + /// A module import declaration. + static const CXCursor_ModuleImportDecl = 600; + static const CXCursor_TypeAliasTemplateDecl = 601; + + /// A static_assert or _Static_assert node + static const CXCursor_StaticAssert = 602; + + /// a friend declaration. + static const CXCursor_FriendDecl = 603; + + /// a concept declaration. + static const CXCursor_ConceptDecl = 604; + static const CXCursor_FirstExtraDecl = 600; + static const CXCursor_LastExtraDecl = 604; + + /// A code completion overload candidate. + static const CXCursor_OverloadCandidate = 700; +} + +/// Describes the kind of type +abstract class CXTypeKind { + /// Represents an invalid type (e.g., where no type is available). + static const CXType_Invalid = 0; + + /// A type whose specific kind is not exposed via this + /// interface. + static const CXType_Unexposed = 1; + static const CXType_Void = 2; + static const CXType_Bool = 3; + static const CXType_Char_U = 4; + static const CXType_UChar = 5; + static const CXType_Char16 = 6; + static const CXType_Char32 = 7; + static const CXType_UShort = 8; + static const CXType_UInt = 9; + static const CXType_ULong = 10; + static const CXType_ULongLong = 11; + static const CXType_UInt128 = 12; + static const CXType_Char_S = 13; + static const CXType_SChar = 14; + static const CXType_WChar = 15; + static const CXType_Short = 16; + static const CXType_Int = 17; + static const CXType_Long = 18; + static const CXType_LongLong = 19; + static const CXType_Int128 = 20; + static const CXType_Float = 21; + static const CXType_Double = 22; + static const CXType_LongDouble = 23; + static const CXType_NullPtr = 24; + static const CXType_Overload = 25; + static const CXType_Dependent = 26; + static const CXType_ObjCId = 27; + static const CXType_ObjCClass = 28; + static const CXType_ObjCSel = 29; + static const CXType_Float128 = 30; + static const CXType_Half = 31; + static const CXType_Float16 = 32; + static const CXType_ShortAccum = 33; + static const CXType_Accum = 34; + static const CXType_LongAccum = 35; + static const CXType_UShortAccum = 36; + static const CXType_UAccum = 37; + static const CXType_ULongAccum = 38; + static const CXType_BFloat16 = 39; + static const CXType_Ibm128 = 40; + static const CXType_FirstBuiltin = 2; + static const CXType_LastBuiltin = 40; + static const CXType_Complex = 100; + static const CXType_Pointer = 101; + static const CXType_BlockPointer = 102; + static const CXType_LValueReference = 103; + static const CXType_RValueReference = 104; + static const CXType_Record = 105; + static const CXType_Enum = 106; + static const CXType_Typedef = 107; + static const CXType_ObjCInterface = 108; + static const CXType_ObjCObjectPointer = 109; + static const CXType_FunctionNoProto = 110; + static const CXType_FunctionProto = 111; + static const CXType_ConstantArray = 112; + static const CXType_Vector = 113; + static const CXType_IncompleteArray = 114; + static const CXType_VariableArray = 115; + static const CXType_DependentSizedArray = 116; + static const CXType_MemberPointer = 117; + static const CXType_Auto = 118; + + /// Represents a type that was referred to using an elaborated type keyword. + /// + /// E.g., struct S, or via a qualified name, e.g., N::M::type, or both. + static const CXType_Elaborated = 119; + static const CXType_Pipe = 120; + static const CXType_OCLImage1dRO = 121; + static const CXType_OCLImage1dArrayRO = 122; + static const CXType_OCLImage1dBufferRO = 123; + static const CXType_OCLImage2dRO = 124; + static const CXType_OCLImage2dArrayRO = 125; + static const CXType_OCLImage2dDepthRO = 126; + static const CXType_OCLImage2dArrayDepthRO = 127; + static const CXType_OCLImage2dMSAARO = 128; + static const CXType_OCLImage2dArrayMSAARO = 129; + static const CXType_OCLImage2dMSAADepthRO = 130; + static const CXType_OCLImage2dArrayMSAADepthRO = 131; + static const CXType_OCLImage3dRO = 132; + static const CXType_OCLImage1dWO = 133; + static const CXType_OCLImage1dArrayWO = 134; + static const CXType_OCLImage1dBufferWO = 135; + static const CXType_OCLImage2dWO = 136; + static const CXType_OCLImage2dArrayWO = 137; + static const CXType_OCLImage2dDepthWO = 138; + static const CXType_OCLImage2dArrayDepthWO = 139; + static const CXType_OCLImage2dMSAAWO = 140; + static const CXType_OCLImage2dArrayMSAAWO = 141; + static const CXType_OCLImage2dMSAADepthWO = 142; + static const CXType_OCLImage2dArrayMSAADepthWO = 143; + static const CXType_OCLImage3dWO = 144; + static const CXType_OCLImage1dRW = 145; + static const CXType_OCLImage1dArrayRW = 146; + static const CXType_OCLImage1dBufferRW = 147; + static const CXType_OCLImage2dRW = 148; + static const CXType_OCLImage2dArrayRW = 149; + static const CXType_OCLImage2dDepthRW = 150; + static const CXType_OCLImage2dArrayDepthRW = 151; + static const CXType_OCLImage2dMSAARW = 152; + static const CXType_OCLImage2dArrayMSAARW = 153; + static const CXType_OCLImage2dMSAADepthRW = 154; + static const CXType_OCLImage2dArrayMSAADepthRW = 155; + static const CXType_OCLImage3dRW = 156; + static const CXType_OCLSampler = 157; + static const CXType_OCLEvent = 158; + static const CXType_OCLQueue = 159; + static const CXType_OCLReserveID = 160; + static const CXType_ObjCObject = 161; + static const CXType_ObjCTypeParam = 162; + static const CXType_Attributed = 163; + static const CXType_OCLIntelSubgroupAVCMcePayload = 164; + static const CXType_OCLIntelSubgroupAVCImePayload = 165; + static const CXType_OCLIntelSubgroupAVCRefPayload = 166; + static const CXType_OCLIntelSubgroupAVCSicPayload = 167; + static const CXType_OCLIntelSubgroupAVCMceResult = 168; + static const CXType_OCLIntelSubgroupAVCImeResult = 169; + static const CXType_OCLIntelSubgroupAVCRefResult = 170; + static const CXType_OCLIntelSubgroupAVCSicResult = 171; + static const CXType_OCLIntelSubgroupAVCImeResultSingleReferenceStreamout = + 172; + static const CXType_OCLIntelSubgroupAVCImeResultDualReferenceStreamout = 173; + static const CXType_OCLIntelSubgroupAVCImeSingleReferenceStreamin = 174; + static const CXType_OCLIntelSubgroupAVCImeDualReferenceStreamin = 175; + static const CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172; + static const CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173; + static const CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174; + static const CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175; + static const CXType_ExtVector = 176; + static const CXType_Atomic = 177; + static const CXType_BTFTagAttributed = 178; +} + +abstract class CXTypeNullabilityKind { + /// Values of this type can never be null. + static const CXTypeNullability_NonNull = 0; + + /// Values of this type can be null. + static const CXTypeNullability_Nullable = 1; + + /// Whether values of this type can be null is (explicitly) + /// unspecified. This captures a (fairly rare) case where we + /// can't conclude anything about the nullability of the type even + /// though it has been considered. + static const CXTypeNullability_Unspecified = 2; + + /// Nullability is not applicable to this type. + static const CXTypeNullability_Invalid = 3; + + /// Generally behaves like Nullable, except when used in a block parameter that + /// was imported into a swift async method. There, swift will assume that the + /// parameter can get null even if no error occurred. _Nullable parameters are + /// assumed to only get null on error. + static const CXTypeNullability_NullableResult = 4; +} + +/// List the possible error codes for \c clang_Type_getSizeOf, +/// \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and +/// \c clang_Cursor_getOffsetOf. +/// +/// A value of this enumeration type can be returned if the target type is not +/// a valid argument to sizeof, alignof or offsetof. +abstract class CXTypeLayoutError { + /// Type is of kind CXType_Invalid. + static const CXTypeLayoutError_Invalid = -1; + + /// The type is an incomplete Type. + static const CXTypeLayoutError_Incomplete = -2; + + /// The type is a dependent Type. + static const CXTypeLayoutError_Dependent = -3; + + /// The type is not a constant size type. + static const CXTypeLayoutError_NotConstantSize = -4; + + /// The Field name is not valid for this record. + static const CXTypeLayoutError_InvalidFieldName = -5; + + /// The type is undeduced. + static const CXTypeLayoutError_Undeduced = -6; +} + +/// Represents the storage classes as declared in the source. CX_SC_Invalid +/// was added for the case that the passed cursor in not a declaration. +abstract class CX_StorageClass { + static const CX_SC_Invalid = 0; + static const CX_SC_None = 1; + static const CX_SC_Extern = 2; + static const CX_SC_Static = 3; + static const CX_SC_PrivateExtern = 4; + static const CX_SC_OpenCLWorkGroupLocal = 5; + static const CX_SC_Auto = 6; + static const CX_SC_Register = 7; +} + +/// Describes how the traversal of the children of a particular +/// cursor should proceed after visiting a particular child cursor. +/// +/// A value of this enumeration type should be returned by each +/// \c CXCursorVisitor to indicate how clang_visitChildren() proceed. +abstract class CXChildVisitResult { + /// Terminates the cursor traversal. + static const CXChildVisit_Break = 0; + + /// Continues the cursor traversal with the next sibling of + /// the cursor just visited, without visiting its children. + static const CXChildVisit_Continue = 1; + + /// Recursively traverse the children of this cursor, using + /// the same visitor and client data. + static const CXChildVisit_Recurse = 2; +} + +/// Property attributes for a \c CXCursor_ObjCPropertyDecl. +abstract class CXObjCPropertyAttrKind { + static const CXObjCPropertyAttr_noattr = 0; + static const CXObjCPropertyAttr_readonly = 1; + static const CXObjCPropertyAttr_getter = 2; + static const CXObjCPropertyAttr_assign = 4; + static const CXObjCPropertyAttr_readwrite = 8; + static const CXObjCPropertyAttr_retain = 16; + static const CXObjCPropertyAttr_copy = 32; + static const CXObjCPropertyAttr_nonatomic = 64; + static const CXObjCPropertyAttr_setter = 128; + static const CXObjCPropertyAttr_atomic = 256; + static const CXObjCPropertyAttr_weak = 512; + static const CXObjCPropertyAttr_strong = 1024; + static const CXObjCPropertyAttr_unsafe_unretained = 2048; + static const CXObjCPropertyAttr_class = 4096; +} + +abstract class CXEvalResultKind { + static const CXEval_Int = 1; + static const CXEval_Float = 2; + static const CXEval_ObjCStrLiteral = 3; + static const CXEval_StrLiteral = 4; + static const CXEval_CFStr = 5; + static const CXEval_Other = 6; + static const CXEval_UnExposed = 0; +} + +/// Evaluation result of a cursor +typedef CXEvalResult = ffi.Pointer; + +/// A character string. +/// +/// The \c CXString type is used to return strings from the interface when +/// the ownership of that string might differ from one call to the next. +/// Use \c clang_getCString() to retrieve the string data and, once finished +/// with the string data, call \c clang_disposeString() to free the string. +final class CXString extends ffi.Opaque {} + +/// A cursor representing some element in the abstract syntax tree for +/// a translation unit. +/// +/// The cursor abstraction unifies the different kinds of entities in a +/// program--declaration, statements, expressions, references to declarations, +/// etc.--under a single "cursor" abstraction with a common set of operations. +/// Common operation for a cursor include: getting the physical location in +/// a source file where the cursor points, getting the name associated with a +/// cursor, and retrieving cursors for any child nodes of a particular cursor. +/// +/// Cursors can be produced in two specific ways. +/// clang_getTranslationUnitCursor() produces a cursor for a translation unit, +/// from which one can use clang_visitChildren() to explore the rest of the +/// translation unit. clang_getCursor() maps from a physical source location +/// to the entity that resides at that location, allowing one to map from the +/// source code into the AST. +final class CXCursor extends ffi.Opaque {} + +/// The type of an element in the abstract syntax tree. +final class CXType extends ffi.Opaque {} + +/// Identifies a half-open character range in the source code. +/// +/// Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the +/// starting and end locations from a source range, respectively. +final class CXSourceRange extends ffi.Opaque {} + +/// Identifies a specific source location within a translation +/// unit. +/// +/// Use clang_getExpansionLocation() or clang_getSpellingLocation() +/// to map a source location to a particular file, line, and column. +final class CXSourceLocation extends ffi.Opaque {} + +/// A particular source file that is part of a translation unit. +typedef CXFile = ffi.Pointer; diff --git a/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_types.dart b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_types.dart new file mode 100644 index 0000000000..8ba3716c2b --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_types.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Wraps every opaque struct in a pointer for similartiy with ffigen codebase. +library; + +import 'dart:ffi'; + +import 'clang_bindings.dart' as clang; + +export 'clang_bindings.dart' + show + CXChildVisitResult, + CXCursorKind, + CXDiagnostic, + CXDiagnosticDisplayOptions, + CXDiagnosticSeverity, + CXEvalResult, + CXEvalResultKind, + CXFile, + CXIndex, + CXObjCPropertyAttrKind, + CXTranslationUnit, + CXTranslationUnit_Flags, + CXTypeKind, + CXTypeLayoutError, + CXTypeNullabilityKind, + CX_StorageClass; + +typedef CXString = Pointer; +typedef CXUnsavedFile = Pointer; +typedef CXCursor = Pointer; +typedef CXType = Pointer; +typedef CXSourceRange = Pointer; +typedef CXSourceLocation = Pointer; diff --git a/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_wrapper.dart b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_wrapper.dart new file mode 100644 index 0000000000..99c0b7957c --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/clang_bindings/clang_wrapper.dart @@ -0,0 +1,90 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// AUTO GENERATED FILE, DO NOT EDIT. +// ignore_for_file: camel_case_types, non_constant_identifier_names + +import 'clang_bindings.dart' as c; + +class Clang { + final clang_createIndex = c.clang_createIndex; + final clang_disposeIndex = c.clang_disposeIndex; + final clang_parseTranslationUnit = c.clang_parseTranslationUnit; + final clang_disposeTranslationUnit = c.clang_disposeTranslationUnit; + final clang_getNumDiagnostics = c.clang_getNumDiagnostics; + final clang_getDiagnostic = c.clang_getDiagnostic; + final clang_getDiagnosticSeverity = c.clang_getDiagnosticSeverity; + final clang_disposeDiagnostic = c.clang_disposeDiagnostic; + final clang_EvalResult_getKind = c.clang_EvalResult_getKind; + final clang_EvalResult_getAsLongLong = c.clang_EvalResult_getAsLongLong; + final clang_EvalResult_getAsDouble = c.clang_EvalResult_getAsDouble; + final clang_EvalResult_getAsStr = c.clang_EvalResult_getAsStr; + final clang_EvalResult_dispose = c.clang_EvalResult_dispose; + final clang_getCString = c.clang_getCString_wrap; + final clang_disposeString = c.clang_disposeString_wrap; + final clang_getClangVersion = c.clang_getClangVersion_wrap; + final clang_getCursorKind = c.clang_getCursorKind_wrap; + final clang_getCursorDefinition = c.clang_getCursorDefinition_wrap; + final clang_getCursorKindSpelling = c.clang_getCursorKindSpelling_wrap; + final clang_getCursorType = c.clang_getCursorType_wrap; + final clang_getTypeSpelling = c.clang_getTypeSpelling_wrap; + final clang_getTypeKindSpelling = c.clang_getTypeKindSpelling_wrap; + final clang_getResultType = c.clang_getResultType_wrap; + final clang_getPointeeType = c.clang_getPointeeType_wrap; + final clang_getCanonicalType = c.clang_getCanonicalType_wrap; + final clang_Type_getModifiedType = c.clang_Type_getModifiedType_wrap; + final clang_Type_getNullability = c.clang_Type_getNullability_wrap; + final clang_Type_getNamedType = c.clang_Type_getNamedType_wrap; + final clang_Type_getAlignOf = c.clang_Type_getAlignOf_wrap; + final clang_getTypeDeclaration = c.clang_getTypeDeclaration_wrap; + final clang_getTypedefName = c.clang_getTypedefName_wrap; + final clang_getTypedefDeclUnderlyingType = + c.clang_getTypedefDeclUnderlyingType_wrap; + final clang_getCursorSpelling = c.clang_getCursorSpelling_wrap; + final clang_getCursorUSR = c.clang_getCursorUSR_wrap; + final clang_getTranslationUnitCursor = c.clang_getTranslationUnitCursor_wrap; + final clang_formatDiagnostic = c.clang_formatDiagnostic_wrap; + final clang_visitChildren = c.clang_visitChildren_wrap; + final clang_getArgType = c.clang_getArgType_wrap; + final clang_getNumArgTypes = c.clang_getNumArgTypes_wrap; + final clang_getEnumConstantDeclValue = c.clang_getEnumConstantDeclValue_wrap; + final clang_equalRanges = c.clang_equalRanges_wrap; + final clang_Cursor_Evaluate = c.clang_Cursor_Evaluate_wrap; + final clang_Cursor_getArgument = c.clang_Cursor_getArgument_wrap; + final clang_Cursor_getNumArguments = c.clang_Cursor_getNumArguments_wrap; + final clang_Cursor_getCommentRange = c.clang_Cursor_getCommentRange_wrap; + final clang_Cursor_getRawCommentText = c.clang_Cursor_getRawCommentText_wrap; + final clang_Cursor_getBriefCommentText = + c.clang_Cursor_getBriefCommentText_wrap; + final clang_Cursor_getStorageClass = c.clang_Cursor_getStorageClass_wrap; + final clang_getFieldDeclBitWidth = c.clang_getFieldDeclBitWidth_wrap; + final clang_Cursor_hasAttrs = c.clang_Cursor_hasAttrs_wrap; + final clang_Cursor_isFunctionInlined = c.clang_Cursor_isFunctionInlined_wrap; + final clang_Cursor_isAnonymous = c.clang_Cursor_isAnonymous_wrap; + final clang_Cursor_isAnonymousRecordDecl = + c.clang_Cursor_isAnonymousRecordDecl_wrap; + final clang_Cursor_isNull = c.clang_Cursor_isNull_wrap; + final clang_Cursor_isMacroFunctionLike = + c.clang_Cursor_isMacroFunctionLike_wrap; + final clang_Cursor_isMacroBuiltin = c.clang_Cursor_isMacroBuiltin_wrap; + final clang_Cursor_getObjCPropertyAttributes = + c.clang_Cursor_getObjCPropertyAttributes_wrap; + final clang_Cursor_isObjCOptional = c.clang_Cursor_isObjCOptional_wrap; + final clang_Cursor_getObjCPropertyGetterName = + c.clang_Cursor_getObjCPropertyGetterName_wrap; + final clang_Cursor_getObjCPropertySetterName = + c.clang_Cursor_getObjCPropertySetterName_wrap; + final clang_getCursorResultType = c.clang_getCursorResultType_wrap; + final clang_isFunctionTypeVariadic = c.clang_isFunctionTypeVariadic_wrap; + final clang_getCursorLocation = c.clang_getCursorLocation_wrap; + final clang_getEnumDeclIntegerType = c.clang_getEnumDeclIntegerType_wrap; + final clang_getFileLocation = c.clang_getFileLocation_wrap; + final clang_getFileName = c.clang_getFileName_wrap; + final clang_getNumElements = c.clang_getNumElements_wrap; + final clang_getArrayElementType = c.clang_getArrayElementType_wrap; + final clang_isConstQualifiedType = c.clang_isConstQualifiedType_wrap; + final clang_Location_isInSystemHeader = + c.clang_Location_isInSystemHeader_wrap; + final getCXTypeKind = c.getCXTypeKind; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/data.dart b/pkgs/ffigenpad/lib/src/header_parser/data.dart new file mode 100644 index 0000000000..28d246782e --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/data.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../code_generator.dart' show Constant, ObjCBuiltInFunctions; +import '../config_provider.dart' show Config; +import 'clang_bindings/clang_wrapper.dart' show Clang; + +import 'utils.dart'; + +// /// Holds configurations. +Config get config => _config; +late Config _config; + +/// Holds clang functions. +Clang get clang => _clang; +Clang _clang = Clang(); + +// Cursor index. +CursorIndex get cursorIndex => _cursorIndex; +CursorIndex _cursorIndex = CursorIndex(); + +// // Tracks seen status for bindings +BindingsIndex get bindingsIndex => _bindingsIndex; +BindingsIndex _bindingsIndex = BindingsIndex(); + +/// Used for naming typedefs. +IncrementalNamer get incrementalNamer => _incrementalNamer; +IncrementalNamer _incrementalNamer = IncrementalNamer(); + +/// Saved macros, Key: prefixedName, Value originalName. +Map get savedMacros => _savedMacros; +Map _savedMacros = {}; + +/// Saved unnamed EnumConstants. +List get unnamedEnumConstants => _unnamedEnumConstants; +List _unnamedEnumConstants = []; + +/// Built in functions used by the Objective C bindings. +ObjCBuiltInFunctions get objCBuiltInFunctions => _objCBuiltInFunctions; +late ObjCBuiltInFunctions _objCBuiltInFunctions; + +/// Tracks if any source error/warning has occured which can potentially cause +/// invalid generated bindings. +bool hasSourceErrors = false; + +void initializeGlobals({required Config config}) { + _config = config; + _clang = Clang(); + _incrementalNamer = IncrementalNamer(); + _savedMacros = {}; + _unnamedEnumConstants = []; + _cursorIndex = CursorIndex(); + _bindingsIndex = BindingsIndex(); + _objCBuiltInFunctions = + ObjCBuiltInFunctions(config.generateForPackageObjectiveC); + hasSourceErrors = false; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/includer.dart b/pkgs/ffigenpad/lib/src/header_parser/includer.dart new file mode 100644 index 0000000000..5173f39512 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/includer.dart @@ -0,0 +1,100 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Utility functions to check whether a binding should be parsed or not +/// based on filters. +library; + +import '../config_provider/config_types.dart'; +import '../strings.dart' as strings; +import 'data.dart'; + +bool _shouldIncludeDecl( + Declaration declaration, + bool Function(String) isSeenDecl, + bool Function(Declaration) configIncludes) { + if (isSeenDecl(declaration.usr) || declaration.originalName == '') { + return false; + } else if (config.usrTypeMappings.containsKey(declaration.usr)) { + return false; + } else if (configIncludes(declaration)) { + return true; + } else { + return false; + } +} + +bool shouldIncludeStruct(Declaration declaration) { + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenType, config.structDecl.shouldInclude); +} + +bool shouldIncludeUnion(Declaration declaration) { + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenType, config.unionDecl.shouldInclude); +} + +bool shouldIncludeFunc(Declaration declaration) { + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenFunc, config.functionDecl.shouldInclude); +} + +bool shouldIncludeEnumClass(Declaration declaration) { + return _shouldIncludeDecl(declaration, bindingsIndex.isSeenType, + config.enumClassDecl.shouldInclude); +} + +bool shouldIncludeUnnamedEnumConstant(Declaration declaration) { + return _shouldIncludeDecl( + declaration, + bindingsIndex.isSeenUnnamedEnumConstant, + config.unnamedEnumConstants.shouldInclude); +} + +bool shouldIncludeGlobalVar(Declaration declaration) { + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenGlobalVar, config.globals.shouldInclude); +} + +bool shouldIncludeMacro(Declaration declaration) { + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenMacro, config.macroDecl.shouldInclude); +} + +bool shouldIncludeTypealias(Declaration declaration) { + // Objective C has some core typedefs that are important to keep. + if (config.language == Language.objc && + declaration.originalName == strings.objcInstanceType) { + return true; + } + return _shouldIncludeDecl( + declaration, bindingsIndex.isSeenType, config.typedefs.shouldInclude); +} + +bool shouldIncludeObjCInterface(Declaration declaration) { + return _shouldIncludeDecl(declaration, bindingsIndex.isSeenType, + config.objcInterfaces.shouldInclude); +} + +bool shouldIncludeObjCProtocol(Declaration declaration) { + return _shouldIncludeDecl(declaration, bindingsIndex.isSeenObjCProtocol, + config.objcProtocols.shouldInclude); +} + +/// True if a cursor should be included based on headers config, used on root +/// declarations. +bool shouldIncludeRootCursor(String sourceFile) { + // Handle empty string in case of system headers or macros. + if (sourceFile.isEmpty) { + return false; + } + + // Add header to seen if it's not. + if (!bindingsIndex.isSeenHeader(sourceFile)) { + bindingsIndex.addHeaderToSeen( + sourceFile, config.shouldIncludeHeader(Uri.file(sourceFile))); + } + + return bindingsIndex.getSeenHeaderStatus(sourceFile)!; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/parser.dart b/pkgs/ffigenpad/lib/src/header_parser/parser.dart new file mode 100644 index 0000000000..0cb2e15bb8 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/parser.dart @@ -0,0 +1,175 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi'; + +import 'package:logging/logging.dart'; + +import '../code_generator.dart'; +import '../config_provider.dart'; +import '../config_provider/config_types.dart'; +import '../strings.dart' as strings; +import 'clang_bindings/clang_types.dart' as clang_types; +import 'data.dart'; +import 'sub_parsers/macro_parser.dart'; +import 'translation_unit_parser.dart'; +import 'utils.dart'; + +/// Main entrypoint for header_parser. +Library parse(Config c) { + initParser(c); + + final bindings = parseToBindings(c); + + final library = Library( + bindings: bindings, + name: c.wrapperName, + description: c.wrapperDocComment, + header: c.preamble, + sort: c.sort, + generateForPackageObjectiveC: c.generateForPackageObjectiveC, + packingOverride: c.structPackingOverride, + libraryImports: c.libraryImports.values.toList(), + silenceEnumWarning: c.silenceEnumWarning, + nativeEntryPoints: c.entryPoints.map((uri) => uri.toFilePath()).toList(), + ); + + return library; +} + +// ============================================================================= +// BELOW FUNCTIONS ARE MEANT FOR INTERNAL USE AND TESTING +// ============================================================================= + +final _logger = Logger('ffigen.header_parser.parser'); + +/// Initializes parser, clears any previous values. +void initParser(Config c) { + // Initialize global variables. + initializeGlobals( + config: c, + ); +} + +/// Parses source files and returns the bindings. +List parseToBindings(Config c) { + final index = clang.clang_createIndex(0, 0); + + Pointer> clangCmdArgs = nullptr; + final compilerOpts = [ + // Add compiler opt for comment parsing for clang based on config. + if (config.commentType.length != CommentLength.none && + config.commentType.style == CommentStyle.any) + strings.fparseAllComments, + + // If the config targets Objective C, add a compiler opt for it. + if (config.language == Language.objc) ...[ + ...strings.clangLangObjC, + ..._findObjectiveCSysroot(), + ], + + // Add the user options last so they can override any other options. + ...config.compilerOpts + ]; + + _logger.fine('CompilerOpts used: $compilerOpts'); + clangCmdArgs = createDynamicStringArray(compilerOpts); + final cmdLen = compilerOpts.length; + + // Contains all bindings. A set ensures we never have duplicates. + final bindings = {}; + + // Log all headers for user. + _logger.info('Input Headers: ${config.entryPoints}'); + + // TODO: for some reason it can't add to a List of pointers + var tuList = []; + + // Parse all translation units from entry points. + for (final headerLocationUri in config.entryPoints) { + final headerLocation = headerLocationUri.toFilePath(); + _logger.fine('Creating TranslationUnit for header: $headerLocation'); + + final tu = clang.clang_parseTranslationUnit( + index, + headerLocation.toNativeUint8().cast(), + clangCmdArgs.cast(), + cmdLen, + nullptr, + 0, + clang_types.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies | + clang_types.CXTranslationUnit_Flags + .CXTranslationUnit_DetailedPreprocessingRecord | + clang_types + .CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, + ); + + if (tu == nullptr) { + _logger.severe( + "Skipped header/file: $headerLocation, couldn't parse source."); + // Skip parsing this header. + continue; + } + + logTuDiagnostics(tu, _logger, headerLocation); + tuList.add(tu.address); + } + + if (hasSourceErrors) { + _logger.warning('The compiler found warnings/errors in source files.'); + _logger.warning('This will likely generate invalid bindings.'); + if (config.ignoreSourceErrors) { + _logger.warning( + 'Ignored source errors. (User supplied --ignore-source-errors)'); + } else if (config.language == Language.objc) { + _logger.warning('Ignored source errors. (ObjC)'); + } else { + _logger.severe( + 'Skipped generating bindings due to errors in source files. See https://github.com/dart-lang/native/blob/main/pkgs/ffigen/doc/errors.md.'); + // return empty bindings instead of exiting + return []; + // exit(1); + } + } + + final tuCursors = tuList.map( + (tu) => clang.clang_getTranslationUnitCursor(Pointer.fromAddress(tu))); + + // Build usr to CXCusror map from translation units. + for (final rootCursor in tuCursors) { + buildUsrCursorDefinitionMap(rootCursor); + } + + // Parse definitions from translation units. + for (final rootCursor in tuCursors) { + bindings.addAll(parseTranslationUnit(rootCursor)); + } + + // Dispose translation units. + for (final tu in tuList) { + clang.clang_disposeTranslationUnit(Pointer.fromAddress(tu)); + } + + // Add all saved unnamed enums. + bindings.addAll(unnamedEnumConstants); + + // Parse all saved macros. + bindings.addAll(parseSavedMacros()); + + clangCmdArgs.dispose(cmdLen); + clang.clang_disposeIndex(index); + return bindings.toList(); +} + +List _findObjectiveCSysroot() { + // final result = Process.runSync('xcrun', ['--show-sdk-path']); + // if (result.exitCode == 0) { + // for (final line in (result.stdout as String).split('\n')) { + // if (line.isNotEmpty) { + // return ['-isysroot', line]; + // } + // } + // } + return []; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/compounddecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/compounddecl_parser.dart new file mode 100644 index 0000000000..b08eb2829d --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/compounddecl_parser.dart @@ -0,0 +1,329 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config.dart'; +import '../../config_provider/config_types.dart'; +import '../../strings.dart' as strings; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.compounddecl_parser'); + +/// Holds temporary information regarding [compound] while parsing. +class _ParsedCompound { + Compound compound; + bool unimplementedMemberType = false; + bool flexibleArrayMember = false; + bool bitFieldMember = false; + bool dartHandleMember = false; + bool incompleteCompoundMember = false; + + _ParsedCompound(this.compound); + + bool get isIncomplete => + unimplementedMemberType || + flexibleArrayMember || + bitFieldMember || + (dartHandleMember && config.useDartHandle) || + incompleteCompoundMember || + alignment == clang_types.CXTypeLayoutError.CXTypeLayoutError_Incomplete; + + // A struct without any attribute is definitely not packed. #pragma pack(...) + // also adds an attribute, but it's unexposed and cannot be travesed. + bool hasAttr = false; + + // A struct which as a __packed__ attribute is definitely packed. + bool hasPackedAttr = false; + + // Stores the maximum alignment from all the children. + int maxChildAlignment = 0; + + // Alignment of this struct. + int alignment = 0; + + bool get _isPacked { + if (!hasAttr || isIncomplete) return false; + if (hasPackedAttr) return true; + + return maxChildAlignment > alignment; + } + + /// Returns pack value of a struct depending on config, returns null for no + /// packing. + int? get packValue { + if (compound.isStruct && _isPacked && !isIncomplete) { + if (strings.packingValuesMap.containsKey(alignment)) { + return alignment; + } else { + _logger.warning('Unsupported pack value "$alignment" for Struct ' + '"${compound.name}".'); + return null; + } + } else { + return null; + } + } +} + +/// Parses a compound declaration. +Compound? parseCompoundDeclaration( + clang_types.CXCursor cursor, + CompoundType compoundType, { + /// Option to ignore declaration filter (Useful in case of extracting + /// declarations when they are passed/returned by an included function.) + bool ignoreFilter = false, + + /// To track if the declaration was used by reference(i.e T*). (Used to only + /// generate these as opaque if `dependency-only` was set to opaque). + bool pointerReference = false, +}) { + // Set includer functions according to compoundType. + final bool Function(Declaration) shouldIncludeDecl; + final DeclarationFilters configDecl; + final className = _compoundTypeDebugName(compoundType); + switch (compoundType) { + case CompoundType.struct: + shouldIncludeDecl = shouldIncludeStruct; + configDecl = config.structDecl; + break; + case CompoundType.union: + shouldIncludeDecl = shouldIncludeUnion; + configDecl = config.unionDecl; + break; + } + + // Parse the cursor definition instead, if this is a forward declaration. + final declUsr = cursor.usr(); + final String declName; + + // Only set name using USR if the type is not Anonymous (A struct is anonymous + // if it has no name, is not inside any typedef and declared inline inside + // another declaration). + if (clang.clang_Cursor_isAnonymous(cursor) == 0) { + // This gives the significant name, i.e name of the struct if defined or + // name of the first typedef declaration that refers to it. + declName = declUsr.split('@').last; + } else { + // Empty names are treated as inline declarations. + declName = ''; + } + + final decl = Declaration(usr: declUsr, originalName: declName); + if (declName.isEmpty) { + if (ignoreFilter) { + cursor = cursorIndex.getDefinition(cursor); + // This declaration is defined inside some other declaration and hence + // must be generated. + return Compound.fromType( + type: compoundType, + name: incrementalNamer.name('Unnamed$className'), + usr: declUsr, + dartDoc: getCursorDocComment(cursor), + objCBuiltInFunctions: objCBuiltInFunctions, + nativeType: cursor.type().spelling(), + ); + } else { + _logger.finest('unnamed $className declaration'); + } + } else if (ignoreFilter || shouldIncludeDecl(decl)) { + cursor = cursorIndex.getDefinition(cursor); + _logger.fine('++++ Adding $className: Name: $declName, ' + '${cursor.completeStringRepr()}'); + return Compound.fromType( + type: compoundType, + usr: declUsr, + originalName: declName, + name: configDecl.rename(decl), + dartDoc: getCursorDocComment(cursor), + objCBuiltInFunctions: objCBuiltInFunctions, + nativeType: cursor.type().spelling(), + ); + } + return null; +} + +void fillCompoundMembersIfNeeded( + Compound compound, + clang_types.CXCursor cursor, { + /// Option to ignore declaration filter (Useful in case of extracting + /// declarations when they are passed/returned by an included function.) + bool ignoreFilter = false, + + /// To track if the declaration was used by reference(i.e T*). (Used to only + /// generate these as opaque if `dependency-only` was set to opaque). + bool pointerReference = false, +}) { + final compoundType = compound.compoundType; + + // Skip dependencies if already seen OR user has specified `dependency-only` + // as opaque AND this is a pointer reference AND the declaration was not + // included according to config (ignoreFilter). + final skipDependencies = compound.parsedDependencies || + (pointerReference && + ignoreFilter && + ((compoundType == CompoundType.struct && + config.structDependencies == CompoundDependencies.opaque) || + (compoundType == CompoundType.union && + config.unionDependencies == CompoundDependencies.opaque))); + if (skipDependencies) return; + cursor = cursorIndex.getDefinition(cursor); + + final parsed = _ParsedCompound(compound); + final className = _compoundTypeDebugName(compoundType); + parsed.hasAttr = clang.clang_Cursor_hasAttrs(cursor) != 0; + parsed.alignment = cursor.type().alignment(); + compound.parsedDependencies = true; // Break cycles. + + cursor.visitChildren((cursor) => _compoundMembersVisitor(cursor, parsed)); + + _logger.finest('Opaque: ${parsed.isIncomplete}, HasAttr: ${parsed.hasAttr}, ' + 'AlignValue: ${parsed.alignment}, ' + 'MaxChildAlignValue: ${parsed.maxChildAlignment}, ' + 'PackValue: ${parsed.packValue}.'); + compound.pack = parsed.packValue; + + if (parsed.unimplementedMemberType) { + _logger.fine('---- Removed $className members, reason: member with ' + 'unimplementedtype ${cursor.completeStringRepr()}'); + _logger.warning('Removed All $className Members from ${compound.name}' + '(${compound.originalName}), struct member has an unsupported type.'); + } else if (parsed.flexibleArrayMember) { + _logger.fine('---- Removed $className members, reason: incomplete array ' + 'member ${cursor.completeStringRepr()}'); + _logger.warning('Removed All $className Members from ${compound.name}' + '(${compound.originalName}), Flexible array members not supported.'); + } else if (parsed.bitFieldMember) { + _logger.fine('---- Removed $className members, reason: bitfield members ' + '${cursor.completeStringRepr()}'); + _logger.warning('Removed All $className Members from ${compound.name}' + '(${compound.originalName}), Bit Field members not supported.'); + } else if (parsed.dartHandleMember && config.useDartHandle) { + _logger.fine('---- Removed $className members, reason: Dart_Handle member. ' + '${cursor.completeStringRepr()}'); + _logger.warning('Removed All $className Members from ${compound.name}' + '(${compound.originalName}), Dart_Handle member not supported.'); + } else if (parsed.incompleteCompoundMember) { + _logger.fine( + '---- Removed $className members, reason: Incomplete Nested Struct ' + 'member. ${cursor.completeStringRepr()}'); + _logger.warning('Removed All $className Members from ${compound.name}' + '(${compound.originalName}), Incomplete Nested Struct member not ' + 'supported.'); + } + + // Clear all members if declaration is incomplete. + if (parsed.isIncomplete) { + compound.members.clear(); + } + + // C allows empty structs/union, but it's undefined behaviour at runtine. + // So we need to mark a declaration incomplete if it has no members. + compound.isIncomplete = parsed.isIncomplete || compound.members.isEmpty; +} + +/// Visitor for the struct/union cursor +/// [clang_types.CXCursorKind.CXCursor_StructDecl]/ +/// [clang_types.CXCursorKind.CXCursor_UnionDecl]. +/// +/// Child visitor invoked on struct/union cursor. +void _compoundMembersVisitor( + clang_types.CXCursor cursor, _ParsedCompound parsed) { + final decl = Declaration( + usr: parsed.compound.usr, + originalName: parsed.compound.originalName, + ); + try { + switch (cursor.kind) { + case clang_types.CXCursorKind.CXCursor_FieldDecl: + _logger.finer('===== member: ${cursor.completeStringRepr()}'); + + // Set maxChildAlignValue. + final align = cursor.type().alignment(); + if (align > parsed.maxChildAlignment) { + parsed.maxChildAlignment = align; + } + + final mt = cursor.toCodeGenType(); + if (mt is IncompleteArray) { + // TODO(https://github.com/dart-lang/ffigen/issues/68): Structs with + // flexible Array Members are not supported. + parsed.flexibleArrayMember = true; + } + if (clang.clang_getFieldDeclBitWidth(cursor) != -1) { + // TODO(https://github.com/dart-lang/ffigen/issues/84): Struct with + // bitfields are not suppoorted. + parsed.bitFieldMember = true; + } + if (mt is HandleType) { + parsed.dartHandleMember = true; + } + if (mt.isIncompleteCompound) { + parsed.incompleteCompoundMember = true; + } + if (mt.baseType is UnimplementedType) { + parsed.unimplementedMemberType = true; + } + parsed.compound.members.add( + Member( + dartDoc: getCursorDocComment( + cursor, + nesting.length + commentPrefix.length, + ), + originalName: cursor.spelling(), + name: config.structDecl.renameMember(decl, cursor.spelling()), + type: mt, + ), + ); + + break; + + case clang_types.CXCursorKind.CXCursor_PackedAttr: + parsed.hasPackedAttr = true; + + break; + case clang_types.CXCursorKind.CXCursor_UnionDecl: + case clang_types.CXCursorKind.CXCursor_StructDecl: + // If the union/struct are anonymous, then we need to add them now, + // otherwise they will be added in the next iteration. + if (!cursor.isAnonymousRecordDecl()) break; + + final mt = cursor.toCodeGenType(); + if (mt.isIncompleteCompound) { + parsed.incompleteCompoundMember = true; + } + + // Anonymous members are always unnamed. To avoid environment- + // dependent naming issues with the generated code, we explicitly + // use the empty string as spelling. + final spelling = ''; + + parsed.compound.members.add( + Member( + dartDoc: getCursorDocComment( + cursor, + nesting.length + commentPrefix.length, + ), + originalName: spelling, + name: config.structDecl.renameMember(decl, spelling), + type: mt, + ), + ); + + break; + } + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } +} + +String _compoundTypeDebugName(CompoundType compoundType) { + return compoundType == CompoundType.struct ? 'Struct' : 'Union'; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/enumdecl_parser.dart new file mode 100644 index 0000000000..e155d1ab8f --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/enumdecl_parser.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../type_extractor/cxtypekindmap.dart'; +import '../utils.dart'; +import 'unnamed_enumdecl_parser.dart'; + +final _logger = Logger('ffigen.header_parser.enumdecl_parser'); + +/// Parses an enum declaration. Returns (enumClass, nativeType). enumClass +/// is null for anonymous enums. +(EnumClass? enumClass, Type nativeType) parseEnumDeclaration( + clang_types.CXCursor cursor, { + /// Option to ignore declaration filter (Useful in case of extracting + /// declarations when they are passed/returned by an included function.) + bool ignoreFilter = false, +}) { + EnumClass? enumClass; + // Parse the cursor definition instead, if this is a forward declaration. + cursor = cursorIndex.getDefinition(cursor); + + final enumUsr = cursor.usr(); + final String enumName; + // Only set name using USR if the type is not Anonymous (i.e not inside + // any typedef and declared inplace inside another type). + if (clang.clang_Cursor_isAnonymous(cursor) == 0) { + // This gives the significant name, i.e name of the enum if defined or + // name of the first typedef declaration that refers to it. + enumName = enumUsr.split('@').last; + } else { + enumName = ''; + } + var nativeType = clang.clang_getEnumDeclIntegerType(cursor).toCodeGenType(); + // Change to unsigned type by default. + nativeType = signedToUnsignedNativeIntType[nativeType] ?? nativeType; + var hasNegativeEnumConstants = false; + + final decl = Declaration(usr: enumUsr, originalName: enumName); + if (enumName.isEmpty) { + _logger.fine('Saving anonymous enum.'); + final addedConstants = saveUnNamedEnum(cursor); + hasNegativeEnumConstants = + addedConstants.where((c) => c.rawValue.startsWith('-')).isNotEmpty; + } else if (ignoreFilter || shouldIncludeEnumClass(decl)) { + _logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}'); + enumClass = EnumClass( + usr: enumUsr, + dartDoc: getCursorDocComment(cursor), + originalName: enumName, + name: config.enumClassDecl.rename(decl), + nativeType: nativeType, + generateAsInt: config.enumShouldBeInt(decl), + objCBuiltInFunctions: objCBuiltInFunctions, + ); + cursor.visitChildren((clang_types.CXCursor child) { + try { + _logger.finest(' enumCursorVisitor: ${child.completeStringRepr()}'); + switch (clang.clang_getCursorKind(child)) { + case clang_types.CXCursorKind.CXCursor_EnumConstantDecl: + final enumIntValue = clang.clang_getEnumConstantDeclValue(child); + enumClass!.enumConstants.add( + EnumConstant( + dartDoc: getCursorDocComment( + child, + nesting.length + commentPrefix.length, + ), + originalName: child.spelling(), + name: config.enumClassDecl.renameMember( + decl, + child.spelling(), + ), + value: enumIntValue), + ); + if (enumIntValue < 0) { + hasNegativeEnumConstants = true; + } + break; + case clang_types.CXCursorKind.CXCursor_UnexposedAttr: + // Ignore. + break; + default: + _logger.fine('invalid enum constant'); + } + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } + }); + } + + if (hasNegativeEnumConstants) { + // Change enum native type to signed type. + _logger.fine('For enum $enumUsr - using signed type for $nativeType : ' + '${unsignedToSignedNativeIntType[nativeType]}'); + nativeType = unsignedToSignedNativeIntType[nativeType] ?? nativeType; + enumClass?.nativeType = nativeType; + } + + return (enumClass, nativeType); +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/function_type_param_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/function_type_param_parser.dart new file mode 100644 index 0000000000..a1c53c6406 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/function_type_param_parser.dart @@ -0,0 +1,39 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../clang_bindings/clang_types.dart'; +import '../utils.dart'; + +/// This type holds the list of `ParmDecl` nodes of a function type declaration. +class FunctionTypeParams { + final List paramNames; + final Map params; + FunctionTypeParams() + : paramNames = [], + params = {}; +} + +/// Returns `ParmDecl` nodes of function pointer declaration +/// directly or indirectly pointed to by [cursor]. +FunctionTypeParams parseFunctionPointerParamNames(CXCursor cursor) { + final params = FunctionTypeParams(); + cursor.visitChildrenMayRecurse((child, parent) { + if (child.kind == CXCursorKind.CXCursor_ParmDecl) { + final spelling = child.spelling(); + if (spelling.isNotEmpty) { + params.paramNames.add(spelling); + params.params[spelling] = child; + return CXChildVisitResult.CXChildVisit_Continue; + } else { + // A parameter's spelling is empty, do not continue further traversal. + params.paramNames.clear(); + params.params.clear(); + return CXChildVisitResult.CXChildVisit_Break; + } + } + // The cursor itself may be a pointer etc.. + return CXChildVisitResult.CXChildVisit_Recurse; + }); + return params; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/functiondecl_parser.dart new file mode 100644 index 0000000000..517247aed2 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/functiondecl_parser.dart @@ -0,0 +1,133 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.functiondecl_parser'); + +/// Parses a function declaration. +List? parseFunctionDeclaration(clang_types.CXCursor cursor) { + /// Multiple values are since there may be more than one instance of the + /// same base C function with different variadic arguments. + final funcs = []; + + final funcUsr = cursor.usr(); + final funcName = cursor.spelling(); + final decl = Declaration(usr: funcUsr, originalName: funcName); + if (shouldIncludeFunc(decl)) { + _logger.fine('++++ Adding Function: ${cursor.completeStringRepr()}'); + + final returnType = cursor.returnType().toCodeGenType(); + + final parameters = []; + var incompleteStructParameter = false; + var unimplementedParameterType = false; + final totalArgs = clang.clang_Cursor_getNumArguments(cursor); + for (var i = 0; i < totalArgs; i++) { + final paramCursor = clang.clang_Cursor_getArgument(cursor, i); + + _logger.finer('===== parameter: ${paramCursor.completeStringRepr()}'); + + final paramType = paramCursor.toCodeGenType(); + if (paramType.isIncompleteCompound) { + incompleteStructParameter = true; + } else if (paramType.baseType is UnimplementedType) { + _logger.finer('Unimplemented type: ${paramType.baseType}'); + unimplementedParameterType = true; + } + + final paramName = paramCursor.spelling(); + + /// If [paramName] is null or empty, its set to `arg$i` by code_generator. + parameters.add( + Parameter( + originalName: paramName, + name: config.functionDecl.renameMember(decl, paramName), + type: paramType, + ), + ); + } + + if (clang.clang_Cursor_isFunctionInlined(cursor) != 0 && + clang.clang_Cursor_getStorageClass(cursor) != + clang_types.CX_StorageClass.CX_SC_Extern) { + _logger.fine('---- Removed Function, reason: inline function: ' + '${cursor.completeStringRepr()}'); + _logger.warning( + "Skipped Function '$funcName', inline functions are not supported."); + // Returning empty so that [addToBindings] function excludes this. + return funcs; + } + + if (returnType.isIncompleteCompound || incompleteStructParameter) { + _logger.fine( + '---- Removed Function, reason: Incomplete struct pass/return by ' + 'value: ${cursor.completeStringRepr()}'); + _logger.warning( + "Skipped Function '$funcName', Incomplete struct pass/return by " + 'value not supported.'); + // Returning null so that [addToBindings] function excludes this. + return funcs; + } + + if (returnType.baseType is UnimplementedType || + unimplementedParameterType) { + _logger.fine('---- Removed Function, reason: unsupported return type or ' + 'parameter type: ${cursor.completeStringRepr()}'); + _logger.warning( + "Skipped Function '$funcName', function has unsupported return type " + 'or parameter type.'); + // Returning null so that [addToBindings] function excludes this. + return funcs; + } + + // Look for any annotations on the function. + final objCReturnsRetained = cursor + .hasChildWithKind(clang_types.CXCursorKind.CXCursor_NSReturnsRetained); + + // Initialized with a single value with no prefix and empty var args. + var varArgFunctions = [VarArgFunction('', [])]; + if (config.varArgFunctions.containsKey(funcName)) { + if (clang.clang_isFunctionTypeVariadic(cursor.type()) == 1) { + varArgFunctions = config.varArgFunctions[funcName]!; + } else { + _logger.warning('Skipping variadic-argument config for function ' + "'$funcName' since its not variadic."); + } + } + for (final vaFunc in varArgFunctions) { + funcs.add(Func( + dartDoc: getCursorDocComment( + cursor, + nesting.length + commentPrefix.length, + ), + usr: funcUsr + vaFunc.postfix, + name: config.functionDecl.rename(decl) + vaFunc.postfix, + originalName: funcName, + returnType: returnType, + parameters: parameters, + varArgParameters: + vaFunc.types.map((ta) => Parameter(type: ta, name: 'va')).toList(), + exposeSymbolAddress: + config.functionDecl.shouldIncludeSymbolAddress(decl), + exposeFunctionTypedefs: config.shouldExposeFunctionTypedef(decl), + isLeaf: config.isLeafFunction(decl), + objCReturnsRetained: objCReturnsRetained, + ffiNativeConfig: config.ffiNativeConfig, + )); + } + bindingsIndex.addFuncToSeen(funcUsr, funcs.last); + } else if (bindingsIndex.isSeenFunc(funcUsr)) { + funcs.add(bindingsIndex.getSeenFunc(funcUsr)!); + } + + return funcs; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/macro_parser.dart new file mode 100644 index 0000000000..c2940dedd6 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/macro_parser.dart @@ -0,0 +1,325 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as p; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../../strings.dart' as strings; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.macro_parser'); + +/// Adds a macro definition to be parsed later. +void saveMacroDefinition(clang_types.CXCursor cursor) { + final macroUsr = cursor.usr(); + final originalMacroName = cursor.spelling(); + final decl = Declaration(usr: macroUsr, originalName: originalMacroName); + if (clang.clang_Cursor_isMacroBuiltin(cursor) == 0 && + clang.clang_Cursor_isMacroFunctionLike(cursor) == 0 && + shouldIncludeMacro(decl)) { + // Parse macro only if it's not builtin or function-like. + _logger.fine("++++ Saved Macro '$originalMacroName' for later : " + '${cursor.completeStringRepr()}'); + final prefixedName = config.macroDecl.rename(decl); + bindingsIndex.addMacroToSeen(macroUsr, prefixedName); + _saveMacro(prefixedName, macroUsr, originalMacroName); + } +} + +/// Saves a macro to be parsed later. +/// +/// Macros are parsed later in [parseSavedMacros()]. +void _saveMacro(String name, String usr, String originalName) { + savedMacros[name] = Macro(usr, originalName); +} + +/// Macros cannot be parsed directly, so we create a new `.hpp` file in which +/// they are assigned to a variable after which their value can be determined +/// by evaluating the value of the variable. +List parseSavedMacros() { + final bindings = []; + + if (savedMacros.keys.isEmpty) { + return bindings; + } + + // Create a file for parsing macros; + final file = createFileForMacros(); + + final index = clang.clang_createIndex(0, 0); + Pointer> clangCmdArgs = nullptr; + var cmdLen = 0; + + final compilerOpts = config.compilerOpts; + clangCmdArgs = createDynamicStringArray(compilerOpts); + + cmdLen = config.compilerOpts.length; + final tu = clang.clang_parseTranslationUnit( + index, + file.path.toNativeUint8().cast(), + clangCmdArgs.cast(), + cmdLen, + nullptr, + 0, + clang_types.CXTranslationUnit_Flags.CXTranslationUnit_KeepGoing, + ); + + if (tu == nullptr) { + _logger.severe('Unable to parse Macros.'); + } else { + logTuDiagnostics(tu, _logger, file.path, logLevel: Level.FINEST); + final rootCursor = clang.clang_getTranslationUnitCursor(tu); + rootCursor.visitChildren((child) => _macroVariablevisitor(child, bindings)); + } + + clang.clang_disposeTranslationUnit(tu); + clang.clang_disposeIndex(index); + // Delete the temp file created for macros. + file.deleteSync(); + + return bindings; +} + +/// Child visitor invoked on translationUnitCursor for parsing macroVariables. +void _macroVariablevisitor( + clang_types.CXCursor cursor, List bindings) { + Constant? constant; + try { + if (isFromGeneratedFile(cursor) && + _macroVarNames.contains(cursor.spelling()) && + cursor.kind == clang_types.CXCursorKind.CXCursor_VarDecl) { + final e = clang.clang_Cursor_Evaluate(cursor); + final k = clang.clang_EvalResult_getKind(e); + _logger.fine('macroVariablevisitor: ${cursor.completeStringRepr()}'); + + /// Get macro name, the variable name starts with '_'. + final macroName = MacroVariableString.decode(cursor.spelling()); + switch (k) { + case clang_types.CXEvalResultKind.CXEval_Int: + constant = Constant( + usr: savedMacros[macroName]!.usr, + originalName: savedMacros[macroName]!.originalName, + name: macroName, + rawType: 'int', + rawValue: clang.clang_EvalResult_getAsLongLong(e).toString(), + ); + break; + case clang_types.CXEvalResultKind.CXEval_Float: + constant = Constant( + usr: savedMacros[macroName]!.usr, + originalName: savedMacros[macroName]!.originalName, + name: macroName, + rawType: 'double', + rawValue: + _writeDoubleAsString(clang.clang_EvalResult_getAsDouble(e)), + ); + break; + case clang_types.CXEvalResultKind.CXEval_StrLiteral: + final rawValue = _getWrittenRepresentation( + macroName, + clang.clang_EvalResult_getAsStr(e), + ); + constant = Constant( + usr: savedMacros[macroName]!.usr, + originalName: savedMacros[macroName]!.originalName, + name: macroName, + rawType: 'String', + rawValue: "'$rawValue'", + ); + break; + } + clang.clang_EvalResult_dispose(e); + + if (constant != null) { + bindings.add(constant); + } + } + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } +} + +/// Returns true if cursor is from generated file. +bool isFromGeneratedFile(clang_types.CXCursor cursor) { + final s = cursor.sourceFileName(); + return p.basename(s) == _generatedFileBaseName; +} + +/// Base name of generated file. +String? _generatedFileBaseName; + +/// Generated macro variable names. +/// +/// Used to determine if macro should be included in bindings or not. +late Set _macroVarNames; + +/// Creates a temporary file for parsing macros in current directory. +File createFileForMacros() { + final fileNameBase = p.join(strings.tmpDir, 'temp_for_macros'); + final fileExt = 'hpp'; + + // Find a filename which doesn't already exist. + var file = File('$fileNameBase.$fileExt'); + var i = 0; + while (file.existsSync()) { + i++; + file = File('${fileNameBase}_$i.$fileExt'); + } + + // Create file. + file.createSync(); + + // Save generated name. + _generatedFileBaseName = p.basename(file.path); + + // Write file contents. + final sb = StringBuffer(); + for (final h in config.entryPoints) { + final fullHeaderPath = File(h.toFilePath()).absolute.path; + sb.writeln('#include "$fullHeaderPath"'); + } + + _macroVarNames = {}; + for (final prefixedMacroName in savedMacros.keys) { + // Write macro. + final macroVarName = MacroVariableString.encode(prefixedMacroName); + sb.writeln('auto $macroVarName = ' + '${savedMacros[prefixedMacroName]!.originalName};'); + // Add to _macroVarNames. + _macroVarNames.add(macroVarName); + } + final macroFileContent = sb.toString(); + // Log this generated file for debugging purpose. + // We use the finest log because this file may be very big. + _logger.finest('=====FILE FOR MACROS===='); + _logger.finest(macroFileContent); + _logger.finest('========================'); + + file.writeAsStringSync(macroFileContent); + return file; +} + +/// Deals with encoding/decoding name of the variable generated for a Macro. +class MacroVariableString { + static String encode(String s) { + return '_${s.length}_${s}_generated_macro_variable'; + } + + static String decode(String s) { + // Remove underscore. + s = s.substring(1); + final intReg = RegExp('[0-9]+'); + final lengthEnd = intReg.matchAsPrefix(s)!.end; + final len = int.parse(s.substring(0, lengthEnd)); + + // Name starts after an unerscore. + final nameStart = lengthEnd + 1; + return s.substring(nameStart, nameStart + len); + } +} + +/// Gets a written representation string of a C string. +/// +/// E.g- For a string "Hello\nWorld", The new line character is converted to \n. +/// Note: The string is considered to be Utf8, but is treated as Extended ASCII, +/// if the conversion fails. +String _getWrittenRepresentation(String macroName, Pointer strPtr) { + final sb = StringBuffer(); + try { + // Consider string to be Utf8 encoded by default. + sb.clear(); + // This throws a Format Exception if string isn't Utf8 so that we handle it + // in the catch block. + final result = strPtr.cast().toDartString(); + for (final s in result.runes) { + sb.write(_getWritableChar(s)); + } + } catch (e) { + // Handle string if it isn't Utf8. String is considered to be + // Extended ASCII in this case. + _logger.warning("Couldn't decode Macro string '$macroName' as Utf8, using " + 'ASCII instead.'); + sb.clear(); + // final length = strPtr.cast().length; + final charList = strPtr.toCharList(); + + for (final char in charList) { + sb.write(_getWritableChar(char, utf8: false)); + } + } + + return sb.toString(); +} + +/// Creates a writable char from [char] code. +/// +/// E.g- `\` is converted to `\\`. +String _getWritableChar(int char, {bool utf8 = true}) { + /// Handle control characters. + if (char >= 0 && char < 32 || char == 127) { + /// Handle these - `\b \t \n \v \f \r` as special cases. + switch (char) { + case 8: // \b + return r'\b'; + case 9: // \t + return r'\t'; + case 10: // \n + return r'\n'; + case 11: // \v + return r'\v'; + case 12: // \f + return r'\f'; + case 13: // \r + return r'\r'; + default: + final h = char.toRadixString(16).toUpperCase().padLeft(2, '0'); + return '\\x$h'; + } + } + + /// Handle characters - `$ ' \` these need to be escaped when writing to file. + switch (char) { + case 36: // $ + return r'\$'; + case 39: // ' + return r"\'"; + case 92: // \ + return r'\\'; + } + + /// In case encoding is not Utf8, we know all characters will fall in [0..255] + /// Print range [128..255] as `\xHH`. + if (!utf8) { + final h = char.toRadixString(16).toUpperCase().padLeft(2, '0'); + return '\\x$h'; + } + + /// In all other cases, simply convert to string. + return String.fromCharCode(char); +} + +/// Converts a double to a string, handling cases like Infinity and NaN. +String _writeDoubleAsString(double d) { + if (d.isFinite) { + return d.toString(); + } else { + // The only Non-Finite numbers are Infinity, NegativeInfinity and NaN. + if (d.isInfinite) { + return d.isNegative + ? strings.doubleNegativeInfinity + : strings.doubleInfinity; + } + return strings.doubleNaN; + } +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objc_block_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objc_block_parser.dart new file mode 100644 index 0000000000..b3ddaa4a5a --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objc_block_parser.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../../code_generator.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../utils.dart'; + +ObjCBlock parseObjCBlock(clang_types.CXType cxtype) { + final blk = clang.clang_getPointeeType(cxtype); + final returnType = clang.clang_getResultType(blk).toCodeGenType(); + final argTypes = []; + final numArgs = clang.clang_getNumArgTypes(blk); + for (var i = 0; i < numArgs; ++i) { + argTypes.add(clang.clang_getArgType(blk, i).toCodeGenType()); + } + return ObjCBlock( + returnType: returnType, + argTypes: argTypes, + ); +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart new file mode 100644 index 0000000000..6a59c1e462 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart @@ -0,0 +1,260 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.objcinterfacedecl_parser'); + +String applyModulePrefix(String name, String? module) => + module == null ? name : '$module.$name'; + +Type? parseObjCInterfaceDeclaration( + clang_types.CXCursor cursor, { + /// Option to ignore declaration filter (Useful in case of extracting + /// declarations when they are passed/returned by an included function.) + bool ignoreFilter = false, +}) { + final itfUsr = cursor.usr(); + final itfName = cursor.spelling(); + final decl = Declaration(usr: itfUsr, originalName: itfName); + if (!ignoreFilter && !shouldIncludeObjCInterface(decl)) { + return null; + } + + _logger.fine('++++ Adding ObjC interface: ' + 'Name: $itfName, ${cursor.completeStringRepr()}'); + + return ObjCInterface( + usr: itfUsr, + originalName: itfName, + name: config.objcInterfaces.rename(decl), + lookupName: applyModulePrefix(itfName, config.interfaceModule(decl)), + dartDoc: getCursorDocComment(cursor), + builtInFunctions: objCBuiltInFunctions, + ); +} + +void fillObjCInterfaceMethodsIfNeeded( + ObjCInterface itf, clang_types.CXCursor cursor) { + if (_isClassDeclaration(cursor)) { + // @class declarations are ObjC's way of forward declaring classes. In that + // case there's nothing to fill yet. + return; + } + + if (itf.filled) return; + itf.filled = true; // Break cycles. + + _logger.fine('++++ Filling ObjC interface: ' + 'Name: ${itf.originalName}, ${cursor.completeStringRepr()}'); + + _fillInterface(itf, cursor); + + _logger.fine('++++ Finished ObjC interface: ' + 'Name: ${itf.originalName}, ${cursor.completeStringRepr()}'); +} + +void _fillInterface(ObjCInterface itf, clang_types.CXCursor cursor) { + cursor.visitChildren((child) { + switch (child.kind) { + case clang_types.CXCursorKind.CXCursor_ObjCSuperClassRef: + _parseSuperType(child, itf); + break; + case clang_types.CXCursorKind.CXCursor_ObjCPropertyDecl: + _parseProperty(child, itf); + break; + case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl: + case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl: + _parseInterfaceMethod(child, itf); + break; + } + }); +} + +bool _isClassDeclaration(clang_types.CXCursor cursor) { + // It's a class declaration if it has no children other than ObjCClassRef. + var result = true; + cursor.visitChildrenMayBreak((child) { + if (child.kind == clang_types.CXCursorKind.CXCursor_ObjCClassRef) { + return true; + } + result = false; + return false; + }); + return result; +} + +void _parseSuperType(clang_types.CXCursor cursor, ObjCInterface itf) { + final superType = cursor.type().toCodeGenType(); + _logger.fine(' > Super type: ' + '$superType ${cursor.completeStringRepr()}'); + if (superType is ObjCInterface) { + itf.superType = superType; + } else { + _logger.severe( + 'Super type of $itf is $superType, which is not a valid interface.'); + } +} + +void _parseProperty(clang_types.CXCursor cursor, ObjCInterface itf) { + final fieldName = cursor.spelling(); + final fieldType = cursor.type().toCodeGenType(); + + if (fieldType.isIncompleteCompound) { + _logger.warning('Property "$fieldName" in instance "${itf.originalName}" ' + 'has incomplete type: $fieldType.'); + return; + } + + final dartDoc = getCursorDocComment(cursor); + + final propertyAttributes = + clang.clang_Cursor_getObjCPropertyAttributes(cursor, 0); + final isClassMethod = propertyAttributes & + clang_types.CXObjCPropertyAttrKind.CXObjCPropertyAttr_class > + 0; + final isReadOnly = propertyAttributes & + clang_types.CXObjCPropertyAttrKind.CXObjCPropertyAttr_readonly > + 0; + final isOptionalMethod = clang.clang_Cursor_isObjCOptional(cursor) != 0; + + final property = ObjCProperty(fieldName); + + _logger.fine(' > Property: ' + '$fieldType $fieldName ${cursor.completeStringRepr()}'); + + final getterName = + clang.clang_Cursor_getObjCPropertyGetterName(cursor).toStringAndDispose(); + final getter = ObjCMethod( + originalName: getterName, + property: property, + dartDoc: dartDoc, + kind: ObjCMethodKind.propertyGetter, + isClassMethod: isClassMethod, + isOptional: isOptionalMethod, + returnType: fieldType, + ); + itf.addMethod(getter); + + if (!isReadOnly) { + final setterName = clang + .clang_Cursor_getObjCPropertySetterName(cursor) + .toStringAndDispose(); + final setter = ObjCMethod( + originalName: setterName, + property: property, + dartDoc: dartDoc, + kind: ObjCMethodKind.propertySetter, + isClassMethod: isClassMethod, + isOptional: isOptionalMethod, + returnType: NativeType(SupportedNativeType.voidType)); + setter.params.add(ObjCMethodParam(fieldType, 'value')); + itf.addMethod(setter); + } +} + +void _parseInterfaceMethod(clang_types.CXCursor cursor, ObjCInterface itf) { + final method = parseObjCMethod(cursor, itf.originalName); + if (method != null) { + itf.addMethod(method); + } +} + +ObjCMethod? parseObjCMethod(clang_types.CXCursor cursor, String itfName) { + final methodName = cursor.spelling(); + final isClassMethod = + cursor.kind == clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl; + final isOptionalMethod = clang.clang_Cursor_isObjCOptional(cursor) != 0; + final returnType = clang.clang_getCursorResultType(cursor).toCodeGenType(); + if (returnType.isIncompleteCompound) { + _logger.warning('Method "$methodName" in instance ' + '"$itfName" has incomplete ' + 'return type: $returnType.'); + return null; + } + final method = ObjCMethod( + originalName: methodName, + dartDoc: getCursorDocComment(cursor), + kind: ObjCMethodKind.method, + isClassMethod: isClassMethod, + isOptional: isOptionalMethod, + returnType: returnType, + ); + _logger.fine(' > ${isClassMethod ? 'Class' : 'Instance'} method: ' + '${method.originalName} ${cursor.completeStringRepr()}'); + var hasError = false; + cursor.visitChildren((child) { + switch (child.kind) { + case clang_types.CXCursorKind.CXCursor_ParmDecl: + if (!_parseMethodParam(child, itfName, method)) { + hasError = true; + } + break; + case clang_types.CXCursorKind.CXCursor_NSReturnsRetained: + method.returnsRetained = true; + break; + default: + } + }); + return hasError ? null : method; +} + +bool _parseMethodParam( + clang_types.CXCursor cursor, String itfName, ObjCMethod method) { + final name = cursor.spelling(); + final type = cursor.type().toCodeGenType(); + if (type.isIncompleteCompound) { + _logger.warning('Method "${method.originalName}" in instance ' + '"$itfName" has incomplete ' + 'parameter type: $type.'); + return false; + } + _logger.fine( + ' >> Parameter: $type $name ${cursor.completeStringRepr()}'); + method.params.add(ObjCMethodParam(type, name)); + return true; +} + +BindingType? parseObjCCategoryDeclaration(clang_types.CXCursor cursor) { + // Categories add methods to an existing interface, so first we run a visitor + // to find the interface, then we fully parse that interface, then we run + // _fillInterface over the category to add its methods etc. Reusing the + // interface visitor relies on the fact that the structure of the category AST + // looks exactly the same as the interface AST, and that the category's + // interface is a different kind of node to the interface's super type (so is + // ignored by _fillInterface). + final name = cursor.spelling(); + _logger.fine('++++ Adding ObjC category: ' + 'Name: $name, ${cursor.completeStringRepr()}'); + + final itfCursor = + cursor.findChildWithKind(clang_types.CXCursorKind.CXCursor_ObjCClassRef); + if (itfCursor == null) { + _logger.severe('Category $name has no interface.'); + return null; + } + + // TODO(https://github.com/dart-lang/ffigen/issues/347): Currently any + // interface with a category bypasses the filters. + final itf = itfCursor.type().toCodeGenType(); + if (itf is! ObjCInterface) { + _logger.severe( + 'Interface of category $name is $itf, which is not a valid interface.'); + return null; + } + + _fillInterface(itf, cursor); + + _logger.fine('++++ Finished ObjC category: ' + 'Name: $name, ${cursor.completeStringRepr()}'); + + return itf; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart new file mode 100644 index 0000000000..07cfe0b78a --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; +import 'objcinterfacedecl_parser.dart'; + +final _logger = Logger('ffigen.header_parser.objcprotocoldecl_parser'); + +ObjCProtocol? parseObjCProtocolDeclaration(clang_types.CXCursor cursor, + {bool ignoreFilter = false}) { + if (cursor.kind != clang_types.CXCursorKind.CXCursor_ObjCProtocolDecl) { + return null; + } + + final usr = cursor.usr(); + final cachedProtocol = bindingsIndex.getSeenObjCProtocol(usr); + if (cachedProtocol != null) { + return cachedProtocol; + } + + final name = cursor.spelling(); + + final decl = Declaration(usr: usr, originalName: name); + if (!ignoreFilter && !shouldIncludeObjCProtocol(decl)) { + return null; + } + + _logger.fine('++++ Adding ObjC protocol: ' + 'Name: $name, ${cursor.completeStringRepr()}'); + + final protocol = ObjCProtocol( + usr: usr, + originalName: name, + name: config.objcProtocols.rename(decl), + lookupName: applyModulePrefix(name, config.protocolModule(decl)), + dartDoc: getCursorDocComment(cursor), + builtInFunctions: objCBuiltInFunctions, + ); + + // Make sure to add the protocol to the index before parsing the AST, to break + // cycles. + bindingsIndex.addObjCProtocolToSeen(usr, protocol); + + cursor.visitChildren((child) { + switch (child.kind) { + case clang_types.CXCursorKind.CXCursor_ObjCProtocolRef: + final declCursor = clang.clang_getCursorDefinition(child); + _logger.fine( + ' > Super protocol: ${declCursor.completeStringRepr()}'); + final superProtocol = + parseObjCProtocolDeclaration(declCursor, ignoreFilter: true); + if (superProtocol != null) { + protocol.superProtocols.add(superProtocol); + } + break; + case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl: + case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl: + final method = parseObjCMethod(child, name); + if (method != null) { + protocol.addMethod(method); + } + break; + } + }); + return protocol; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart new file mode 100644 index 0000000000..c137026f29 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../type_extractor/extractor.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.typedefdecl_parser'); + +/// Parses a typedef declaration. +/// +/// Notes: +/// - Pointer to Typedefs structs are skipped if the struct is seen. +/// - If there are multiple typedefs for a declaration (struct/enum), the last +/// seen name is used. +/// - Typerefs are completely ignored. +/// +/// Libclang marks them as following - +/// ```C +/// typedef struct A{ +/// int a +/// } B, *pB; // Typedef(s). +/// +/// typedef A D; // Typeref. +/// ``` +/// +/// Returns `null` if the typedef could not be generated or has been excluded +/// by the config. +Typealias? parseTypedefDeclaration( + clang_types.CXCursor cursor, { + bool pointerReference = false, +}) { + final typedefName = cursor.spelling(); + final typedefUsr = cursor.usr(); + final decl = Declaration(usr: typedefUsr, originalName: typedefName); + if (shouldIncludeTypealias(decl)) { + final ct = clang.clang_getTypedefDeclUnderlyingType(cursor); + final s = getCodeGenType(ct, + pointerReference: pointerReference, originalCursor: cursor); + + if (bindingsIndex.isSeenUnsupportedTypealias(typedefUsr)) { + // Do not process unsupported typealiases again. + } else if (s is UnimplementedType) { + _logger.fine("Skipped Typedef '$typedefName': " + 'Unimplemented type referred.'); + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + } else if (s is Compound && s.originalName == typedefName) { + // Ignore typedef if it refers to a compound with the same original name. + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + _logger.fine("Skipped Typedef '$typedefName': " + 'Name matches with referred struct/union.'); + } else if (s is EnumClass) { + // Ignore typedefs to Enum. + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + _logger.fine("Skipped Typedef '$typedefName': typedef to enum."); + } else if (s is HandleType) { + // Ignore typedefs to Handle. + _logger.fine("Skipped Typedef '$typedefName': typedef to Dart Handle."); + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + } else if (s is ConstantArray || s is IncompleteArray) { + // Ignore typedefs to Constant Array. + _logger.fine("Skipped Typedef '$typedefName': typedef to array."); + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + } else if (s is BooleanType) { + // Ignore typedefs to Boolean. + _logger.fine("Skipped Typedef '$typedefName': typedef to bool."); + bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr); + } else { + // Create typealias. + return Typealias( + usr: typedefUsr, + originalName: typedefName, + name: config.typedefs.rename(decl), + type: s, + dartDoc: getCursorDocComment(cursor), + ); + } + } + return null; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart new file mode 100644 index 0000000000..0cf3d3fd9d --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart @@ -0,0 +1,61 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser'); + +/// Saves unnamed enums. +List saveUnNamedEnum(clang_types.CXCursor cursor) { + final addedConstants = []; + cursor.visitChildren((child) { + try { + _logger + .finest(' unnamedenumCursorVisitor: ${child.completeStringRepr()}'); + switch (clang.clang_getCursorKind(child)) { + case clang_types.CXCursorKind.CXCursor_EnumConstantDecl: + if (shouldIncludeUnnamedEnumConstant( + Declaration(usr: child.usr(), originalName: child.spelling()))) { + addedConstants.add(_addUnNamedEnumConstant(child)); + } + break; + case clang_types.CXCursorKind.CXCursor_UnexposedAttr: + // Ignore. + break; + default: + _logger.severe('Invalid enum constant.'); + } + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } + }); + return addedConstants; +} + +/// Adds the parameter to func in functiondecl_parser.dart. +Constant _addUnNamedEnumConstant(clang_types.CXCursor cursor) { + _logger.fine( + '++++ Adding Constant from unnamed enum: ${cursor.completeStringRepr()}'); + final constant = Constant( + usr: cursor.usr(), + originalName: cursor.spelling(), + name: config.unnamedEnumConstants.rename( + Declaration(usr: cursor.usr(), originalName: cursor.spelling()), + ), + rawType: 'int', + rawValue: clang.clang_getEnumConstantDeclValue(cursor).toString(), + ); + bindingsIndex.addUnnamedEnumConstantToSeen(cursor.usr(), constant); + unnamedEnumConstants.add(constant); + return constant; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/var_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/var_parser.dart new file mode 100644 index 0000000000..9bc77ffa87 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/sub_parsers/var_parser.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../includer.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.var_parser'); + +/// Parses a global variable +Global? parseVarDeclaration(clang_types.CXCursor cursor) { + final name = cursor.spelling(); + final usr = cursor.usr(); + if (bindingsIndex.isSeenGlobalVar(usr)) { + return bindingsIndex.getSeenGlobalVar(usr); + } + final decl = Declaration(usr: usr, originalName: name); + if (!shouldIncludeGlobalVar(decl)) { + return null; + } + + _logger.fine('++++ Adding Global: ${cursor.completeStringRepr()}'); + + final cType = cursor.type(); + + final type = cType.toCodeGenType( + // Native fields can be arrays, but if we use the lookup based method of + // reading fields there's no way to turn a Pointer into an array. + supportNonInlineArray: config.ffiNativeConfig.enabled); + if (type.baseType is UnimplementedType) { + _logger.fine('---- Removed Global, reason: unsupported type: ' + '${cursor.completeStringRepr()}'); + _logger.warning("Skipped global variable '$name', type not supported."); + return null; + } + + final global = Global( + originalName: name, + name: config.globals.rename(decl), + usr: usr, + type: type, + dartDoc: getCursorDocComment(cursor), + exposeSymbolAddress: config.globals.shouldIncludeSymbolAddress(decl), + constant: cType.isConstQualified, + nativeConfig: config.ffiNativeConfig, + ); + bindingsIndex.addGlobalVarToSeen(usr, global); + + return global; +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/translation_unit_parser.dart b/pkgs/ffigenpad/lib/src/header_parser/translation_unit_parser.dart new file mode 100644 index 0000000000..b2f688eb97 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/translation_unit_parser.dart @@ -0,0 +1,98 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:logging/logging.dart'; + +import '../code_generator.dart'; +import 'clang_bindings/clang_types.dart' as clang_types; +import 'data.dart'; +import 'includer.dart'; +import 'sub_parsers/functiondecl_parser.dart'; +import 'sub_parsers/macro_parser.dart'; +import 'sub_parsers/objcinterfacedecl_parser.dart'; +import 'sub_parsers/objcprotocoldecl_parser.dart'; +import 'sub_parsers/typedefdecl_parser.dart'; +import 'sub_parsers/var_parser.dart'; +import 'type_extractor/extractor.dart'; +import 'utils.dart'; + +final _logger = Logger('ffigen.header_parser.translation_unit_parser'); + +/// Parses the translation unit and returns the generated bindings. +Set parseTranslationUnit(clang_types.CXCursor translationUnitCursor) { + final bindings = {}; + + translationUnitCursor.visitChildren((cursor) { + try { + if (shouldIncludeRootCursor(cursor.sourceFileName())) { + _logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}'); + switch (clang.clang_getCursorKind(cursor)) { + case clang_types.CXCursorKind.CXCursor_FunctionDecl: + bindings.addAll(parseFunctionDeclaration(cursor) as List); + break; + case clang_types.CXCursorKind.CXCursor_StructDecl: + case clang_types.CXCursorKind.CXCursor_UnionDecl: + case clang_types.CXCursorKind.CXCursor_EnumDecl: + case clang_types.CXCursorKind.CXCursor_ObjCInterfaceDecl: + addToBindings(bindings, _getCodeGenTypeFromCursor(cursor)); + break; + case clang_types.CXCursorKind.CXCursor_ObjCCategoryDecl: + addToBindings(bindings, parseObjCCategoryDeclaration(cursor)); + break; + case clang_types.CXCursorKind.CXCursor_ObjCProtocolDecl: + addToBindings(bindings, parseObjCProtocolDeclaration(cursor)); + break; + case clang_types.CXCursorKind.CXCursor_MacroDefinition: + saveMacroDefinition(cursor); + break; + case clang_types.CXCursorKind.CXCursor_VarDecl: + addToBindings(bindings, parseVarDeclaration(cursor)); + break; + case clang_types.CXCursorKind.CXCursor_TypedefDecl: + if (config.includeUnusedTypedefs) { + addToBindings(bindings, parseTypedefDeclaration(cursor)); + } + break; + default: + _logger.finer('rootCursorVisitor: CursorKind not implemented'); + } + } else { + _logger.finest( + 'rootCursorVisitor:(not included) ${cursor.completeStringRepr()}'); + } + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } + }); + + return bindings; +} + +/// Adds to binding if unseen and not null. +void addToBindings(Set bindings, Binding? b) { + if (b != null) { + // This is a set, and hence will not have duplicates. + bindings.add(b); + } +} + +BindingType? _getCodeGenTypeFromCursor(clang_types.CXCursor cursor) { + final t = getCodeGenType(cursor.type(), ignoreFilter: false); + return t is BindingType ? t : null; +} + +/// Visits all cursors and builds a map of usr and [clang_types.CXCursor]. +void buildUsrCursorDefinitionMap(clang_types.CXCursor translationUnitCursor) { + translationUnitCursor.visitChildren((cursor) { + try { + cursorIndex.saveDefinition(cursor); + } catch (e, s) { + _logger.severe(e); + _logger.severe(s); + rethrow; + } + }); +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/type_extractor/cxtypekindmap.dart b/pkgs/ffigenpad/lib/src/header_parser/type_extractor/cxtypekindmap.dart new file mode 100644 index 0000000000..89f6c5f57e --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/type_extractor/cxtypekindmap.dart @@ -0,0 +1,54 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; +import '../../code_generator.dart' show SupportedNativeType, Type; +import '../../code_generator/imports.dart'; + +Map cxTypeKindToImportedTypes = { + 'void': voidType, + 'unsigned char': unsignedCharType, + 'signed char': signedCharType, + 'char': charType, + 'unsigned short': unsignedShortType, + 'short': shortType, + 'unsigned int': unsignedIntType, + 'int': intType, + 'unsigned long': unsignedLongType, + 'long': longType, + 'unsigned long long': unsignedLongLongType, + 'long long': longLongType, + 'float': floatType, + 'double': doubleType, +}; + +Map unsignedToSignedNativeIntType = Map.fromEntries( + cxTypeKindToImportedTypes.entries + .where((e) => e.key.contains('unsigned')) + .map((e) => MapEntry(e.value as Type, + cxTypeKindToImportedTypes[e.key.replaceFirst('unsigned ', '')]))); + +Map signedToUnsignedNativeIntType = Map.fromEntries( + cxTypeKindToImportedTypes.entries + .whereNot((e) => e.key.contains('unsigned')) + .map((e) => MapEntry( + e.value as Type, cxTypeKindToImportedTypes['unsigned ${e.key}']))); + +Map suportedTypedefToSuportedNativeType = { + 'uint8_t': SupportedNativeType.uint8, + 'uint16_t': SupportedNativeType.uint16, + 'uint32_t': SupportedNativeType.uint32, + 'uint64_t': SupportedNativeType.uint64, + 'int8_t': SupportedNativeType.int8, + 'int16_t': SupportedNativeType.int16, + 'int32_t': SupportedNativeType.int32, + 'int64_t': SupportedNativeType.int64, + 'intptr_t': SupportedNativeType.intPtr, + 'uintptr_t': SupportedNativeType.uintPtr, +}; + +Map supportedTypedefToImportedType = { + 'size_t': sizeType, + 'wchar_t': wCharType, +}; diff --git a/pkgs/ffigenpad/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigenpad/lib/src/header_parser/type_extractor/extractor.dart new file mode 100644 index 0000000000..9df103b666 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/type_extractor/extractor.dart @@ -0,0 +1,379 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Extracts code_gen Type from type. +library; + +import 'package:logging/logging.dart'; + +import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; +import '../../strings.dart' as strings; +import '../clang_bindings/clang_types.dart' as clang_types; +import '../data.dart'; +import '../sub_parsers/compounddecl_parser.dart'; +import '../sub_parsers/enumdecl_parser.dart'; +import '../sub_parsers/function_type_param_parser.dart'; +import '../sub_parsers/objc_block_parser.dart'; +import '../sub_parsers/objcinterfacedecl_parser.dart'; +import '../sub_parsers/typedefdecl_parser.dart'; +import '../type_extractor/cxtypekindmap.dart'; +import '../utils.dart'; + +final _logger = Logger('ffigen.header_parser.extractor'); +const _padding = ' '; + +const maxRecursionDepth = 5; + +/// Converts cxtype to a typestring code_generator can accept. +Type getCodeGenType( + clang_types.CXType cxtype, { + /// Option to ignore declaration filter (Useful in case of extracting + /// declarations when they are passed/returned by an included function.) + bool ignoreFilter = true, + + /// Passed on if a value was marked as a pointer before this one. + bool pointerReference = false, + + /// Cursor of the declaration, currently this is useful only to extract + /// parameter names in function types. + clang_types.CXCursor? originalCursor, + bool supportNonInlineArray = false, +}) { + _logger.fine('${_padding}getCodeGenType ${cxtype.completeStringRepr()}'); + + // Special case: Elaborated types just refer to another type. + if (cxtype.kind == clang_types.CXTypeKind.CXType_Elaborated) { + return getCodeGenType(clang.clang_Type_getNamedType(cxtype), + ignoreFilter: ignoreFilter, pointerReference: pointerReference); + } + + // These basic Objective C types skip the cache, and are conditional on the + // language flag. + if (config.language == Language.objc) { + switch (cxtype.kind) { + case clang_types.CXTypeKind.CXType_ObjCObjectPointer: + final pt = clang.clang_getPointeeType(cxtype); + final s = getCodeGenType(pt, + ignoreFilter: ignoreFilter, pointerReference: true); + if (s is ObjCInterface) { + return s; + } + return PointerType(objCObjectType); + case clang_types.CXTypeKind.CXType_ObjCId: + case clang_types.CXTypeKind.CXType_ObjCTypeParam: + case clang_types.CXTypeKind.CXType_ObjCClass: + return PointerType(objCObjectType); + case clang_types.CXTypeKind.CXType_ObjCSel: + return PointerType(objCSelType); + case clang_types.CXTypeKind.CXType_BlockPointer: + return parseObjCBlock(cxtype); + } + } + + // If the type has a declaration cursor, then use the BindingsIndex to break + // any potential cycles, and dedupe the Type. + final cursor = clang.clang_getTypeDeclaration(cxtype); + if (cursor.kind != clang_types.CXCursorKind.CXCursor_NoDeclFound) { + final usr = cursor.usr(); + var type = bindingsIndex.getSeenType(usr); + if (type == null) { + final result = + _createTypeFromCursor(cxtype, cursor, ignoreFilter, pointerReference); + type = result.type; + if (type == null) { + return UnimplementedType('${cxtype.kindSpelling()} not implemented'); + } + if (result.addToCache) { + bindingsIndex.addTypeToSeen(usr, type); + } + } + _fillFromCursorIfNeeded(type, cursor, ignoreFilter, pointerReference); + return type; + } + + // If the type doesn't have a declaration cursor, then it's a basic type such + // as int, or a simple derived type like a pointer, so doesn't need to be + // cached. + switch (cxtype.kind) { + case clang_types.CXTypeKind.CXType_Pointer: + final pt = clang.clang_getPointeeType(cxtype); + final s = getCodeGenType( + pt, + pointerReference: true, + originalCursor: originalCursor, + ); + + // Replace Pointer<_Dart_Handle> with Handle. + if (config.useDartHandle && + s is Compound && + s.compoundType == CompoundType.struct && + s.usr == strings.dartHandleUsr) { + return HandleType(); + } + return PointerType(s); + case clang_types.CXTypeKind.CXType_FunctionProto: + // Primarily used for function pointers. + return _extractFromFunctionProto(cxtype, cursor: originalCursor); + case clang_types.CXTypeKind.CXType_FunctionNoProto: + // Primarily used for function types with zero arguments. + return _extractFromFunctionProto(cxtype, cursor: originalCursor); + case clang_types.CXTypeKind.CXType_ConstantArray: + // Primarily used for constant array in struct members. + final numElements = clang.clang_getNumElements(cxtype); + final elementType = clang + .clang_getArrayElementType(cxtype) + .toCodeGenType(supportNonInlineArray: supportNonInlineArray); + // Handle numElements being 0 as an incomplete array. + return numElements == 0 + ? IncompleteArray(elementType) + : ConstantArray( + numElements, + elementType, + useArrayType: supportNonInlineArray, + ); + case clang_types.CXTypeKind.CXType_IncompleteArray: + // Primarily used for incomplete array in function parameters. + return IncompleteArray( + clang.clang_getArrayElementType(cxtype).toCodeGenType(), + ); + case clang_types.CXTypeKind.CXType_Bool: + return BooleanType(); + case clang_types.CXTypeKind.CXType_Attributed: + case clang_types.CXTypeKind.CXType_Unexposed: + final innerType = getCodeGenType( + clang.clang_Type_getModifiedType(cxtype), + ignoreFilter: ignoreFilter, + originalCursor: originalCursor, + ); + final isNullable = clang.clang_Type_getNullability(cxtype) == + clang_types.CXTypeNullabilityKind.CXTypeNullability_Nullable; + return isNullable && ObjCNullable.isSupported(innerType) + ? ObjCNullable(innerType) + : innerType; + default: + var typeSpellKey = + clang.clang_getTypeSpelling(cxtype).toStringAndDispose(); + if (typeSpellKey.startsWith('const ')) { + typeSpellKey = typeSpellKey.replaceFirst('const ', ''); + } + if (config.nativeTypeMappings.containsKey(typeSpellKey)) { + _logger.fine(' Type $typeSpellKey mapped from type-map.'); + return config.nativeTypeMappings[typeSpellKey]!; + } else if (cxTypeKindToImportedTypes.containsKey(typeSpellKey)) { + return cxTypeKindToImportedTypes[typeSpellKey]!; + } else { + _logger.fine('typedeclarationCursorVisitor: getCodeGenType: Type Not ' + 'Implemented, ${cxtype.completeStringRepr()}'); + return UnimplementedType('${cxtype.kindSpelling()} not implemented'); + } + } +} + +class _CreateTypeFromCursorResult { + final Type? type; + + // Flag that controls whether the type is added to the cache. It should not + // be added to the cache if it's just a fallback implementation, such as the + // int that is returned when an enum is excluded by the config. Later we might + // need to build the full enum type (eg if it's part of an included struct), + // and if we put the fallback int in the cache then the full enum will never + // be created. + final bool addToCache; + + _CreateTypeFromCursorResult(this.type, {this.addToCache = true}); +} + +_CreateTypeFromCursorResult _createTypeFromCursor(clang_types.CXType cxtype, + clang_types.CXCursor cursor, bool ignoreFilter, bool pointerReference) { + switch (cxtype.kind) { + case clang_types.CXTypeKind.CXType_Typedef: + final spelling = clang.clang_getTypedefName(cxtype).toStringAndDispose(); + if (config.language == Language.objc && spelling == strings.objcBOOL) { + // Objective C's BOOL type can be either bool or signed char, depending + // on the platform. We want to present a consistent API to the user, and + // those two types are ABI compatible, so just return bool regardless. + return _CreateTypeFromCursorResult(BooleanType()); + } + final usr = cursor.usr(); + if (config.typedefTypeMappings.containsKey(spelling)) { + _logger.fine(' Type $spelling mapped from type-map'); + return _CreateTypeFromCursorResult( + config.typedefTypeMappings[spelling]!); + } + if (config.usrTypeMappings.containsKey(usr)) { + _logger.fine(' Type $spelling mapped from usr'); + return _CreateTypeFromCursorResult(config.usrTypeMappings[usr]!); + } + // Get name from supported typedef name if config allows. + if (config.useSupportedTypedefs) { + if (suportedTypedefToSuportedNativeType.containsKey(spelling)) { + _logger.fine(' Type Mapped from supported typedef'); + return _CreateTypeFromCursorResult( + NativeType(suportedTypedefToSuportedNativeType[spelling]!)); + } else if (supportedTypedefToImportedType.containsKey(spelling)) { + _logger.fine(' Type Mapped from supported typedef'); + return _CreateTypeFromCursorResult( + supportedTypedefToImportedType[spelling]!); + } + } + + final typealias = + parseTypedefDeclaration(cursor, pointerReference: pointerReference); + + if (typealias != null) { + return _CreateTypeFromCursorResult(typealias); + } else { + // Use underlying type if typealias couldn't be created or if the user + // excluded this typedef. + final ct = clang.clang_getTypedefDeclUnderlyingType(cursor); + return _CreateTypeFromCursorResult( + getCodeGenType(ct, pointerReference: pointerReference), + addToCache: false); + } + case clang_types.CXTypeKind.CXType_Record: + return _CreateTypeFromCursorResult( + _extractfromRecord(cxtype, cursor, ignoreFilter, pointerReference)); + case clang_types.CXTypeKind.CXType_Enum: + final (enumClass, nativeType) = parseEnumDeclaration( + cursor, + ignoreFilter: ignoreFilter, + ); + if (enumClass == null) { + // Handle anonymous enum declarations within another declaration. + return _CreateTypeFromCursorResult(nativeType, addToCache: false); + } else { + return _CreateTypeFromCursorResult(enumClass); + } + case clang_types.CXTypeKind.CXType_ObjCInterface: + return _CreateTypeFromCursorResult( + parseObjCInterfaceDeclaration(cursor, ignoreFilter: ignoreFilter)); + default: + return _CreateTypeFromCursorResult( + UnimplementedType('Unknown type: ${cxtype.completeStringRepr()}'), + addToCache: false); + } +} + +void _fillFromCursorIfNeeded(Type? type, clang_types.CXCursor cursor, + bool ignoreFilter, bool pointerReference) { + if (type == null) return; + if (type is Compound) { + fillCompoundMembersIfNeeded(type, cursor, + ignoreFilter: ignoreFilter, pointerReference: pointerReference); + } else if (type is ObjCInterface) { + fillObjCInterfaceMethodsIfNeeded(type, cursor); + } +} + +Type? _extractfromRecord(clang_types.CXType cxtype, clang_types.CXCursor cursor, + bool ignoreFilter, bool pointerReference) { + _logger.fine('${_padding}_extractfromRecord: ${cursor.completeStringRepr()}'); + + final cursorKind = clang.clang_getCursorKind(cursor); + if (cursorKind == clang_types.CXCursorKind.CXCursor_StructDecl || + cursorKind == clang_types.CXCursorKind.CXCursor_UnionDecl) { + final declSpelling = cursor.spelling(); + final declUsr = cursor.usr(); + + // Set includer functions according to compoundType. + final CompoundType compoundType; + final Map compoundTypeMappings; + + switch (cursorKind) { + case clang_types.CXCursorKind.CXCursor_StructDecl: + compoundType = CompoundType.struct; + compoundTypeMappings = config.structTypeMappings; + break; + case clang_types.CXCursorKind.CXCursor_UnionDecl: + compoundType = CompoundType.union; + compoundTypeMappings = config.unionTypeMappings; + break; + default: + throw Exception('Unhandled compound type cursorkind.'); + } + + // Also add a struct binding, if its unseen. + if (compoundTypeMappings.containsKey(declSpelling)) { + _logger.fine(' Type Mapped from type-map'); + return compoundTypeMappings[declSpelling]!; + } else if (config.usrTypeMappings.containsKey(declUsr)) { + _logger.fine(' Type Mapped from usr'); + return config.usrTypeMappings[declUsr]!; + } else { + final struct = parseCompoundDeclaration( + cursor, + compoundType, + ignoreFilter: ignoreFilter, + pointerReference: pointerReference, + ); + return struct; + } + } + _logger.fine('typedeclarationCursorVisitor: _extractfromRecord: ' + 'Not Implemented, ${cursor.completeStringRepr()}'); + return UnimplementedType('${cxtype.kindSpelling()} not implemented'); +} + +// Used for function pointer arguments. +Type _extractFromFunctionProto(clang_types.CXType cxtype, + {clang_types.CXCursor? cursor}) { + final parameters = []; + final totalArgs = clang.clang_getNumArgTypes(cxtype); + for (var i = 0; i < totalArgs; i++) { + final t = clang.clang_getArgType(cxtype, i); + final pt = t.toCodeGenType(); + + if (pt.isIncompleteCompound) { + return UnimplementedType( + 'Incomplete Struct by value in function parameter.'); + } else if (pt.baseType is UnimplementedType) { + return UnimplementedType('Function parameter has an unsupported type.'); + } + + parameters.add( + Parameter(name: '', type: pt), + ); + } + + final functionType = FunctionType( + parameters: parameters, + returnType: clang.clang_getResultType(cxtype).toCodeGenType(), + ); + _parseAndMergeParamNames(functionType, cursor, maxRecursionDepth); + return NativeFunc(functionType); +} + +void _parseAndMergeParamNames( + FunctionType functionType, + clang_types.CXCursor? cursor, + int recursionDepth, +) { + if (cursor == null) { + return; + } + if (recursionDepth == 0) { + final cursorRepr = cursor.completeStringRepr(); + _logger.warning('Recursion depth exceeded when merging function parameters.' + ' Last cursor encountered was $cursorRepr'); + return; + } + + final paramsInfo = parseFunctionPointerParamNames(cursor); + functionType.addParameterNames(paramsInfo.paramNames); + + for (final param in functionType.parameters) { + final paramRealType = param.type.typealiasType; + final paramBaseType = paramRealType.baseType.typealiasType; + if (paramBaseType is NativeFunc && param.name.isNotEmpty) { + final paramFunctionType = paramBaseType.type; + final paramCursor = paramsInfo.params[param.name]; + _parseAndMergeParamNames( + paramFunctionType, + paramCursor, + recursionDepth - 1, + ); + } + } +} diff --git a/pkgs/ffigenpad/lib/src/header_parser/utils.dart b/pkgs/ffigenpad/lib/src/header_parser/utils.dart new file mode 100644 index 0000000000..e10a2c7271 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/header_parser/utils.dart @@ -0,0 +1,516 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' as convert; +import 'dart:ffi'; +import 'dart:js_interop'; + +import 'package:ffigen/src/header_parser/utils.dart' + show commentPrefix, removeRawCommentMarkups; +import 'package:logging/logging.dart'; + +import '../code_generator.dart'; +import '../config_provider/config_types.dart'; +import 'calloc.dart'; +import 'clang_bindings/clang_types.dart' as clang_types; +import 'data.dart'; +import 'type_extractor/extractor.dart'; + +export 'package:ffigen/src/header_parser/utils.dart' + show + IncrementalNamer, + Macro, + Stack, + commentPrefix, + nesting, + removeRawCommentMarkups; + +final _logger = Logger('ffigen.header_parser.utils'); + +const exceptionalVisitorReturn = + clang_types.CXChildVisitResult.CXChildVisit_Break; + +/// Logs the warnings/errors returned by clang for a translation unit. +void logTuDiagnostics( + clang_types.CXTranslationUnit tu, Logger logger, String header, + {Level logLevel = Level.SEVERE}) { + final total = clang.clang_getNumDiagnostics(tu); + if (total == 0) { + return; + } + logger.log(logLevel, 'Header $header: Total errors/warnings: $total.'); + for (var i = 0; i < total; i++) { + final diag = clang.clang_getDiagnostic(tu, i); + if (clang.clang_getDiagnosticSeverity(diag) >= + clang_types.CXDiagnosticSeverity.CXDiagnostic_Warning) { + hasSourceErrors = true; + } + final cxstring = clang.clang_formatDiagnostic( + diag, + clang_types + .CXDiagnosticDisplayOptions.CXDiagnostic_DisplaySourceLocation | + clang_types.CXDiagnosticDisplayOptions.CXDiagnostic_DisplayColumn | + clang_types + .CXDiagnosticDisplayOptions.CXDiagnostic_DisplayCategoryName, + ); + logger.log(logLevel, ' ${cxstring.toStringAndDispose()}'); + clang.clang_disposeDiagnostic(diag); + } +} + +extension CXSourceRangeExt on clang_types.CXSourceRange { + void dispose() { + calloc.free(this); + } +} + +extension CXCursorExt on clang_types.CXCursor { + String usr() { + var res = clang.clang_getCursorUSR(this).toStringAndDispose(); + if (isAnonymousRecordDecl()) { + res += '@offset:${sourceFileOffset()}'; + } + return res; + } + + /// Returns the kind int from [clang_types.CXCursorKind]. + int get kind { + return clang.clang_getCursorKind(this); + } + + /// Name of the cursor (E.g function name, Struct name, Parameter name). + String spelling() { + return clang.clang_getCursorSpelling(this).toStringAndDispose(); + } + + /// Spelling for a [clang_types.CXCursorKind], useful for debug purposes. + String kindSpelling() { + return clang + .clang_getCursorKindSpelling(clang.clang_getCursorKind(this)) + .toStringAndDispose(); + } + + /// Get code_gen [Type] representation of [clang_types.CXType]. + Type toCodeGenType() { + return getCodeGenType(type(), originalCursor: this); + } + + /// for debug: returns [spelling] [kind] [kindSpelling] type typeSpelling. + String completeStringRepr() { + final cxtype = type(); + final s = '(Cursor) spelling: ${spelling()}, kind: $kind, ' + 'kindSpelling: ${kindSpelling()}, type: ${cxtype.kind}, ' + 'typeSpelling: ${cxtype.spelling()}, usr: ${usr()}'; + return s; + } + + /// Type associated with the pointer if any. Type will have kind + /// [clang.CXTypeKind.CXType_Invalid] otherwise. + clang_types.CXType type() { + return clang.clang_getCursorType(this); + } + + /// Determine whether the given cursor + /// represents an anonymous record declaration. + bool isAnonymousRecordDecl() { + return clang.clang_Cursor_isAnonymousRecordDecl(this) == 1; + } + + /// Only valid for [clang.CXCursorKind.CXCursor_FunctionDecl]. Type will have + /// kind [clang.CXTypeKind.CXType_Invalid] otherwise. + clang_types.CXType returnType() { + return clang.clang_getResultType(type()); + } + + /// Returns the file name of the file that the cursor is inside. + String sourceFileName() { + final cxsource = clang.clang_getCursorLocation(this); + final cxfilePtr = calloc(); + + // Puts the values in these pointers. + clang.clang_getFileLocation(cxsource, cxfilePtr, nullptr, nullptr, nullptr); + final s = clang.clang_getFileName(cxfilePtr.value).toStringAndDispose(); + + calloc.free(cxfilePtr); + return s; + } + + int sourceFileOffset() { + final cxsource = clang.clang_getCursorLocation(this); + final cxOffset = calloc(); + + // Puts the values in these pointers. + clang.clang_getFileLocation(cxsource, nullptr, nullptr, nullptr, cxOffset); + final offset = cxOffset.value; + calloc.free(cxOffset); + return offset; + } + + /// Returns whether the file that the cursor is inside is a system header. + bool isInSystemHeader() { + final location = clang.clang_getCursorLocation(this); + return clang.clang_Location_isInSystemHeader(location) != 0; + } + + /// Visits all the direct children of this cursor. + /// + /// [callback] is called with the child cursor. The iteration continues until + /// completion. The only way it can be interrupted is if the [callback] + /// throws, in which case this method also throws. + void visitChildren(void Function(clang_types.CXCursor child) callback) { + final completed = visitChildrenMayBreak((clang_types.CXCursor child) { + callback(child); + return true; + }); + if (!completed) { + throw Exception('Exception thrown in a dart function called via C, ' + 'use --verbose to see more details'); + } + } + + /// Visits all the direct children of this cursor. + /// + /// [callback] is called with the child cursor. If [callback] returns true, + /// the iteration will continue. Otherwise, if [callback] returns false, the + /// iteration will stop. + /// + /// Returns whether the iteration completed. + bool visitChildrenMayBreak( + bool Function(clang_types.CXCursor child) callback) => + visitChildrenMayRecurse( + (clang_types.CXCursor child, clang_types.CXCursor parent) => + callback(child) + ? clang_types.CXChildVisitResult.CXChildVisit_Continue + : clang_types.CXChildVisitResult.CXChildVisit_Break); + + /// Visits all the direct children of this cursor. + /// + /// [callback] is called with the child cursor and parent cursor. If + /// [callback] returns CXChildVisit_Continue, the iteration continues. If it + /// returns CXChildVisit_Break the iteration stops. If it returns + /// CXChildVisit_Recurse, the iteration recurses into the node. + /// + /// Returns whether the iteration completed. + bool visitChildrenMayRecurse( + int Function(clang_types.CXCursor child, clang_types.CXCursor parent) + callback) { + int visitorWrapper(int childAddress, int parentAddress, int _) { + final child = clang_types.CXCursor.fromAddress(childAddress); + final parent = clang_types.CXCursor.fromAddress(parentAddress); + return callback(child, parent); + } + + final visitorIndex = addFunction(visitorWrapper.toJS, 'iiii'); + final result = clang.clang_visitChildren(this, visitorIndex); + removeFunction(visitorIndex); + return result == 0; + } + + /// Returns the first child with the given CXCursorKind, or null if there + /// isn't one. + clang_types.CXCursor? findChildWithKind(int kind) { + clang_types.CXCursor? result; + visitChildrenMayBreak((child) { + if (child.kind == kind) { + result = child; + return false; + } + return true; + }); + return result; + } + + /// Returns whether there is a child with the given CXCursorKind. + bool hasChildWithKind(int kind) => findChildWithKind(kind) != null; + + /// Recursively print the AST, for debugging. + void printAst([int maxDepth = 3]) => _printAst(maxDepth, 0); + void _printAst(int maxDepth, int depth) { + if (depth > maxDepth) { + return; + } + print((' ' * depth) + completeStringRepr()); + visitChildren((child) => child._printAst(maxDepth, depth + 1)); + } +} + +/// Stores the [clang_types.CXSourceRange] of the last comment. +clang_types.CXSourceRange? lastCommentRange; + +/// Returns a cursor's associated comment. +/// +/// The given string is wrapped at line width = 80 - [indent]. The [indent] is +/// [commentPrefix].length by default because a comment starts with +/// [commentPrefix]. +String? getCursorDocComment(clang_types.CXCursor cursor, + [int indent = commentPrefix.length]) { + String? formattedDocComment; + final currentCommentRange = clang.clang_Cursor_getCommentRange(cursor); + + // See if this comment and the last comment both point to the same source + // range. + if (lastCommentRange != null && + clang.clang_equalRanges(lastCommentRange!, currentCommentRange) != 0) { + formattedDocComment = null; + } else { + switch (config.commentType.length) { + case CommentLength.full: + formattedDocComment = removeRawCommentMarkups( + clang.clang_Cursor_getRawCommentText(cursor).toStringAndDispose()); + break; + case CommentLength.brief: + formattedDocComment = _wrapNoNewLineString( + clang.clang_Cursor_getBriefCommentText(cursor).toStringAndDispose(), + 80 - indent); + break; + default: + formattedDocComment = null; + } + } + lastCommentRange = currentCommentRange; + return formattedDocComment; +} + +/// Wraps [string] according to given [lineWidth]. +/// +/// Wrapping will work properly only when String has no new lines +/// characters(\n). +String? _wrapNoNewLineString(String? string, int lineWidth) { + if (string == null || string.isEmpty) { + return null; + } + final sb = StringBuffer(); + + final words = string.split(' '); + + sb.write(words[0]); + var trackLineWidth = words[0].length; + for (var i = 1; i < words.length; i++) { + final word = words[i]; + if (trackLineWidth + word.length < lineWidth) { + sb.write(' '); + sb.write(word); + trackLineWidth += word.length + 1; + } else { + sb.write('\n'); + sb.write(word); + trackLineWidth = word.length; + } + } + return sb.toString(); +} + +extension CXTypeExt on clang_types.CXType { + /// Get code_gen [Type] representation of [clang_types.CXType]. + Type toCodeGenType({bool supportNonInlineArray = false}) { + return getCodeGenType(this, supportNonInlineArray: supportNonInlineArray); + } + + /// Spelling for a [clang_types.CXTypeKind], useful for debug purposes. + String spelling() { + return clang.clang_getTypeSpelling(this).toStringAndDispose(); + } + + /// Returns the typeKind int from [clang_types.CXTypeKind]. + int get kind { + return clang.getCXTypeKind(this); + } + + String kindSpelling() { + return clang.clang_getTypeKindSpelling(kind).toStringAndDispose(); + } + + int alignment() { + return clang.clang_Type_getAlignOf(this); + } + + /// For debugging: returns [spelling] [kind] [kindSpelling]. + String completeStringRepr() { + final s = '(Type) spelling: ${spelling()}, kind: $kind, ' + 'kindSpelling: ${kindSpelling()}'; + return s; + } + + bool get isConstQualified { + return clang.clang_isConstQualifiedType(this) != 0; + } +} + +extension CXStringExt on clang_types.CXString { + /// Convert CXString to a Dart string + /// + /// Make sure to dispose CXstring using dispose method, or use the + /// [toStringAndDispose] method. + String string() { + final cstring = clang.clang_getCString(this); + if (cstring != nullptr) { + return cstring.toDartString(); + } else { + return ''; + } + } + + /// Converts CXString to dart string and disposes CXString. + String toStringAndDispose() { + // Note: clang_getCString_wrap returns a const char *, calling free will + // result in error. + final s = string(); + dispose(); + return s; + } + + void dispose() { + clang.clang_disposeString(this); + } +} + +extension UTF on Pointer { + int get length { + var output = 0; + while (this[output] != 0) { + output++; + } + return output; + } + + List toCharList() { + return List.generate( + length, + (int index) => this[index], + growable: false, + ); + } + + String toDartString() { + // TODO: why do we need allowMalformed as true? + return convert.utf8.decode(toCharList(), allowMalformed: true); + } +} + +extension StringUtf8Pointer on String { + /// Converts string into an array of bytes and allocates it in WASM memory + Pointer toNativeUint8() { + final units = convert.utf8.encode(this); + final result = calloc(units.length + 1); + for (var i = 0; i < units.length; i++) { + result[i] = units[i]; + } + result[units.length] = 0; + return result; + } +} + +/// Converts a [List<String>] to [Pointer<Pointer<Uint8>>]. +Pointer> createDynamicStringArray(List list) { + final nativeCmdArgs = calloc>(list.length); + + for (var i = 0; i < list.length; i++) { + nativeCmdArgs[i] = list[i].toNativeUint8(); + } + + return nativeCmdArgs; +} + +extension DynamicCStringArray on Pointer> { + // Properly disposes a Pointer, ensure that sure length is + // correct. + void dispose(int length) { + for (var i = 0; i < length; i++) { + calloc.free(this[i]); + } + calloc.free(this); + } +} + +/// Tracks if a binding is 'seen' or not. +class BindingsIndex { + // Tracks if bindings are already seen, Map key is USR obtained from libclang. + final Map _declaredTypes = {}; + final Map _functions = {}; + final Map _unnamedEnumConstants = {}; + final Map _macros = {}; + final Map _globals = {}; + final Map _objcBlocks = {}; + final Map _objcProtocols = {}; + + /// Contains usr for typedefs which cannot be generated. + final Set _unsupportedTypealiases = {}; + + /// Index for headers. + final Map _headerCache = {}; + + bool isSeenType(String usr) => _declaredTypes.containsKey(usr); + void addTypeToSeen(String usr, Type type) => _declaredTypes[usr] = type; + Type? getSeenType(String usr) => _declaredTypes[usr]; + bool isSeenFunc(String usr) => _functions.containsKey(usr); + void addFuncToSeen(String usr, Func func) => _functions[usr] = func; + Func? getSeenFunc(String usr) => _functions[usr]; + bool isSeenUnnamedEnumConstant(String usr) => + _unnamedEnumConstants.containsKey(usr); + void addUnnamedEnumConstantToSeen(String usr, Constant enumConstant) => + _unnamedEnumConstants[usr] = enumConstant; + Constant? getSeenUnnamedEnumConstant(String usr) => + _unnamedEnumConstants[usr]; + bool isSeenGlobalVar(String usr) => _globals.containsKey(usr); + void addGlobalVarToSeen(String usr, Global global) => _globals[usr] = global; + Global? getSeenGlobalVar(String usr) => _globals[usr]; + bool isSeenMacro(String usr) => _macros.containsKey(usr); + void addMacroToSeen(String usr, String macro) => _macros[usr] = macro; + String? getSeenMacro(String usr) => _macros[usr]; + bool isSeenUnsupportedTypealias(String usr) => + _unsupportedTypealiases.contains(usr); + void addUnsupportedTypealiasToSeen(String usr) => + _unsupportedTypealiases.add(usr); + bool isSeenHeader(String source) => _headerCache.containsKey(source); + void addHeaderToSeen(String source, bool includeStatus) => + _headerCache[source] = includeStatus; + bool? getSeenHeaderStatus(String source) => _headerCache[source]; + void addObjCBlockToSeen(String key, ObjCBlock t) => _objcBlocks[key] = t; + ObjCBlock? getSeenObjCBlock(String key) => _objcBlocks[key]; + void addObjCProtocolToSeen(String usr, ObjCProtocol t) => + _objcProtocols[usr] = t; + ObjCProtocol? getSeenObjCProtocol(String usr) => _objcProtocols[usr]; + bool isSeenObjCProtocol(String usr) => _objcProtocols.containsKey(usr); +} + +class CursorIndex { + final _usrCursorDefinition = {}; + + /// Returns the Cursor definition (if found) or itself. + clang_types.CXCursor getDefinition(clang_types.CXCursor cursor) { + final cursorDefinition = clang.clang_getCursorDefinition(cursor); + if (clang.clang_Cursor_isNull(cursorDefinition) == 0) { + return cursorDefinition; + } else { + final usr = cursor.usr(); + if (_usrCursorDefinition.containsKey(usr)) { + return _usrCursorDefinition[cursor.usr()]!; + } else { + _logger.warning('No definition found for declaration -' + '${cursor.completeStringRepr()}'); + return cursor; + } + } + } + + /// Saves cursor definition based on its kind. + void saveDefinition(clang_types.CXCursor cursor) { + switch (cursor.kind) { + case clang_types.CXCursorKind.CXCursor_StructDecl: + case clang_types.CXCursorKind.CXCursor_UnionDecl: + case clang_types.CXCursorKind.CXCursor_EnumDecl: + final usr = cursor.usr(); + if (!_usrCursorDefinition.containsKey(usr)) { + final cursorDefinition = clang.clang_getCursorDefinition(cursor); + if (clang.clang_Cursor_isNull(cursorDefinition) == 0) { + _usrCursorDefinition[usr] = cursorDefinition; + } else { + _logger.finest( + 'Missing cursor definition in current translation unit: ' + '${cursor.completeStringRepr()}'); + } + } + } + } +} diff --git a/pkgs/ffigenpad/lib/src/strings.dart b/pkgs/ffigenpad/lib/src/strings.dart new file mode 100644 index 0000000000..cc430494c4 --- /dev/null +++ b/pkgs/ffigenpad/lib/src/strings.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:ffigen/src/strings.dart'; +import 'header_parser/clang_bindings/clang_types.dart' as clang; + +export 'package:ffigen/src/strings.dart'; + +final sizemapNativeMapping = { + sChar: clang.CXTypeKind.CXType_SChar, + uChar: clang.CXTypeKind.CXType_UChar, + short: clang.CXTypeKind.CXType_Short, + uShort: clang.CXTypeKind.CXType_UShort, + intType: clang.CXTypeKind.CXType_Int, + uInt: clang.CXTypeKind.CXType_UInt, + long: clang.CXTypeKind.CXType_Long, + uLong: clang.CXTypeKind.CXType_ULong, + longLong: clang.CXTypeKind.CXType_LongLong, + uLongLong: clang.CXTypeKind.CXType_ULongLong, + enumType: clang.CXTypeKind.CXType_Enum +}; + +/// A path to a unique temporary directory that should be used for files meant +/// to be discarded after the current execution is finished. +String get tmpDir { + return '/tmp'; +} diff --git a/pkgs/ffigenpad/pubspec.lock b/pkgs/ffigenpad/pubspec.lock new file mode 100644 index 0000000000..df6e59d338 --- /dev/null +++ b/pkgs/ffigenpad/pubspec.lock @@ -0,0 +1,457 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + url: "https://pub.dev" + source: hosted + version: "76.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + url: "https://pub.dev" + source: hosted + version: "6.11.0" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + collection: + dependency: "direct main" + description: + name: collection + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "576aaab8b1abdd452e0f656c3e73da9ead9d7880e15bdc494189d9c1a1baf0db" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + url: "https://pub.dev" + source: hosted + version: "3.0.5" + dart_flutter_team_lints: + dependency: "direct dev" + description: + name: dart_flutter_team_lints + sha256: "084338b81e33917c7c180da7aaccb59a5e5d16ece372465c6a2b930841b9009a" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + dart_style: + dependency: "direct main" + description: + name: dart_style + sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + ffigen: + dependency: "direct main" + description: + path: "../ffigen" + relative: true + source: path + version: "17.0.0-wip" + file: + dependency: "direct main" + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: "direct main" + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + logging: + dependency: "direct main" + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" + url: "https://pub.dev" + source: hosted + version: "0.1.3-main.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + meta: + dependency: transitive + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: "direct main" + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: "direct main" + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + quiver: + dependency: "direct main" + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + url: "https://pub.dev" + source: hosted + version: "1.25.8" + test_api: + dependency: transitive + description: + name: test_api + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + test_core: + dependency: transitive + description: + name: test_core + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: "direct main" + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + yaml_edit: + dependency: "direct main" + description: + name: yaml_edit + sha256: e9c1a3543d2da0db3e90270dbb1e4eebc985ee5e3ffe468d83224472b2194a5f + url: "https://pub.dev" + source: hosted + version: "2.2.1" +sdks: + dart: ">=3.5.1 <4.0.0" diff --git a/pkgs/ffigenpad/pubspec.yaml b/pkgs/ffigenpad/pubspec.yaml new file mode 100644 index 0000000000..0b8e29c23d --- /dev/null +++ b/pkgs/ffigenpad/pubspec.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +name: ffigenpad +description: A web app thats outputs dart:ffi bindings generated by ffigen entirely on the client. +version: 0.1.0 +repository: https://github.com/dart-lang/native/tree/main/pkgs/ffigenpad +publish_to: none +environment: + sdk: ^3.5.1 + +# Add regular dependencies here. +dependencies: + collection: ^1.19.0 + dart_style: ^3.0.1 + ffigen: + path: ../ffigen + file: ^7.0.0 + glob: ^2.1.2 + logging: ^1.2.0 + package_config: ^2.1.0 + path: ^1.9.0 + quiver: ^3.0.0 + yaml: ^3.1.2 + yaml_edit: ^2.2.1 + +dev_dependencies: + dart_flutter_team_lints: ^3.2.0 + lints: ^4.0.0 + test: ^1.24.0 diff --git a/pkgs/ffigenpad/third_party/libclang/.gitignore b/pkgs/ffigenpad/third_party/libclang/.gitignore new file mode 100644 index 0000000000..40ba0fc6c1 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/.gitignore @@ -0,0 +1 @@ +llvm-project \ No newline at end of file diff --git a/pkgs/ffigenpad/third_party/libclang/README.md b/pkgs/ffigenpad/third_party/libclang/README.md new file mode 100644 index 0000000000..2056f69a52 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/README.md @@ -0,0 +1,19 @@ +# Overview + +## Contents + +### wrapper.c + +Contains wrapper functions that interact with pointers because directly passing around structs in dart2wasm is currently not possible. + +### libclang.exports + +List of functions `bin/libclang.wasm` is made to export by emscripten. + +### include/ + +Contains header files for libclang that are used by ffigen to generate `dart:ffi` bindings. + +### llvm-project/ + +Contains precompiled archive files for building libclang, downloaded using `tool/setup.dart`. diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/BuildSystem.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/BuildSystem.h new file mode 100644 index 0000000000..57e16af20a --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/BuildSystem.h @@ -0,0 +1,153 @@ +/*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides various utilities for use by build systems. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_BUILDSYSTEM_H +#define LLVM_CLANG_C_BUILDSYSTEM_H + +#include "clang-c/CXErrorCode.h" +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup BUILD_SYSTEM Build system utilities + * @{ + */ + +/** + * Return the timestamp for use with Clang's + * \c -fbuild-session-timestamp= option. + */ +CINDEX_LINKAGE unsigned long long clang_getBuildSessionTimestamp(void); + +/** + * Object encapsulating information about overlaying virtual + * file/directories over the real file system. + */ +typedef struct CXVirtualFileOverlayImpl *CXVirtualFileOverlay; + +/** + * Create a \c CXVirtualFileOverlay object. + * Must be disposed with \c clang_VirtualFileOverlay_dispose(). + * + * \param options is reserved, always pass 0. + */ +CINDEX_LINKAGE CXVirtualFileOverlay +clang_VirtualFileOverlay_create(unsigned options); + +/** + * Map an absolute virtual file path to an absolute real one. + * The virtual path must be canonicalized (not contain "."/".."). + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay, + const char *virtualPath, + const char *realPath); + +/** + * Set the case sensitivity for the \c CXVirtualFileOverlay object. + * The \c CXVirtualFileOverlay object is case-sensitive by default, this + * option can be used to override the default. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay, + int caseSensitive); + +/** + * Write out the \c CXVirtualFileOverlay object to a char buffer. + * + * \param options is reserved, always pass 0. + * \param out_buffer_ptr pointer to receive the buffer pointer, which should be + * disposed using \c clang_free(). + * \param out_buffer_size pointer to receive the buffer size. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options, + char **out_buffer_ptr, + unsigned *out_buffer_size); + +/** + * free memory allocated by libclang, such as the buffer returned by + * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer(). + * + * \param buffer memory pointer to free. + */ +CINDEX_LINKAGE void clang_free(void *buffer); + +/** + * Dispose a \c CXVirtualFileOverlay object. + */ +CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay); + +/** + * Object encapsulating information about a module.modulemap file. + */ +typedef struct CXModuleMapDescriptorImpl *CXModuleMapDescriptor; + +/** + * Create a \c CXModuleMapDescriptor object. + * Must be disposed with \c clang_ModuleMapDescriptor_dispose(). + * + * \param options is reserved, always pass 0. + */ +CINDEX_LINKAGE CXModuleMapDescriptor +clang_ModuleMapDescriptor_create(unsigned options); + +/** + * Sets the framework module name that the module.modulemap describes. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor, + const char *name); + +/** + * Sets the umbrella header name that the module.modulemap describes. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor, + const char *name); + +/** + * Write out the \c CXModuleMapDescriptor object to a char buffer. + * + * \param options is reserved, always pass 0. + * \param out_buffer_ptr pointer to receive the buffer pointer, which should be + * disposed using \c clang_free(). + * \param out_buffer_size pointer to receive the buffer size. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor, unsigned options, + char **out_buffer_ptr, + unsigned *out_buffer_size); + +/** + * Dispose a \c CXModuleMapDescriptor object. + */ +CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif /* CLANG_C_BUILD_SYSTEM_H */ + diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXCompilationDatabase.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXCompilationDatabase.h new file mode 100644 index 0000000000..2b336e5464 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXCompilationDatabase.h @@ -0,0 +1,174 @@ +/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a public interface to use CompilationDatabase without *| +|* the full Clang C++ API. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H +#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H + +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** \defgroup COMPILATIONDB CompilationDatabase functions + * \ingroup CINDEX + * + * @{ + */ + +/** + * A compilation database holds all information used to compile files in a + * project. For each file in the database, it can be queried for the working + * directory or the command line used for the compiler invocation. + * + * Must be freed by \c clang_CompilationDatabase_dispose + */ +typedef void * CXCompilationDatabase; + +/** + * Contains the results of a search in the compilation database + * + * When searching for the compile command for a file, the compilation db can + * return several commands, as the file may have been compiled with + * different options in different places of the project. This choice of compile + * commands is wrapped in this opaque data structure. It must be freed by + * \c clang_CompileCommands_dispose. + */ +typedef void * CXCompileCommands; + +/** + * Represents the command line invocation to compile a specific file. + */ +typedef void * CXCompileCommand; + +/** + * Error codes for Compilation Database + */ +typedef enum { + /* + * No error occurred + */ + CXCompilationDatabase_NoError = 0, + + /* + * Database can not be loaded + */ + CXCompilationDatabase_CanNotLoadDatabase = 1 + +} CXCompilationDatabase_Error; + +/** + * Creates a compilation database from the database found in directory + * buildDir. For example, CMake can output a compile_commands.json which can + * be used to build the database. + * + * It must be freed by \c clang_CompilationDatabase_dispose. + */ +CINDEX_LINKAGE CXCompilationDatabase +clang_CompilationDatabase_fromDirectory(const char *BuildDir, + CXCompilationDatabase_Error *ErrorCode); + +/** + * Free the given compilation database + */ +CINDEX_LINKAGE void +clang_CompilationDatabase_dispose(CXCompilationDatabase); + +/** + * Find the compile commands used for a file. The compile commands + * must be freed by \c clang_CompileCommands_dispose. + */ +CINDEX_LINKAGE CXCompileCommands +clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase, + const char *CompleteFileName); + +/** + * Get all the compile commands in the given compilation database. + */ +CINDEX_LINKAGE CXCompileCommands +clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase); + +/** + * Free the given CompileCommands + */ +CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands); + +/** + * Get the number of CompileCommand we have for a file + */ +CINDEX_LINKAGE unsigned +clang_CompileCommands_getSize(CXCompileCommands); + +/** + * Get the I'th CompileCommand for a file + * + * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands) + */ +CINDEX_LINKAGE CXCompileCommand +clang_CompileCommands_getCommand(CXCompileCommands, unsigned I); + +/** + * Get the working directory where the CompileCommand was executed from + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getDirectory(CXCompileCommand); + +/** + * Get the filename associated with the CompileCommand. + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getFilename(CXCompileCommand); + +/** + * Get the number of arguments in the compiler invocation. + * + */ +CINDEX_LINKAGE unsigned +clang_CompileCommand_getNumArgs(CXCompileCommand); + +/** + * Get the I'th argument value in the compiler invocations + * + * Invariant : + * - argument 0 is the compiler executable + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getArg(CXCompileCommand, unsigned I); + +/** + * Get the number of source mappings for the compiler invocation. + */ +CINDEX_LINKAGE unsigned +clang_CompileCommand_getNumMappedSources(CXCompileCommand); + +/** + * Get the I'th mapped source path for the compiler invocation. + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getMappedSourcePath(CXCompileCommand, unsigned I); + +/** + * Get the I'th mapped source content for the compiler invocation. + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif + diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXDiagnostic.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXDiagnostic.h new file mode 100644 index 0000000000..911d001f06 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXDiagnostic.h @@ -0,0 +1,379 @@ +/*===-- clang-c/CXDiagnostic.h - C Index Diagnostics --------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides the interface to C Index diagnostics. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXDIAGNOSTIC_H +#define LLVM_CLANG_C_CXDIAGNOSTIC_H + +#include "clang-c/CXSourceLocation.h" +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup CINDEX_DIAG Diagnostic reporting + * + * @{ + */ + +/** + * Describes the severity of a particular diagnostic. + */ +enum CXDiagnosticSeverity { + /** + * A diagnostic that has been suppressed, e.g., by a command-line + * option. + */ + CXDiagnostic_Ignored = 0, + + /** + * This diagnostic is a note that should be attached to the + * previous (non-note) diagnostic. + */ + CXDiagnostic_Note = 1, + + /** + * This diagnostic indicates suspicious code that may not be + * wrong. + */ + CXDiagnostic_Warning = 2, + + /** + * This diagnostic indicates that the code is ill-formed. + */ + CXDiagnostic_Error = 3, + + /** + * This diagnostic indicates that the code is ill-formed such + * that future parser recovery is unlikely to produce useful + * results. + */ + CXDiagnostic_Fatal = 4 +}; + +/** + * A single diagnostic, containing the diagnostic's severity, + * location, text, source ranges, and fix-it hints. + */ +typedef void *CXDiagnostic; + +/** + * A group of CXDiagnostics. + */ +typedef void *CXDiagnosticSet; + +/** + * Determine the number of diagnostics in a CXDiagnosticSet. + */ +CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags); + +/** + * Retrieve a diagnostic associated with the given CXDiagnosticSet. + * + * \param Diags the CXDiagnosticSet to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, + unsigned Index); + +/** + * Describes the kind of error that occurred (if any) in a call to + * \c clang_loadDiagnostics. + */ +enum CXLoadDiag_Error { + /** + * Indicates that no error occurred. + */ + CXLoadDiag_None = 0, + + /** + * Indicates that an unknown error occurred while attempting to + * deserialize diagnostics. + */ + CXLoadDiag_Unknown = 1, + + /** + * Indicates that the file containing the serialized diagnostics + * could not be opened. + */ + CXLoadDiag_CannotLoad = 2, + + /** + * Indicates that the serialized diagnostics file is invalid or + * corrupt. + */ + CXLoadDiag_InvalidFile = 3 +}; + +/** + * Deserialize a set of diagnostics from a Clang diagnostics bitcode + * file. + * + * \param file The name of the file to deserialize. + * \param error A pointer to a enum value recording if there was a problem + * deserializing the diagnostics. + * \param errorString A pointer to a CXString for recording the error string + * if the file was not successfully loaded. + * + * \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These + * diagnostics should be released using clang_disposeDiagnosticSet(). + */ +CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics( + const char *file, enum CXLoadDiag_Error *error, CXString *errorString); + +/** + * Release a CXDiagnosticSet and all of its contained diagnostics. + */ +CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags); + +/** + * Retrieve the child diagnostics of a CXDiagnostic. + * + * This CXDiagnosticSet does not need to be released by + * clang_disposeDiagnosticSet. + */ +CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D); + +/** + * Destroy a diagnostic. + */ +CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); + +/** + * Options to control the display of diagnostics. + * + * The values in this enum are meant to be combined to customize the + * behavior of \c clang_formatDiagnostic(). + */ +enum CXDiagnosticDisplayOptions { + /** + * Display the source-location information where the + * diagnostic was located. + * + * When set, diagnostics will be prefixed by the file, line, and + * (optionally) column to which the diagnostic refers. For example, + * + * \code + * test.c:28: warning: extra tokens at end of #endif directive + * \endcode + * + * This option corresponds to the clang flag \c -fshow-source-location. + */ + CXDiagnostic_DisplaySourceLocation = 0x01, + + /** + * If displaying the source-location information of the + * diagnostic, also include the column number. + * + * This option corresponds to the clang flag \c -fshow-column. + */ + CXDiagnostic_DisplayColumn = 0x02, + + /** + * If displaying the source-location information of the + * diagnostic, also include information about source ranges in a + * machine-parsable format. + * + * This option corresponds to the clang flag + * \c -fdiagnostics-print-source-range-info. + */ + CXDiagnostic_DisplaySourceRanges = 0x04, + + /** + * Display the option name associated with this diagnostic, if any. + * + * The option name displayed (e.g., -Wconversion) will be placed in brackets + * after the diagnostic text. This option corresponds to the clang flag + * \c -fdiagnostics-show-option. + */ + CXDiagnostic_DisplayOption = 0x08, + + /** + * Display the category number associated with this diagnostic, if any. + * + * The category number is displayed within brackets after the diagnostic text. + * This option corresponds to the clang flag + * \c -fdiagnostics-show-category=id. + */ + CXDiagnostic_DisplayCategoryId = 0x10, + + /** + * Display the category name associated with this diagnostic, if any. + * + * The category name is displayed within brackets after the diagnostic text. + * This option corresponds to the clang flag + * \c -fdiagnostics-show-category=name. + */ + CXDiagnostic_DisplayCategoryName = 0x20 +}; + +/** + * Format the given diagnostic in a manner that is suitable for display. + * + * This routine will format the given diagnostic to a string, rendering + * the diagnostic according to the various options given. The + * \c clang_defaultDiagnosticDisplayOptions() function returns the set of + * options that most closely mimics the behavior of the clang compiler. + * + * \param Diagnostic The diagnostic to print. + * + * \param Options A set of options that control the diagnostic display, + * created by combining \c CXDiagnosticDisplayOptions values. + * + * \returns A new string containing for formatted diagnostic. + */ +CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, + unsigned Options); + +/** + * Retrieve the set of display options most similar to the + * default behavior of the clang compiler. + * + * \returns A set of display options suitable for use with \c + * clang_formatDiagnostic(). + */ +CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); + +/** + * Determine the severity of the given diagnostic. + */ +CINDEX_LINKAGE enum CXDiagnosticSeverity + clang_getDiagnosticSeverity(CXDiagnostic); + +/** + * Retrieve the source location of the given diagnostic. + * + * This location is where Clang would print the caret ('^') when + * displaying the diagnostic on the command line. + */ +CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic); + +/** + * Retrieve the text of the given diagnostic. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic); + +/** + * Retrieve the name of the command-line option that enabled this + * diagnostic. + * + * \param Diag The diagnostic to be queried. + * + * \param Disable If non-NULL, will be set to the option that disables this + * diagnostic (if any). + * + * \returns A string that contains the command-line option used to enable this + * warning, such as "-Wconversion" or "-pedantic". + */ +CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag, + CXString *Disable); + +/** + * Retrieve the category number for this diagnostic. + * + * Diagnostics can be categorized into groups along with other, related + * diagnostics (e.g., diagnostics under the same warning flag). This routine + * retrieves the category number for the given diagnostic. + * + * \returns The number of the category that contains this diagnostic, or zero + * if this diagnostic is uncategorized. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic); + +/** + * Retrieve the name of a particular diagnostic category. This + * is now deprecated. Use clang_getDiagnosticCategoryText() + * instead. + * + * \param Category A diagnostic category number, as returned by + * \c clang_getDiagnosticCategory(). + * + * \returns The name of the given diagnostic category. + */ +CINDEX_DEPRECATED CINDEX_LINKAGE CXString +clang_getDiagnosticCategoryName(unsigned Category); + +/** + * Retrieve the diagnostic category text for a given diagnostic. + * + * \returns The text of the given diagnostic category. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic); + +/** + * Determine the number of source ranges associated with the given + * diagnostic. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic); + +/** + * Retrieve a source range associated with the diagnostic. + * + * A diagnostic's source ranges highlight important elements in the source + * code. On the command line, Clang displays source ranges by + * underlining them with '~' characters. + * + * \param Diagnostic the diagnostic whose range is being extracted. + * + * \param Range the zero-based index specifying which range to + * + * \returns the requested source range. + */ +CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, + unsigned Range); + +/** + * Determine the number of fix-it hints associated with the + * given diagnostic. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); + +/** + * Retrieve the replacement information for a given fix-it. + * + * Fix-its are described in terms of a source range whose contents + * should be replaced by a string. This approach generalizes over + * three kinds of operations: removal of source code (the range covers + * the code to be removed and the replacement string is empty), + * replacement of source code (the range covers the code to be + * replaced and the replacement string provides the new code), and + * insertion (both the start and end of the range point at the + * insertion location, and the replacement string provides the text to + * insert). + * + * \param Diagnostic The diagnostic whose fix-its are being queried. + * + * \param FixIt The zero-based index of the fix-it. + * + * \param ReplacementRange The source range whose contents will be + * replaced with the returned replacement string. Note that source + * ranges are half-open ranges [a, b), so the source code should be + * replaced from a and up to (but not including) b. + * + * \returns A string containing text that should be replace the source + * code indicated by the \c ReplacementRange. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticFixIt( + CXDiagnostic Diagnostic, unsigned FixIt, CXSourceRange *ReplacementRange); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXErrorCode.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXErrorCode.h new file mode 100644 index 0000000000..b3a0b9d66d --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXErrorCode.h @@ -0,0 +1,62 @@ +/*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides the CXErrorCode enumerators. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXERRORCODE_H +#define LLVM_CLANG_C_CXERRORCODE_H + +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * Error codes returned by libclang routines. + * + * Zero (\c CXError_Success) is the only error code indicating success. Other + * error codes, including not yet assigned non-zero values, indicate errors. + */ +enum CXErrorCode { + /** + * No error. + */ + CXError_Success = 0, + + /** + * A generic error code, no further details are available. + * + * Errors of this kind can get their own specific error codes in future + * libclang versions. + */ + CXError_Failure = 1, + + /** + * libclang crashed while performing the requested operation. + */ + CXError_Crashed = 2, + + /** + * The function detected that the arguments violate the function + * contract. + */ + CXError_InvalidArguments = 3, + + /** + * An AST deserialization error has occurred. + */ + CXError_ASTReadError = 4 +}; + +LLVM_CLANG_C_EXTERN_C_END + +#endif + diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXFile.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXFile.h new file mode 100644 index 0000000000..c48f58c940 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXFile.h @@ -0,0 +1,83 @@ +/*===-- clang-c/CXFile.h - C Index File ---------------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides the interface to C Index files. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXFILE_H +#define LLVM_CLANG_C_CXFILE_H + +#include + +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup CINDEX_FILES File manipulation routines + * + * @{ + */ + +/** + * A particular source file that is part of a translation unit. + */ +typedef void *CXFile; + +/** + * Retrieve the complete file and path name of the given file. + */ +CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile); + +/** + * Retrieve the last modification time of the given file. + */ +CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile); + +/** + * Uniquely identifies a CXFile, that refers to the same underlying file, + * across an indexing session. + */ +typedef struct { + unsigned long long data[3]; +} CXFileUniqueID; + +/** + * Retrieve the unique ID for the given \c file. + * + * \param file the file to get the ID for. + * \param outID stores the returned CXFileUniqueID. + * \returns If there was a failure getting the unique ID, returns non-zero, + * otherwise returns 0. + */ +CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID); + +/** + * Returns non-zero if the \c file1 and \c file2 point to the same file, + * or they are both NULL. + */ +CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2); + +/** + * Returns the real path name of \c file. + * + * An empty string may be returned. Use \c clang_getFileName() in that case. + */ +CINDEX_LINKAGE CXString clang_File_tryGetRealPathName(CXFile file); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXSourceLocation.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXSourceLocation.h new file mode 100644 index 0000000000..dcb13ba273 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXSourceLocation.h @@ -0,0 +1,286 @@ +/*===-- clang-c/CXSourceLocation.h - C Index Source Location ------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides the interface to C Index source locations. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXSOURCE_LOCATION_H +#define LLVM_CLANG_C_CXSOURCE_LOCATION_H + +#include "clang-c/CXFile.h" +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup CINDEX_LOCATIONS Physical source locations + * + * Clang represents physical source locations in its abstract syntax tree in + * great detail, with file, line, and column information for the majority of + * the tokens parsed in the source code. These data types and functions are + * used to represent source location information, either for a particular + * point in the program or for a range of points in the program, and extract + * specific location information from those data types. + * + * @{ + */ + +/** + * Identifies a specific source location within a translation + * unit. + * + * Use clang_getExpansionLocation() or clang_getSpellingLocation() + * to map a source location to a particular file, line, and column. + */ +typedef struct { + const void *ptr_data[2]; + unsigned int_data; +} CXSourceLocation; + +/** + * Identifies a half-open character range in the source code. + * + * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the + * starting and end locations from a source range, respectively. + */ +typedef struct { + const void *ptr_data[2]; + unsigned begin_int_data; + unsigned end_int_data; +} CXSourceRange; + +/** + * Retrieve a NULL (invalid) source location. + */ +CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void); + +/** + * Determine whether two source locations, which must refer into + * the same translation unit, refer to exactly the same point in the source + * code. + * + * \returns non-zero if the source locations refer to the same location, zero + * if they refer to different locations. + */ +CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1, + CXSourceLocation loc2); + +/** + * Returns non-zero if the given source location is in a system header. + */ +CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location); + +/** + * Returns non-zero if the given source location is in the main file of + * the corresponding translation unit. + */ +CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location); + +/** + * Retrieve a NULL (invalid) source range. + */ +CINDEX_LINKAGE CXSourceRange clang_getNullRange(void); + +/** + * Retrieve a source range given the beginning and ending source + * locations. + */ +CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin, + CXSourceLocation end); + +/** + * Determine whether two ranges are equivalent. + * + * \returns non-zero if the ranges are the same, zero if they differ. + */ +CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1, + CXSourceRange range2); + +/** + * Returns non-zero if \p range is null. + */ +CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range); + +/** + * Retrieve the file, line, column, and offset represented by + * the given source location. + * + * If the location refers into a macro expansion, retrieves the + * location of the macro expansion. + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param file [out] if non-NULL, will be set to the file to which the given + * source location points. + * + * \param line [out] if non-NULL, will be set to the line to which the given + * source location points. + * + * \param column [out] if non-NULL, will be set to the column to which the given + * source location points. + * + * \param offset [out] if non-NULL, will be set to the offset into the + * buffer to which the given source location points. + */ +CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location, + CXFile *file, unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * Retrieve the file, line and column represented by the given source + * location, as specified in a # line directive. + * + * Example: given the following source code in a file somefile.c + * + * \code + * #123 "dummy.c" 1 + * + * static int func(void) + * { + * return 0; + * } + * \endcode + * + * the location information returned by this function would be + * + * File: dummy.c Line: 124 Column: 12 + * + * whereas clang_getExpansionLocation would have returned + * + * File: somefile.c Line: 3 Column: 12 + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param filename [out] if non-NULL, will be set to the filename of the + * source location. Note that filenames returned will be for "virtual" files, + * which don't necessarily exist on the machine running clang - e.g. when + * parsing preprocessed output obtained from a different environment. If + * a non-NULL value is passed in, remember to dispose of the returned value + * using \c clang_disposeString() once you've finished with it. For an invalid + * source location, an empty string is returned. + * + * \param line [out] if non-NULL, will be set to the line number of the + * source location. For an invalid source location, zero is returned. + * + * \param column [out] if non-NULL, will be set to the column number of the + * source location. For an invalid source location, zero is returned. + */ +CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location, + CXString *filename, + unsigned *line, unsigned *column); + +/** + * Legacy API to retrieve the file, line, column, and offset represented + * by the given source location. + * + * This interface has been replaced by the newer interface + * #clang_getExpansionLocation(). See that interface's documentation for + * details. + */ +CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location, + CXFile *file, unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * Retrieve the file, line, column, and offset represented by + * the given source location. + * + * If the location refers into a macro instantiation, return where the + * location was originally spelled in the source file. + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param file [out] if non-NULL, will be set to the file to which the given + * source location points. + * + * \param line [out] if non-NULL, will be set to the line to which the given + * source location points. + * + * \param column [out] if non-NULL, will be set to the column to which the given + * source location points. + * + * \param offset [out] if non-NULL, will be set to the offset into the + * buffer to which the given source location points. + */ +CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location, + CXFile *file, unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * Retrieve the file, line, column, and offset represented by + * the given source location. + * + * If the location refers into a macro expansion, return where the macro was + * expanded or where the macro argument was written, if the location points at + * a macro argument. + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param file [out] if non-NULL, will be set to the file to which the given + * source location points. + * + * \param line [out] if non-NULL, will be set to the line to which the given + * source location points. + * + * \param column [out] if non-NULL, will be set to the column to which the given + * source location points. + * + * \param offset [out] if non-NULL, will be set to the offset into the + * buffer to which the given source location points. + */ +CINDEX_LINKAGE void clang_getFileLocation(CXSourceLocation location, + CXFile *file, unsigned *line, + unsigned *column, unsigned *offset); + +/** + * Retrieve a source location representing the first character within a + * source range. + */ +CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range); + +/** + * Retrieve a source location representing the last character within a + * source range. + */ +CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); + +/** + * Identifies an array of ranges. + */ +typedef struct { + /** The number of ranges in the \c ranges array. */ + unsigned count; + /** + * An array of \c CXSourceRanges. + */ + CXSourceRange *ranges; +} CXSourceRangeList; + +/** + * Destroy the given \c CXSourceRangeList. + */ +CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXString.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXString.h new file mode 100644 index 0000000000..f117010c71 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/CXString.h @@ -0,0 +1,69 @@ +/*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides the interface to C Index strings. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_CXSTRING_H +#define LLVM_CLANG_C_CXSTRING_H + +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup CINDEX_STRING String manipulation routines + * \ingroup CINDEX + * + * @{ + */ + +/** + * A character string. + * + * The \c CXString type is used to return strings from the interface when + * the ownership of that string might differ from one call to the next. + * Use \c clang_getCString() to retrieve the string data and, once finished + * with the string data, call \c clang_disposeString() to free the string. + */ +typedef struct { + const void *data; + unsigned private_flags; +} CXString; + +typedef struct { + CXString *Strings; + unsigned Count; +} CXStringSet; + +/** + * Retrieve the character data associated with the given string. + */ +CINDEX_LINKAGE const char *clang_getCString(CXString string); + +/** + * Free the given string. + */ +CINDEX_LINKAGE void clang_disposeString(CXString string); + +/** + * Free the given string set. + */ +CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif + diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/Documentation.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Documentation.h new file mode 100644 index 0000000000..e04c50a0e6 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Documentation.h @@ -0,0 +1,619 @@ +/*==-- clang-c/Documentation.h - Utilities for comment processing -*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a supplementary interface for inspecting *| +|* documentation comments. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_DOCUMENTATION_H +#define LLVM_CLANG_C_DOCUMENTATION_H + +#include "clang-c/CXErrorCode.h" +#include "clang-c/ExternC.h" +#include "clang-c/Index.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * \defgroup CINDEX_COMMENT Comment introspection + * + * The routines in this group provide access to information in documentation + * comments. These facilities are distinct from the core and may be subject to + * their own schedule of stability and deprecation. + * + * @{ + */ + +/** + * A parsed comment. + */ +typedef struct { + const void *ASTNode; + CXTranslationUnit TranslationUnit; +} CXComment; + +/** + * Given a cursor that represents a documentable entity (e.g., + * declaration), return the associated parsed comment as a + * \c CXComment_FullComment AST node. + */ +CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C); + +/** + * Describes the type of the comment AST node (\c CXComment). A comment + * node can be considered block content (e. g., paragraph), inline content + * (plain text) or neither (the root AST node). + */ +enum CXCommentKind { + /** + * Null comment. No AST node is constructed at the requested location + * because there is no text or a syntax error. + */ + CXComment_Null = 0, + + /** + * Plain text. Inline content. + */ + CXComment_Text = 1, + + /** + * A command with word-like arguments that is considered inline content. + * + * For example: \\c command. + */ + CXComment_InlineCommand = 2, + + /** + * HTML start tag with attributes (name-value pairs). Considered + * inline content. + * + * For example: + * \verbatim + *

+ * \endverbatim + */ + CXComment_HTMLStartTag = 3, + + /** + * HTML end tag. Considered inline content. + * + * For example: + * \verbatim + * + * \endverbatim + */ + CXComment_HTMLEndTag = 4, + + /** + * A paragraph, contains inline comment. The paragraph itself is + * block content. + */ + CXComment_Paragraph = 5, + + /** + * A command that has zero or more word-like arguments (number of + * word-like arguments depends on command name) and a paragraph as an + * argument. Block command is block content. + * + * Paragraph argument is also a child of the block command. + * + * For example: \has 0 word-like arguments and a paragraph argument. + * + * AST nodes of special kinds that parser knows about (e. g., \\param + * command) have their own node kinds. + */ + CXComment_BlockCommand = 6, + + /** + * A \\param or \\arg command that describes the function parameter + * (name, passing direction, description). + * + * For example: \\param [in] ParamName description. + */ + CXComment_ParamCommand = 7, + + /** + * A \\tparam command that describes a template parameter (name and + * description). + * + * For example: \\tparam T description. + */ + CXComment_TParamCommand = 8, + + /** + * A verbatim block command (e. g., preformatted code). Verbatim + * block has an opening and a closing command and contains multiple lines of + * text (\c CXComment_VerbatimBlockLine child nodes). + * + * For example: + * \\verbatim + * aaa + * \\endverbatim + */ + CXComment_VerbatimBlockCommand = 9, + + /** + * A line of text that is contained within a + * CXComment_VerbatimBlockCommand node. + */ + CXComment_VerbatimBlockLine = 10, + + /** + * A verbatim line command. Verbatim line has an opening command, + * a single line of text (up to the newline after the opening command) and + * has no closing command. + */ + CXComment_VerbatimLine = 11, + + /** + * A full comment attached to a declaration, contains block content. + */ + CXComment_FullComment = 12 +}; + +/** + * The most appropriate rendering mode for an inline command, chosen on + * command semantics in Doxygen. + */ +enum CXCommentInlineCommandRenderKind { + /** + * Command argument should be rendered in a normal font. + */ + CXCommentInlineCommandRenderKind_Normal, + + /** + * Command argument should be rendered in a bold font. + */ + CXCommentInlineCommandRenderKind_Bold, + + /** + * Command argument should be rendered in a monospaced font. + */ + CXCommentInlineCommandRenderKind_Monospaced, + + /** + * Command argument should be rendered emphasized (typically italic + * font). + */ + CXCommentInlineCommandRenderKind_Emphasized, + + /** + * Command argument should not be rendered (since it only defines an anchor). + */ + CXCommentInlineCommandRenderKind_Anchor +}; + +/** + * Describes parameter passing direction for \\param or \\arg command. + */ +enum CXCommentParamPassDirection { + /** + * The parameter is an input parameter. + */ + CXCommentParamPassDirection_In, + + /** + * The parameter is an output parameter. + */ + CXCommentParamPassDirection_Out, + + /** + * The parameter is an input and output parameter. + */ + CXCommentParamPassDirection_InOut +}; + +/** + * \param Comment AST node of any kind. + * + * \returns the type of the AST node. + */ +CINDEX_LINKAGE enum CXCommentKind clang_Comment_getKind(CXComment Comment); + +/** + * \param Comment AST node of any kind. + * + * \returns number of children of the AST node. + */ +CINDEX_LINKAGE unsigned clang_Comment_getNumChildren(CXComment Comment); + +/** + * \param Comment AST node of any kind. + * + * \param ChildIdx child index (zero-based). + * + * \returns the specified child of the AST node. + */ +CINDEX_LINKAGE +CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx); + +/** + * A \c CXComment_Paragraph node is considered whitespace if it contains + * only \c CXComment_Text nodes that are empty or whitespace. + * + * Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are + * never considered whitespace. + * + * \returns non-zero if \c Comment is whitespace. + */ +CINDEX_LINKAGE unsigned clang_Comment_isWhitespace(CXComment Comment); + +/** + * \returns non-zero if \c Comment is inline content and has a newline + * immediately following it in the comment text. Newlines between paragraphs + * do not count. + */ +CINDEX_LINKAGE +unsigned clang_InlineContentComment_hasTrailingNewline(CXComment Comment); + +/** + * \param Comment a \c CXComment_Text AST node. + * + * \returns text contained in the AST node. + */ +CINDEX_LINKAGE CXString clang_TextComment_getText(CXComment Comment); + +/** + * \param Comment a \c CXComment_InlineCommand AST node. + * + * \returns name of the inline command. + */ +CINDEX_LINKAGE +CXString clang_InlineCommandComment_getCommandName(CXComment Comment); + +/** + * \param Comment a \c CXComment_InlineCommand AST node. + * + * \returns the most appropriate rendering mode, chosen on command + * semantics in Doxygen. + */ +CINDEX_LINKAGE enum CXCommentInlineCommandRenderKind +clang_InlineCommandComment_getRenderKind(CXComment Comment); + +/** + * \param Comment a \c CXComment_InlineCommand AST node. + * + * \returns number of command arguments. + */ +CINDEX_LINKAGE +unsigned clang_InlineCommandComment_getNumArgs(CXComment Comment); + +/** + * \param Comment a \c CXComment_InlineCommand AST node. + * + * \param ArgIdx argument index (zero-based). + * + * \returns text of the specified argument. + */ +CINDEX_LINKAGE +CXString clang_InlineCommandComment_getArgText(CXComment Comment, + unsigned ArgIdx); + +/** + * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST + * node. + * + * \returns HTML tag name. + */ +CINDEX_LINKAGE CXString clang_HTMLTagComment_getTagName(CXComment Comment); + +/** + * \param Comment a \c CXComment_HTMLStartTag AST node. + * + * \returns non-zero if tag is self-closing (for example, <br />). + */ +CINDEX_LINKAGE +unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment Comment); + +/** + * \param Comment a \c CXComment_HTMLStartTag AST node. + * + * \returns number of attributes (name-value pairs) attached to the start tag. + */ +CINDEX_LINKAGE unsigned clang_HTMLStartTag_getNumAttrs(CXComment Comment); + +/** + * \param Comment a \c CXComment_HTMLStartTag AST node. + * + * \param AttrIdx attribute index (zero-based). + * + * \returns name of the specified attribute. + */ +CINDEX_LINKAGE +CXString clang_HTMLStartTag_getAttrName(CXComment Comment, unsigned AttrIdx); + +/** + * \param Comment a \c CXComment_HTMLStartTag AST node. + * + * \param AttrIdx attribute index (zero-based). + * + * \returns value of the specified attribute. + */ +CINDEX_LINKAGE +CXString clang_HTMLStartTag_getAttrValue(CXComment Comment, unsigned AttrIdx); + +/** + * \param Comment a \c CXComment_BlockCommand AST node. + * + * \returns name of the block command. + */ +CINDEX_LINKAGE +CXString clang_BlockCommandComment_getCommandName(CXComment Comment); + +/** + * \param Comment a \c CXComment_BlockCommand AST node. + * + * \returns number of word-like arguments. + */ +CINDEX_LINKAGE +unsigned clang_BlockCommandComment_getNumArgs(CXComment Comment); + +/** + * \param Comment a \c CXComment_BlockCommand AST node. + * + * \param ArgIdx argument index (zero-based). + * + * \returns text of the specified word-like argument. + */ +CINDEX_LINKAGE +CXString clang_BlockCommandComment_getArgText(CXComment Comment, + unsigned ArgIdx); + +/** + * \param Comment a \c CXComment_BlockCommand or + * \c CXComment_VerbatimBlockCommand AST node. + * + * \returns paragraph argument of the block command. + */ +CINDEX_LINKAGE +CXComment clang_BlockCommandComment_getParagraph(CXComment Comment); + +/** + * \param Comment a \c CXComment_ParamCommand AST node. + * + * \returns parameter name. + */ +CINDEX_LINKAGE +CXString clang_ParamCommandComment_getParamName(CXComment Comment); + +/** + * \param Comment a \c CXComment_ParamCommand AST node. + * + * \returns non-zero if the parameter that this AST node represents was found + * in the function prototype and \c clang_ParamCommandComment_getParamIndex + * function will return a meaningful value. + */ +CINDEX_LINKAGE +unsigned clang_ParamCommandComment_isParamIndexValid(CXComment Comment); + +/** + * \param Comment a \c CXComment_ParamCommand AST node. + * + * \returns zero-based parameter index in function prototype. + */ +CINDEX_LINKAGE +unsigned clang_ParamCommandComment_getParamIndex(CXComment Comment); + +/** + * \param Comment a \c CXComment_ParamCommand AST node. + * + * \returns non-zero if parameter passing direction was specified explicitly in + * the comment. + */ +CINDEX_LINKAGE +unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment Comment); + +/** + * \param Comment a \c CXComment_ParamCommand AST node. + * + * \returns parameter passing direction. + */ +CINDEX_LINKAGE +enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection( + CXComment Comment); + +/** + * \param Comment a \c CXComment_TParamCommand AST node. + * + * \returns template parameter name. + */ +CINDEX_LINKAGE +CXString clang_TParamCommandComment_getParamName(CXComment Comment); + +/** + * \param Comment a \c CXComment_TParamCommand AST node. + * + * \returns non-zero if the parameter that this AST node represents was found + * in the template parameter list and + * \c clang_TParamCommandComment_getDepth and + * \c clang_TParamCommandComment_getIndex functions will return a meaningful + * value. + */ +CINDEX_LINKAGE +unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment); + +/** + * \param Comment a \c CXComment_TParamCommand AST node. + * + * \returns zero-based nesting depth of this parameter in the template parameter list. + * + * For example, + * \verbatim + * template class TT> + * void test(TT aaa); + * \endverbatim + * for C and TT nesting depth is 0, + * for T nesting depth is 1. + */ +CINDEX_LINKAGE +unsigned clang_TParamCommandComment_getDepth(CXComment Comment); + +/** + * \param Comment a \c CXComment_TParamCommand AST node. + * + * \returns zero-based parameter index in the template parameter list at a + * given nesting depth. + * + * For example, + * \verbatim + * template class TT> + * void test(TT aaa); + * \endverbatim + * for C and TT nesting depth is 0, so we can ask for index at depth 0: + * at depth 0 C's index is 0, TT's index is 1. + * + * For T nesting depth is 1, so we can ask for index at depth 0 and 1: + * at depth 0 T's index is 1 (same as TT's), + * at depth 1 T's index is 0. + */ +CINDEX_LINKAGE +unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth); + +/** + * \param Comment a \c CXComment_VerbatimBlockLine AST node. + * + * \returns text contained in the AST node. + */ +CINDEX_LINKAGE +CXString clang_VerbatimBlockLineComment_getText(CXComment Comment); + +/** + * \param Comment a \c CXComment_VerbatimLine AST node. + * + * \returns text contained in the AST node. + */ +CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment); + +/** + * Convert an HTML tag AST node to string. + * + * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST + * node. + * + * \returns string containing an HTML tag. + */ +CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment); + +/** + * Convert a given full parsed comment to an HTML fragment. + * + * Specific details of HTML layout are subject to change. Don't try to parse + * this HTML back into an AST, use other APIs instead. + * + * Currently the following CSS classes are used: + * \li "para-brief" for \paragraph and equivalent commands; + * \li "para-returns" for \\returns paragraph and equivalent commands; + * \li "word-returns" for the "Returns" word in \\returns paragraph. + * + * Function argument documentation is rendered as a \ list with arguments + * sorted in function prototype order. CSS classes used: + * \li "param-name-index-NUMBER" for parameter name (\); + * \li "param-descr-index-NUMBER" for parameter description (\); + * \li "param-name-index-invalid" and "param-descr-index-invalid" are used if + * parameter index is invalid. + * + * Template parameter documentation is rendered as a \ list with + * parameters sorted in template parameter list order. CSS classes used: + * \li "tparam-name-index-NUMBER" for parameter name (\); + * \li "tparam-descr-index-NUMBER" for parameter description (\); + * \li "tparam-name-index-other" and "tparam-descr-index-other" are used for + * names inside template template parameters; + * \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if + * parameter position is invalid. + * + * \param Comment a \c CXComment_FullComment AST node. + * + * \returns string containing an HTML fragment. + */ +CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment); + +/** + * Convert a given full parsed comment to an XML document. + * + * A Relax NG schema for the XML can be found in comment-xml-schema.rng file + * inside clang source tree. + * + * \param Comment a \c CXComment_FullComment AST node. + * + * \returns string containing an XML document. + */ +CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); + +/** + * CXAPISet is an opaque type that represents a data structure containing all + * the API information for a given translation unit. This can be used for a + * single symbol symbol graph for a given symbol. + */ +typedef struct CXAPISetImpl *CXAPISet; + +/** + * Traverses the translation unit to create a \c CXAPISet. + * + * \param tu is the \c CXTranslationUnit to build the \c CXAPISet for. + * + * \param out_api is a pointer to the output of this function. It is needs to be + * disposed of by calling clang_disposeAPISet. + * + * \returns Error code indicating success or failure of the APISet creation. + */ +CINDEX_LINKAGE enum CXErrorCode clang_createAPISet(CXTranslationUnit tu, + CXAPISet *out_api); + +/** + * Dispose of an APISet. + * + * The provided \c CXAPISet can not be used after this function is called. + */ +CINDEX_LINKAGE void clang_disposeAPISet(CXAPISet api); + +/** + * Generate a single symbol symbol graph for the given USR. Returns a null + * string if the associated symbol can not be found in the provided \c CXAPISet. + * + * The output contains the symbol graph as well as some additional information + * about related symbols. + * + * \param usr is a string containing the USR of the symbol to generate the + * symbol graph for. + * + * \param api the \c CXAPISet to look for the symbol in. + * + * \returns a string containing the serialized symbol graph representation for + * the symbol being queried or a null string if it can not be found in the + * APISet. + */ +CINDEX_LINKAGE CXString clang_getSymbolGraphForUSR(const char *usr, + CXAPISet api); + +/** + * Generate a single symbol symbol graph for the declaration at the given + * cursor. Returns a null string if the AST node for the cursor isn't a + * declaration. + * + * The output contains the symbol graph as well as some additional information + * about related symbols. + * + * \param cursor the declaration for which to generate the single symbol symbol + * graph. + * + * \returns a string containing the serialized symbol graph representation for + * the symbol being queried or a null string if it can not be found in the + * APISet. + */ +CINDEX_LINKAGE CXString clang_getSymbolGraphForCursor(CXCursor cursor); + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif /* CLANG_C_DOCUMENTATION_H */ + diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/ExternC.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/ExternC.h new file mode 100644 index 0000000000..384f24d47b --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/ExternC.h @@ -0,0 +1,39 @@ +/*===- clang-c/ExternC.h - Wrapper for 'extern "C"' ---------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines an 'extern "C"' wrapper. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_EXTERN_C_H +#define LLVM_CLANG_C_EXTERN_C_H + +#ifdef __clang__ +#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") +#define LLVM_CLANG_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") +#else +#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_STRICT_PROTOTYPES_END +#endif + +#ifdef __cplusplus +#define LLVM_CLANG_C_EXTERN_C_BEGIN \ + extern "C" { \ + LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_EXTERN_C_END \ + LLVM_CLANG_C_STRICT_PROTOTYPES_END \ + } +#else +#define LLVM_CLANG_C_EXTERN_C_BEGIN LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_STRICT_PROTOTYPES_END +#endif + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/FatalErrorHandler.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/FatalErrorHandler.h new file mode 100644 index 0000000000..22f34fa815 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/FatalErrorHandler.h @@ -0,0 +1,32 @@ +/*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H +#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H + +#include "clang-c/ExternC.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** + * Installs error handler that prints error message to stderr and calls abort(). + * Replaces currently installed error handler (if any). + */ +void clang_install_aborting_llvm_fatal_error_handler(void); + +/** + * Removes currently installed error handler (if any). + * If no error handler is intalled, the default strategy is to print error + * message to stderr and call exit(1). + */ +void clang_uninstall_llvm_fatal_error_handler(void); + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/Index.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Index.h new file mode 100644 index 0000000000..64ab337895 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Index.h @@ -0,0 +1,6666 @@ +/*===-- clang-c/Index.h - Indexing Public C Interface -------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a public interface to a Clang library for extracting *| +|* high-level symbol information from source files without exposing the full *| +|* Clang C++ API. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_INDEX_H +#define LLVM_CLANG_C_INDEX_H + +#include "clang-c/BuildSystem.h" +#include "clang-c/CXDiagnostic.h" +#include "clang-c/CXErrorCode.h" +#include "clang-c/CXFile.h" +#include "clang-c/CXSourceLocation.h" +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" + +/** + * The version constants for the libclang API. + * CINDEX_VERSION_MINOR should increase when there are API additions. + * CINDEX_VERSION_MAJOR is intended for "major" source/ABI breaking changes. + * + * The policy about the libclang API was always to keep it source and ABI + * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. + */ +#define CINDEX_VERSION_MAJOR 0 +#define CINDEX_VERSION_MINOR 64 + +#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) + +#define CINDEX_VERSION \ + CINDEX_VERSION_ENCODE(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR) + +#define CINDEX_VERSION_STRINGIZE_(major, minor) #major "." #minor +#define CINDEX_VERSION_STRINGIZE(major, minor) \ + CINDEX_VERSION_STRINGIZE_(major, minor) + +#define CINDEX_VERSION_STRING \ + CINDEX_VERSION_STRINGIZE(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR) + +#ifndef __has_feature +#define __has_feature(feature) 0 +#endif + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/** \defgroup CINDEX libclang: C Interface to Clang + * + * The C Interface to Clang provides a relatively small API that exposes + * facilities for parsing source code into an abstract syntax tree (AST), + * loading already-parsed ASTs, traversing the AST, associating + * physical source locations with elements within the AST, and other + * facilities that support Clang-based development tools. + * + * This C interface to Clang will never provide all of the information + * representation stored in Clang's C++ AST, nor should it: the intent is to + * maintain an API that is relatively stable from one release to the next, + * providing only the basic functionality needed to support development tools. + * + * To avoid namespace pollution, data types are prefixed with "CX" and + * functions are prefixed with "clang_". + * + * @{ + */ + +/** + * An "index" that consists of a set of translation units that would + * typically be linked together into an executable or library. + */ +typedef void *CXIndex; + +/** + * An opaque type representing target information for a given translation + * unit. + */ +typedef struct CXTargetInfoImpl *CXTargetInfo; + +/** + * A single translation unit, which resides in an index. + */ +typedef struct CXTranslationUnitImpl *CXTranslationUnit; + +/** + * Opaque pointer representing client data that will be passed through + * to various callbacks and visitors. + */ +typedef void *CXClientData; + +/** + * Provides the contents of a file that has not yet been saved to disk. + * + * Each CXUnsavedFile instance provides the name of a file on the + * system along with the current contents of that file that have not + * yet been saved to disk. + */ +struct CXUnsavedFile { + /** + * The file whose contents have not yet been saved. + * + * This file must already exist in the file system. + */ + const char *Filename; + + /** + * A buffer containing the unsaved contents of this file. + */ + const char *Contents; + + /** + * The length of the unsaved contents of this buffer. + */ + unsigned long Length; +}; + +/** + * Describes the availability of a particular entity, which indicates + * whether the use of this entity will result in a warning or error due to + * it being deprecated or unavailable. + */ +enum CXAvailabilityKind { + /** + * The entity is available. + */ + CXAvailability_Available, + /** + * The entity is available, but has been deprecated (and its use is + * not recommended). + */ + CXAvailability_Deprecated, + /** + * The entity is not available; any use of it will be an error. + */ + CXAvailability_NotAvailable, + /** + * The entity is available, but not accessible; any use of it will be + * an error. + */ + CXAvailability_NotAccessible +}; + +/** + * Describes a version number of the form major.minor.subminor. + */ +typedef struct CXVersion { + /** + * The major version number, e.g., the '10' in '10.7.3'. A negative + * value indicates that there is no version number at all. + */ + int Major; + /** + * The minor version number, e.g., the '7' in '10.7.3'. This value + * will be negative if no minor version number was provided, e.g., for + * version '10'. + */ + int Minor; + /** + * The subminor version number, e.g., the '3' in '10.7.3'. This value + * will be negative if no minor or subminor version number was provided, + * e.g., in version '10' or '10.7'. + */ + int Subminor; +} CXVersion; + +/** + * Describes the exception specification of a cursor. + * + * A negative value indicates that the cursor is not a function declaration. + */ +enum CXCursor_ExceptionSpecificationKind { + /** + * The cursor has no exception specification. + */ + CXCursor_ExceptionSpecificationKind_None, + + /** + * The cursor has exception specification throw() + */ + CXCursor_ExceptionSpecificationKind_DynamicNone, + + /** + * The cursor has exception specification throw(T1, T2) + */ + CXCursor_ExceptionSpecificationKind_Dynamic, + + /** + * The cursor has exception specification throw(...). + */ + CXCursor_ExceptionSpecificationKind_MSAny, + + /** + * The cursor has exception specification basic noexcept. + */ + CXCursor_ExceptionSpecificationKind_BasicNoexcept, + + /** + * The cursor has exception specification computed noexcept. + */ + CXCursor_ExceptionSpecificationKind_ComputedNoexcept, + + /** + * The exception specification has not yet been evaluated. + */ + CXCursor_ExceptionSpecificationKind_Unevaluated, + + /** + * The exception specification has not yet been instantiated. + */ + CXCursor_ExceptionSpecificationKind_Uninstantiated, + + /** + * The exception specification has not been parsed yet. + */ + CXCursor_ExceptionSpecificationKind_Unparsed, + + /** + * The cursor has a __declspec(nothrow) exception specification. + */ + CXCursor_ExceptionSpecificationKind_NoThrow +}; + +/** + * Provides a shared context for creating translation units. + * + * It provides two options: + * + * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" + * declarations (when loading any new translation units). A "local" declaration + * is one that belongs in the translation unit itself and not in a precompiled + * header that was used by the translation unit. If zero, all declarations + * will be enumerated. + * + * Here is an example: + * + * \code + * // excludeDeclsFromPCH = 1, displayDiagnostics=1 + * Idx = clang_createIndex(1, 1); + * + * // IndexTest.pch was produced with the following command: + * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" + * TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); + * + * // This will load all the symbols from 'IndexTest.pch' + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * // This will load all the symbols from 'IndexTest.c', excluding symbols + * // from 'IndexTest.pch'. + * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" }; + * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args, + * 0, 0); + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * \endcode + * + * This process of creating the 'pch', loading it separately, and using it (via + * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks + * (which gives the indexer the same performance benefit as the compiler). + */ +CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics); + +/** + * Destroy the given index. + * + * The index must not be destroyed until all of the translation units created + * within that index have been destroyed. + */ +CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); + +typedef enum { + /** + * Use the default value of an option that may depend on the process + * environment. + */ + CXChoice_Default = 0, + /** + * Enable the option. + */ + CXChoice_Enabled = 1, + /** + * Disable the option. + */ + CXChoice_Disabled = 2 +} CXChoice; + +typedef enum { + /** + * Used to indicate that no special CXIndex options are needed. + */ + CXGlobalOpt_None = 0x0, + + /** + * Used to indicate that threads that libclang creates for indexing + * purposes should use background priority. + * + * Affects #clang_indexSourceFile, #clang_indexTranslationUnit, + * #clang_parseTranslationUnit, #clang_saveTranslationUnit. + */ + CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1, + + /** + * Used to indicate that threads that libclang creates for editing + * purposes should use background priority. + * + * Affects #clang_reparseTranslationUnit, #clang_codeCompleteAt, + * #clang_annotateTokens + */ + CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2, + + /** + * Used to indicate that all threads that libclang creates should use + * background priority. + */ + CXGlobalOpt_ThreadBackgroundPriorityForAll = + CXGlobalOpt_ThreadBackgroundPriorityForIndexing | + CXGlobalOpt_ThreadBackgroundPriorityForEditing + +} CXGlobalOptFlags; + +/** + * Index initialization options. + * + * 0 is the default value of each member of this struct except for Size. + * Initialize the struct in one of the following three ways to avoid adapting + * code each time a new member is added to it: + * \code + * CXIndexOptions Opts; + * memset(&Opts, 0, sizeof(Opts)); + * Opts.Size = sizeof(CXIndexOptions); + * \endcode + * or explicitly initialize the first data member and zero-initialize the rest: + * \code + * CXIndexOptions Opts = { sizeof(CXIndexOptions) }; + * \endcode + * or to prevent the -Wmissing-field-initializers warning for the above version: + * \code + * CXIndexOptions Opts{}; + * Opts.Size = sizeof(CXIndexOptions); + * \endcode + */ +typedef struct CXIndexOptions { + /** + * The size of struct CXIndexOptions used for option versioning. + * + * Always initialize this member to sizeof(CXIndexOptions), or assign + * sizeof(CXIndexOptions) to it right after creating a CXIndexOptions object. + */ + unsigned Size; + /** + * A CXChoice enumerator that specifies the indexing priority policy. + * \sa CXGlobalOpt_ThreadBackgroundPriorityForIndexing + */ + unsigned char ThreadBackgroundPriorityForIndexing; + /** + * A CXChoice enumerator that specifies the editing priority policy. + * \sa CXGlobalOpt_ThreadBackgroundPriorityForEditing + */ + unsigned char ThreadBackgroundPriorityForEditing; + /** + * \see clang_createIndex() + */ + unsigned ExcludeDeclarationsFromPCH : 1; + /** + * \see clang_createIndex() + */ + unsigned DisplayDiagnostics : 1; + /** + * Store PCH in memory. If zero, PCH are stored in temporary files. + */ + unsigned StorePreamblesInMemory : 1; + unsigned /*Reserved*/ : 13; + + /** + * The path to a directory, in which to store temporary PCH files. If null or + * empty, the default system temporary directory is used. These PCH files are + * deleted on clean exit but stay on disk if the program crashes or is killed. + * + * This option is ignored if \a StorePreamblesInMemory is non-zero. + * + * Libclang does not create the directory at the specified path in the file + * system. Therefore it must exist, or storing PCH files will fail. + */ + const char *PreambleStoragePath; + /** + * Specifies a path which will contain log files for certain libclang + * invocations. A null value implies that libclang invocations are not logged. + */ + const char *InvocationEmissionPath; +} CXIndexOptions; + +/** + * Provides a shared context for creating translation units. + * + * Call this function instead of clang_createIndex() if you need to configure + * the additional options in CXIndexOptions. + * + * \returns The created index or null in case of error, such as an unsupported + * value of options->Size. + * + * For example: + * \code + * CXIndex createIndex(const char *ApplicationTemporaryPath) { + * const int ExcludeDeclarationsFromPCH = 1; + * const int DisplayDiagnostics = 1; + * CXIndex Idx; + * #if CINDEX_VERSION_MINOR >= 64 + * CXIndexOptions Opts; + * memset(&Opts, 0, sizeof(Opts)); + * Opts.Size = sizeof(CXIndexOptions); + * Opts.ThreadBackgroundPriorityForIndexing = 1; + * Opts.ExcludeDeclarationsFromPCH = ExcludeDeclarationsFromPCH; + * Opts.DisplayDiagnostics = DisplayDiagnostics; + * Opts.PreambleStoragePath = ApplicationTemporaryPath; + * Idx = clang_createIndexWithOptions(&Opts); + * if (Idx) + * return Idx; + * fprintf(stderr, + * "clang_createIndexWithOptions() failed. " + * "CINDEX_VERSION_MINOR = %d, sizeof(CXIndexOptions) = %u\n", + * CINDEX_VERSION_MINOR, Opts.Size); + * #else + * (void)ApplicationTemporaryPath; + * #endif + * Idx = clang_createIndex(ExcludeDeclarationsFromPCH, DisplayDiagnostics); + * clang_CXIndex_setGlobalOptions( + * Idx, clang_CXIndex_getGlobalOptions(Idx) | + * CXGlobalOpt_ThreadBackgroundPriorityForIndexing); + * return Idx; + * } + * \endcode + * + * \sa clang_createIndex() + */ +CINDEX_LINKAGE CXIndex +clang_createIndexWithOptions(const CXIndexOptions *options); + +/** + * Sets general options associated with a CXIndex. + * + * This function is DEPRECATED. Set + * CXIndexOptions::ThreadBackgroundPriorityForIndexing and/or + * CXIndexOptions::ThreadBackgroundPriorityForEditing and call + * clang_createIndexWithOptions() instead. + * + * For example: + * \code + * CXIndex idx = ...; + * clang_CXIndex_setGlobalOptions(idx, + * clang_CXIndex_getGlobalOptions(idx) | + * CXGlobalOpt_ThreadBackgroundPriorityForIndexing); + * \endcode + * + * \param options A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags. + */ +CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options); + +/** + * Gets the general options associated with a CXIndex. + * + * This function allows to obtain the final option values used by libclang after + * specifying the option policies via CXChoice enumerators. + * + * \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that + * are associated with the given CXIndex object. + */ +CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex); + +/** + * Sets the invocation emission path option in a CXIndex. + * + * This function is DEPRECATED. Set CXIndexOptions::InvocationEmissionPath and + * call clang_createIndexWithOptions() instead. + * + * The invocation emission path specifies a path which will contain log + * files for certain libclang invocations. A null value (default) implies that + * libclang invocations are not logged.. + */ +CINDEX_LINKAGE void +clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path); + +/** + * Determine whether the given header is guarded against + * multiple inclusions, either with the conventional + * \#ifndef/\#define/\#endif macro guards or with \#pragma once. + */ +CINDEX_LINKAGE unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, + CXFile file); + +/** + * Retrieve a file handle within the given translation unit. + * + * \param tu the translation unit + * + * \param file_name the name of the file. + * + * \returns the file handle for the named file in the translation unit \p tu, + * or a NULL file handle if the file was not a part of this translation unit. + */ +CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu, + const char *file_name); + +/** + * Retrieve the buffer associated with the given file. + * + * \param tu the translation unit + * + * \param file the file for which to retrieve the buffer. + * + * \param size [out] if non-NULL, will be set to the size of the buffer. + * + * \returns a pointer to the buffer in memory that holds the contents of + * \p file, or a NULL pointer when the file is not loaded. + */ +CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu, + CXFile file, size_t *size); + +/** + * Retrieves the source location associated with a given file/line/column + * in a particular translation unit. + */ +CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu, + CXFile file, unsigned line, + unsigned column); +/** + * Retrieves the source location associated with a given character offset + * in a particular translation unit. + */ +CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu, + CXFile file, + unsigned offset); + +/** + * Retrieve all ranges that were skipped by the preprocessor. + * + * The preprocessor will skip lines when they are surrounded by an + * if/ifdef/ifndef directive whose condition does not evaluate to true. + */ +CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu, + CXFile file); + +/** + * Retrieve all ranges from all files that were skipped by the + * preprocessor. + * + * The preprocessor will skip lines when they are surrounded by an + * if/ifdef/ifndef directive whose condition does not evaluate to true. + */ +CINDEX_LINKAGE CXSourceRangeList * +clang_getAllSkippedRanges(CXTranslationUnit tu); + +/** + * Determine the number of diagnostics produced for the given + * translation unit. + */ +CINDEX_LINKAGE unsigned clang_getNumDiagnostics(CXTranslationUnit Unit); + +/** + * Retrieve a diagnostic associated with the given translation unit. + * + * \param Unit the translation unit to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, + unsigned Index); + +/** + * Retrieve the complete set of diagnostics associated with a + * translation unit. + * + * \param Unit the translation unit to query. + */ +CINDEX_LINKAGE CXDiagnosticSet +clang_getDiagnosticSetFromTU(CXTranslationUnit Unit); + +/** + * \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation + * + * The routines in this group provide the ability to create and destroy + * translation units from files, either by parsing the contents of the files or + * by reading in a serialized representation of a translation unit. + * + * @{ + */ + +/** + * Get the original translation unit source file name. + */ +CINDEX_LINKAGE CXString +clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); + +/** + * Return the CXTranslationUnit for a given source file and the provided + * command line arguments one would pass to the compiler. + * + * Note: The 'source_filename' argument is optional. If the caller provides a + * NULL pointer, the name of the source file is expected to reside in the + * specified command line arguments. + * + * Note: When encountered in 'clang_command_line_args', the following options + * are ignored: + * + * '-c' + * '-emit-ast' + * '-fsyntax-only' + * '-o \' (both '-o' and '\' are ignored) + * + * \param CIdx The index object with which the translation unit will be + * associated. + * + * \param source_filename The name of the source file to load, or NULL if the + * source file is included in \p clang_command_line_args. + * + * \param num_clang_command_line_args The number of command-line arguments in + * \p clang_command_line_args. + * + * \param clang_command_line_args The command-line arguments that would be + * passed to the \c clang executable if it were being invoked out-of-process. + * These command-line options will be parsed and will affect how the translation + * unit is parsed. Note that the following options are ignored: '-c', + * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \'. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for code completion, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + */ +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, const char *source_filename, int num_clang_command_line_args, + const char *const *clang_command_line_args, unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files); + +/** + * Same as \c clang_createTranslationUnit2, but returns + * the \c CXTranslationUnit instead of an error code. In case of an error this + * routine returns a \c NULL \c CXTranslationUnit, without further detailed + * error codes. + */ +CINDEX_LINKAGE CXTranslationUnit +clang_createTranslationUnit(CXIndex CIdx, const char *ast_filename); + +/** + * Create a translation unit from an AST file (\c -emit-ast). + * + * \param[out] out_TU A non-NULL pointer to store the created + * \c CXTranslationUnit. + * + * \returns Zero on success, otherwise returns an error code. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_createTranslationUnit2(CXIndex CIdx, const char *ast_filename, + CXTranslationUnit *out_TU); + +/** + * Flags that control the creation of translation units. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * constructing the translation unit. + */ +enum CXTranslationUnit_Flags { + /** + * Used to indicate that no special translation-unit options are + * needed. + */ + CXTranslationUnit_None = 0x0, + + /** + * Used to indicate that the parser should construct a "detailed" + * preprocessing record, including all macro definitions and instantiations. + * + * Constructing a detailed preprocessing record requires more memory + * and time to parse, since the information contained in the record + * is usually not retained. However, it can be useful for + * applications that require more detailed information about the + * behavior of the preprocessor. + */ + CXTranslationUnit_DetailedPreprocessingRecord = 0x01, + + /** + * Used to indicate that the translation unit is incomplete. + * + * When a translation unit is considered "incomplete", semantic + * analysis that is typically performed at the end of the + * translation unit will be suppressed. For example, this suppresses + * the completion of tentative declarations in C and of + * instantiation of implicitly-instantiation function templates in + * C++. This option is typically used when parsing a header with the + * intent of producing a precompiled header. + */ + CXTranslationUnit_Incomplete = 0x02, + + /** + * Used to indicate that the translation unit should be built with an + * implicit precompiled header for the preamble. + * + * An implicit precompiled header is used as an optimization when a + * particular translation unit is likely to be reparsed many times + * when the sources aren't changing that often. In this case, an + * implicit precompiled header will be built containing all of the + * initial includes at the top of the main file (what we refer to as + * the "preamble" of the file). In subsequent parses, if the + * preamble or the files in it have not changed, \c + * clang_reparseTranslationUnit() will re-use the implicit + * precompiled header to improve parsing performance. + */ + CXTranslationUnit_PrecompiledPreamble = 0x04, + + /** + * Used to indicate that the translation unit should cache some + * code-completion results with each reparse of the source file. + * + * Caching of code-completion results is a performance optimization that + * introduces some overhead to reparsing but improves the performance of + * code-completion operations. + */ + CXTranslationUnit_CacheCompletionResults = 0x08, + + /** + * Used to indicate that the translation unit will be serialized with + * \c clang_saveTranslationUnit. + * + * This option is typically used when parsing a header with the intent of + * producing a precompiled header. + */ + CXTranslationUnit_ForSerialization = 0x10, + + /** + * DEPRECATED: Enabled chained precompiled preambles in C++. + * + * Note: this is a *temporary* option that is available only while + * we are testing C++ precompiled preamble support. It is deprecated. + */ + CXTranslationUnit_CXXChainedPCH = 0x20, + + /** + * Used to indicate that function/method bodies should be skipped while + * parsing. + * + * This option can be used to search for declarations/definitions while + * ignoring the usages. + */ + CXTranslationUnit_SkipFunctionBodies = 0x40, + + /** + * Used to indicate that brief documentation comments should be + * included into the set of code completions returned from this translation + * unit. + */ + CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80, + + /** + * Used to indicate that the precompiled preamble should be created on + * the first parse. Otherwise it will be created on the first reparse. This + * trades runtime on the first parse (serializing the preamble takes time) for + * reduced runtime on the second parse (can now reuse the preamble). + */ + CXTranslationUnit_CreatePreambleOnFirstParse = 0x100, + + /** + * Do not stop processing when fatal errors are encountered. + * + * When fatal errors are encountered while parsing a translation unit, + * semantic analysis is typically stopped early when compiling code. A common + * source for fatal errors are unresolvable include files. For the + * purposes of an IDE, this is undesirable behavior and as much information + * as possible should be reported. Use this flag to enable this behavior. + */ + CXTranslationUnit_KeepGoing = 0x200, + + /** + * Sets the preprocessor in a mode for parsing a single file only. + */ + CXTranslationUnit_SingleFileParse = 0x400, + + /** + * Used in combination with CXTranslationUnit_SkipFunctionBodies to + * constrain the skipping of function bodies to the preamble. + * + * The function bodies of the main file are not skipped. + */ + CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800, + + /** + * Used to indicate that attributed types should be included in CXType. + */ + CXTranslationUnit_IncludeAttributedTypes = 0x1000, + + /** + * Used to indicate that implicit attributes should be visited. + */ + CXTranslationUnit_VisitImplicitAttributes = 0x2000, + + /** + * Used to indicate that non-errors from included files should be ignored. + * + * If set, clang_getDiagnosticSetFromTU() will not report e.g. warnings from + * included files anymore. This speeds up clang_getDiagnosticSetFromTU() for + * the case where these warnings are not of interest, as for an IDE for + * example, which typically shows only the diagnostics in the main file. + */ + CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000, + + /** + * Tells the preprocessor not to skip excluded conditional blocks. + */ + CXTranslationUnit_RetainExcludedConditionalBlocks = 0x8000 +}; + +/** + * Returns the set of flags that is suitable for parsing a translation + * unit that is being edited. + * + * The set of flags returned provide options for \c clang_parseTranslationUnit() + * to indicate that the translation unit is likely to be reparsed many times, + * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly + * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag + * set contains an unspecified set of optimizations (e.g., the precompiled + * preamble) geared toward improving the performance of these routines. The + * set of optimizations enabled may change from one version to the next. + */ +CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); + +/** + * Same as \c clang_parseTranslationUnit2, but returns + * the \c CXTranslationUnit instead of an error code. In case of an error this + * routine returns a \c NULL \c CXTranslationUnit, without further detailed + * error codes. + */ +CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit( + CXIndex CIdx, const char *source_filename, + const char *const *command_line_args, int num_command_line_args, + struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, + unsigned options); + +/** + * Parse the given source file and the translation unit corresponding + * to that file. + * + * This routine is the main entry point for the Clang C API, providing the + * ability to parse a source file into a translation unit that can then be + * queried by other functions in the API. This routine accepts a set of + * command-line arguments so that the compilation can be configured in the same + * way that the compiler is configured on the command line. + * + * \param CIdx The index object with which the translation unit will be + * associated. + * + * \param source_filename The name of the source file to load, or NULL if the + * source file is included in \c command_line_args. + * + * \param command_line_args The command-line arguments that would be + * passed to the \c clang executable if it were being invoked out-of-process. + * These command-line options will be parsed and will affect how the translation + * unit is parsed. Note that the following options are ignored: '-c', + * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \'. + * + * \param num_command_line_args The number of command-line arguments in + * \c command_line_args. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for parsing, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param options A bitmask of options that affects how the translation unit + * is managed but not its compilation. This should be a bitwise OR of the + * CXTranslationUnit_XXX flags. + * + * \param[out] out_TU A non-NULL pointer to store the created + * \c CXTranslationUnit, describing the parsed code and containing any + * diagnostics produced by the compiler. + * + * \returns Zero on success, otherwise returns an error code. + */ +CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2( + CXIndex CIdx, const char *source_filename, + const char *const *command_line_args, int num_command_line_args, + struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, + unsigned options, CXTranslationUnit *out_TU); + +/** + * Same as clang_parseTranslationUnit2 but requires a full command line + * for \c command_line_args including argv[0]. This is useful if the standard + * library paths are relative to the binary. + */ +CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv( + CXIndex CIdx, const char *source_filename, + const char *const *command_line_args, int num_command_line_args, + struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, + unsigned options, CXTranslationUnit *out_TU); + +/** + * Flags that control how translation units are saved. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * saving the translation unit. + */ +enum CXSaveTranslationUnit_Flags { + /** + * Used to indicate that no special saving options are needed. + */ + CXSaveTranslationUnit_None = 0x0 +}; + +/** + * Returns the set of flags that is suitable for saving a translation + * unit. + * + * The set of flags returned provide options for + * \c clang_saveTranslationUnit() by default. The returned flag + * set contains an unspecified set of options that save translation units with + * the most commonly-requested data. + */ +CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU); + +/** + * Describes the kind of error that occurred (if any) in a call to + * \c clang_saveTranslationUnit(). + */ +enum CXSaveError { + /** + * Indicates that no error occurred while saving a translation unit. + */ + CXSaveError_None = 0, + + /** + * Indicates that an unknown error occurred while attempting to save + * the file. + * + * This error typically indicates that file I/O failed when attempting to + * write the file. + */ + CXSaveError_Unknown = 1, + + /** + * Indicates that errors during translation prevented this attempt + * to save the translation unit. + * + * Errors that prevent the translation unit from being saved can be + * extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic(). + */ + CXSaveError_TranslationErrors = 2, + + /** + * Indicates that the translation unit to be saved was somehow + * invalid (e.g., NULL). + */ + CXSaveError_InvalidTU = 3 +}; + +/** + * Saves a translation unit into a serialized representation of + * that translation unit on disk. + * + * Any translation unit that was parsed without error can be saved + * into a file. The translation unit can then be deserialized into a + * new \c CXTranslationUnit with \c clang_createTranslationUnit() or, + * if it is an incomplete translation unit that corresponds to a + * header, used as a precompiled header when parsing other translation + * units. + * + * \param TU The translation unit to save. + * + * \param FileName The file to which the translation unit will be saved. + * + * \param options A bitmask of options that affects how the translation unit + * is saved. This should be a bitwise OR of the + * CXSaveTranslationUnit_XXX flags. + * + * \returns A value that will match one of the enumerators of the CXSaveError + * enumeration. Zero (CXSaveError_None) indicates that the translation unit was + * saved successfully, while a non-zero value indicates that a problem occurred. + */ +CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU, + const char *FileName, + unsigned options); + +/** + * Suspend a translation unit in order to free memory associated with it. + * + * A suspended translation unit uses significantly less memory but on the other + * side does not support any other calls than \c clang_reparseTranslationUnit + * to resume it or \c clang_disposeTranslationUnit to dispose it completely. + */ +CINDEX_LINKAGE unsigned clang_suspendTranslationUnit(CXTranslationUnit); + +/** + * Destroy the specified CXTranslationUnit object. + */ +CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); + +/** + * Flags that control the reparsing of translation units. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * reparsing the translation unit. + */ +enum CXReparse_Flags { + /** + * Used to indicate that no special reparsing options are needed. + */ + CXReparse_None = 0x0 +}; + +/** + * Returns the set of flags that is suitable for reparsing a translation + * unit. + * + * The set of flags returned provide options for + * \c clang_reparseTranslationUnit() by default. The returned flag + * set contains an unspecified set of optimizations geared toward common uses + * of reparsing. The set of optimizations enabled may change from one version + * to the next. + */ +CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU); + +/** + * Reparse the source files that produced this translation unit. + * + * This routine can be used to re-parse the source files that originally + * created the given translation unit, for example because those source files + * have changed (either on disk or as passed via \p unsaved_files). The + * source code will be reparsed with the same command-line options as it + * was originally parsed. + * + * Reparsing a translation unit invalidates all cursors and source locations + * that refer into that translation unit. This makes reparsing a translation + * unit semantically equivalent to destroying the translation unit and then + * creating a new translation unit with the same command-line arguments. + * However, it may be more efficient to reparse a translation + * unit using this routine. + * + * \param TU The translation unit whose contents will be re-parsed. The + * translation unit must originally have been built with + * \c clang_createTranslationUnitFromSourceFile(). + * + * \param num_unsaved_files The number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files The files that have not yet been saved to disk + * but may be required for parsing, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param options A bitset of options composed of the flags in CXReparse_Flags. + * The function \c clang_defaultReparseOptions() produces a default set of + * options recommended for most uses, based on the translation unit. + * + * \returns 0 if the sources could be reparsed. A non-zero error code will be + * returned if reparsing was impossible, such that the translation unit is + * invalid. In such cases, the only valid call for \c TU is + * \c clang_disposeTranslationUnit(TU). The error codes returned by this + * routine are described by the \c CXErrorCode enum. + */ +CINDEX_LINKAGE int +clang_reparseTranslationUnit(CXTranslationUnit TU, unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, + unsigned options); + +/** + * Categorizes how memory is being used by a translation unit. + */ +enum CXTUResourceUsageKind { + CXTUResourceUsage_AST = 1, + CXTUResourceUsage_Identifiers = 2, + CXTUResourceUsage_Selectors = 3, + CXTUResourceUsage_GlobalCompletionResults = 4, + CXTUResourceUsage_SourceManagerContentCache = 5, + CXTUResourceUsage_AST_SideTables = 6, + CXTUResourceUsage_SourceManager_Membuffer_Malloc = 7, + CXTUResourceUsage_SourceManager_Membuffer_MMap = 8, + CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9, + CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10, + CXTUResourceUsage_Preprocessor = 11, + CXTUResourceUsage_PreprocessingRecord = 12, + CXTUResourceUsage_SourceManager_DataStructures = 13, + CXTUResourceUsage_Preprocessor_HeaderSearch = 14, + CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST, + CXTUResourceUsage_MEMORY_IN_BYTES_END = + CXTUResourceUsage_Preprocessor_HeaderSearch, + + CXTUResourceUsage_First = CXTUResourceUsage_AST, + CXTUResourceUsage_Last = CXTUResourceUsage_Preprocessor_HeaderSearch +}; + +/** + * Returns the human-readable null-terminated C string that represents + * the name of the memory category. This string should never be freed. + */ +CINDEX_LINKAGE +const char *clang_getTUResourceUsageName(enum CXTUResourceUsageKind kind); + +typedef struct CXTUResourceUsageEntry { + /* The memory usage category. */ + enum CXTUResourceUsageKind kind; + /* Amount of resources used. + The units will depend on the resource kind. */ + unsigned long amount; +} CXTUResourceUsageEntry; + +/** + * The memory usage of a CXTranslationUnit, broken into categories. + */ +typedef struct CXTUResourceUsage { + /* Private data member, used for queries. */ + void *data; + + /* The number of entries in the 'entries' array. */ + unsigned numEntries; + + /* An array of key-value pairs, representing the breakdown of memory + usage. */ + CXTUResourceUsageEntry *entries; + +} CXTUResourceUsage; + +/** + * Return the memory usage of a translation unit. This object + * should be released with clang_disposeCXTUResourceUsage(). + */ +CINDEX_LINKAGE CXTUResourceUsage +clang_getCXTUResourceUsage(CXTranslationUnit TU); + +CINDEX_LINKAGE void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage); + +/** + * Get target information for this translation unit. + * + * The CXTargetInfo object cannot outlive the CXTranslationUnit object. + */ +CINDEX_LINKAGE CXTargetInfo +clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit); + +/** + * Destroy the CXTargetInfo object. + */ +CINDEX_LINKAGE void clang_TargetInfo_dispose(CXTargetInfo Info); + +/** + * Get the normalized target triple as a string. + * + * Returns the empty string in case of any error. + */ +CINDEX_LINKAGE CXString clang_TargetInfo_getTriple(CXTargetInfo Info); + +/** + * Get the pointer width of the target in bits. + * + * Returns -1 in case of error. + */ +CINDEX_LINKAGE int clang_TargetInfo_getPointerWidth(CXTargetInfo Info); + +/** + * @} + */ + +/** + * Describes the kind of entity that a cursor refers to. + */ +enum CXCursorKind { + /* Declarations */ + /** + * A declaration whose specific kind is not exposed via this + * interface. + * + * Unexposed declarations have the same operations as any other kind + * of declaration; one can extract their location information, + * spelling, find their definitions, etc. However, the specific kind + * of the declaration is not reported. + */ + CXCursor_UnexposedDecl = 1, + /** A C or C++ struct. */ + CXCursor_StructDecl = 2, + /** A C or C++ union. */ + CXCursor_UnionDecl = 3, + /** A C++ class. */ + CXCursor_ClassDecl = 4, + /** An enumeration. */ + CXCursor_EnumDecl = 5, + /** + * A field (in C) or non-static data member (in C++) in a + * struct, union, or C++ class. + */ + CXCursor_FieldDecl = 6, + /** An enumerator constant. */ + CXCursor_EnumConstantDecl = 7, + /** A function. */ + CXCursor_FunctionDecl = 8, + /** A variable. */ + CXCursor_VarDecl = 9, + /** A function or method parameter. */ + CXCursor_ParmDecl = 10, + /** An Objective-C \@interface. */ + CXCursor_ObjCInterfaceDecl = 11, + /** An Objective-C \@interface for a category. */ + CXCursor_ObjCCategoryDecl = 12, + /** An Objective-C \@protocol declaration. */ + CXCursor_ObjCProtocolDecl = 13, + /** An Objective-C \@property declaration. */ + CXCursor_ObjCPropertyDecl = 14, + /** An Objective-C instance variable. */ + CXCursor_ObjCIvarDecl = 15, + /** An Objective-C instance method. */ + CXCursor_ObjCInstanceMethodDecl = 16, + /** An Objective-C class method. */ + CXCursor_ObjCClassMethodDecl = 17, + /** An Objective-C \@implementation. */ + CXCursor_ObjCImplementationDecl = 18, + /** An Objective-C \@implementation for a category. */ + CXCursor_ObjCCategoryImplDecl = 19, + /** A typedef. */ + CXCursor_TypedefDecl = 20, + /** A C++ class method. */ + CXCursor_CXXMethod = 21, + /** A C++ namespace. */ + CXCursor_Namespace = 22, + /** A linkage specification, e.g. 'extern "C"'. */ + CXCursor_LinkageSpec = 23, + /** A C++ constructor. */ + CXCursor_Constructor = 24, + /** A C++ destructor. */ + CXCursor_Destructor = 25, + /** A C++ conversion function. */ + CXCursor_ConversionFunction = 26, + /** A C++ template type parameter. */ + CXCursor_TemplateTypeParameter = 27, + /** A C++ non-type template parameter. */ + CXCursor_NonTypeTemplateParameter = 28, + /** A C++ template template parameter. */ + CXCursor_TemplateTemplateParameter = 29, + /** A C++ function template. */ + CXCursor_FunctionTemplate = 30, + /** A C++ class template. */ + CXCursor_ClassTemplate = 31, + /** A C++ class template partial specialization. */ + CXCursor_ClassTemplatePartialSpecialization = 32, + /** A C++ namespace alias declaration. */ + CXCursor_NamespaceAlias = 33, + /** A C++ using directive. */ + CXCursor_UsingDirective = 34, + /** A C++ using declaration. */ + CXCursor_UsingDeclaration = 35, + /** A C++ alias declaration */ + CXCursor_TypeAliasDecl = 36, + /** An Objective-C \@synthesize definition. */ + CXCursor_ObjCSynthesizeDecl = 37, + /** An Objective-C \@dynamic definition. */ + CXCursor_ObjCDynamicDecl = 38, + /** An access specifier. */ + CXCursor_CXXAccessSpecifier = 39, + + CXCursor_FirstDecl = CXCursor_UnexposedDecl, + CXCursor_LastDecl = CXCursor_CXXAccessSpecifier, + + /* References */ + CXCursor_FirstRef = 40, /* Decl references */ + CXCursor_ObjCSuperClassRef = 40, + CXCursor_ObjCProtocolRef = 41, + CXCursor_ObjCClassRef = 42, + /** + * A reference to a type declaration. + * + * A type reference occurs anywhere where a type is named but not + * declared. For example, given: + * + * \code + * typedef unsigned size_type; + * size_type size; + * \endcode + * + * The typedef is a declaration of size_type (CXCursor_TypedefDecl), + * while the type of the variable "size" is referenced. The cursor + * referenced by the type of size is the typedef for size_type. + */ + CXCursor_TypeRef = 43, + CXCursor_CXXBaseSpecifier = 44, + /** + * A reference to a class template, function template, template + * template parameter, or class template partial specialization. + */ + CXCursor_TemplateRef = 45, + /** + * A reference to a namespace or namespace alias. + */ + CXCursor_NamespaceRef = 46, + /** + * A reference to a member of a struct, union, or class that occurs in + * some non-expression context, e.g., a designated initializer. + */ + CXCursor_MemberRef = 47, + /** + * A reference to a labeled statement. + * + * This cursor kind is used to describe the jump to "start_over" in the + * goto statement in the following example: + * + * \code + * start_over: + * ++counter; + * + * goto start_over; + * \endcode + * + * A label reference cursor refers to a label statement. + */ + CXCursor_LabelRef = 48, + + /** + * A reference to a set of overloaded functions or function templates + * that has not yet been resolved to a specific function or function template. + * + * An overloaded declaration reference cursor occurs in C++ templates where + * a dependent name refers to a function. For example: + * + * \code + * template void swap(T&, T&); + * + * struct X { ... }; + * void swap(X&, X&); + * + * template + * void reverse(T* first, T* last) { + * while (first < last - 1) { + * swap(*first, *--last); + * ++first; + * } + * } + * + * struct Y { }; + * void swap(Y&, Y&); + * \endcode + * + * Here, the identifier "swap" is associated with an overloaded declaration + * reference. In the template definition, "swap" refers to either of the two + * "swap" functions declared above, so both results will be available. At + * instantiation time, "swap" may also refer to other functions found via + * argument-dependent lookup (e.g., the "swap" function at the end of the + * example). + * + * The functions \c clang_getNumOverloadedDecls() and + * \c clang_getOverloadedDecl() can be used to retrieve the definitions + * referenced by this cursor. + */ + CXCursor_OverloadedDeclRef = 49, + + /** + * A reference to a variable that occurs in some non-expression + * context, e.g., a C++ lambda capture list. + */ + CXCursor_VariableRef = 50, + + CXCursor_LastRef = CXCursor_VariableRef, + + /* Error conditions */ + CXCursor_FirstInvalid = 70, + CXCursor_InvalidFile = 70, + CXCursor_NoDeclFound = 71, + CXCursor_NotImplemented = 72, + CXCursor_InvalidCode = 73, + CXCursor_LastInvalid = CXCursor_InvalidCode, + + /* Expressions */ + CXCursor_FirstExpr = 100, + + /** + * An expression whose specific kind is not exposed via this + * interface. + * + * Unexposed expressions have the same operations as any other kind + * of expression; one can extract their location information, + * spelling, children, etc. However, the specific kind of the + * expression is not reported. + */ + CXCursor_UnexposedExpr = 100, + + /** + * An expression that refers to some value declaration, such + * as a function, variable, or enumerator. + */ + CXCursor_DeclRefExpr = 101, + + /** + * An expression that refers to a member of a struct, union, + * class, Objective-C class, etc. + */ + CXCursor_MemberRefExpr = 102, + + /** An expression that calls a function. */ + CXCursor_CallExpr = 103, + + /** An expression that sends a message to an Objective-C + object or class. */ + CXCursor_ObjCMessageExpr = 104, + + /** An expression that represents a block literal. */ + CXCursor_BlockExpr = 105, + + /** An integer literal. + */ + CXCursor_IntegerLiteral = 106, + + /** A floating point number literal. + */ + CXCursor_FloatingLiteral = 107, + + /** An imaginary number literal. + */ + CXCursor_ImaginaryLiteral = 108, + + /** A string literal. + */ + CXCursor_StringLiteral = 109, + + /** A character literal. + */ + CXCursor_CharacterLiteral = 110, + + /** A parenthesized expression, e.g. "(1)". + * + * This AST node is only formed if full location information is requested. + */ + CXCursor_ParenExpr = 111, + + /** This represents the unary-expression's (except sizeof and + * alignof). + */ + CXCursor_UnaryOperator = 112, + + /** [C99 6.5.2.1] Array Subscripting. + */ + CXCursor_ArraySubscriptExpr = 113, + + /** A builtin binary operation expression such as "x + y" or + * "x <= y". + */ + CXCursor_BinaryOperator = 114, + + /** Compound assignment such as "+=". + */ + CXCursor_CompoundAssignOperator = 115, + + /** The ?: ternary operator. + */ + CXCursor_ConditionalOperator = 116, + + /** An explicit cast in C (C99 6.5.4) or a C-style cast in C++ + * (C++ [expr.cast]), which uses the syntax (Type)expr. + * + * For example: (int)f. + */ + CXCursor_CStyleCastExpr = 117, + + /** [C99 6.5.2.5] + */ + CXCursor_CompoundLiteralExpr = 118, + + /** Describes an C or C++ initializer list. + */ + CXCursor_InitListExpr = 119, + + /** The GNU address of label extension, representing &&label. + */ + CXCursor_AddrLabelExpr = 120, + + /** This is the GNU Statement Expression extension: ({int X=4; X;}) + */ + CXCursor_StmtExpr = 121, + + /** Represents a C11 generic selection. + */ + CXCursor_GenericSelectionExpr = 122, + + /** Implements the GNU __null extension, which is a name for a null + * pointer constant that has integral type (e.g., int or long) and is the same + * size and alignment as a pointer. + * + * The __null extension is typically only used by system headers, which define + * NULL as __null in C++ rather than using 0 (which is an integer that may not + * match the size of a pointer). + */ + CXCursor_GNUNullExpr = 123, + + /** C++'s static_cast<> expression. + */ + CXCursor_CXXStaticCastExpr = 124, + + /** C++'s dynamic_cast<> expression. + */ + CXCursor_CXXDynamicCastExpr = 125, + + /** C++'s reinterpret_cast<> expression. + */ + CXCursor_CXXReinterpretCastExpr = 126, + + /** C++'s const_cast<> expression. + */ + CXCursor_CXXConstCastExpr = 127, + + /** Represents an explicit C++ type conversion that uses "functional" + * notion (C++ [expr.type.conv]). + * + * Example: + * \code + * x = int(0.5); + * \endcode + */ + CXCursor_CXXFunctionalCastExpr = 128, + + /** A C++ typeid expression (C++ [expr.typeid]). + */ + CXCursor_CXXTypeidExpr = 129, + + /** [C++ 2.13.5] C++ Boolean Literal. + */ + CXCursor_CXXBoolLiteralExpr = 130, + + /** [C++0x 2.14.7] C++ Pointer Literal. + */ + CXCursor_CXXNullPtrLiteralExpr = 131, + + /** Represents the "this" expression in C++ + */ + CXCursor_CXXThisExpr = 132, + + /** [C++ 15] C++ Throw Expression. + * + * This handles 'throw' and 'throw' assignment-expression. When + * assignment-expression isn't present, Op will be null. + */ + CXCursor_CXXThrowExpr = 133, + + /** A new expression for memory allocation and constructor calls, e.g: + * "new CXXNewExpr(foo)". + */ + CXCursor_CXXNewExpr = 134, + + /** A delete expression for memory deallocation and destructor calls, + * e.g. "delete[] pArray". + */ + CXCursor_CXXDeleteExpr = 135, + + /** A unary expression. (noexcept, sizeof, or other traits) + */ + CXCursor_UnaryExpr = 136, + + /** An Objective-C string literal i.e. @"foo". + */ + CXCursor_ObjCStringLiteral = 137, + + /** An Objective-C \@encode expression. + */ + CXCursor_ObjCEncodeExpr = 138, + + /** An Objective-C \@selector expression. + */ + CXCursor_ObjCSelectorExpr = 139, + + /** An Objective-C \@protocol expression. + */ + CXCursor_ObjCProtocolExpr = 140, + + /** An Objective-C "bridged" cast expression, which casts between + * Objective-C pointers and C pointers, transferring ownership in the process. + * + * \code + * NSString *str = (__bridge_transfer NSString *)CFCreateString(); + * \endcode + */ + CXCursor_ObjCBridgedCastExpr = 141, + + /** Represents a C++0x pack expansion that produces a sequence of + * expressions. + * + * A pack expansion expression contains a pattern (which itself is an + * expression) followed by an ellipsis. For example: + * + * \code + * template + * void forward(F f, Types &&...args) { + * f(static_cast(args)...); + * } + * \endcode + */ + CXCursor_PackExpansionExpr = 142, + + /** Represents an expression that computes the length of a parameter + * pack. + * + * \code + * template + * struct count { + * static const unsigned value = sizeof...(Types); + * }; + * \endcode + */ + CXCursor_SizeOfPackExpr = 143, + + /* Represents a C++ lambda expression that produces a local function + * object. + * + * \code + * void abssort(float *x, unsigned N) { + * std::sort(x, x + N, + * [](float a, float b) { + * return std::abs(a) < std::abs(b); + * }); + * } + * \endcode + */ + CXCursor_LambdaExpr = 144, + + /** Objective-c Boolean Literal. + */ + CXCursor_ObjCBoolLiteralExpr = 145, + + /** Represents the "self" expression in an Objective-C method. + */ + CXCursor_ObjCSelfExpr = 146, + + /** OpenMP 5.0 [2.1.5, Array Section]. + */ + CXCursor_OMPArraySectionExpr = 147, + + /** Represents an @available(...) check. + */ + CXCursor_ObjCAvailabilityCheckExpr = 148, + + /** + * Fixed point literal + */ + CXCursor_FixedPointLiteral = 149, + + /** OpenMP 5.0 [2.1.4, Array Shaping]. + */ + CXCursor_OMPArrayShapingExpr = 150, + + /** + * OpenMP 5.0 [2.1.6 Iterators] + */ + CXCursor_OMPIteratorExpr = 151, + + /** OpenCL's addrspace_cast<> expression. + */ + CXCursor_CXXAddrspaceCastExpr = 152, + + /** + * Expression that references a C++20 concept. + */ + CXCursor_ConceptSpecializationExpr = 153, + + /** + * Expression that references a C++20 concept. + */ + CXCursor_RequiresExpr = 154, + + /** + * Expression that references a C++20 parenthesized list aggregate + * initializer. + */ + CXCursor_CXXParenListInitExpr = 155, + + CXCursor_LastExpr = CXCursor_CXXParenListInitExpr, + + /* Statements */ + CXCursor_FirstStmt = 200, + /** + * A statement whose specific kind is not exposed via this + * interface. + * + * Unexposed statements have the same operations as any other kind of + * statement; one can extract their location information, spelling, + * children, etc. However, the specific kind of the statement is not + * reported. + */ + CXCursor_UnexposedStmt = 200, + + /** A labelled statement in a function. + * + * This cursor kind is used to describe the "start_over:" label statement in + * the following example: + * + * \code + * start_over: + * ++counter; + * \endcode + * + */ + CXCursor_LabelStmt = 201, + + /** A group of statements like { stmt stmt }. + * + * This cursor kind is used to describe compound statements, e.g. function + * bodies. + */ + CXCursor_CompoundStmt = 202, + + /** A case statement. + */ + CXCursor_CaseStmt = 203, + + /** A default statement. + */ + CXCursor_DefaultStmt = 204, + + /** An if statement + */ + CXCursor_IfStmt = 205, + + /** A switch statement. + */ + CXCursor_SwitchStmt = 206, + + /** A while statement. + */ + CXCursor_WhileStmt = 207, + + /** A do statement. + */ + CXCursor_DoStmt = 208, + + /** A for statement. + */ + CXCursor_ForStmt = 209, + + /** A goto statement. + */ + CXCursor_GotoStmt = 210, + + /** An indirect goto statement. + */ + CXCursor_IndirectGotoStmt = 211, + + /** A continue statement. + */ + CXCursor_ContinueStmt = 212, + + /** A break statement. + */ + CXCursor_BreakStmt = 213, + + /** A return statement. + */ + CXCursor_ReturnStmt = 214, + + /** A GCC inline assembly statement extension. + */ + CXCursor_GCCAsmStmt = 215, + CXCursor_AsmStmt = CXCursor_GCCAsmStmt, + + /** Objective-C's overall \@try-\@catch-\@finally statement. + */ + CXCursor_ObjCAtTryStmt = 216, + + /** Objective-C's \@catch statement. + */ + CXCursor_ObjCAtCatchStmt = 217, + + /** Objective-C's \@finally statement. + */ + CXCursor_ObjCAtFinallyStmt = 218, + + /** Objective-C's \@throw statement. + */ + CXCursor_ObjCAtThrowStmt = 219, + + /** Objective-C's \@synchronized statement. + */ + CXCursor_ObjCAtSynchronizedStmt = 220, + + /** Objective-C's autorelease pool statement. + */ + CXCursor_ObjCAutoreleasePoolStmt = 221, + + /** Objective-C's collection statement. + */ + CXCursor_ObjCForCollectionStmt = 222, + + /** C++'s catch statement. + */ + CXCursor_CXXCatchStmt = 223, + + /** C++'s try statement. + */ + CXCursor_CXXTryStmt = 224, + + /** C++'s for (* : *) statement. + */ + CXCursor_CXXForRangeStmt = 225, + + /** Windows Structured Exception Handling's try statement. + */ + CXCursor_SEHTryStmt = 226, + + /** Windows Structured Exception Handling's except statement. + */ + CXCursor_SEHExceptStmt = 227, + + /** Windows Structured Exception Handling's finally statement. + */ + CXCursor_SEHFinallyStmt = 228, + + /** A MS inline assembly statement extension. + */ + CXCursor_MSAsmStmt = 229, + + /** The null statement ";": C99 6.8.3p3. + * + * This cursor kind is used to describe the null statement. + */ + CXCursor_NullStmt = 230, + + /** Adaptor class for mixing declarations with statements and + * expressions. + */ + CXCursor_DeclStmt = 231, + + /** OpenMP parallel directive. + */ + CXCursor_OMPParallelDirective = 232, + + /** OpenMP SIMD directive. + */ + CXCursor_OMPSimdDirective = 233, + + /** OpenMP for directive. + */ + CXCursor_OMPForDirective = 234, + + /** OpenMP sections directive. + */ + CXCursor_OMPSectionsDirective = 235, + + /** OpenMP section directive. + */ + CXCursor_OMPSectionDirective = 236, + + /** OpenMP single directive. + */ + CXCursor_OMPSingleDirective = 237, + + /** OpenMP parallel for directive. + */ + CXCursor_OMPParallelForDirective = 238, + + /** OpenMP parallel sections directive. + */ + CXCursor_OMPParallelSectionsDirective = 239, + + /** OpenMP task directive. + */ + CXCursor_OMPTaskDirective = 240, + + /** OpenMP master directive. + */ + CXCursor_OMPMasterDirective = 241, + + /** OpenMP critical directive. + */ + CXCursor_OMPCriticalDirective = 242, + + /** OpenMP taskyield directive. + */ + CXCursor_OMPTaskyieldDirective = 243, + + /** OpenMP barrier directive. + */ + CXCursor_OMPBarrierDirective = 244, + + /** OpenMP taskwait directive. + */ + CXCursor_OMPTaskwaitDirective = 245, + + /** OpenMP flush directive. + */ + CXCursor_OMPFlushDirective = 246, + + /** Windows Structured Exception Handling's leave statement. + */ + CXCursor_SEHLeaveStmt = 247, + + /** OpenMP ordered directive. + */ + CXCursor_OMPOrderedDirective = 248, + + /** OpenMP atomic directive. + */ + CXCursor_OMPAtomicDirective = 249, + + /** OpenMP for SIMD directive. + */ + CXCursor_OMPForSimdDirective = 250, + + /** OpenMP parallel for SIMD directive. + */ + CXCursor_OMPParallelForSimdDirective = 251, + + /** OpenMP target directive. + */ + CXCursor_OMPTargetDirective = 252, + + /** OpenMP teams directive. + */ + CXCursor_OMPTeamsDirective = 253, + + /** OpenMP taskgroup directive. + */ + CXCursor_OMPTaskgroupDirective = 254, + + /** OpenMP cancellation point directive. + */ + CXCursor_OMPCancellationPointDirective = 255, + + /** OpenMP cancel directive. + */ + CXCursor_OMPCancelDirective = 256, + + /** OpenMP target data directive. + */ + CXCursor_OMPTargetDataDirective = 257, + + /** OpenMP taskloop directive. + */ + CXCursor_OMPTaskLoopDirective = 258, + + /** OpenMP taskloop simd directive. + */ + CXCursor_OMPTaskLoopSimdDirective = 259, + + /** OpenMP distribute directive. + */ + CXCursor_OMPDistributeDirective = 260, + + /** OpenMP target enter data directive. + */ + CXCursor_OMPTargetEnterDataDirective = 261, + + /** OpenMP target exit data directive. + */ + CXCursor_OMPTargetExitDataDirective = 262, + + /** OpenMP target parallel directive. + */ + CXCursor_OMPTargetParallelDirective = 263, + + /** OpenMP target parallel for directive. + */ + CXCursor_OMPTargetParallelForDirective = 264, + + /** OpenMP target update directive. + */ + CXCursor_OMPTargetUpdateDirective = 265, + + /** OpenMP distribute parallel for directive. + */ + CXCursor_OMPDistributeParallelForDirective = 266, + + /** OpenMP distribute parallel for simd directive. + */ + CXCursor_OMPDistributeParallelForSimdDirective = 267, + + /** OpenMP distribute simd directive. + */ + CXCursor_OMPDistributeSimdDirective = 268, + + /** OpenMP target parallel for simd directive. + */ + CXCursor_OMPTargetParallelForSimdDirective = 269, + + /** OpenMP target simd directive. + */ + CXCursor_OMPTargetSimdDirective = 270, + + /** OpenMP teams distribute directive. + */ + CXCursor_OMPTeamsDistributeDirective = 271, + + /** OpenMP teams distribute simd directive. + */ + CXCursor_OMPTeamsDistributeSimdDirective = 272, + + /** OpenMP teams distribute parallel for simd directive. + */ + CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273, + + /** OpenMP teams distribute parallel for directive. + */ + CXCursor_OMPTeamsDistributeParallelForDirective = 274, + + /** OpenMP target teams directive. + */ + CXCursor_OMPTargetTeamsDirective = 275, + + /** OpenMP target teams distribute directive. + */ + CXCursor_OMPTargetTeamsDistributeDirective = 276, + + /** OpenMP target teams distribute parallel for directive. + */ + CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277, + + /** OpenMP target teams distribute parallel for simd directive. + */ + CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective = 278, + + /** OpenMP target teams distribute simd directive. + */ + CXCursor_OMPTargetTeamsDistributeSimdDirective = 279, + + /** C++2a std::bit_cast expression. + */ + CXCursor_BuiltinBitCastExpr = 280, + + /** OpenMP master taskloop directive. + */ + CXCursor_OMPMasterTaskLoopDirective = 281, + + /** OpenMP parallel master taskloop directive. + */ + CXCursor_OMPParallelMasterTaskLoopDirective = 282, + + /** OpenMP master taskloop simd directive. + */ + CXCursor_OMPMasterTaskLoopSimdDirective = 283, + + /** OpenMP parallel master taskloop simd directive. + */ + CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284, + + /** OpenMP parallel master directive. + */ + CXCursor_OMPParallelMasterDirective = 285, + + /** OpenMP depobj directive. + */ + CXCursor_OMPDepobjDirective = 286, + + /** OpenMP scan directive. + */ + CXCursor_OMPScanDirective = 287, + + /** OpenMP tile directive. + */ + CXCursor_OMPTileDirective = 288, + + /** OpenMP canonical loop. + */ + CXCursor_OMPCanonicalLoop = 289, + + /** OpenMP interop directive. + */ + CXCursor_OMPInteropDirective = 290, + + /** OpenMP dispatch directive. + */ + CXCursor_OMPDispatchDirective = 291, + + /** OpenMP masked directive. + */ + CXCursor_OMPMaskedDirective = 292, + + /** OpenMP unroll directive. + */ + CXCursor_OMPUnrollDirective = 293, + + /** OpenMP metadirective directive. + */ + CXCursor_OMPMetaDirective = 294, + + /** OpenMP loop directive. + */ + CXCursor_OMPGenericLoopDirective = 295, + + /** OpenMP teams loop directive. + */ + CXCursor_OMPTeamsGenericLoopDirective = 296, + + /** OpenMP target teams loop directive. + */ + CXCursor_OMPTargetTeamsGenericLoopDirective = 297, + + /** OpenMP parallel loop directive. + */ + CXCursor_OMPParallelGenericLoopDirective = 298, + + /** OpenMP target parallel loop directive. + */ + CXCursor_OMPTargetParallelGenericLoopDirective = 299, + + /** OpenMP parallel masked directive. + */ + CXCursor_OMPParallelMaskedDirective = 300, + + /** OpenMP masked taskloop directive. + */ + CXCursor_OMPMaskedTaskLoopDirective = 301, + + /** OpenMP masked taskloop simd directive. + */ + CXCursor_OMPMaskedTaskLoopSimdDirective = 302, + + /** OpenMP parallel masked taskloop directive. + */ + CXCursor_OMPParallelMaskedTaskLoopDirective = 303, + + /** OpenMP parallel masked taskloop simd directive. + */ + CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304, + + /** OpenMP error directive. + */ + CXCursor_OMPErrorDirective = 305, + + /** OpenMP scope directive. + */ + CXCursor_OMPScopeDirective = 306, + + CXCursor_LastStmt = CXCursor_OMPScopeDirective, + + /** + * Cursor that represents the translation unit itself. + * + * The translation unit cursor exists primarily to act as the root + * cursor for traversing the contents of a translation unit. + */ + CXCursor_TranslationUnit = 350, + + /* Attributes */ + CXCursor_FirstAttr = 400, + /** + * An attribute whose specific kind is not exposed via this + * interface. + */ + CXCursor_UnexposedAttr = 400, + + CXCursor_IBActionAttr = 401, + CXCursor_IBOutletAttr = 402, + CXCursor_IBOutletCollectionAttr = 403, + CXCursor_CXXFinalAttr = 404, + CXCursor_CXXOverrideAttr = 405, + CXCursor_AnnotateAttr = 406, + CXCursor_AsmLabelAttr = 407, + CXCursor_PackedAttr = 408, + CXCursor_PureAttr = 409, + CXCursor_ConstAttr = 410, + CXCursor_NoDuplicateAttr = 411, + CXCursor_CUDAConstantAttr = 412, + CXCursor_CUDADeviceAttr = 413, + CXCursor_CUDAGlobalAttr = 414, + CXCursor_CUDAHostAttr = 415, + CXCursor_CUDASharedAttr = 416, + CXCursor_VisibilityAttr = 417, + CXCursor_DLLExport = 418, + CXCursor_DLLImport = 419, + CXCursor_NSReturnsRetained = 420, + CXCursor_NSReturnsNotRetained = 421, + CXCursor_NSReturnsAutoreleased = 422, + CXCursor_NSConsumesSelf = 423, + CXCursor_NSConsumed = 424, + CXCursor_ObjCException = 425, + CXCursor_ObjCNSObject = 426, + CXCursor_ObjCIndependentClass = 427, + CXCursor_ObjCPreciseLifetime = 428, + CXCursor_ObjCReturnsInnerPointer = 429, + CXCursor_ObjCRequiresSuper = 430, + CXCursor_ObjCRootClass = 431, + CXCursor_ObjCSubclassingRestricted = 432, + CXCursor_ObjCExplicitProtocolImpl = 433, + CXCursor_ObjCDesignatedInitializer = 434, + CXCursor_ObjCRuntimeVisible = 435, + CXCursor_ObjCBoxable = 436, + CXCursor_FlagEnum = 437, + CXCursor_ConvergentAttr = 438, + CXCursor_WarnUnusedAttr = 439, + CXCursor_WarnUnusedResultAttr = 440, + CXCursor_AlignedAttr = 441, + CXCursor_LastAttr = CXCursor_AlignedAttr, + + /* Preprocessing */ + CXCursor_PreprocessingDirective = 500, + CXCursor_MacroDefinition = 501, + CXCursor_MacroExpansion = 502, + CXCursor_MacroInstantiation = CXCursor_MacroExpansion, + CXCursor_InclusionDirective = 503, + CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective, + CXCursor_LastPreprocessing = CXCursor_InclusionDirective, + + /* Extra Declarations */ + /** + * A module import declaration. + */ + CXCursor_ModuleImportDecl = 600, + CXCursor_TypeAliasTemplateDecl = 601, + /** + * A static_assert or _Static_assert node + */ + CXCursor_StaticAssert = 602, + /** + * a friend declaration. + */ + CXCursor_FriendDecl = 603, + /** + * a concept declaration. + */ + CXCursor_ConceptDecl = 604, + + CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl, + CXCursor_LastExtraDecl = CXCursor_ConceptDecl, + + /** + * A code completion overload candidate. + */ + CXCursor_OverloadCandidate = 700 +}; + +/** + * A cursor representing some element in the abstract syntax tree for + * a translation unit. + * + * The cursor abstraction unifies the different kinds of entities in a + * program--declaration, statements, expressions, references to declarations, + * etc.--under a single "cursor" abstraction with a common set of operations. + * Common operation for a cursor include: getting the physical location in + * a source file where the cursor points, getting the name associated with a + * cursor, and retrieving cursors for any child nodes of a particular cursor. + * + * Cursors can be produced in two specific ways. + * clang_getTranslationUnitCursor() produces a cursor for a translation unit, + * from which one can use clang_visitChildren() to explore the rest of the + * translation unit. clang_getCursor() maps from a physical source location + * to the entity that resides at that location, allowing one to map from the + * source code into the AST. + */ +typedef struct { + enum CXCursorKind kind; + int xdata; + const void *data[3]; +} CXCursor; + +/** + * \defgroup CINDEX_CURSOR_MANIP Cursor manipulations + * + * @{ + */ + +/** + * Retrieve the NULL cursor, which represents no entity. + */ +CINDEX_LINKAGE CXCursor clang_getNullCursor(void); + +/** + * Retrieve the cursor that represents the given translation unit. + * + * The translation unit cursor can be used to start traversing the + * various declarations within the given translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit); + +/** + * Determine whether two cursors are equivalent. + */ +CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor); + +/** + * Returns non-zero if \p cursor is null. + */ +CINDEX_LINKAGE int clang_Cursor_isNull(CXCursor cursor); + +/** + * Compute a hash value for the given cursor. + */ +CINDEX_LINKAGE unsigned clang_hashCursor(CXCursor); + +/** + * Retrieve the kind of the given cursor. + */ +CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor); + +/** + * Determine whether the given cursor kind represents a declaration. + */ +CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind); + +/** + * Determine whether the given declaration is invalid. + * + * A declaration is invalid if it could not be parsed successfully. + * + * \returns non-zero if the cursor represents a declaration and it is + * invalid, otherwise NULL. + */ +CINDEX_LINKAGE unsigned clang_isInvalidDeclaration(CXCursor); + +/** + * Determine whether the given cursor kind represents a simple + * reference. + * + * Note that other kinds of cursors (such as expressions) can also refer to + * other cursors. Use clang_getCursorReferenced() to determine whether a + * particular cursor refers to another entity. + */ +CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind); + +/** + * Determine whether the given cursor kind represents an expression. + */ +CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind); + +/** + * Determine whether the given cursor kind represents a statement. + */ +CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind); + +/** + * Determine whether the given cursor kind represents an attribute. + */ +CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind); + +/** + * Determine whether the given cursor has any attributes. + */ +CINDEX_LINKAGE unsigned clang_Cursor_hasAttrs(CXCursor C); + +/** + * Determine whether the given cursor kind represents an invalid + * cursor. + */ +CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); + +/** + * Determine whether the given cursor kind represents a translation + * unit. + */ +CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind); + +/*** + * Determine whether the given cursor represents a preprocessing + * element, such as a preprocessor directive or macro instantiation. + */ +CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind); + +/*** + * Determine whether the given cursor represents a currently + * unexposed piece of the AST (e.g., CXCursor_UnexposedStmt). + */ +CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind); + +/** + * Describe the linkage of the entity referred to by a cursor. + */ +enum CXLinkageKind { + /** This value indicates that no linkage information is available + * for a provided CXCursor. */ + CXLinkage_Invalid, + /** + * This is the linkage for variables, parameters, and so on that + * have automatic storage. This covers normal (non-extern) local variables. + */ + CXLinkage_NoLinkage, + /** This is the linkage for static variables and static functions. */ + CXLinkage_Internal, + /** This is the linkage for entities with external linkage that live + * in C++ anonymous namespaces.*/ + CXLinkage_UniqueExternal, + /** This is the linkage for entities with true, external linkage. */ + CXLinkage_External +}; + +/** + * Determine the linkage of the entity referred to by a given cursor. + */ +CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor); + +enum CXVisibilityKind { + /** This value indicates that no visibility information is available + * for a provided CXCursor. */ + CXVisibility_Invalid, + + /** Symbol not seen by the linker. */ + CXVisibility_Hidden, + /** Symbol seen by the linker but resolves to a symbol inside this object. */ + CXVisibility_Protected, + /** Symbol seen by the linker and acts like a normal symbol. */ + CXVisibility_Default +}; + +/** + * Describe the visibility of the entity referred to by a cursor. + * + * This returns the default visibility if not explicitly specified by + * a visibility attribute. The default visibility may be changed by + * commandline arguments. + * + * \param cursor The cursor to query. + * + * \returns The visibility of the cursor. + */ +CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor); + +/** + * Determine the availability of the entity that this cursor refers to, + * taking the current target platform into account. + * + * \param cursor The cursor to query. + * + * \returns The availability of the cursor. + */ +CINDEX_LINKAGE enum CXAvailabilityKind +clang_getCursorAvailability(CXCursor cursor); + +/** + * Describes the availability of a given entity on a particular platform, e.g., + * a particular class might only be available on Mac OS 10.7 or newer. + */ +typedef struct CXPlatformAvailability { + /** + * A string that describes the platform for which this structure + * provides availability information. + * + * Possible values are "ios" or "macos". + */ + CXString Platform; + /** + * The version number in which this entity was introduced. + */ + CXVersion Introduced; + /** + * The version number in which this entity was deprecated (but is + * still available). + */ + CXVersion Deprecated; + /** + * The version number in which this entity was obsoleted, and therefore + * is no longer available. + */ + CXVersion Obsoleted; + /** + * Whether the entity is unconditionally unavailable on this platform. + */ + int Unavailable; + /** + * An optional message to provide to a user of this API, e.g., to + * suggest replacement APIs. + */ + CXString Message; +} CXPlatformAvailability; + +/** + * Determine the availability of the entity that this cursor refers to + * on any platforms for which availability information is known. + * + * \param cursor The cursor to query. + * + * \param always_deprecated If non-NULL, will be set to indicate whether the + * entity is deprecated on all platforms. + * + * \param deprecated_message If non-NULL, will be set to the message text + * provided along with the unconditional deprecation of this entity. The client + * is responsible for deallocating this string. + * + * \param always_unavailable If non-NULL, will be set to indicate whether the + * entity is unavailable on all platforms. + * + * \param unavailable_message If non-NULL, will be set to the message text + * provided along with the unconditional unavailability of this entity. The + * client is responsible for deallocating this string. + * + * \param availability If non-NULL, an array of CXPlatformAvailability instances + * that will be populated with platform availability information, up to either + * the number of platforms for which availability information is available (as + * returned by this function) or \c availability_size, whichever is smaller. + * + * \param availability_size The number of elements available in the + * \c availability array. + * + * \returns The number of platforms (N) for which availability information is + * available (which is unrelated to \c availability_size). + * + * Note that the client is responsible for calling + * \c clang_disposeCXPlatformAvailability to free each of the + * platform-availability structures returned. There are + * \c min(N, availability_size) such structures. + */ +CINDEX_LINKAGE int clang_getCursorPlatformAvailability( + CXCursor cursor, int *always_deprecated, CXString *deprecated_message, + int *always_unavailable, CXString *unavailable_message, + CXPlatformAvailability *availability, int availability_size); + +/** + * Free the memory associated with a \c CXPlatformAvailability structure. + */ +CINDEX_LINKAGE void +clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability); + +/** + * If cursor refers to a variable declaration and it has initializer returns + * cursor referring to the initializer otherwise return null cursor. + */ +CINDEX_LINKAGE CXCursor clang_Cursor_getVarDeclInitializer(CXCursor cursor); + +/** + * If cursor refers to a variable declaration that has global storage returns 1. + * If cursor refers to a variable declaration that doesn't have global storage + * returns 0. Otherwise returns -1. + */ +CINDEX_LINKAGE int clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor); + +/** + * If cursor refers to a variable declaration that has external storage + * returns 1. If cursor refers to a variable declaration that doesn't have + * external storage returns 0. Otherwise returns -1. + */ +CINDEX_LINKAGE int clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor); + +/** + * Describe the "language" of the entity referred to by a cursor. + */ +enum CXLanguageKind { + CXLanguage_Invalid = 0, + CXLanguage_C, + CXLanguage_ObjC, + CXLanguage_CPlusPlus +}; + +/** + * Determine the "language" of the entity referred to by a given cursor. + */ +CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor); + +/** + * Describe the "thread-local storage (TLS) kind" of the declaration + * referred to by a cursor. + */ +enum CXTLSKind { CXTLS_None = 0, CXTLS_Dynamic, CXTLS_Static }; + +/** + * Determine the "thread-local storage (TLS) kind" of the declaration + * referred to by a cursor. + */ +CINDEX_LINKAGE enum CXTLSKind clang_getCursorTLSKind(CXCursor cursor); + +/** + * Returns the translation unit that a cursor originated from. + */ +CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor); + +/** + * A fast container representing a set of CXCursors. + */ +typedef struct CXCursorSetImpl *CXCursorSet; + +/** + * Creates an empty CXCursorSet. + */ +CINDEX_LINKAGE CXCursorSet clang_createCXCursorSet(void); + +/** + * Disposes a CXCursorSet and releases its associated memory. + */ +CINDEX_LINKAGE void clang_disposeCXCursorSet(CXCursorSet cset); + +/** + * Queries a CXCursorSet to see if it contains a specific CXCursor. + * + * \returns non-zero if the set contains the specified cursor. + */ +CINDEX_LINKAGE unsigned clang_CXCursorSet_contains(CXCursorSet cset, + CXCursor cursor); + +/** + * Inserts a CXCursor into a CXCursorSet. + * + * \returns zero if the CXCursor was already in the set, and non-zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset, + CXCursor cursor); + +/** + * Determine the semantic parent of the given cursor. + * + * The semantic parent of a cursor is the cursor that semantically contains + * the given \p cursor. For many declarations, the lexical and semantic parents + * are equivalent (the lexical parent is returned by + * \c clang_getCursorLexicalParent()). They diverge when declarations or + * definitions are provided out-of-line. For example: + * + * \code + * class C { + * void f(); + * }; + * + * void C::f() { } + * \endcode + * + * In the out-of-line definition of \c C::f, the semantic parent is + * the class \c C, of which this function is a member. The lexical parent is + * the place where the declaration actually occurs in the source code; in this + * case, the definition occurs in the translation unit. In general, the + * lexical parent for a given entity can change without affecting the semantics + * of the program, and the lexical parent of different declarations of the + * same entity may be different. Changing the semantic parent of a declaration, + * on the other hand, can have a major impact on semantics, and redeclarations + * of a particular entity should all have the same semantic context. + * + * In the example above, both declarations of \c C::f have \c C as their + * semantic context, while the lexical context of the first \c C::f is \c C + * and the lexical context of the second \c C::f is the translation unit. + * + * For global declarations, the semantic parent is the translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor); + +/** + * Determine the lexical parent of the given cursor. + * + * The lexical parent of a cursor is the cursor in which the given \p cursor + * was actually written. For many declarations, the lexical and semantic parents + * are equivalent (the semantic parent is returned by + * \c clang_getCursorSemanticParent()). They diverge when declarations or + * definitions are provided out-of-line. For example: + * + * \code + * class C { + * void f(); + * }; + * + * void C::f() { } + * \endcode + * + * In the out-of-line definition of \c C::f, the semantic parent is + * the class \c C, of which this function is a member. The lexical parent is + * the place where the declaration actually occurs in the source code; in this + * case, the definition occurs in the translation unit. In general, the + * lexical parent for a given entity can change without affecting the semantics + * of the program, and the lexical parent of different declarations of the + * same entity may be different. Changing the semantic parent of a declaration, + * on the other hand, can have a major impact on semantics, and redeclarations + * of a particular entity should all have the same semantic context. + * + * In the example above, both declarations of \c C::f have \c C as their + * semantic context, while the lexical context of the first \c C::f is \c C + * and the lexical context of the second \c C::f is the translation unit. + * + * For declarations written in the global scope, the lexical parent is + * the translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor); + +/** + * Determine the set of methods that are overridden by the given + * method. + * + * In both Objective-C and C++, a method (aka virtual member function, + * in C++) can override a virtual method in a base class. For + * Objective-C, a method is said to override any method in the class's + * base class, its protocols, or its categories' protocols, that has the same + * selector and is of the same kind (class or instance). + * If no such method exists, the search continues to the class's superclass, + * its protocols, and its categories, and so on. A method from an Objective-C + * implementation is considered to override the same methods as its + * corresponding method in the interface. + * + * For C++, a virtual member function overrides any virtual member + * function with the same signature that occurs in its base + * classes. With multiple inheritance, a virtual member function can + * override several virtual member functions coming from different + * base classes. + * + * In all cases, this function determines the immediate overridden + * method, rather than all of the overridden methods. For example, if + * a method is originally declared in a class A, then overridden in B + * (which in inherits from A) and also in C (which inherited from B), + * then the only overridden method returned from this function when + * invoked on C's method will be B's method. The client may then + * invoke this function again, given the previously-found overridden + * methods, to map out the complete method-override set. + * + * \param cursor A cursor representing an Objective-C or C++ + * method. This routine will compute the set of methods that this + * method overrides. + * + * \param overridden A pointer whose pointee will be replaced with a + * pointer to an array of cursors, representing the set of overridden + * methods. If there are no overridden methods, the pointee will be + * set to NULL. The pointee must be freed via a call to + * \c clang_disposeOverriddenCursors(). + * + * \param num_overridden A pointer to the number of overridden + * functions, will be set to the number of overridden functions in the + * array pointed to by \p overridden. + */ +CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor, + CXCursor **overridden, + unsigned *num_overridden); + +/** + * Free the set of overridden cursors returned by \c + * clang_getOverriddenCursors(). + */ +CINDEX_LINKAGE void clang_disposeOverriddenCursors(CXCursor *overridden); + +/** + * Retrieve the file that is included by the given inclusion directive + * cursor. + */ +CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_SOURCE Mapping between cursors and source code + * + * Cursors represent a location within the Abstract Syntax Tree (AST). These + * routines help map between cursors and the physical locations where the + * described entities occur in the source code. The mapping is provided in + * both directions, so one can map from source code to the AST and back. + * + * @{ + */ + +/** + * Map a source location to the cursor that describes the entity at that + * location in the source code. + * + * clang_getCursor() maps an arbitrary source location within a translation + * unit down to the most specific cursor that describes the entity at that + * location. For example, given an expression \c x + y, invoking + * clang_getCursor() with a source location pointing to "x" will return the + * cursor for "x"; similarly for "y". If the cursor points anywhere between + * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor() + * will return a cursor referring to the "+" expression. + * + * \returns a cursor representing the entity at the given source location, or + * a NULL cursor if no such entity can be found. + */ +CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation); + +/** + * Retrieve the physical location of the source constructor referenced + * by the given cursor. + * + * The location of a declaration is typically the location of the name of that + * declaration, where the name of that declaration would occur if it is + * unnamed, or some keyword that introduces that particular declaration. + * The location of a reference is where that reference occurs within the + * source code. + */ +CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor); + +/** + * Retrieve the physical extent of the source construct referenced by + * the given cursor. + * + * The extent of a cursor starts with the file/line/column pointing at the + * first character within the source construct that the cursor refers to and + * ends with the last character within that source construct. For a + * declaration, the extent covers the declaration itself. For a reference, + * the extent covers the location of the reference (e.g., where the referenced + * entity was actually used). + */ +CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_TYPES Type information for CXCursors + * + * @{ + */ + +/** + * Describes the kind of type + */ +enum CXTypeKind { + /** + * Represents an invalid type (e.g., where no type is available). + */ + CXType_Invalid = 0, + + /** + * A type whose specific kind is not exposed via this + * interface. + */ + CXType_Unexposed = 1, + + /* Builtin types */ + CXType_Void = 2, + CXType_Bool = 3, + CXType_Char_U = 4, + CXType_UChar = 5, + CXType_Char16 = 6, + CXType_Char32 = 7, + CXType_UShort = 8, + CXType_UInt = 9, + CXType_ULong = 10, + CXType_ULongLong = 11, + CXType_UInt128 = 12, + CXType_Char_S = 13, + CXType_SChar = 14, + CXType_WChar = 15, + CXType_Short = 16, + CXType_Int = 17, + CXType_Long = 18, + CXType_LongLong = 19, + CXType_Int128 = 20, + CXType_Float = 21, + CXType_Double = 22, + CXType_LongDouble = 23, + CXType_NullPtr = 24, + CXType_Overload = 25, + CXType_Dependent = 26, + CXType_ObjCId = 27, + CXType_ObjCClass = 28, + CXType_ObjCSel = 29, + CXType_Float128 = 30, + CXType_Half = 31, + CXType_Float16 = 32, + CXType_ShortAccum = 33, + CXType_Accum = 34, + CXType_LongAccum = 35, + CXType_UShortAccum = 36, + CXType_UAccum = 37, + CXType_ULongAccum = 38, + CXType_BFloat16 = 39, + CXType_Ibm128 = 40, + CXType_FirstBuiltin = CXType_Void, + CXType_LastBuiltin = CXType_Ibm128, + + CXType_Complex = 100, + CXType_Pointer = 101, + CXType_BlockPointer = 102, + CXType_LValueReference = 103, + CXType_RValueReference = 104, + CXType_Record = 105, + CXType_Enum = 106, + CXType_Typedef = 107, + CXType_ObjCInterface = 108, + CXType_ObjCObjectPointer = 109, + CXType_FunctionNoProto = 110, + CXType_FunctionProto = 111, + CXType_ConstantArray = 112, + CXType_Vector = 113, + CXType_IncompleteArray = 114, + CXType_VariableArray = 115, + CXType_DependentSizedArray = 116, + CXType_MemberPointer = 117, + CXType_Auto = 118, + + /** + * Represents a type that was referred to using an elaborated type keyword. + * + * E.g., struct S, or via a qualified name, e.g., N::M::type, or both. + */ + CXType_Elaborated = 119, + + /* OpenCL PipeType. */ + CXType_Pipe = 120, + + /* OpenCL builtin types. */ + CXType_OCLImage1dRO = 121, + CXType_OCLImage1dArrayRO = 122, + CXType_OCLImage1dBufferRO = 123, + CXType_OCLImage2dRO = 124, + CXType_OCLImage2dArrayRO = 125, + CXType_OCLImage2dDepthRO = 126, + CXType_OCLImage2dArrayDepthRO = 127, + CXType_OCLImage2dMSAARO = 128, + CXType_OCLImage2dArrayMSAARO = 129, + CXType_OCLImage2dMSAADepthRO = 130, + CXType_OCLImage2dArrayMSAADepthRO = 131, + CXType_OCLImage3dRO = 132, + CXType_OCLImage1dWO = 133, + CXType_OCLImage1dArrayWO = 134, + CXType_OCLImage1dBufferWO = 135, + CXType_OCLImage2dWO = 136, + CXType_OCLImage2dArrayWO = 137, + CXType_OCLImage2dDepthWO = 138, + CXType_OCLImage2dArrayDepthWO = 139, + CXType_OCLImage2dMSAAWO = 140, + CXType_OCLImage2dArrayMSAAWO = 141, + CXType_OCLImage2dMSAADepthWO = 142, + CXType_OCLImage2dArrayMSAADepthWO = 143, + CXType_OCLImage3dWO = 144, + CXType_OCLImage1dRW = 145, + CXType_OCLImage1dArrayRW = 146, + CXType_OCLImage1dBufferRW = 147, + CXType_OCLImage2dRW = 148, + CXType_OCLImage2dArrayRW = 149, + CXType_OCLImage2dDepthRW = 150, + CXType_OCLImage2dArrayDepthRW = 151, + CXType_OCLImage2dMSAARW = 152, + CXType_OCLImage2dArrayMSAARW = 153, + CXType_OCLImage2dMSAADepthRW = 154, + CXType_OCLImage2dArrayMSAADepthRW = 155, + CXType_OCLImage3dRW = 156, + CXType_OCLSampler = 157, + CXType_OCLEvent = 158, + CXType_OCLQueue = 159, + CXType_OCLReserveID = 160, + + CXType_ObjCObject = 161, + CXType_ObjCTypeParam = 162, + CXType_Attributed = 163, + + CXType_OCLIntelSubgroupAVCMcePayload = 164, + CXType_OCLIntelSubgroupAVCImePayload = 165, + CXType_OCLIntelSubgroupAVCRefPayload = 166, + CXType_OCLIntelSubgroupAVCSicPayload = 167, + CXType_OCLIntelSubgroupAVCMceResult = 168, + CXType_OCLIntelSubgroupAVCImeResult = 169, + CXType_OCLIntelSubgroupAVCRefResult = 170, + CXType_OCLIntelSubgroupAVCSicResult = 171, + CXType_OCLIntelSubgroupAVCImeResultSingleReferenceStreamout = 172, + CXType_OCLIntelSubgroupAVCImeResultDualReferenceStreamout = 173, + CXType_OCLIntelSubgroupAVCImeSingleReferenceStreamin = 174, + CXType_OCLIntelSubgroupAVCImeDualReferenceStreamin = 175, + + /* Old aliases for AVC OpenCL extension types. */ + CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172, + CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173, + CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174, + CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175, + + CXType_ExtVector = 176, + CXType_Atomic = 177, + CXType_BTFTagAttributed = 178 +}; + +/** + * Describes the calling convention of a function type + */ +enum CXCallingConv { + CXCallingConv_Default = 0, + CXCallingConv_C = 1, + CXCallingConv_X86StdCall = 2, + CXCallingConv_X86FastCall = 3, + CXCallingConv_X86ThisCall = 4, + CXCallingConv_X86Pascal = 5, + CXCallingConv_AAPCS = 6, + CXCallingConv_AAPCS_VFP = 7, + CXCallingConv_X86RegCall = 8, + CXCallingConv_IntelOclBicc = 9, + CXCallingConv_Win64 = 10, + /* Alias for compatibility with older versions of API. */ + CXCallingConv_X86_64Win64 = CXCallingConv_Win64, + CXCallingConv_X86_64SysV = 11, + CXCallingConv_X86VectorCall = 12, + CXCallingConv_Swift = 13, + CXCallingConv_PreserveMost = 14, + CXCallingConv_PreserveAll = 15, + CXCallingConv_AArch64VectorCall = 16, + CXCallingConv_SwiftAsync = 17, + CXCallingConv_AArch64SVEPCS = 18, + CXCallingConv_M68kRTD = 19, + + CXCallingConv_Invalid = 100, + CXCallingConv_Unexposed = 200 +}; + +/** + * The type of an element in the abstract syntax tree. + * + */ +typedef struct { + enum CXTypeKind kind; + void *data[2]; +} CXType; + +/** + * Retrieve the type of a CXCursor (if any). + */ +CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C); + +/** + * Pretty-print the underlying type using the rules of the + * language of the translation unit from which it came. + * + * If the type is invalid, an empty string is returned. + */ +CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT); + +/** + * Retrieve the underlying type of a typedef declaration. + * + * If the cursor does not reference a typedef declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C); + +/** + * Retrieve the integer type of an enum declaration. + * + * If the cursor does not reference an enum declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C); + +/** + * Retrieve the integer value of an enum constant declaration as a signed + * long long. + * + * If the cursor does not reference an enum constant declaration, LLONG_MIN is + * returned. Since this is also potentially a valid constant value, the kind of + * the cursor must be verified before calling this function. + */ +CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C); + +/** + * Retrieve the integer value of an enum constant declaration as an unsigned + * long long. + * + * If the cursor does not reference an enum constant declaration, ULLONG_MAX is + * returned. Since this is also potentially a valid constant value, the kind of + * the cursor must be verified before calling this function. + */ +CINDEX_LINKAGE unsigned long long +clang_getEnumConstantDeclUnsignedValue(CXCursor C); + +/** + * Returns non-zero if the cursor specifies a Record member that is a bit-field. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C); + +/** + * Retrieve the bit width of a bit-field declaration as an integer. + * + * If the cursor does not reference a bit-field, or if the bit-field's width + * expression cannot be evaluated, -1 is returned. + * + * For example: + * \code + * if (clang_Cursor_isBitField(Cursor)) { + * int Width = clang_getFieldDeclBitWidth(Cursor); + * if (Width != -1) { + * // The bit-field width is not value-dependent. + * } + * } + * \endcode + */ +CINDEX_LINKAGE int clang_getFieldDeclBitWidth(CXCursor C); + +/** + * Retrieve the number of non-variadic arguments associated with a given + * cursor. + * + * The number of arguments can be determined for calls as well as for + * declarations of functions or methods. For other cursors -1 is returned. + */ +CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C); + +/** + * Retrieve the argument cursor of a function or method. + * + * The argument cursor can be determined for calls as well as for declarations + * of functions or methods. For other cursors and for invalid indices, an + * invalid cursor is returned. + */ +CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i); + +/** + * Describes the kind of a template argument. + * + * See the definition of llvm::clang::TemplateArgument::ArgKind for full + * element descriptions. + */ +enum CXTemplateArgumentKind { + CXTemplateArgumentKind_Null, + CXTemplateArgumentKind_Type, + CXTemplateArgumentKind_Declaration, + CXTemplateArgumentKind_NullPtr, + CXTemplateArgumentKind_Integral, + CXTemplateArgumentKind_Template, + CXTemplateArgumentKind_TemplateExpansion, + CXTemplateArgumentKind_Expression, + CXTemplateArgumentKind_Pack, + /* Indicates an error case, preventing the kind from being deduced. */ + CXTemplateArgumentKind_Invalid +}; + +/** + * Returns the number of template args of a function, struct, or class decl + * representing a template specialization. + * + * If the argument cursor cannot be converted into a template function + * declaration, -1 is returned. + * + * For example, for the following declaration and specialization: + * template + * void foo() { ... } + * + * template <> + * void foo(); + * + * The value 3 would be returned from this call. + */ +CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C); + +/** + * Retrieve the kind of the I'th template argument of the CXCursor C. + * + * If the argument CXCursor does not represent a FunctionDecl, StructDecl, or + * ClassTemplatePartialSpecialization, an invalid template argument kind is + * returned. + * + * For example, for the following declaration and specialization: + * template + * void foo() { ... } + * + * template <> + * void foo(); + * + * For I = 0, 1, and 2, Type, Integral, and Integral will be returned, + * respectively. + */ +CINDEX_LINKAGE enum CXTemplateArgumentKind +clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I); + +/** + * Retrieve a CXType representing the type of a TemplateArgument of a + * function decl representing a template specialization. + * + * If the argument CXCursor does not represent a FunctionDecl, StructDecl, + * ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument + * has a kind of CXTemplateArgKind_Integral, an invalid type is returned. + * + * For example, for the following declaration and specialization: + * template + * void foo() { ... } + * + * template <> + * void foo(); + * + * If called with I = 0, "float", will be returned. + * Invalid types will be returned for I == 1 or 2. + */ +CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C, + unsigned I); + +/** + * Retrieve the value of an Integral TemplateArgument (of a function + * decl representing a template specialization) as a signed long long. + * + * It is undefined to call this function on a CXCursor that does not represent a + * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization + * whose I'th template argument is not an integral value. + * + * For example, for the following declaration and specialization: + * template + * void foo() { ... } + * + * template <> + * void foo(); + * + * If called with I = 1 or 2, -7 or true will be returned, respectively. + * For I == 0, this function's behavior is undefined. + */ +CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C, + unsigned I); + +/** + * Retrieve the value of an Integral TemplateArgument (of a function + * decl representing a template specialization) as an unsigned long long. + * + * It is undefined to call this function on a CXCursor that does not represent a + * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization or + * whose I'th template argument is not an integral value. + * + * For example, for the following declaration and specialization: + * template + * void foo() { ... } + * + * template <> + * void foo(); + * + * If called with I = 1 or 2, 2147483649 or true will be returned, respectively. + * For I == 0, this function's behavior is undefined. + */ +CINDEX_LINKAGE unsigned long long +clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C, unsigned I); + +/** + * Determine whether two CXTypes represent the same type. + * + * \returns non-zero if the CXTypes represent the same type and + * zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B); + +/** + * Return the canonical type for a CXType. + * + * Clang's type system explicitly models typedefs and all the ways + * a specific type can be represented. The canonical type is the underlying + * type with all the "sugar" removed. For example, if 'T' is a typedef + * for 'int', the canonical type for 'T' would be 'int'. + */ +CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T); + +/** + * Determine whether a CXType has the "const" qualifier set, + * without looking through typedefs that may have added "const" at a + * different level. + */ +CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T); + +/** + * Determine whether a CXCursor that is a macro, is + * function like. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroFunctionLike(CXCursor C); + +/** + * Determine whether a CXCursor that is a macro, is a + * builtin one. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C); + +/** + * Determine whether a CXCursor that is a function declaration, is an + * inline declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C); + +/** + * Determine whether a CXType has the "volatile" qualifier set, + * without looking through typedefs that may have added "volatile" at + * a different level. + */ +CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T); + +/** + * Determine whether a CXType has the "restrict" qualifier set, + * without looking through typedefs that may have added "restrict" at a + * different level. + */ +CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T); + +/** + * Returns the address space of the given type. + */ +CINDEX_LINKAGE unsigned clang_getAddressSpace(CXType T); + +/** + * Returns the typedef name of the given type. + */ +CINDEX_LINKAGE CXString clang_getTypedefName(CXType CT); + +/** + * For pointer types, returns the type of the pointee. + */ +CINDEX_LINKAGE CXType clang_getPointeeType(CXType T); + +/** + * Retrieve the unqualified variant of the given type, removing as + * little sugar as possible. + * + * For example, given the following series of typedefs: + * + * \code + * typedef int Integer; + * typedef const Integer CInteger; + * typedef CInteger DifferenceType; + * \endcode + * + * Executing \c clang_getUnqualifiedType() on a \c CXType that + * represents \c DifferenceType, will desugar to a type representing + * \c Integer, that has no qualifiers. + * + * And, executing \c clang_getUnqualifiedType() on the type of the + * first argument of the following function declaration: + * + * \code + * void foo(const int); + * \endcode + * + * Will return a type representing \c int, removing the \c const + * qualifier. + * + * Sugar over array types is not desugared. + * + * A type can be checked for qualifiers with \c + * clang_isConstQualifiedType(), \c clang_isVolatileQualifiedType() + * and \c clang_isRestrictQualifiedType(). + * + * A type that resulted from a call to \c clang_getUnqualifiedType + * will return \c false for all of the above calls. + */ +CINDEX_LINKAGE CXType clang_getUnqualifiedType(CXType CT); + +/** + * For reference types (e.g., "const int&"), returns the type that the + * reference refers to (e.g "const int"). + * + * Otherwise, returns the type itself. + * + * A type that has kind \c CXType_LValueReference or + * \c CXType_RValueReference is a reference type. + */ +CINDEX_LINKAGE CXType clang_getNonReferenceType(CXType CT); + +/** + * Return the cursor for the declaration of the given type. + */ +CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T); + +/** + * Returns the Objective-C type encoding for the specified declaration. + */ +CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C); + +/** + * Returns the Objective-C type encoding for the specified CXType. + */ +CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type); + +/** + * Retrieve the spelling of a given CXTypeKind. + */ +CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); + +/** + * Retrieve the calling convention associated with a function type. + * + * If a non-function type is passed in, CXCallingConv_Invalid is returned. + */ +CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T); + +/** + * Retrieve the return type associated with a function type. + * + * If a non-function type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getResultType(CXType T); + +/** + * Retrieve the exception specification type associated with a function type. + * This is a value of type CXCursor_ExceptionSpecificationKind. + * + * If a non-function type is passed in, an error code of -1 is returned. + */ +CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T); + +/** + * Retrieve the number of non-variadic parameters associated with a + * function type. + * + * If a non-function type is passed in, -1 is returned. + */ +CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); + +/** + * Retrieve the type of a parameter of a function type. + * + * If a non-function type is passed in or the function does not have enough + * parameters, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i); + +/** + * Retrieves the base type of the ObjCObjectType. + * + * If the type is not an ObjC object, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getObjCObjectBaseType(CXType T); + +/** + * Retrieve the number of protocol references associated with an ObjC object/id. + * + * If the type is not an ObjC object, 0 is returned. + */ +CINDEX_LINKAGE unsigned clang_Type_getNumObjCProtocolRefs(CXType T); + +/** + * Retrieve the decl for a protocol reference for an ObjC object/id. + * + * If the type is not an ObjC object or there are not enough protocol + * references, an invalid cursor is returned. + */ +CINDEX_LINKAGE CXCursor clang_Type_getObjCProtocolDecl(CXType T, unsigned i); + +/** + * Retrieve the number of type arguments associated with an ObjC object. + * + * If the type is not an ObjC object, 0 is returned. + */ +CINDEX_LINKAGE unsigned clang_Type_getNumObjCTypeArgs(CXType T); + +/** + * Retrieve a type argument associated with an ObjC object. + * + * If the type is not an ObjC or the index is not valid, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getObjCTypeArg(CXType T, unsigned i); + +/** + * Return 1 if the CXType is a variadic function type, and 0 otherwise. + */ +CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T); + +/** + * Retrieve the return type associated with a given cursor. + * + * This only returns a valid type if the cursor refers to a function or method. + */ +CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); + +/** + * Retrieve the exception specification type associated with a given cursor. + * This is a value of type CXCursor_ExceptionSpecificationKind. + * + * This only returns a valid result if the cursor refers to a function or + * method. + */ +CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C); + +/** + * Return 1 if the CXType is a POD (plain old data) type, and 0 + * otherwise. + */ +CINDEX_LINKAGE unsigned clang_isPODType(CXType T); + +/** + * Return the element type of an array, complex, or vector type. + * + * If a type is passed in that is not an array, complex, or vector type, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getElementType(CXType T); + +/** + * Return the number of elements of an array or vector type. + * + * If a type is passed in that is not an array or vector type, + * -1 is returned. + */ +CINDEX_LINKAGE long long clang_getNumElements(CXType T); + +/** + * Return the element type of an array type. + * + * If a non-array type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T); + +/** + * Return the array size of a constant array. + * + * If a non-array type is passed in, -1 is returned. + */ +CINDEX_LINKAGE long long clang_getArraySize(CXType T); + +/** + * Retrieve the type named by the qualified-id. + * + * If a non-elaborated type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T); + +/** + * Determine if a typedef is 'transparent' tag. + * + * A typedef is considered 'transparent' if it shares a name and spelling + * location with its underlying tag type, as is the case with the NS_ENUM macro. + * + * \returns non-zero if transparent and zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(CXType T); + +enum CXTypeNullabilityKind { + /** + * Values of this type can never be null. + */ + CXTypeNullability_NonNull = 0, + /** + * Values of this type can be null. + */ + CXTypeNullability_Nullable = 1, + /** + * Whether values of this type can be null is (explicitly) + * unspecified. This captures a (fairly rare) case where we + * can't conclude anything about the nullability of the type even + * though it has been considered. + */ + CXTypeNullability_Unspecified = 2, + /** + * Nullability is not applicable to this type. + */ + CXTypeNullability_Invalid = 3, + + /** + * Generally behaves like Nullable, except when used in a block parameter that + * was imported into a swift async method. There, swift will assume that the + * parameter can get null even if no error occurred. _Nullable parameters are + * assumed to only get null on error. + */ + CXTypeNullability_NullableResult = 4 +}; + +/** + * Retrieve the nullability kind of a pointer type. + */ +CINDEX_LINKAGE enum CXTypeNullabilityKind clang_Type_getNullability(CXType T); + +/** + * List the possible error codes for \c clang_Type_getSizeOf, + * \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and + * \c clang_Cursor_getOffsetOf. + * + * A value of this enumeration type can be returned if the target type is not + * a valid argument to sizeof, alignof or offsetof. + */ +enum CXTypeLayoutError { + /** + * Type is of kind CXType_Invalid. + */ + CXTypeLayoutError_Invalid = -1, + /** + * The type is an incomplete Type. + */ + CXTypeLayoutError_Incomplete = -2, + /** + * The type is a dependent Type. + */ + CXTypeLayoutError_Dependent = -3, + /** + * The type is not a constant size type. + */ + CXTypeLayoutError_NotConstantSize = -4, + /** + * The Field name is not valid for this record. + */ + CXTypeLayoutError_InvalidFieldName = -5, + /** + * The type is undeduced. + */ + CXTypeLayoutError_Undeduced = -6 +}; + +/** + * Return the alignment of a type in bytes as per C++[expr.alignof] + * standard. + * + * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned. + * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete + * is returned. + * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is + * returned. + * If the type declaration is not a constant size type, + * CXTypeLayoutError_NotConstantSize is returned. + */ +CINDEX_LINKAGE long long clang_Type_getAlignOf(CXType T); + +/** + * Return the class type of an member pointer type. + * + * If a non-member-pointer type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getClassType(CXType T); + +/** + * Return the size of a type in bytes as per C++[expr.sizeof] standard. + * + * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned. + * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete + * is returned. + * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is + * returned. + */ +CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T); + +/** + * Return the offset of a field named S in a record of type T in bits + * as it would be returned by __offsetof__ as per C++11[18.2p4] + * + * If the cursor is not a record field declaration, CXTypeLayoutError_Invalid + * is returned. + * If the field's type declaration is an incomplete type, + * CXTypeLayoutError_Incomplete is returned. + * If the field's type declaration is a dependent type, + * CXTypeLayoutError_Dependent is returned. + * If the field's name S is not found, + * CXTypeLayoutError_InvalidFieldName is returned. + */ +CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S); + +/** + * Return the type that was modified by this attributed type. + * + * If the type is not an attributed type, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getModifiedType(CXType T); + +/** + * Gets the type contained by this atomic type. + * + * If a non-atomic type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getValueType(CXType CT); + +/** + * Return the offset of the field represented by the Cursor. + * + * If the cursor is not a field declaration, -1 is returned. + * If the cursor semantic parent is not a record field declaration, + * CXTypeLayoutError_Invalid is returned. + * If the field's type declaration is an incomplete type, + * CXTypeLayoutError_Incomplete is returned. + * If the field's type declaration is a dependent type, + * CXTypeLayoutError_Dependent is returned. + * If the field's name S is not found, + * CXTypeLayoutError_InvalidFieldName is returned. + */ +CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C); + +/** + * Determine whether the given cursor represents an anonymous + * tag or namespace + */ +CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C); + +/** + * Determine whether the given cursor represents an anonymous record + * declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C); + +/** + * Determine whether the given cursor represents an inline namespace + * declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isInlineNamespace(CXCursor C); + +enum CXRefQualifierKind { + /** No ref-qualifier was provided. */ + CXRefQualifier_None = 0, + /** An lvalue ref-qualifier was provided (\c &). */ + CXRefQualifier_LValue, + /** An rvalue ref-qualifier was provided (\c &&). */ + CXRefQualifier_RValue +}; + +/** + * Returns the number of template arguments for given template + * specialization, or -1 if type \c T is not a template specialization. + */ +CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T); + +/** + * Returns the type template argument of a template class specialization + * at given index. + * + * This function only returns template type arguments and does not handle + * template template arguments or variadic packs. + */ +CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, + unsigned i); + +/** + * Retrieve the ref-qualifier kind of a function or method. + * + * The ref-qualifier is returned for C++ functions or methods. For other types + * or non-C++ declarations, CXRefQualifier_None is returned. + */ +CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T); + +/** + * Returns 1 if the base class specified by the cursor with kind + * CX_CXXBaseSpecifier is virtual. + */ +CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor); + +/** + * Represents the C++ access control level to a base class for a + * cursor with kind CX_CXXBaseSpecifier. + */ +enum CX_CXXAccessSpecifier { + CX_CXXInvalidAccessSpecifier, + CX_CXXPublic, + CX_CXXProtected, + CX_CXXPrivate +}; + +/** + * Returns the access control level for the referenced object. + * + * If the cursor refers to a C++ declaration, its access control level within + * its parent scope is returned. Otherwise, if the cursor refers to a base + * specifier or access specifier, the specifier itself is returned. + */ +CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor); + +/** + * Represents the storage classes as declared in the source. CX_SC_Invalid + * was added for the case that the passed cursor in not a declaration. + */ +enum CX_StorageClass { + CX_SC_Invalid, + CX_SC_None, + CX_SC_Extern, + CX_SC_Static, + CX_SC_PrivateExtern, + CX_SC_OpenCLWorkGroupLocal, + CX_SC_Auto, + CX_SC_Register +}; + +/** + * Returns the storage class for a function or variable declaration. + * + * If the passed in Cursor is not a function or variable declaration, + * CX_SC_Invalid is returned else the storage class. + */ +CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor); + +/** + * Determine the number of overloaded declarations referenced by a + * \c CXCursor_OverloadedDeclRef cursor. + * + * \param cursor The cursor whose overloaded declarations are being queried. + * + * \returns The number of overloaded declarations referenced by \c cursor. If it + * is not a \c CXCursor_OverloadedDeclRef cursor, returns 0. + */ +CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor); + +/** + * Retrieve a cursor for one of the overloaded declarations referenced + * by a \c CXCursor_OverloadedDeclRef cursor. + * + * \param cursor The cursor whose overloaded declarations are being queried. + * + * \param index The zero-based index into the set of overloaded declarations in + * the cursor. + * + * \returns A cursor representing the declaration referenced by the given + * \c cursor at the specified \c index. If the cursor does not have an + * associated set of overloaded declarations, or if the index is out of bounds, + * returns \c clang_getNullCursor(); + */ +CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor, + unsigned index); + +/** + * @} + */ + +/** + * \defgroup CINDEX_ATTRIBUTES Information for attributes + * + * @{ + */ + +/** + * For cursors representing an iboutletcollection attribute, + * this function returns the collection element type. + * + */ +CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors + * + * These routines provide the ability to traverse the abstract syntax tree + * using cursors. + * + * @{ + */ + +/** + * Describes how the traversal of the children of a particular + * cursor should proceed after visiting a particular child cursor. + * + * A value of this enumeration type should be returned by each + * \c CXCursorVisitor to indicate how clang_visitChildren() proceed. + */ +enum CXChildVisitResult { + /** + * Terminates the cursor traversal. + */ + CXChildVisit_Break, + /** + * Continues the cursor traversal with the next sibling of + * the cursor just visited, without visiting its children. + */ + CXChildVisit_Continue, + /** + * Recursively traverse the children of this cursor, using + * the same visitor and client data. + */ + CXChildVisit_Recurse +}; + +/** + * Visitor invoked for each cursor found by a traversal. + * + * This visitor function will be invoked for each cursor found by + * clang_visitCursorChildren(). Its first argument is the cursor being + * visited, its second argument is the parent visitor for that cursor, + * and its third argument is the client data provided to + * clang_visitCursorChildren(). + * + * The visitor should return one of the \c CXChildVisitResult values + * to direct clang_visitCursorChildren(). + */ +typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor, + CXCursor parent, + CXClientData client_data); + +/** + * Visit the children of a particular cursor. + * + * This function visits all the direct children of the given cursor, + * invoking the given \p visitor function with the cursors of each + * visited child. The traversal may be recursive, if the visitor returns + * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if + * the visitor returns \c CXChildVisit_Break. + * + * \param parent the cursor whose child may be visited. All kinds of + * cursors can be visited, including invalid cursors (which, by + * definition, have no children). + * + * \param visitor the visitor function that will be invoked for each + * child of \p parent. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the visitor each time it is invoked. + * + * \returns a non-zero value if the traversal was terminated + * prematurely by the visitor returning \c CXChildVisit_Break. + */ +CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, + CXCursorVisitor visitor, + CXClientData client_data); +/** + * Visitor invoked for each cursor found by a traversal. + * + * This visitor block will be invoked for each cursor found by + * clang_visitChildrenWithBlock(). Its first argument is the cursor being + * visited, its second argument is the parent visitor for that cursor. + * + * The visitor should return one of the \c CXChildVisitResult values + * to direct clang_visitChildrenWithBlock(). + */ +#if __has_feature(blocks) +typedef enum CXChildVisitResult (^CXCursorVisitorBlock)(CXCursor cursor, + CXCursor parent); +#else +typedef struct _CXChildVisitResult *CXCursorVisitorBlock; +#endif + +/** + * Visits the children of a cursor using the specified block. Behaves + * identically to clang_visitChildren() in all other respects. + */ +CINDEX_LINKAGE unsigned +clang_visitChildrenWithBlock(CXCursor parent, CXCursorVisitorBlock block); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_XREF Cross-referencing in the AST + * + * These routines provide the ability to determine references within and + * across translation units, by providing the names of the entities referenced + * by cursors, follow reference cursors to the declarations they reference, + * and associate declarations with their definitions. + * + * @{ + */ + +/** + * Retrieve a Unified Symbol Resolution (USR) for the entity referenced + * by the given cursor. + * + * A Unified Symbol Resolution (USR) is a string that identifies a particular + * entity (function, class, variable, etc.) within a program. USRs can be + * compared across translation units to determine, e.g., when references in + * one translation refer to an entity defined in another translation unit. + */ +CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor); + +/** + * Construct a USR for a specified Objective-C class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name); + +/** + * Construct a USR for a specified Objective-C category. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCCategory( + const char *class_name, const char *category_name); + +/** + * Construct a USR for a specified Objective-C protocol. + */ +CINDEX_LINKAGE CXString +clang_constructUSR_ObjCProtocol(const char *protocol_name); + +/** + * Construct a USR for a specified Objective-C instance variable and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name, + CXString classUSR); + +/** + * Construct a USR for a specified Objective-C method and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name, + unsigned isInstanceMethod, + CXString classUSR); + +/** + * Construct a USR for a specified Objective-C property and the USR + * for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property, + CXString classUSR); + +/** + * Retrieve a name for the entity referenced by this cursor. + */ +CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); + +/** + * Retrieve a range for a piece that forms the cursors spelling name. + * Most of the times there is only one range for the complete spelling but for + * Objective-C methods and Objective-C message expressions, there are multiple + * pieces for each selector identifier. + * + * \param pieceIndex the index of the spelling name piece. If this is greater + * than the actual number of pieces, it will return a NULL (invalid) range. + * + * \param options Reserved. + */ +CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange( + CXCursor, unsigned pieceIndex, unsigned options); + +/** + * Opaque pointer representing a policy that controls pretty printing + * for \c clang_getCursorPrettyPrinted. + */ +typedef void *CXPrintingPolicy; + +/** + * Properties for the printing policy. + * + * See \c clang::PrintingPolicy for more information. + */ +enum CXPrintingPolicyProperty { + CXPrintingPolicy_Indentation, + CXPrintingPolicy_SuppressSpecifiers, + CXPrintingPolicy_SuppressTagKeyword, + CXPrintingPolicy_IncludeTagDefinition, + CXPrintingPolicy_SuppressScope, + CXPrintingPolicy_SuppressUnwrittenScope, + CXPrintingPolicy_SuppressInitializers, + CXPrintingPolicy_ConstantArraySizeAsWritten, + CXPrintingPolicy_AnonymousTagLocations, + CXPrintingPolicy_SuppressStrongLifetime, + CXPrintingPolicy_SuppressLifetimeQualifiers, + CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors, + CXPrintingPolicy_Bool, + CXPrintingPolicy_Restrict, + CXPrintingPolicy_Alignof, + CXPrintingPolicy_UnderscoreAlignof, + CXPrintingPolicy_UseVoidForZeroParams, + CXPrintingPolicy_TerseOutput, + CXPrintingPolicy_PolishForDeclaration, + CXPrintingPolicy_Half, + CXPrintingPolicy_MSWChar, + CXPrintingPolicy_IncludeNewlines, + CXPrintingPolicy_MSVCFormatting, + CXPrintingPolicy_ConstantsAsWritten, + CXPrintingPolicy_SuppressImplicitBase, + CXPrintingPolicy_FullyQualifiedName, + + CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName +}; + +/** + * Get a property value for the given printing policy. + */ +CINDEX_LINKAGE unsigned +clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy, + enum CXPrintingPolicyProperty Property); + +/** + * Set a property value for the given printing policy. + */ +CINDEX_LINKAGE void +clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy, + enum CXPrintingPolicyProperty Property, + unsigned Value); + +/** + * Retrieve the default policy for the cursor. + * + * The policy should be released after use with \c + * clang_PrintingPolicy_dispose. + */ +CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor); + +/** + * Release a printing policy. + */ +CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy); + +/** + * Pretty print declarations. + * + * \param Cursor The cursor representing a declaration. + * + * \param Policy The policy to control the entities being printed. If + * NULL, a default policy is used. + * + * \returns The pretty printed declaration or the empty string for + * other cursors. + */ +CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor, + CXPrintingPolicy Policy); + +/** + * Retrieve the display name for the entity referenced by this cursor. + * + * The display name contains extra information that helps identify the cursor, + * such as the parameters of a function or template or the arguments of a + * class template specialization. + */ +CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor); + +/** For a cursor that is a reference, retrieve a cursor representing the + * entity that it references. + * + * Reference cursors refer to other entities in the AST. For example, an + * Objective-C superclass reference cursor refers to an Objective-C class. + * This function produces the cursor for the Objective-C class from the + * cursor for the superclass reference. If the input cursor is a declaration or + * definition, it returns that declaration or definition unchanged. + * Otherwise, returns the NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor); + +/** + * For a cursor that is either a reference to or a declaration + * of some entity, retrieve a cursor that describes the definition of + * that entity. + * + * Some entities can be declared multiple times within a translation + * unit, but only one of those declarations can also be a + * definition. For example, given: + * + * \code + * int f(int, int); + * int g(int x, int y) { return f(x, y); } + * int f(int a, int b) { return a + b; } + * int f(int, int); + * \endcode + * + * there are three declarations of the function "f", but only the + * second one is a definition. The clang_getCursorDefinition() + * function will take any cursor pointing to a declaration of "f" + * (the first or fourth lines of the example) or a cursor referenced + * that uses "f" (the call to "f' inside "g") and will return a + * declaration cursor pointing to the definition (the second "f" + * declaration). + * + * If given a cursor for which there is no corresponding definition, + * e.g., because there is no definition of that entity within this + * translation unit, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor); + +/** + * Determine whether the declaration pointed to by this cursor + * is also a definition of that entity. + */ +CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); + +/** + * Retrieve the canonical cursor corresponding to the given cursor. + * + * In the C family of languages, many kinds of entities can be declared several + * times within a single translation unit. For example, a structure type can + * be forward-declared (possibly multiple times) and later defined: + * + * \code + * struct X; + * struct X; + * struct X { + * int member; + * }; + * \endcode + * + * The declarations and the definition of \c X are represented by three + * different cursors, all of which are declarations of the same underlying + * entity. One of these cursor is considered the "canonical" cursor, which + * is effectively the representative for the underlying entity. One can + * determine if two cursors are declarations of the same underlying entity by + * comparing their canonical cursors. + * + * \returns The canonical cursor for the entity referred to by the given cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor); + +/** + * If the cursor points to a selector identifier in an Objective-C + * method or message expression, this returns the selector index. + * + * After getting a cursor with #clang_getCursor, this can be called to + * determine if the location points to a selector identifier. + * + * \returns The selector index if the cursor is an Objective-C method or message + * expression and the cursor is pointing to a selector identifier, or -1 + * otherwise. + */ +CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor); + +/** + * Given a cursor pointing to a C++ method call or an Objective-C + * message, returns non-zero if the method/message is "dynamic", meaning: + * + * For a C++ method: the call is virtual. + * For an Objective-C message: the receiver is an object instance, not 'super' + * or a specific class. + * + * If the method/message is "static" or the cursor does not point to a + * method/message, it will return zero. + */ +CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C); + +/** + * Given a cursor pointing to an Objective-C message or property + * reference, or C++ method call, returns the CXType of the receiver. + */ +CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C); + +/** + * Property attributes for a \c CXCursor_ObjCPropertyDecl. + */ +typedef enum { + CXObjCPropertyAttr_noattr = 0x00, + CXObjCPropertyAttr_readonly = 0x01, + CXObjCPropertyAttr_getter = 0x02, + CXObjCPropertyAttr_assign = 0x04, + CXObjCPropertyAttr_readwrite = 0x08, + CXObjCPropertyAttr_retain = 0x10, + CXObjCPropertyAttr_copy = 0x20, + CXObjCPropertyAttr_nonatomic = 0x40, + CXObjCPropertyAttr_setter = 0x80, + CXObjCPropertyAttr_atomic = 0x100, + CXObjCPropertyAttr_weak = 0x200, + CXObjCPropertyAttr_strong = 0x400, + CXObjCPropertyAttr_unsafe_unretained = 0x800, + CXObjCPropertyAttr_class = 0x1000 +} CXObjCPropertyAttrKind; + +/** + * Given a cursor that represents a property declaration, return the + * associated property attributes. The bits are formed from + * \c CXObjCPropertyAttrKind. + * + * \param reserved Reserved for future use, pass 0. + */ +CINDEX_LINKAGE unsigned +clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved); + +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the getter. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C); + +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the setter, if any. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertySetterName(CXCursor C); + +/** + * 'Qualifiers' written next to the return and parameter types in + * Objective-C method declarations. + */ +typedef enum { + CXObjCDeclQualifier_None = 0x0, + CXObjCDeclQualifier_In = 0x1, + CXObjCDeclQualifier_Inout = 0x2, + CXObjCDeclQualifier_Out = 0x4, + CXObjCDeclQualifier_Bycopy = 0x8, + CXObjCDeclQualifier_Byref = 0x10, + CXObjCDeclQualifier_Oneway = 0x20 +} CXObjCDeclQualifierKind; + +/** + * Given a cursor that represents an Objective-C method or parameter + * declaration, return the associated Objective-C qualifiers for the return + * type or the parameter respectively. The bits are formed from + * CXObjCDeclQualifierKind. + */ +CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C); + +/** + * Given a cursor that represents an Objective-C method or property + * declaration, return non-zero if the declaration was affected by "\@optional". + * Returns zero if the cursor is not such a declaration or it is "\@required". + */ +CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C); + +/** + * Returns non-zero if the given cursor is a variadic function or method. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C); + +/** + * Returns non-zero if the given cursor points to a symbol marked with + * external_source_symbol attribute. + * + * \param language If non-NULL, and the attribute is present, will be set to + * the 'language' string from the attribute. + * + * \param definedIn If non-NULL, and the attribute is present, will be set to + * the 'definedIn' string from the attribute. + * + * \param isGenerated If non-NULL, and the attribute is present, will be set to + * non-zero if the 'generated_declaration' is set in the attribute. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isExternalSymbol(CXCursor C, + CXString *language, + CXString *definedIn, + unsigned *isGenerated); + +/** + * Given a cursor that represents a declaration, return the associated + * comment's source range. The range may include multiple consecutive comments + * with whitespace in between. + */ +CINDEX_LINKAGE CXSourceRange clang_Cursor_getCommentRange(CXCursor C); + +/** + * Given a cursor that represents a declaration, return the associated + * comment text, including comment markers. + */ +CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C); + +/** + * Given a cursor that represents a documentable entity (e.g., + * declaration), return the associated \paragraph; otherwise return the + * first paragraph. + */ +CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C); + +/** + * @} + */ + +/** \defgroup CINDEX_MANGLE Name Mangling API Functions + * + * @{ + */ + +/** + * Retrieve the CXString representing the mangled name of the cursor. + */ +CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor); + +/** + * Retrieve the CXStrings representing the mangled symbols of the C++ + * constructor or destructor at the cursor. + */ +CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor); + +/** + * Retrieve the CXStrings representing the mangled symbols of the ObjC + * class interface or implementation at the cursor. + */ +CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_MODULE Module introspection + * + * The functions in this group provide access to information about modules. + * + * @{ + */ + +typedef void *CXModule; + +/** + * Given a CXCursor_ModuleImportDecl cursor, return the associated module. + */ +CINDEX_LINKAGE CXModule clang_Cursor_getModule(CXCursor C); + +/** + * Given a CXFile header file, return the module that contains it, if one + * exists. + */ +CINDEX_LINKAGE CXModule clang_getModuleForFile(CXTranslationUnit, CXFile); + +/** + * \param Module a module object. + * + * \returns the module file where the provided module object came from. + */ +CINDEX_LINKAGE CXFile clang_Module_getASTFile(CXModule Module); + +/** + * \param Module a module object. + * + * \returns the parent of a sub-module or NULL if the given module is top-level, + * e.g. for 'std.vector' it will return the 'std' module. + */ +CINDEX_LINKAGE CXModule clang_Module_getParent(CXModule Module); + +/** + * \param Module a module object. + * + * \returns the name of the module, e.g. for the 'std.vector' sub-module it + * will return "vector". + */ +CINDEX_LINKAGE CXString clang_Module_getName(CXModule Module); + +/** + * \param Module a module object. + * + * \returns the full name of the module, e.g. "std.vector". + */ +CINDEX_LINKAGE CXString clang_Module_getFullName(CXModule Module); + +/** + * \param Module a module object. + * + * \returns non-zero if the module is a system one. + */ +CINDEX_LINKAGE int clang_Module_isSystem(CXModule Module); + +/** + * \param Module a module object. + * + * \returns the number of top level headers associated with this module. + */ +CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit, + CXModule Module); + +/** + * \param Module a module object. + * + * \param Index top level header index (zero-based). + * + * \returns the specified top level header associated with the module. + */ +CINDEX_LINKAGE +CXFile clang_Module_getTopLevelHeader(CXTranslationUnit, CXModule Module, + unsigned Index); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CPP C++ AST introspection + * + * The routines in this group provide access information in the ASTs specific + * to C++ language features. + * + * @{ + */ + +/** + * Determine if a C++ constructor is a converting constructor. + */ +CINDEX_LINKAGE unsigned +clang_CXXConstructor_isConvertingConstructor(CXCursor C); + +/** + * Determine if a C++ constructor is a copy constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isCopyConstructor(CXCursor C); + +/** + * Determine if a C++ constructor is the default constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C); + +/** + * Determine if a C++ constructor is a move constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isMoveConstructor(CXCursor C); + +/** + * Determine if a C++ field is declared 'mutable'. + */ +CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C); + +/** + * Determine if a C++ method is declared '= default'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isDefaulted(CXCursor C); + +/** + * Determine if a C++ method is declared '= delete'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isDeleted(CXCursor C); + +/** + * Determine if a C++ member function or member function template is + * pure virtual. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isPureVirtual(CXCursor C); + +/** + * Determine if a C++ member function or member function template is + * declared 'static'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); + +/** + * Determine if a C++ member function or member function template is + * explicitly declared 'virtual' or if it overrides a virtual method from + * one of the base classes. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C); + +/** + * Determine if a C++ member function is a copy-assignment operator, + * returning 1 if such is the case and 0 otherwise. + * + * > A copy-assignment operator `X::operator=` is a non-static, + * > non-template member function of _class_ `X` with exactly one + * > parameter of type `X`, `X&`, `const X&`, `volatile X&` or `const + * > volatile X&`. + * + * That is, for example, the `operator=` in: + * + * class Foo { + * bool operator=(const volatile Foo&); + * }; + * + * Is a copy-assignment operator, while the `operator=` in: + * + * class Bar { + * bool operator=(const int&); + * }; + * + * Is not. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isCopyAssignmentOperator(CXCursor C); + +/** + * Determine if a C++ member function is a move-assignment operator, + * returning 1 if such is the case and 0 otherwise. + * + * > A move-assignment operator `X::operator=` is a non-static, + * > non-template member function of _class_ `X` with exactly one + * > parameter of type `X&&`, `const X&&`, `volatile X&&` or `const + * > volatile X&&`. + * + * That is, for example, the `operator=` in: + * + * class Foo { + * bool operator=(const volatile Foo&&); + * }; + * + * Is a move-assignment operator, while the `operator=` in: + * + * class Bar { + * bool operator=(const int&&); + * }; + * + * Is not. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isMoveAssignmentOperator(CXCursor C); + +/** + * Determines if a C++ constructor or conversion function was declared + * explicit, returning 1 if such is the case and 0 otherwise. + * + * Constructors or conversion functions are declared explicit through + * the use of the explicit specifier. + * + * For example, the following constructor and conversion function are + * not explicit as they lack the explicit specifier: + * + * class Foo { + * Foo(); + * operator int(); + * }; + * + * While the following constructor and conversion function are + * explicit as they are declared with the explicit specifier. + * + * class Foo { + * explicit Foo(); + * explicit operator int(); + * }; + * + * This function will return 0 when given a cursor pointing to one of + * the former declarations and it will return 1 for a cursor pointing + * to the latter declarations. + * + * The explicit specifier allows the user to specify a + * conditional compile-time expression whose value decides + * whether the marked element is explicit or not. + * + * For example: + * + * constexpr bool foo(int i) { return i % 2 == 0; } + * + * class Foo { + * explicit(foo(1)) Foo(); + * explicit(foo(2)) operator int(); + * } + * + * This function will return 0 for the constructor and 1 for + * the conversion function. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isExplicit(CXCursor C); + +/** + * Determine if a C++ record is abstract, i.e. whether a class or struct + * has a pure virtual member function. + */ +CINDEX_LINKAGE unsigned clang_CXXRecord_isAbstract(CXCursor C); + +/** + * Determine if an enum declaration refers to a scoped enum. + */ +CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C); + +/** + * Determine if a C++ member function or member function template is + * declared 'const'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C); + +/** + * Given a cursor that represents a template, determine + * the cursor kind of the specializations would be generated by instantiating + * the template. + * + * This routine can be used to determine what flavor of function template, + * class template, or class template partial specialization is stored in the + * cursor. For example, it can describe whether a class template cursor is + * declared with "struct", "class" or "union". + * + * \param C The cursor to query. This cursor should represent a template + * declaration. + * + * \returns The cursor kind of the specializations that would be generated + * by instantiating the template \p C. If \p C is not a template, returns + * \c CXCursor_NoDeclFound. + */ +CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C); + +/** + * Given a cursor that may represent a specialization or instantiation + * of a template, retrieve the cursor that represents the template that it + * specializes or from which it was instantiated. + * + * This routine determines the template involved both for explicit + * specializations of templates and for implicit instantiations of the template, + * both of which are referred to as "specializations". For a class template + * specialization (e.g., \c std::vector), this routine will return + * either the primary template (\c std::vector) or, if the specialization was + * instantiated from a class template partial specialization, the class template + * partial specialization. For a class template partial specialization and a + * function template specialization (including instantiations), this + * this routine will return the specialized template. + * + * For members of a class template (e.g., member functions, member classes, or + * static data members), returns the specialized or instantiated member. + * Although not strictly "templates" in the C++ language, members of class + * templates have the same notions of specializations and instantiations that + * templates do, so this routine treats them similarly. + * + * \param C A cursor that may be a specialization of a template or a member + * of a template. + * + * \returns If the given cursor is a specialization or instantiation of a + * template or a member thereof, the template or member that it specializes or + * from which it was instantiated. Otherwise, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C); + +/** + * Given a cursor that references something else, return the source range + * covering that reference. + * + * \param C A cursor pointing to a member reference, a declaration reference, or + * an operator call. + * \param NameFlags A bitset with three independent flags: + * CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and + * CXNameRange_WantSinglePiece. + * \param PieceIndex For contiguous names or when passing the flag + * CXNameRange_WantSinglePiece, only one piece with index 0 is + * available. When the CXNameRange_WantSinglePiece flag is not passed for a + * non-contiguous names, this index can be used to retrieve the individual + * pieces of the name. See also CXNameRange_WantSinglePiece. + * + * \returns The piece of the name pointed to by the given cursor. If there is no + * name, or if the PieceIndex is out-of-range, a null-cursor will be returned. + */ +CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange( + CXCursor C, unsigned NameFlags, unsigned PieceIndex); + +enum CXNameRefFlags { + /** + * Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the + * range. + */ + CXNameRange_WantQualifier = 0x1, + + /** + * Include the explicit template arguments, e.g. \ in x.f, + * in the range. + */ + CXNameRange_WantTemplateArgs = 0x2, + + /** + * If the name is non-contiguous, return the full spanning range. + * + * Non-contiguous names occur in Objective-C when a selector with two or more + * parameters is used, or in C++ when using an operator: + * \code + * [object doSomething:here withValue:there]; // Objective-C + * return some_vector[1]; // C++ + * \endcode + */ + CXNameRange_WantSinglePiece = 0x4 +}; + +/** + * @} + */ + +/** + * \defgroup CINDEX_LEX Token extraction and manipulation + * + * The routines in this group provide access to the tokens within a + * translation unit, along with a semantic mapping of those tokens to + * their corresponding cursors. + * + * @{ + */ + +/** + * Describes a kind of token. + */ +typedef enum CXTokenKind { + /** + * A token that contains some kind of punctuation. + */ + CXToken_Punctuation, + + /** + * A language keyword. + */ + CXToken_Keyword, + + /** + * An identifier (that is not a keyword). + */ + CXToken_Identifier, + + /** + * A numeric, string, or character literal. + */ + CXToken_Literal, + + /** + * A comment. + */ + CXToken_Comment +} CXTokenKind; + +/** + * Describes a single preprocessing token. + */ +typedef struct { + unsigned int_data[4]; + void *ptr_data; +} CXToken; + +/** + * Get the raw lexical token starting with the given location. + * + * \param TU the translation unit whose text is being tokenized. + * + * \param Location the source location with which the token starts. + * + * \returns The token starting with the given location or NULL if no such token + * exist. The returned pointer must be freed with clang_disposeTokens before the + * translation unit is destroyed. + */ +CINDEX_LINKAGE CXToken *clang_getToken(CXTranslationUnit TU, + CXSourceLocation Location); + +/** + * Determine the kind of the given token. + */ +CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken); + +/** + * Determine the spelling of the given token. + * + * The spelling of a token is the textual representation of that token, e.g., + * the text of an identifier or keyword. + */ +CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken); + +/** + * Retrieve the source location of the given token. + */ +CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit, + CXToken); + +/** + * Retrieve a source range that covers the given token. + */ +CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken); + +/** + * Tokenize the source code described by the given range into raw + * lexical tokens. + * + * \param TU the translation unit whose text is being tokenized. + * + * \param Range the source range in which text should be tokenized. All of the + * tokens produced by tokenization will fall within this source range, + * + * \param Tokens this pointer will be set to point to the array of tokens + * that occur within the given source range. The returned pointer must be + * freed with clang_disposeTokens() before the translation unit is destroyed. + * + * \param NumTokens will be set to the number of tokens in the \c *Tokens + * array. + * + */ +CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, + CXToken **Tokens, unsigned *NumTokens); + +/** + * Annotate the given set of tokens by providing cursors for each token + * that can be mapped to a specific entity within the abstract syntax tree. + * + * This token-annotation routine is equivalent to invoking + * clang_getCursor() for the source locations of each of the + * tokens. The cursors provided are filtered, so that only those + * cursors that have a direct correspondence to the token are + * accepted. For example, given a function call \c f(x), + * clang_getCursor() would provide the following cursors: + * + * * when the cursor is over the 'f', a DeclRefExpr cursor referring to 'f'. + * * when the cursor is over the '(' or the ')', a CallExpr referring to 'f'. + * * when the cursor is over the 'x', a DeclRefExpr cursor referring to 'x'. + * + * Only the first and last of these cursors will occur within the + * annotate, since the tokens "f" and "x' directly refer to a function + * and a variable, respectively, but the parentheses are just a small + * part of the full syntax of the function call expression, which is + * not provided as an annotation. + * + * \param TU the translation unit that owns the given tokens. + * + * \param Tokens the set of tokens to annotate. + * + * \param NumTokens the number of tokens in \p Tokens. + * + * \param Cursors an array of \p NumTokens cursors, whose contents will be + * replaced with the cursors corresponding to each token. + */ +CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens, + unsigned NumTokens, CXCursor *Cursors); + +/** + * Free the given set of tokens. + */ +CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, CXToken *Tokens, + unsigned NumTokens); + +/** + * @} + */ + +/** + * \defgroup CINDEX_DEBUG Debugging facilities + * + * These routines are used for testing and debugging, only, and should not + * be relied upon. + * + * @{ + */ + +/* for debug/testing */ +CINDEX_LINKAGE CXString clang_getCursorKindSpelling(enum CXCursorKind Kind); +CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent( + CXCursor, const char **startBuf, const char **endBuf, unsigned *startLine, + unsigned *startColumn, unsigned *endLine, unsigned *endColumn); +CINDEX_LINKAGE void clang_enableStackTraces(void); +CINDEX_LINKAGE void clang_executeOnThread(void (*fn)(void *), void *user_data, + unsigned stack_size); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CODE_COMPLET Code completion + * + * Code completion involves taking an (incomplete) source file, along with + * knowledge of where the user is actively editing that file, and suggesting + * syntactically- and semantically-valid constructs that the user might want to + * use at that particular point in the source code. These data structures and + * routines provide support for code completion. + * + * @{ + */ + +/** + * A semantic string that describes a code-completion result. + * + * A semantic string that describes the formatting of a code-completion + * result as a single "template" of text that should be inserted into the + * source buffer when a particular code-completion result is selected. + * Each semantic string is made up of some number of "chunks", each of which + * contains some text along with a description of what that text means, e.g., + * the name of the entity being referenced, whether the text chunk is part of + * the template, or whether it is a "placeholder" that the user should replace + * with actual code,of a specific kind. See \c CXCompletionChunkKind for a + * description of the different kinds of chunks. + */ +typedef void *CXCompletionString; + +/** + * A single result of code completion. + */ +typedef struct { + /** + * The kind of entity that this completion refers to. + * + * The cursor kind will be a macro, keyword, or a declaration (one of the + * *Decl cursor kinds), describing the entity that the completion is + * referring to. + * + * \todo In the future, we would like to provide a full cursor, to allow + * the client to extract additional information from declaration. + */ + enum CXCursorKind CursorKind; + + /** + * The code-completion string that describes how to insert this + * code-completion result into the editing buffer. + */ + CXCompletionString CompletionString; +} CXCompletionResult; + +/** + * Describes a single piece of text within a code-completion string. + * + * Each "chunk" within a code-completion string (\c CXCompletionString) is + * either a piece of text with a specific "kind" that describes how that text + * should be interpreted by the client or is another completion string. + */ +enum CXCompletionChunkKind { + /** + * A code-completion string that describes "optional" text that + * could be a part of the template (but is not required). + * + * The Optional chunk is the only kind of chunk that has a code-completion + * string for its representation, which is accessible via + * \c clang_getCompletionChunkCompletionString(). The code-completion string + * describes an additional part of the template that is completely optional. + * For example, optional chunks can be used to describe the placeholders for + * arguments that match up with defaulted function parameters, e.g. given: + * + * \code + * void f(int x, float y = 3.14, double z = 2.71828); + * \endcode + * + * The code-completion string for this function would contain: + * - a TypedText chunk for "f". + * - a LeftParen chunk for "(". + * - a Placeholder chunk for "int x" + * - an Optional chunk containing the remaining defaulted arguments, e.g., + * - a Comma chunk for "," + * - a Placeholder chunk for "float y" + * - an Optional chunk containing the last defaulted argument: + * - a Comma chunk for "," + * - a Placeholder chunk for "double z" + * - a RightParen chunk for ")" + * + * There are many ways to handle Optional chunks. Two simple approaches are: + * - Completely ignore optional chunks, in which case the template for the + * function "f" would only include the first parameter ("int x"). + * - Fully expand all optional chunks, in which case the template for the + * function "f" would have all of the parameters. + */ + CXCompletionChunk_Optional, + /** + * Text that a user would be expected to type to get this + * code-completion result. + * + * There will be exactly one "typed text" chunk in a semantic string, which + * will typically provide the spelling of a keyword or the name of a + * declaration that could be used at the current code point. Clients are + * expected to filter the code-completion results based on the text in this + * chunk. + */ + CXCompletionChunk_TypedText, + /** + * Text that should be inserted as part of a code-completion result. + * + * A "text" chunk represents text that is part of the template to be + * inserted into user code should this particular code-completion result + * be selected. + */ + CXCompletionChunk_Text, + /** + * Placeholder text that should be replaced by the user. + * + * A "placeholder" chunk marks a place where the user should insert text + * into the code-completion template. For example, placeholders might mark + * the function parameters for a function declaration, to indicate that the + * user should provide arguments for each of those parameters. The actual + * text in a placeholder is a suggestion for the text to display before + * the user replaces the placeholder with real code. + */ + CXCompletionChunk_Placeholder, + /** + * Informative text that should be displayed but never inserted as + * part of the template. + * + * An "informative" chunk contains annotations that can be displayed to + * help the user decide whether a particular code-completion result is the + * right option, but which is not part of the actual template to be inserted + * by code completion. + */ + CXCompletionChunk_Informative, + /** + * Text that describes the current parameter when code-completion is + * referring to function call, message send, or template specialization. + * + * A "current parameter" chunk occurs when code-completion is providing + * information about a parameter corresponding to the argument at the + * code-completion point. For example, given a function + * + * \code + * int add(int x, int y); + * \endcode + * + * and the source code \c add(, where the code-completion point is after the + * "(", the code-completion string will contain a "current parameter" chunk + * for "int x", indicating that the current argument will initialize that + * parameter. After typing further, to \c add(17, (where the code-completion + * point is after the ","), the code-completion string will contain a + * "current parameter" chunk to "int y". + */ + CXCompletionChunk_CurrentParameter, + /** + * A left parenthesis ('('), used to initiate a function call or + * signal the beginning of a function parameter list. + */ + CXCompletionChunk_LeftParen, + /** + * A right parenthesis (')'), used to finish a function call or + * signal the end of a function parameter list. + */ + CXCompletionChunk_RightParen, + /** + * A left bracket ('['). + */ + CXCompletionChunk_LeftBracket, + /** + * A right bracket (']'). + */ + CXCompletionChunk_RightBracket, + /** + * A left brace ('{'). + */ + CXCompletionChunk_LeftBrace, + /** + * A right brace ('}'). + */ + CXCompletionChunk_RightBrace, + /** + * A left angle bracket ('<'). + */ + CXCompletionChunk_LeftAngle, + /** + * A right angle bracket ('>'). + */ + CXCompletionChunk_RightAngle, + /** + * A comma separator (','). + */ + CXCompletionChunk_Comma, + /** + * Text that specifies the result type of a given result. + * + * This special kind of informative chunk is not meant to be inserted into + * the text buffer. Rather, it is meant to illustrate the type that an + * expression using the given completion string would have. + */ + CXCompletionChunk_ResultType, + /** + * A colon (':'). + */ + CXCompletionChunk_Colon, + /** + * A semicolon (';'). + */ + CXCompletionChunk_SemiColon, + /** + * An '=' sign. + */ + CXCompletionChunk_Equal, + /** + * Horizontal space (' '). + */ + CXCompletionChunk_HorizontalSpace, + /** + * Vertical space ('\\n'), after which it is generally a good idea to + * perform indentation. + */ + CXCompletionChunk_VerticalSpace +}; + +/** + * Determine the kind of a particular chunk within a completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the kind of the chunk at the index \c chunk_number. + */ +CINDEX_LINKAGE enum CXCompletionChunkKind +clang_getCompletionChunkKind(CXCompletionString completion_string, + unsigned chunk_number); + +/** + * Retrieve the text associated with a particular chunk within a + * completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the text associated with the chunk at index \c chunk_number. + */ +CINDEX_LINKAGE CXString clang_getCompletionChunkText( + CXCompletionString completion_string, unsigned chunk_number); + +/** + * Retrieve the completion string associated with a particular chunk + * within a completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the completion string associated with the chunk at index + * \c chunk_number. + */ +CINDEX_LINKAGE CXCompletionString clang_getCompletionChunkCompletionString( + CXCompletionString completion_string, unsigned chunk_number); + +/** + * Retrieve the number of chunks in the given code-completion string. + */ +CINDEX_LINKAGE unsigned +clang_getNumCompletionChunks(CXCompletionString completion_string); + +/** + * Determine the priority of this code completion. + * + * The priority of a code completion indicates how likely it is that this + * particular completion is the completion that the user will select. The + * priority is selected by various internal heuristics. + * + * \param completion_string The completion string to query. + * + * \returns The priority of this completion string. Smaller values indicate + * higher-priority (more likely) completions. + */ +CINDEX_LINKAGE unsigned +clang_getCompletionPriority(CXCompletionString completion_string); + +/** + * Determine the availability of the entity that this code-completion + * string refers to. + * + * \param completion_string The completion string to query. + * + * \returns The availability of the completion string. + */ +CINDEX_LINKAGE enum CXAvailabilityKind +clang_getCompletionAvailability(CXCompletionString completion_string); + +/** + * Retrieve the number of annotations associated with the given + * completion string. + * + * \param completion_string the completion string to query. + * + * \returns the number of annotations associated with the given completion + * string. + */ +CINDEX_LINKAGE unsigned +clang_getCompletionNumAnnotations(CXCompletionString completion_string); + +/** + * Retrieve the annotation associated with the given completion string. + * + * \param completion_string the completion string to query. + * + * \param annotation_number the 0-based index of the annotation of the + * completion string. + * + * \returns annotation string associated with the completion at index + * \c annotation_number, or a NULL string if that annotation is not available. + */ +CINDEX_LINKAGE CXString clang_getCompletionAnnotation( + CXCompletionString completion_string, unsigned annotation_number); + +/** + * Retrieve the parent context of the given completion string. + * + * The parent context of a completion string is the semantic parent of + * the declaration (if any) that the code completion represents. For example, + * a code completion for an Objective-C method would have the method's class + * or protocol as its context. + * + * \param completion_string The code completion string whose parent is + * being queried. + * + * \param kind DEPRECATED: always set to CXCursor_NotImplemented if non-NULL. + * + * \returns The name of the completion parent, e.g., "NSObject" if + * the completion string represents a method in the NSObject class. + */ +CINDEX_LINKAGE CXString clang_getCompletionParent( + CXCompletionString completion_string, enum CXCursorKind *kind); + +/** + * Retrieve the brief documentation comment attached to the declaration + * that corresponds to the given completion string. + */ +CINDEX_LINKAGE CXString +clang_getCompletionBriefComment(CXCompletionString completion_string); + +/** + * Retrieve a completion string for an arbitrary declaration or macro + * definition cursor. + * + * \param cursor The cursor to query. + * + * \returns A non-context-sensitive completion string for declaration and macro + * definition cursors, or NULL for other kinds of cursors. + */ +CINDEX_LINKAGE CXCompletionString +clang_getCursorCompletionString(CXCursor cursor); + +/** + * Contains the results of code-completion. + * + * This data structure contains the results of code completion, as + * produced by \c clang_codeCompleteAt(). Its contents must be freed by + * \c clang_disposeCodeCompleteResults. + */ +typedef struct { + /** + * The code-completion results. + */ + CXCompletionResult *Results; + + /** + * The number of code-completion results stored in the + * \c Results array. + */ + unsigned NumResults; +} CXCodeCompleteResults; + +/** + * Retrieve the number of fix-its for the given completion index. + * + * Calling this makes sense only if CXCodeComplete_IncludeCompletionsWithFixIts + * option was set. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \return The number of fix-its which must be applied before the completion at + * completion_index can be applied + */ +CINDEX_LINKAGE unsigned +clang_getCompletionNumFixIts(CXCodeCompleteResults *results, + unsigned completion_index); + +/** + * Fix-its that *must* be applied before inserting the text for the + * corresponding completion. + * + * By default, clang_codeCompleteAt() only returns completions with empty + * fix-its. Extra completions with non-empty fix-its should be explicitly + * requested by setting CXCodeComplete_IncludeCompletionsWithFixIts. + * + * For the clients to be able to compute position of the cursor after applying + * fix-its, the following conditions are guaranteed to hold for + * replacement_range of the stored fix-its: + * - Ranges in the fix-its are guaranteed to never contain the completion + * point (or identifier under completion point, if any) inside them, except + * at the start or at the end of the range. + * - If a fix-it range starts or ends with completion point (or starts or + * ends after the identifier under completion point), it will contain at + * least one character. It allows to unambiguously recompute completion + * point after applying the fix-it. + * + * The intuition is that provided fix-its change code around the identifier we + * complete, but are not allowed to touch the identifier itself or the + * completion point. One example of completions with corrections are the ones + * replacing '.' with '->' and vice versa: + * + * std::unique_ptr> vec_ptr; + * In 'vec_ptr.^', one of the completions is 'push_back', it requires + * replacing '.' with '->'. + * In 'vec_ptr->^', one of the completions is 'release', it requires + * replacing '->' with '.'. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \param fixit_index The index of the fix-it for the completion at + * completion_index + * + * \param replacement_range The fix-it range that must be replaced before the + * completion at completion_index can be applied + * + * \returns The fix-it string that must replace the code at replacement_range + * before the completion at completion_index can be applied + */ +CINDEX_LINKAGE CXString clang_getCompletionFixIt( + CXCodeCompleteResults *results, unsigned completion_index, + unsigned fixit_index, CXSourceRange *replacement_range); + +/** + * Flags that can be passed to \c clang_codeCompleteAt() to + * modify its behavior. + * + * The enumerators in this enumeration can be bitwise-OR'd together to + * provide multiple options to \c clang_codeCompleteAt(). + */ +enum CXCodeComplete_Flags { + /** + * Whether to include macros within the set of code + * completions returned. + */ + CXCodeComplete_IncludeMacros = 0x01, + + /** + * Whether to include code patterns for language constructs + * within the set of code completions, e.g., for loops. + */ + CXCodeComplete_IncludeCodePatterns = 0x02, + + /** + * Whether to include brief documentation within the set of code + * completions returned. + */ + CXCodeComplete_IncludeBriefComments = 0x04, + + /** + * Whether to speed up completion by omitting top- or namespace-level entities + * defined in the preamble. There's no guarantee any particular entity is + * omitted. This may be useful if the headers are indexed externally. + */ + CXCodeComplete_SkipPreamble = 0x08, + + /** + * Whether to include completions with small + * fix-its, e.g. change '.' to '->' on member access, etc. + */ + CXCodeComplete_IncludeCompletionsWithFixIts = 0x10 +}; + +/** + * Bits that represent the context under which completion is occurring. + * + * The enumerators in this enumeration may be bitwise-OR'd together if multiple + * contexts are occurring simultaneously. + */ +enum CXCompletionContext { + /** + * The context for completions is unexposed, as only Clang results + * should be included. (This is equivalent to having no context bits set.) + */ + CXCompletionContext_Unexposed = 0, + + /** + * Completions for any possible type should be included in the results. + */ + CXCompletionContext_AnyType = 1 << 0, + + /** + * Completions for any possible value (variables, function calls, etc.) + * should be included in the results. + */ + CXCompletionContext_AnyValue = 1 << 1, + /** + * Completions for values that resolve to an Objective-C object should + * be included in the results. + */ + CXCompletionContext_ObjCObjectValue = 1 << 2, + /** + * Completions for values that resolve to an Objective-C selector + * should be included in the results. + */ + CXCompletionContext_ObjCSelectorValue = 1 << 3, + /** + * Completions for values that resolve to a C++ class type should be + * included in the results. + */ + CXCompletionContext_CXXClassTypeValue = 1 << 4, + + /** + * Completions for fields of the member being accessed using the dot + * operator should be included in the results. + */ + CXCompletionContext_DotMemberAccess = 1 << 5, + /** + * Completions for fields of the member being accessed using the arrow + * operator should be included in the results. + */ + CXCompletionContext_ArrowMemberAccess = 1 << 6, + /** + * Completions for properties of the Objective-C object being accessed + * using the dot operator should be included in the results. + */ + CXCompletionContext_ObjCPropertyAccess = 1 << 7, + + /** + * Completions for enum tags should be included in the results. + */ + CXCompletionContext_EnumTag = 1 << 8, + /** + * Completions for union tags should be included in the results. + */ + CXCompletionContext_UnionTag = 1 << 9, + /** + * Completions for struct tags should be included in the results. + */ + CXCompletionContext_StructTag = 1 << 10, + + /** + * Completions for C++ class names should be included in the results. + */ + CXCompletionContext_ClassTag = 1 << 11, + /** + * Completions for C++ namespaces and namespace aliases should be + * included in the results. + */ + CXCompletionContext_Namespace = 1 << 12, + /** + * Completions for C++ nested name specifiers should be included in + * the results. + */ + CXCompletionContext_NestedNameSpecifier = 1 << 13, + + /** + * Completions for Objective-C interfaces (classes) should be included + * in the results. + */ + CXCompletionContext_ObjCInterface = 1 << 14, + /** + * Completions for Objective-C protocols should be included in + * the results. + */ + CXCompletionContext_ObjCProtocol = 1 << 15, + /** + * Completions for Objective-C categories should be included in + * the results. + */ + CXCompletionContext_ObjCCategory = 1 << 16, + /** + * Completions for Objective-C instance messages should be included + * in the results. + */ + CXCompletionContext_ObjCInstanceMessage = 1 << 17, + /** + * Completions for Objective-C class messages should be included in + * the results. + */ + CXCompletionContext_ObjCClassMessage = 1 << 18, + /** + * Completions for Objective-C selector names should be included in + * the results. + */ + CXCompletionContext_ObjCSelectorName = 1 << 19, + + /** + * Completions for preprocessor macro names should be included in + * the results. + */ + CXCompletionContext_MacroName = 1 << 20, + + /** + * Natural language completions should be included in the results. + */ + CXCompletionContext_NaturalLanguage = 1 << 21, + + /** + * #include file completions should be included in the results. + */ + CXCompletionContext_IncludedFile = 1 << 22, + + /** + * The current context is unknown, so set all contexts. + */ + CXCompletionContext_Unknown = ((1 << 23) - 1) +}; + +/** + * Returns a default set of code-completion options that can be + * passed to\c clang_codeCompleteAt(). + */ +CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void); + +/** + * Perform code completion at a given location in a translation unit. + * + * This function performs code completion at a particular file, line, and + * column within source code, providing results that suggest potential + * code snippets based on the context of the completion. The basic model + * for code completion is that Clang will parse a complete source file, + * performing syntax checking up to the location where code-completion has + * been requested. At that point, a special code-completion token is passed + * to the parser, which recognizes this token and determines, based on the + * current location in the C/Objective-C/C++ grammar and the state of + * semantic analysis, what completions to provide. These completions are + * returned via a new \c CXCodeCompleteResults structure. + * + * Code completion itself is meant to be triggered by the client when the + * user types punctuation characters or whitespace, at which point the + * code-completion location will coincide with the cursor. For example, if \c p + * is a pointer, code-completion might be triggered after the "-" and then + * after the ">" in \c p->. When the code-completion location is after the ">", + * the completion results will provide, e.g., the members of the struct that + * "p" points to. The client is responsible for placing the cursor at the + * beginning of the token currently being typed, then filtering the results + * based on the contents of the token. For example, when code-completing for + * the expression \c p->get, the client should provide the location just after + * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the + * client can filter the results based on the current token text ("get"), only + * showing those results that start with "get". The intent of this interface + * is to separate the relatively high-latency acquisition of code-completion + * results from the filtering of results on a per-character basis, which must + * have a lower latency. + * + * \param TU The translation unit in which code-completion should + * occur. The source files for this translation unit need not be + * completely up-to-date (and the contents of those source files may + * be overridden via \p unsaved_files). Cursors referring into the + * translation unit may be invalidated by this invocation. + * + * \param complete_filename The name of the source file where code + * completion should be performed. This filename may be any file + * included in the translation unit. + * + * \param complete_line The line at which code-completion should occur. + * + * \param complete_column The column at which code-completion should occur. + * Note that the column should point just after the syntactic construct that + * initiated code completion, and not in the middle of a lexical token. + * + * \param unsaved_files the Files that have not yet been saved to disk + * but may be required for parsing or code completion, including the + * contents of those files. The contents and name of these files (as + * specified by CXUnsavedFile) are copied when necessary, so the + * client only needs to guarantee their validity until the call to + * this function returns. + * + * \param num_unsaved_files The number of unsaved file entries in \p + * unsaved_files. + * + * \param options Extra options that control the behavior of code + * completion, expressed as a bitwise OR of the enumerators of the + * CXCodeComplete_Flags enumeration. The + * \c clang_defaultCodeCompleteOptions() function returns a default set + * of code-completion options. + * + * \returns If successful, a new \c CXCodeCompleteResults structure + * containing code-completion results, which should eventually be + * freed with \c clang_disposeCodeCompleteResults(). If code + * completion fails, returns NULL. + */ +CINDEX_LINKAGE +CXCodeCompleteResults * +clang_codeCompleteAt(CXTranslationUnit TU, const char *complete_filename, + unsigned complete_line, unsigned complete_column, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, unsigned options); + +/** + * Sort the code-completion results in case-insensitive alphabetical + * order. + * + * \param Results The set of results to sort. + * \param NumResults The number of results in \p Results. + */ +CINDEX_LINKAGE +void clang_sortCodeCompletionResults(CXCompletionResult *Results, + unsigned NumResults); + +/** + * Free the given set of code-completion results. + */ +CINDEX_LINKAGE +void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); + +/** + * Determine the number of diagnostics produced prior to the + * location where code completion was performed. + */ +CINDEX_LINKAGE +unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results); + +/** + * Retrieve a diagnostic associated with the given code completion. + * + * \param Results the code completion results to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE +CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, + unsigned Index); + +/** + * Determines what completions are appropriate for the context + * the given code completion. + * + * \param Results the code completion results to query + * + * \returns the kinds of completions that are appropriate for use + * along with the given code completion results. + */ +CINDEX_LINKAGE +unsigned long long +clang_codeCompleteGetContexts(CXCodeCompleteResults *Results); + +/** + * Returns the cursor kind for the container for the current code + * completion context. The container is only guaranteed to be set for + * contexts where a container exists (i.e. member accesses or Objective-C + * message sends); if there is not a container, this function will return + * CXCursor_InvalidCode. + * + * \param Results the code completion results to query + * + * \param IsIncomplete on return, this value will be false if Clang has complete + * information about the container. If Clang does not have complete + * information, this value will be true. + * + * \returns the container kind, or CXCursor_InvalidCode if there is not a + * container + */ +CINDEX_LINKAGE +enum CXCursorKind +clang_codeCompleteGetContainerKind(CXCodeCompleteResults *Results, + unsigned *IsIncomplete); + +/** + * Returns the USR for the container for the current code completion + * context. If there is not a container for the current context, this + * function will return the empty string. + * + * \param Results the code completion results to query + * + * \returns the USR for the container + */ +CINDEX_LINKAGE +CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results); + +/** + * Returns the currently-entered selector for an Objective-C message + * send, formatted like "initWithFoo:bar:". Only guaranteed to return a + * non-empty string for CXCompletionContext_ObjCInstanceMessage and + * CXCompletionContext_ObjCClassMessage. + * + * \param Results the code completion results to query + * + * \returns the selector (or partial selector) that has been entered thus far + * for an Objective-C message send. + */ +CINDEX_LINKAGE +CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results); + +/** + * @} + */ + +/** + * \defgroup CINDEX_MISC Miscellaneous utility functions + * + * @{ + */ + +/** + * Return a version string, suitable for showing to a user, but not + * intended to be parsed (the format is not guaranteed to be stable). + */ +CINDEX_LINKAGE CXString clang_getClangVersion(void); + +/** + * Enable/disable crash recovery. + * + * \param isEnabled Flag to indicate if crash recovery is enabled. A non-zero + * value enables crash recovery, while 0 disables it. + */ +CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled); + +/** + * Visitor invoked for each file in a translation unit + * (used with clang_getInclusions()). + * + * This visitor function will be invoked by clang_getInclusions() for each + * file included (either at the top-level or by \#include directives) within + * a translation unit. The first argument is the file being included, and + * the second and third arguments provide the inclusion stack. The + * array is sorted in order of immediate inclusion. For example, + * the first element refers to the location that included 'included_file'. + */ +typedef void (*CXInclusionVisitor)(CXFile included_file, + CXSourceLocation *inclusion_stack, + unsigned include_len, + CXClientData client_data); + +/** + * Visit the set of preprocessor inclusions in a translation unit. + * The visitor function is called with the provided data for every included + * file. This does not include headers included by the PCH file (unless one + * is inspecting the inclusions in the PCH file itself). + */ +CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu, + CXInclusionVisitor visitor, + CXClientData client_data); + +typedef enum { + CXEval_Int = 1, + CXEval_Float = 2, + CXEval_ObjCStrLiteral = 3, + CXEval_StrLiteral = 4, + CXEval_CFStr = 5, + CXEval_Other = 6, + + CXEval_UnExposed = 0 + +} CXEvalResultKind; + +/** + * Evaluation result of a cursor + */ +typedef void *CXEvalResult; + +/** + * If cursor is a statement declaration tries to evaluate the + * statement and if its variable, tries to evaluate its initializer, + * into its corresponding type. + * If it's an expression, tries to evaluate the expression. + */ +CINDEX_LINKAGE CXEvalResult clang_Cursor_Evaluate(CXCursor C); + +/** + * Returns the kind of the evaluated result. + */ +CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E); + +/** + * Returns the evaluation result as integer if the + * kind is Int. + */ +CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E); + +/** + * Returns the evaluation result as a long long integer if the + * kind is Int. This prevents overflows that may happen if the result is + * returned with clang_EvalResult_getAsInt. + */ +CINDEX_LINKAGE long long clang_EvalResult_getAsLongLong(CXEvalResult E); + +/** + * Returns a non-zero value if the kind is Int and the evaluation + * result resulted in an unsigned integer. + */ +CINDEX_LINKAGE unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E); + +/** + * Returns the evaluation result as an unsigned integer if + * the kind is Int and clang_EvalResult_isUnsignedInt is non-zero. + */ +CINDEX_LINKAGE unsigned long long +clang_EvalResult_getAsUnsigned(CXEvalResult E); + +/** + * Returns the evaluation result as double if the + * kind is double. + */ +CINDEX_LINKAGE double clang_EvalResult_getAsDouble(CXEvalResult E); + +/** + * Returns the evaluation result as a constant string if the + * kind is other than Int or float. User must not free this pointer, + * instead call clang_EvalResult_dispose on the CXEvalResult returned + * by clang_Cursor_Evaluate. + */ +CINDEX_LINKAGE const char *clang_EvalResult_getAsStr(CXEvalResult E); + +/** + * Disposes the created Eval memory. + */ +CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E); +/** + * @} + */ + +/** \defgroup CINDEX_REMAPPING Remapping functions + * + * @{ + */ + +/** + * A remapping of original source files and their translated files. + */ +typedef void *CXRemapping; + +/** + * Retrieve a remapping. + * + * \param path the path that contains metadata about remappings. + * + * \returns the requested remapping. This remapping must be freed + * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred. + */ +CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path); + +/** + * Retrieve a remapping. + * + * \param filePaths pointer to an array of file paths containing remapping info. + * + * \param numFiles number of file paths. + * + * \returns the requested remapping. This remapping must be freed + * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred. + */ +CINDEX_LINKAGE +CXRemapping clang_getRemappingsFromFileList(const char **filePaths, + unsigned numFiles); + +/** + * Determine the number of remappings. + */ +CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping); + +/** + * Get the original and the associated filename from the remapping. + * + * \param original If non-NULL, will be set to the original filename. + * + * \param transformed If non-NULL, will be set to the filename that the original + * is associated with. + */ +CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index, + CXString *original, + CXString *transformed); + +/** + * Dispose the remapping. + */ +CINDEX_LINKAGE void clang_remap_dispose(CXRemapping); + +/** + * @} + */ + +/** \defgroup CINDEX_HIGH Higher level API functions + * + * @{ + */ + +enum CXVisitorResult { CXVisit_Break, CXVisit_Continue }; + +typedef struct CXCursorAndRangeVisitor { + void *context; + enum CXVisitorResult (*visit)(void *context, CXCursor, CXSourceRange); +} CXCursorAndRangeVisitor; + +typedef enum { + /** + * Function returned successfully. + */ + CXResult_Success = 0, + /** + * One of the parameters was invalid for the function. + */ + CXResult_Invalid = 1, + /** + * The function was terminated by a callback (e.g. it returned + * CXVisit_Break) + */ + CXResult_VisitBreak = 2 + +} CXResult; + +/** + * Find references of a declaration in a specific file. + * + * \param cursor pointing to a declaration or a reference of one. + * + * \param file to search for references. + * + * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for + * each reference found. + * The CXSourceRange will point inside the file; if the reference is inside + * a macro (and not a macro argument) the CXSourceRange will be invalid. + * + * \returns one of the CXResult enumerators. + */ +CINDEX_LINKAGE CXResult clang_findReferencesInFile( + CXCursor cursor, CXFile file, CXCursorAndRangeVisitor visitor); + +/** + * Find #import/#include directives in a specific file. + * + * \param TU translation unit containing the file to query. + * + * \param file to search for #import/#include directives. + * + * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for + * each directive found. + * + * \returns one of the CXResult enumerators. + */ +CINDEX_LINKAGE CXResult clang_findIncludesInFile( + CXTranslationUnit TU, CXFile file, CXCursorAndRangeVisitor visitor); + +#if __has_feature(blocks) +typedef enum CXVisitorResult (^CXCursorAndRangeVisitorBlock)(CXCursor, + CXSourceRange); +#else +typedef struct _CXCursorAndRangeVisitorBlock *CXCursorAndRangeVisitorBlock; +#endif + +CINDEX_LINKAGE +CXResult clang_findReferencesInFileWithBlock(CXCursor, CXFile, + CXCursorAndRangeVisitorBlock); + +CINDEX_LINKAGE +CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit, CXFile, + CXCursorAndRangeVisitorBlock); + +/** + * The client's data object that is associated with a CXFile. + */ +typedef void *CXIdxClientFile; + +/** + * The client's data object that is associated with a semantic entity. + */ +typedef void *CXIdxClientEntity; + +/** + * The client's data object that is associated with a semantic container + * of entities. + */ +typedef void *CXIdxClientContainer; + +/** + * The client's data object that is associated with an AST file (PCH + * or module). + */ +typedef void *CXIdxClientASTFile; + +/** + * Source location passed to index callbacks. + */ +typedef struct { + void *ptr_data[2]; + unsigned int_data; +} CXIdxLoc; + +/** + * Data for ppIncludedFile callback. + */ +typedef struct { + /** + * Location of '#' in the \#include/\#import directive. + */ + CXIdxLoc hashLoc; + /** + * Filename as written in the \#include/\#import directive. + */ + const char *filename; + /** + * The actual file that the \#include/\#import directive resolved to. + */ + CXFile file; + int isImport; + int isAngled; + /** + * Non-zero if the directive was automatically turned into a module + * import. + */ + int isModuleImport; +} CXIdxIncludedFileInfo; + +/** + * Data for IndexerCallbacks#importedASTFile. + */ +typedef struct { + /** + * Top level AST file containing the imported PCH, module or submodule. + */ + CXFile file; + /** + * The imported module or NULL if the AST file is a PCH. + */ + CXModule module; + /** + * Location where the file is imported. Applicable only for modules. + */ + CXIdxLoc loc; + /** + * Non-zero if an inclusion directive was automatically turned into + * a module import. Applicable only for modules. + */ + int isImplicit; + +} CXIdxImportedASTFileInfo; + +typedef enum { + CXIdxEntity_Unexposed = 0, + CXIdxEntity_Typedef = 1, + CXIdxEntity_Function = 2, + CXIdxEntity_Variable = 3, + CXIdxEntity_Field = 4, + CXIdxEntity_EnumConstant = 5, + + CXIdxEntity_ObjCClass = 6, + CXIdxEntity_ObjCProtocol = 7, + CXIdxEntity_ObjCCategory = 8, + + CXIdxEntity_ObjCInstanceMethod = 9, + CXIdxEntity_ObjCClassMethod = 10, + CXIdxEntity_ObjCProperty = 11, + CXIdxEntity_ObjCIvar = 12, + + CXIdxEntity_Enum = 13, + CXIdxEntity_Struct = 14, + CXIdxEntity_Union = 15, + + CXIdxEntity_CXXClass = 16, + CXIdxEntity_CXXNamespace = 17, + CXIdxEntity_CXXNamespaceAlias = 18, + CXIdxEntity_CXXStaticVariable = 19, + CXIdxEntity_CXXStaticMethod = 20, + CXIdxEntity_CXXInstanceMethod = 21, + CXIdxEntity_CXXConstructor = 22, + CXIdxEntity_CXXDestructor = 23, + CXIdxEntity_CXXConversionFunction = 24, + CXIdxEntity_CXXTypeAlias = 25, + CXIdxEntity_CXXInterface = 26, + CXIdxEntity_CXXConcept = 27 + +} CXIdxEntityKind; + +typedef enum { + CXIdxEntityLang_None = 0, + CXIdxEntityLang_C = 1, + CXIdxEntityLang_ObjC = 2, + CXIdxEntityLang_CXX = 3, + CXIdxEntityLang_Swift = 4 +} CXIdxEntityLanguage; + +/** + * Extra C++ template information for an entity. This can apply to: + * CXIdxEntity_Function + * CXIdxEntity_CXXClass + * CXIdxEntity_CXXStaticMethod + * CXIdxEntity_CXXInstanceMethod + * CXIdxEntity_CXXConstructor + * CXIdxEntity_CXXConversionFunction + * CXIdxEntity_CXXTypeAlias + */ +typedef enum { + CXIdxEntity_NonTemplate = 0, + CXIdxEntity_Template = 1, + CXIdxEntity_TemplatePartialSpecialization = 2, + CXIdxEntity_TemplateSpecialization = 3 +} CXIdxEntityCXXTemplateKind; + +typedef enum { + CXIdxAttr_Unexposed = 0, + CXIdxAttr_IBAction = 1, + CXIdxAttr_IBOutlet = 2, + CXIdxAttr_IBOutletCollection = 3 +} CXIdxAttrKind; + +typedef struct { + CXIdxAttrKind kind; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxAttrInfo; + +typedef struct { + CXIdxEntityKind kind; + CXIdxEntityCXXTemplateKind templateKind; + CXIdxEntityLanguage lang; + const char *name; + const char *USR; + CXCursor cursor; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; +} CXIdxEntityInfo; + +typedef struct { + CXCursor cursor; +} CXIdxContainerInfo; + +typedef struct { + const CXIdxAttrInfo *attrInfo; + const CXIdxEntityInfo *objcClass; + CXCursor classCursor; + CXIdxLoc classLoc; +} CXIdxIBOutletCollectionAttrInfo; + +typedef enum { CXIdxDeclFlag_Skipped = 0x1 } CXIdxDeclInfoFlags; + +typedef struct { + const CXIdxEntityInfo *entityInfo; + CXCursor cursor; + CXIdxLoc loc; + const CXIdxContainerInfo *semanticContainer; + /** + * Generally same as #semanticContainer but can be different in + * cases like out-of-line C++ member functions. + */ + const CXIdxContainerInfo *lexicalContainer; + int isRedeclaration; + int isDefinition; + int isContainer; + const CXIdxContainerInfo *declAsContainer; + /** + * Whether the declaration exists in code or was created implicitly + * by the compiler, e.g. implicit Objective-C methods for properties. + */ + int isImplicit; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; + + unsigned flags; + +} CXIdxDeclInfo; + +typedef enum { + CXIdxObjCContainer_ForwardRef = 0, + CXIdxObjCContainer_Interface = 1, + CXIdxObjCContainer_Implementation = 2 +} CXIdxObjCContainerKind; + +typedef struct { + const CXIdxDeclInfo *declInfo; + CXIdxObjCContainerKind kind; +} CXIdxObjCContainerDeclInfo; + +typedef struct { + const CXIdxEntityInfo *base; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxBaseClassInfo; + +typedef struct { + const CXIdxEntityInfo *protocol; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxObjCProtocolRefInfo; + +typedef struct { + const CXIdxObjCProtocolRefInfo *const *protocols; + unsigned numProtocols; +} CXIdxObjCProtocolRefListInfo; + +typedef struct { + const CXIdxObjCContainerDeclInfo *containerInfo; + const CXIdxBaseClassInfo *superInfo; + const CXIdxObjCProtocolRefListInfo *protocols; +} CXIdxObjCInterfaceDeclInfo; + +typedef struct { + const CXIdxObjCContainerDeclInfo *containerInfo; + const CXIdxEntityInfo *objcClass; + CXCursor classCursor; + CXIdxLoc classLoc; + const CXIdxObjCProtocolRefListInfo *protocols; +} CXIdxObjCCategoryDeclInfo; + +typedef struct { + const CXIdxDeclInfo *declInfo; + const CXIdxEntityInfo *getter; + const CXIdxEntityInfo *setter; +} CXIdxObjCPropertyDeclInfo; + +typedef struct { + const CXIdxDeclInfo *declInfo; + const CXIdxBaseClassInfo *const *bases; + unsigned numBases; +} CXIdxCXXClassDeclInfo; + +/** + * Data for IndexerCallbacks#indexEntityReference. + * + * This may be deprecated in a future version as this duplicates + * the \c CXSymbolRole_Implicit bit in \c CXSymbolRole. + */ +typedef enum { + /** + * The entity is referenced directly in user's code. + */ + CXIdxEntityRef_Direct = 1, + /** + * An implicit reference, e.g. a reference of an Objective-C method + * via the dot syntax. + */ + CXIdxEntityRef_Implicit = 2 +} CXIdxEntityRefKind; + +/** + * Roles that are attributed to symbol occurrences. + * + * Internal: this currently mirrors low 9 bits of clang::index::SymbolRole with + * higher bits zeroed. These high bits may be exposed in the future. + */ +typedef enum { + CXSymbolRole_None = 0, + CXSymbolRole_Declaration = 1 << 0, + CXSymbolRole_Definition = 1 << 1, + CXSymbolRole_Reference = 1 << 2, + CXSymbolRole_Read = 1 << 3, + CXSymbolRole_Write = 1 << 4, + CXSymbolRole_Call = 1 << 5, + CXSymbolRole_Dynamic = 1 << 6, + CXSymbolRole_AddressOf = 1 << 7, + CXSymbolRole_Implicit = 1 << 8 +} CXSymbolRole; + +/** + * Data for IndexerCallbacks#indexEntityReference. + */ +typedef struct { + CXIdxEntityRefKind kind; + /** + * Reference cursor. + */ + CXCursor cursor; + CXIdxLoc loc; + /** + * The entity that gets referenced. + */ + const CXIdxEntityInfo *referencedEntity; + /** + * Immediate "parent" of the reference. For example: + * + * \code + * Foo *var; + * \endcode + * + * The parent of reference of type 'Foo' is the variable 'var'. + * For references inside statement bodies of functions/methods, + * the parentEntity will be the function/method. + */ + const CXIdxEntityInfo *parentEntity; + /** + * Lexical container context of the reference. + */ + const CXIdxContainerInfo *container; + /** + * Sets of symbol roles of the reference. + */ + CXSymbolRole role; +} CXIdxEntityRefInfo; + +/** + * A group of callbacks used by #clang_indexSourceFile and + * #clang_indexTranslationUnit. + */ +typedef struct { + /** + * Called periodically to check whether indexing should be aborted. + * Should return 0 to continue, and non-zero to abort. + */ + int (*abortQuery)(CXClientData client_data, void *reserved); + + /** + * Called at the end of indexing; passes the complete diagnostic set. + */ + void (*diagnostic)(CXClientData client_data, CXDiagnosticSet, void *reserved); + + CXIdxClientFile (*enteredMainFile)(CXClientData client_data, CXFile mainFile, + void *reserved); + + /** + * Called when a file gets \#included/\#imported. + */ + CXIdxClientFile (*ppIncludedFile)(CXClientData client_data, + const CXIdxIncludedFileInfo *); + + /** + * Called when a AST file (PCH or module) gets imported. + * + * AST files will not get indexed (there will not be callbacks to index all + * the entities in an AST file). The recommended action is that, if the AST + * file is not already indexed, to initiate a new indexing job specific to + * the AST file. + */ + CXIdxClientASTFile (*importedASTFile)(CXClientData client_data, + const CXIdxImportedASTFileInfo *); + + /** + * Called at the beginning of indexing a translation unit. + */ + CXIdxClientContainer (*startedTranslationUnit)(CXClientData client_data, + void *reserved); + + void (*indexDeclaration)(CXClientData client_data, const CXIdxDeclInfo *); + + /** + * Called to index a reference of an entity. + */ + void (*indexEntityReference)(CXClientData client_data, + const CXIdxEntityRefInfo *); + +} IndexerCallbacks; + +CINDEX_LINKAGE int clang_index_isEntityObjCContainerKind(CXIdxEntityKind); +CINDEX_LINKAGE const CXIdxObjCContainerDeclInfo * +clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCInterfaceDeclInfo * +clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE +const CXIdxObjCCategoryDeclInfo * +clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCProtocolRefListInfo * +clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCPropertyDeclInfo * +clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxIBOutletCollectionAttrInfo * +clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *); + +CINDEX_LINKAGE const CXIdxCXXClassDeclInfo * +clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *); + +/** + * For retrieving a custom CXIdxClientContainer attached to a + * container. + */ +CINDEX_LINKAGE CXIdxClientContainer +clang_index_getClientContainer(const CXIdxContainerInfo *); + +/** + * For setting a custom CXIdxClientContainer attached to a + * container. + */ +CINDEX_LINKAGE void clang_index_setClientContainer(const CXIdxContainerInfo *, + CXIdxClientContainer); + +/** + * For retrieving a custom CXIdxClientEntity attached to an entity. + */ +CINDEX_LINKAGE CXIdxClientEntity +clang_index_getClientEntity(const CXIdxEntityInfo *); + +/** + * For setting a custom CXIdxClientEntity attached to an entity. + */ +CINDEX_LINKAGE void clang_index_setClientEntity(const CXIdxEntityInfo *, + CXIdxClientEntity); + +/** + * An indexing action/session, to be applied to one or multiple + * translation units. + */ +typedef void *CXIndexAction; + +/** + * An indexing action/session, to be applied to one or multiple + * translation units. + * + * \param CIdx The index object with which the index action will be associated. + */ +CINDEX_LINKAGE CXIndexAction clang_IndexAction_create(CXIndex CIdx); + +/** + * Destroy the given index action. + * + * The index action must not be destroyed until all of the translation units + * created within that index action have been destroyed. + */ +CINDEX_LINKAGE void clang_IndexAction_dispose(CXIndexAction); + +typedef enum { + /** + * Used to indicate that no special indexing options are needed. + */ + CXIndexOpt_None = 0x0, + + /** + * Used to indicate that IndexerCallbacks#indexEntityReference should + * be invoked for only one reference of an entity per source file that does + * not also include a declaration/definition of the entity. + */ + CXIndexOpt_SuppressRedundantRefs = 0x1, + + /** + * Function-local symbols should be indexed. If this is not set + * function-local symbols will be ignored. + */ + CXIndexOpt_IndexFunctionLocalSymbols = 0x2, + + /** + * Implicit function/class template instantiations should be indexed. + * If this is not set, implicit instantiations will be ignored. + */ + CXIndexOpt_IndexImplicitTemplateInstantiations = 0x4, + + /** + * Suppress all compiler warnings when parsing for indexing. + */ + CXIndexOpt_SuppressWarnings = 0x8, + + /** + * Skip a function/method body that was already parsed during an + * indexing session associated with a \c CXIndexAction object. + * Bodies in system headers are always skipped. + */ + CXIndexOpt_SkipParsedBodiesInSession = 0x10 + +} CXIndexOptFlags; + +/** + * Index the given source file and the translation unit corresponding + * to that file via callbacks implemented through #IndexerCallbacks. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the invoked callbacks. + * + * \param index_callbacks Pointer to indexing callbacks that the client + * implements. + * + * \param index_callbacks_size Size of #IndexerCallbacks structure that gets + * passed in index_callbacks. + * + * \param index_options A bitmask of options that affects how indexing is + * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags. + * + * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be + * reused after indexing is finished. Set to \c NULL if you do not require it. + * + * \returns 0 on success or if there were errors from which the compiler could + * recover. If there is a failure from which there is no recovery, returns + * a non-zero \c CXErrorCode. + * + * The rest of the parameters are the same as #clang_parseTranslationUnit. + */ +CINDEX_LINKAGE int clang_indexSourceFile( + CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks, + unsigned index_callbacks_size, unsigned index_options, + const char *source_filename, const char *const *command_line_args, + int num_command_line_args, struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options); + +/** + * Same as clang_indexSourceFile but requires a full command line + * for \c command_line_args including argv[0]. This is useful if the standard + * library paths are relative to the binary. + */ +CINDEX_LINKAGE int clang_indexSourceFileFullArgv( + CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks, + unsigned index_callbacks_size, unsigned index_options, + const char *source_filename, const char *const *command_line_args, + int num_command_line_args, struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options); + +/** + * Index the given translation unit via callbacks implemented through + * #IndexerCallbacks. + * + * The order of callback invocations is not guaranteed to be the same as + * when indexing a source file. The high level order will be: + * + * -Preprocessor callbacks invocations + * -Declaration/reference callbacks invocations + * -Diagnostic callback invocations + * + * The parameters are the same as #clang_indexSourceFile. + * + * \returns If there is a failure from which there is no recovery, returns + * non-zero, otherwise returns 0. + */ +CINDEX_LINKAGE int clang_indexTranslationUnit( + CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks, + unsigned index_callbacks_size, unsigned index_options, CXTranslationUnit); + +/** + * Retrieve the CXIdxFile, file, line, column, and offset represented by + * the given CXIdxLoc. + * + * If the location refers into a macro expansion, retrieves the + * location of the macro expansion and if it refers into a macro argument + * retrieves the location of the argument. + */ +CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc, + CXIdxClientFile *indexFile, + CXFile *file, unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * Retrieve the CXSourceLocation represented by the given CXIdxLoc. + */ +CINDEX_LINKAGE +CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc); + +/** + * Visitor invoked for each field found by a traversal. + * + * This visitor function will be invoked for each field found by + * \c clang_Type_visitFields. Its first argument is the cursor being + * visited, its second argument is the client data provided to + * \c clang_Type_visitFields. + * + * The visitor should return one of the \c CXVisitorResult values + * to direct \c clang_Type_visitFields. + */ +typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C, + CXClientData client_data); + +/** + * Visit the fields of a particular type. + * + * This function visits all the direct fields of the given cursor, + * invoking the given \p visitor function with the cursors of each + * visited field. The traversal may be ended prematurely, if + * the visitor returns \c CXFieldVisit_Break. + * + * \param T the record type whose field may be visited. + * + * \param visitor the visitor function that will be invoked for each + * field of \p T. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the visitor each time it is invoked. + * + * \returns a non-zero value if the traversal was terminated + * prematurely by the visitor returning \c CXFieldVisit_Break. + */ +CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T, CXFieldVisitor visitor, + CXClientData client_data); + +/** + * Describes the kind of binary operators. + */ +enum CXBinaryOperatorKind { + /** This value describes cursors which are not binary operators. */ + CXBinaryOperator_Invalid, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemD, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemI, + /** Multiplication operator. */ + CXBinaryOperator_Mul, + /** Division operator. */ + CXBinaryOperator_Div, + /** Remainder operator. */ + CXBinaryOperator_Rem, + /** Addition operator. */ + CXBinaryOperator_Add, + /** Subtraction operator. */ + CXBinaryOperator_Sub, + /** Bitwise shift left operator. */ + CXBinaryOperator_Shl, + /** Bitwise shift right operator. */ + CXBinaryOperator_Shr, + /** C++ three-way comparison (spaceship) operator. */ + CXBinaryOperator_Cmp, + /** Less than operator. */ + CXBinaryOperator_LT, + /** Greater than operator. */ + CXBinaryOperator_GT, + /** Less or equal operator. */ + CXBinaryOperator_LE, + /** Greater or equal operator. */ + CXBinaryOperator_GE, + /** Equal operator. */ + CXBinaryOperator_EQ, + /** Not equal operator. */ + CXBinaryOperator_NE, + /** Bitwise AND operator. */ + CXBinaryOperator_And, + /** Bitwise XOR operator. */ + CXBinaryOperator_Xor, + /** Bitwise OR operator. */ + CXBinaryOperator_Or, + /** Logical AND operator. */ + CXBinaryOperator_LAnd, + /** Logical OR operator. */ + CXBinaryOperator_LOr, + /** Assignment operator. */ + CXBinaryOperator_Assign, + /** Multiplication assignment operator. */ + CXBinaryOperator_MulAssign, + /** Division assignment operator. */ + CXBinaryOperator_DivAssign, + /** Remainder assignment operator. */ + CXBinaryOperator_RemAssign, + /** Addition assignment operator. */ + CXBinaryOperator_AddAssign, + /** Subtraction assignment operator. */ + CXBinaryOperator_SubAssign, + /** Bitwise shift left assignment operator. */ + CXBinaryOperator_ShlAssign, + /** Bitwise shift right assignment operator. */ + CXBinaryOperator_ShrAssign, + /** Bitwise AND assignment operator. */ + CXBinaryOperator_AndAssign, + /** Bitwise XOR assignment operator. */ + CXBinaryOperator_XorAssign, + /** Bitwise OR assignment operator. */ + CXBinaryOperator_OrAssign, + /** Comma operator. */ + CXBinaryOperator_Comma +}; + +/** + * Retrieve the spelling of a given CXBinaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind); + +/** + * Retrieve the binary operator kind of this cursor. + * + * If this cursor is not a binary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXBinaryOperatorKind +clang_getCursorBinaryOperatorKind(CXCursor cursor); + +/** + * Describes the kind of unary operators. + */ +enum CXUnaryOperatorKind { + /** This value describes cursors which are not unary operators. */ + CXUnaryOperator_Invalid, + /** Postfix increment operator. */ + CXUnaryOperator_PostInc, + /** Postfix decrement operator. */ + CXUnaryOperator_PostDec, + /** Prefix increment operator. */ + CXUnaryOperator_PreInc, + /** Prefix decrement operator. */ + CXUnaryOperator_PreDec, + /** Address of operator. */ + CXUnaryOperator_AddrOf, + /** Dereference operator. */ + CXUnaryOperator_Deref, + /** Plus operator. */ + CXUnaryOperator_Plus, + /** Minus operator. */ + CXUnaryOperator_Minus, + /** Not operator. */ + CXUnaryOperator_Not, + /** LNot operator. */ + CXUnaryOperator_LNot, + /** "__real expr" operator. */ + CXUnaryOperator_Real, + /** "__imag expr" operator. */ + CXUnaryOperator_Imag, + /** __extension__ marker operator. */ + CXUnaryOperator_Extension, + /** C++ co_await operator. */ + CXUnaryOperator_Coawait +}; + +/** + * Retrieve the spelling of a given CXUnaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind); + +/** + * Retrieve the unary operator kind of this cursor. + * + * If this cursor is not a unary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXUnaryOperatorKind +clang_getCursorUnaryOperatorKind(CXCursor cursor); + +/** + * @} + */ + +/** + * @} + */ + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/Platform.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Platform.h new file mode 100644 index 0000000000..67c1fff8ff --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Platform.h @@ -0,0 +1,53 @@ +/*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides platform specific macros (dllimport, deprecated, ...) *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_PLATFORM_H +#define LLVM_CLANG_C_PLATFORM_H + +#include "clang-c/ExternC.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +/* Windows DLL import/export. */ +#ifndef CINDEX_NO_EXPORTS + #define CINDEX_EXPORTS +#endif +#ifdef _WIN32 + #ifdef CINDEX_EXPORTS + #ifdef _CINDEX_LIB_ + #define CINDEX_LINKAGE __declspec(dllexport) + #else + #define CINDEX_LINKAGE __declspec(dllimport) + #endif + #endif +#elif defined(CINDEX_EXPORTS) && defined(__GNUC__) + #define CINDEX_LINKAGE __attribute__((visibility("default"))) +#endif + +#ifndef CINDEX_LINKAGE + #define CINDEX_LINKAGE +#endif + +#ifdef __GNUC__ + #define CINDEX_DEPRECATED __attribute__((deprecated)) +#else + #ifdef _MSC_VER + #define CINDEX_DEPRECATED __declspec(deprecated) + #else + #define CINDEX_DEPRECATED + #endif +#endif + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/include/clang-c/Rewrite.h b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Rewrite.h new file mode 100644 index 0000000000..ce1b05594b --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/include/clang-c/Rewrite.h @@ -0,0 +1,63 @@ +/*===-- clang-c/Rewrite.h - C CXRewriter --------------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_REWRITE_H +#define LLVM_CLANG_C_REWRITE_H + +#include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Index.h" +#include "clang-c/Platform.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN + +typedef void *CXRewriter; + +/** + * Create CXRewriter. + */ +CINDEX_LINKAGE CXRewriter clang_CXRewriter_create(CXTranslationUnit TU); + +/** + * Insert the specified string at the specified location in the original buffer. + */ +CINDEX_LINKAGE void clang_CXRewriter_insertTextBefore(CXRewriter Rew, CXSourceLocation Loc, + const char *Insert); + +/** + * Replace the specified range of characters in the input with the specified + * replacement. + */ +CINDEX_LINKAGE void clang_CXRewriter_replaceText(CXRewriter Rew, CXSourceRange ToBeReplaced, + const char *Replacement); + +/** + * Remove the specified range. + */ +CINDEX_LINKAGE void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved); + +/** + * Save all changed files to disk. + * Returns 1 if any files were not saved successfully, returns 0 otherwise. + */ +CINDEX_LINKAGE int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew); + +/** + * Write out rewritten version of the main file to stdout. + */ +CINDEX_LINKAGE void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew); + +/** + * Free the given CXRewriter. + */ +CINDEX_LINKAGE void clang_CXRewriter_dispose(CXRewriter Rew); + +LLVM_CLANG_C_EXTERN_C_END + +#endif diff --git a/pkgs/ffigenpad/third_party/libclang/libclang.exports b/pkgs/ffigenpad/third_party/libclang/libclang.exports new file mode 100644 index 0000000000..da50f74474 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/libclang.exports @@ -0,0 +1,73 @@ +_clang_createIndex +_clang_disposeIndex +_clang_parseTranslationUnit +_clang_disposeTranslationUnit +_clang_getNumDiagnostics +_clang_getDiagnostic +_clang_getDiagnosticSeverity +_clang_disposeDiagnostic +_clang_EvalResult_getKind +_clang_EvalResult_getAsLongLong +_clang_EvalResult_getAsDouble +_clang_EvalResult_getAsStr +_clang_EvalResult_dispose +_clang_getCString_wrap +_clang_disposeString_wrap +_clang_getClangVersion_wrap +_clang_getCursorKind_wrap +_clang_getCursorDefinition_wrap +_clang_getCursorKindSpelling_wrap +_clang_getCursorType_wrap +_clang_getTypeSpelling_wrap +_clang_getTypeKindSpelling_wrap +_clang_getResultType_wrap +_clang_getPointeeType_wrap +_clang_getCanonicalType_wrap +_clang_Type_getModifiedType_wrap +_clang_Type_getNullability_wrap +_clang_Type_getNamedType_wrap +_clang_Type_getAlignOf_wrap +_clang_getTypeDeclaration_wrap +_clang_getTypedefName_wrap +_clang_getTypedefDeclUnderlyingType_wrap +_clang_getCursorSpelling_wrap +_clang_getCursorUSR_wrap +_clang_getTranslationUnitCursor_wrap +_clang_formatDiagnostic_wrap +_clang_visitChildren_wrap +_clang_getArgType_wrap +_clang_getNumArgTypes_wrap +_clang_getEnumConstantDeclValue_wrap +_clang_equalRanges_wrap +_clang_Cursor_Evaluate_wrap +_clang_Cursor_getArgument_wrap +_clang_Cursor_getNumArguments_wrap +_clang_Cursor_getCommentRange_wrap +_clang_Cursor_getRawCommentText_wrap +_clang_Cursor_getBriefCommentText_wrap +_clang_Cursor_getStorageClass_wrap +_clang_getFieldDeclBitWidth_wrap +_clang_Cursor_hasAttrs_wrap +_clang_Cursor_isFunctionInlined_wrap +_clang_Cursor_isAnonymous_wrap +_clang_Cursor_isAnonymousRecordDecl_wrap +_clang_Cursor_isNull_wrap +_clang_Cursor_isMacroFunctionLike_wrap +_clang_Cursor_isMacroBuiltin_wrap +_clang_Cursor_getObjCPropertyAttributes_wrap +_clang_Cursor_isObjCOptional_wrap +_clang_Cursor_getObjCPropertyGetterName_wrap +_clang_Cursor_getObjCPropertySetterName_wrap +_clang_getCursorResultType_wrap +_clang_isFunctionTypeVariadic_wrap +_clang_getCursorLocation_wrap +_clang_getEnumDeclIntegerType_wrap +_clang_getFileLocation_wrap +_clang_getFileName_wrap +_clang_getNumElements_wrap +_clang_getArrayElementType_wrap +_clang_isConstQualifiedType_wrap +_clang_Location_isInSystemHeader_wrap +_getCXTypeKind +_malloc +_free \ No newline at end of file diff --git a/pkgs/ffigenpad/third_party/libclang/license.txt b/pkgs/ffigenpad/third_party/libclang/license.txt new file mode 100644 index 0000000000..eeea4338d5 --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/license.txt @@ -0,0 +1,222 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + + +Files generated from libclang source code are +- lib/src/header_parser/clang_bindings/clang_bindings.dart diff --git a/pkgs/ffigenpad/third_party/libclang/wrapper.c b/pkgs/ffigenpad/third_party/libclang/wrapper.c new file mode 100644 index 0000000000..bddba41dad --- /dev/null +++ b/pkgs/ffigenpad/third_party/libclang/wrapper.c @@ -0,0 +1,300 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Heavily adapted from +// https://github.com/dart-archive/ffigen/blob/46ddca94b6f623590fe9f2ad7202cef250e554e2/tool/wrapped_libclang/wrapper.c + +#include "clang-c/Index.h" +#include +#include +#include + +// utility. +#define aloc(T) ((T *)malloc(sizeof(T))) +CXCursor *ptrToCXCursor(CXCursor t) { + CXCursor *c = aloc(CXCursor); + *c = t; + return c; +} +CXString *ptrToCXString(CXString t) { + CXString *c = aloc(CXString); + *c = t; + return c; +} +CXType *ptrToCXType(CXType t) { + CXType *c = aloc(CXType); + *c = t; + return c; +} +CXSourceLocation *ptrToCXSourceLocation(CXSourceLocation t) { + CXSourceLocation *c = aloc(CXSourceLocation); + *c = t; + return c; +} +CXSourceRange *ptrToCXSourceRange(CXSourceRange t) { + CXSourceRange *c = aloc(CXSourceRange); + *c = t; + return c; +} + +// START ===== WRAPPER FUNCTIONS ===================== + +CXString *clang_getClangVersion_wrap() { + return ptrToCXString(clang_getClangVersion()); +} + +const char *clang_getCString_wrap(CXString *string) { + const char *a = clang_getCString(*string); + + return a; +} + +void clang_disposeString_wrap(CXString *string) { + clang_disposeString(*string); + free(string); + return; +} + +enum CXCursorKind clang_getCursorKind_wrap(CXCursor *cursor) { + return clang_getCursorKind(*cursor); +} + +CXCursor *clang_getCursorDefinition_wrap(CXCursor *cursor) { + return ptrToCXCursor(clang_getCursorDefinition(*cursor)); +} + +CXString *clang_getCursorKindSpelling_wrap(enum CXCursorKind kind) { + return ptrToCXString(clang_getCursorKindSpelling(kind)); +} + +CXType *clang_getCursorType_wrap(CXCursor *cursor) { + return ptrToCXType(clang_getCursorType(*cursor)); +} + +CXString *clang_getTypeSpelling_wrap(CXType *type) { + return ptrToCXString(clang_getTypeSpelling(*type)); +} + +CXString *clang_getTypeKindSpelling_wrap(enum CXTypeKind typeKind) { + return ptrToCXString(clang_getTypeKindSpelling(typeKind)); +} + +CXType *clang_getResultType_wrap(CXType *functionType) { + return ptrToCXType(clang_getResultType(*functionType)); +} + +CXType *clang_getPointeeType_wrap(CXType *pointerType) { + return ptrToCXType(clang_getPointeeType(*pointerType)); +} + +CXType *clang_getCanonicalType_wrap(CXType *typerefType) { + return ptrToCXType(clang_getCanonicalType(*typerefType)); +} + +enum CXTypeKind getCXTypeKind(CXType *cxtype) { + return cxtype->kind; +} + +CXType *clang_Type_getModifiedType_wrap(CXType *type) { + return ptrToCXType(clang_Type_getModifiedType(*type)); +} + +enum CXTypeNullabilityKind clang_Type_getNullability_wrap(CXType *type) { + return clang_Type_getNullability(*type); +} + +CXType *clang_Type_getNamedType_wrap(CXType *elaboratedType) { + return ptrToCXType(clang_Type_getNamedType(*elaboratedType)); +} + +long long clang_Type_getAlignOf_wrap(CXType *cxtype) { + return clang_Type_getAlignOf(*cxtype); +} + +CXCursor *clang_getTypeDeclaration_wrap(CXType *cxtype) { + return ptrToCXCursor(clang_getTypeDeclaration(*cxtype)); +} + +CXString *clang_getTypedefName_wrap(CXType *cxtype) { + return ptrToCXString(clang_getTypedefName(*cxtype)); +} + +CXType *clang_getTypedefDeclUnderlyingType_wrap(CXCursor *cxcursor) { + return ptrToCXType(clang_getTypedefDeclUnderlyingType(*cxcursor)); +} + +/** The name of parameter, struct, typedef. */ +CXString *clang_getCursorSpelling_wrap(CXCursor *cursor) { + return ptrToCXString(clang_getCursorSpelling(*cursor)); +} + +CXString *clang_getCursorUSR_wrap(CXCursor *cursor) { + return ptrToCXString(clang_getCursorUSR(*cursor)); +} + +CXCursor *clang_getTranslationUnitCursor_wrap(CXTranslationUnit tu) { + return ptrToCXCursor(clang_getTranslationUnitCursor(tu)); +} + +CXString *clang_formatDiagnostic_wrap(CXDiagnostic diag, int opts) { + return ptrToCXString(clang_formatDiagnostic(diag, opts)); +} + +// Alternative typedef for [CXCursorVisitor] using pointer for passing cursor +// and parent instead of passing by value +typedef enum CXChildVisitResult (*ModifiedCXCursorVisitor)( + CXCursor *cursor, CXCursor *parent, CXClientData client_data); + +// Do not write binding for this function. +// used by [clang_visitChildren_wrap]. +enum CXChildVisitResult _visitorwrap(CXCursor cursor, CXCursor parent, + CXClientData clientData) { + uintptr_t loc = *((uintptr_t *) clientData); + ModifiedCXCursorVisitor visitor = (ModifiedCXCursorVisitor) loc; + return visitor(&cursor, &parent, NULL); +} +/** Visitor is a function pointer with parameters having pointers to cxcursor + * instead of cxcursor by default. */ +unsigned clang_visitChildren_wrap(CXCursor *parent, uintptr_t _modifiedVisitor) { + return clang_visitChildren(*parent, _visitorwrap, &_modifiedVisitor); +} + +int clang_getNumArgTypes_wrap(CXType *cxtype) { + return clang_getNumArgTypes(*cxtype); +} + +CXType *clang_getArgType_wrap(CXType *cxtype, unsigned i) { + return ptrToCXType(clang_getArgType(*cxtype, i)); +} + +long long clang_getEnumConstantDeclValue_wrap(CXCursor *cursor) { + return clang_getEnumConstantDeclValue(*cursor); +} + +/** Returns non-zero if the ranges are the same, zero if they differ. */ +unsigned clang_equalRanges_wrap(CXSourceRange *c1, CXSourceRange *c2) { + return clang_equalRanges(*c1, *c2); +} + +CXEvalResult clang_Cursor_Evaluate_wrap(CXCursor *cursor) { + return clang_Cursor_Evaluate(*cursor); +} + +CXCursor *clang_Cursor_getArgument_wrap(CXCursor *cursor, unsigned i) { + return ptrToCXCursor(clang_Cursor_getArgument(*cursor, i)); +} + +int clang_Cursor_getNumArguments_wrap(CXCursor *cursor) { + return clang_Cursor_getNumArguments(*cursor); +} + +/** Returns the comment range. */ +CXSourceRange *clang_Cursor_getCommentRange_wrap(CXCursor *cursor) { + return ptrToCXSourceRange(clang_Cursor_getCommentRange(*cursor)); +} + +/** Returns the raw comment. */ +CXString *clang_Cursor_getRawCommentText_wrap(CXCursor *cursor) { + return ptrToCXString(clang_Cursor_getRawCommentText(*cursor)); +} + +/** Returns the first paragraph of doxygen doc comment. */ +CXString *clang_Cursor_getBriefCommentText_wrap(CXCursor *cursor) { + return ptrToCXString(clang_Cursor_getBriefCommentText(*cursor)); +} + +enum CX_StorageClass clang_Cursor_getStorageClass_wrap(CXCursor *cursor) { + return clang_Cursor_getStorageClass(*cursor); +} + +int clang_getFieldDeclBitWidth_wrap(CXCursor *C) { + return clang_getFieldDeclBitWidth(*C); +} + +unsigned clang_Cursor_hasAttrs_wrap(CXCursor *C) { + return clang_Cursor_hasAttrs(*C); +} + +unsigned clang_Cursor_isFunctionInlined_wrap(CXCursor *cursor) { + return clang_Cursor_isFunctionInlined(*cursor); +} + +unsigned clang_Cursor_isAnonymous_wrap(CXCursor *cursor) { + return clang_Cursor_isAnonymous(*cursor); +} + +unsigned clang_Cursor_isAnonymousRecordDecl_wrap(CXCursor *cursor) { + return clang_Cursor_isAnonymousRecordDecl(*cursor); +} + +int clang_Cursor_isNull_wrap(CXCursor *cursor) { + return clang_Cursor_isNull(*cursor); +} + +unsigned clang_Cursor_isMacroFunctionLike_wrap(CXCursor *cursor) { + return clang_Cursor_isMacroFunctionLike(*cursor); +} + +unsigned clang_Cursor_isMacroBuiltin_wrap(CXCursor *cursor) { + return clang_Cursor_isMacroBuiltin(*cursor); +} + +unsigned clang_Cursor_getObjCPropertyAttributes_wrap(CXCursor *cursor, unsigned reserved) { + return clang_Cursor_getObjCPropertyAttributes(*cursor, reserved); +} + +unsigned clang_Cursor_isObjCOptional_wrap(CXCursor *cursor) { + return clang_Cursor_isObjCOptional(*cursor); +} + +CXString *clang_Cursor_getObjCPropertyGetterName_wrap(CXCursor *C) { + return ptrToCXString(clang_Cursor_getObjCPropertyGetterName(*C)); +} + +CXString *clang_Cursor_getObjCPropertySetterName_wrap(CXCursor *C) { + return ptrToCXString(clang_Cursor_getObjCPropertySetterName(*C)); +} + +CXType *clang_getCursorResultType_wrap(CXCursor *C) { + return ptrToCXType(clang_getCursorResultType(*C)); +} + +unsigned clang_isFunctionTypeVariadic_wrap(CXType *type) { + return clang_isFunctionTypeVariadic(*type); +} + +CXSourceLocation *clang_getCursorLocation_wrap(CXCursor *cursor) { + return ptrToCXSourceLocation(clang_getCursorLocation(*cursor)); +} + +CXType *clang_getEnumDeclIntegerType_wrap(CXCursor *cursor) { + return ptrToCXType(clang_getEnumDeclIntegerType(*cursor)); +} + +void clang_getFileLocation_wrap(CXSourceLocation *location, CXFile *file, + unsigned *line, unsigned *column, + unsigned *offset) { + return clang_getFileLocation(*location, file, line, column, offset); +} + +CXString *clang_getFileName_wrap(CXFile SFile) { + return ptrToCXString(clang_getFileName(SFile)); +} + +unsigned long long clang_getNumElements_wrap(CXType *cxtype) { + return clang_getNumElements(*cxtype); +} + +CXType *clang_getArrayElementType_wrap(CXType *cxtype) { + return ptrToCXType(clang_getArrayElementType(*cxtype)); +} + +unsigned clang_isConstQualifiedType_wrap(CXType *cxtype) { + return clang_isConstQualifiedType(*cxtype); +} + +int clang_Location_isInSystemHeader_wrap(CXSourceLocation *location) { + return clang_Location_isInSystemHeader(*location); +} +// END ===== WRAPPER FUNCTIONS ===================== diff --git a/pkgs/ffigenpad/tool/build_libclang.dart b/pkgs/ffigenpad/tool/build_libclang.dart new file mode 100644 index 0000000000..2ec1a247ef --- /dev/null +++ b/pkgs/ffigenpad/tool/build_libclang.dart @@ -0,0 +1,138 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// cd to project's root, and run - +// dart run tool/build_libclang.dart + +import 'dart:io'; +import 'package:dart_style/dart_style.dart'; +import 'package:path/path.dart' as p; +import 'package:yaml/yaml.dart'; + +final _formatter = DartFormatter( + languageVersion: DartFormatter.latestLanguageVersion, +); + +/// Used to mock the Clang class in ffigen. +/// Generates `lib/src/header_parser/clang_bindings/clang_wrapper.dart`. +void _generateClangClassWrapper(List exportedFunctions) { + final wrapperFunctions = exportedFunctions.map((func) { + final funcAlias = func.replaceFirst(RegExp(r'_wrap'), ''); + return 'final $funcAlias = c.$func;'; + }).join('\n'); + + final output = """ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// AUTO GENERATED FILE, DO NOT EDIT. +// ignore_for_file: camel_case_types, non_constant_identifier_names + +import 'clang_bindings.dart' as c; + +class Clang { +$wrapperFunctions +} +"""; + + File(p.joinAll([ + p.dirname(Platform.script.path), + '..', + 'lib', + 'src', + 'header_parser', + 'clang_bindings', + 'clang_wrapper.dart' + ])).writeAsStringSync(_formatter.format(output)); +} + +void _generateClangExports(String filePath, List exportedFunctions) { + // export malloc and free additionally to use to do memory + // management in ffigenpad + final functions = [...exportedFunctions, 'malloc', 'free'] + .map((func) => '_$func') + .join('\n'); + File(filePath).writeAsStringSync(functions); +} + +void _checkEmscriptenVersion() { + final process = Process.runSync('emcc', ['--version']); + final versionExp = RegExp(r'\d+.\d+.\d+'); + final version = versionExp.stringMatch(process.stdout.toString()); + if (version == null) { + throw Exception('Failed to extract emscripten version.'); + } + final versionList = version.split('.').map(int.parse).toList(growable: false); + if (!(versionList[0] > 3 || versionList[1] > 1 || versionList[2] > 60)) { + throw Exception('Upgrade to atleast v3.1.61 of emscripten to proceed.'); + } + print('Acceptable emscripten version: $version'); +} + +void main(List args) async { + // Load the ffigen config for libclang to extract included functions. + final configYaml = await File(p.join( + p.dirname(Platform.script.path), + 'libclang_config.yaml', + )).readAsString(); + final config = loadYaml(configYaml) as YamlMap; + + // Get the list of functions to be exported from libclang. + final exportedFunctions = + // ignore: avoid_dynamic_calls + List.from(config['functions']['include'] as YamlList); + + final libclangDir = p.joinAll( + [p.dirname(Platform.script.path), '..', 'third_party', 'libclang'], + ); + + print('Writing third_party/libclang/libclang.exports'); + _generateClangExports( + p.join(libclangDir, 'libclang.exports'), + exportedFunctions, + ); + + print('Writing lib/src/header_parser/clang_wrapper.dart'); + _generateClangClassWrapper(exportedFunctions); + + print('Checking emscripten version'); + _checkEmscriptenVersion(); + + print('Building bin/libclang.wasm'); + final archiveFiles = + await Directory(p.join(libclangDir, 'llvm-project', 'lib')) + .list(recursive: false) + .map((file) => p.relative(file.path, from: libclangDir)) + .where((filepath) => filepath.endsWith('.a')) + .toList(); + + final result = await Process.run( + 'emcc', + [ + ...archiveFiles, + 'wrapper.c', + '-I./llvm-project/include', + '-o', + '../../bin/libclang.mjs', + '--no-entry', + '-sALLOW_MEMORY_GROWTH', + '-sALLOW_TABLE_GROWTH', + '-sWASM_BIGINT', + '-sENVIRONMENT=web,worker', + '--embed-file', + './llvm-project/lib/clang@/lib/clang', + '-sEXPORTED_FUNCTIONS=@libclang.exports', + '-sFS_DEBUG', + // ignore: lines_longer_than_80_chars + '-sEXPORTED_RUNTIME_METHODS=FS,wasmExports,wasmMemory,addFunction,removeFunction', + // used for production builds + if (args.contains('--optimize')) ...['-O3', '-lexports.js'] + ], + workingDirectory: libclangDir, + runInShell: true, + ); + stdout.write(result.stdout); + stderr.write(result.stderr); +} diff --git a/pkgs/ffigenpad/tool/libclang_config.yaml b/pkgs/ffigenpad/tool/libclang_config.yaml new file mode 100644 index 0000000000..7417f5c70e --- /dev/null +++ b/pkgs/ffigenpad/tool/libclang_config.yaml @@ -0,0 +1,174 @@ +# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +# Config file for generating the libclang.wasm bindings used by ffigenpad. + +# ===================== GENERATING BINDINGS ===================== +# cd to project's root, and run - +# dart run ffigen --config tool/libclang_config.yaml +# =============================================================== + +# yaml-language-server: $schema=../../ffigen/ffigen.schema.json + +name: Clang +description: Holds bindings to libclang.wasm used by ffigenpad +output: "../lib/src/header_parser/clang_bindings/clang_bindings.dart" +ffi-native: + assetId: libclang +compiler-opts: + - "-Ithird_party/libclang/include" + - "-I/usr/lib/clang/17/include" +headers: + entry-points: + - "../third_party/libclang/wrapper.c" +preamble: | + // Part of the LLVM Project, under the Apache License v2.0 with LLVM + // Exceptions. + // See https://llvm.org/LICENSE.txt for license information. + // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + // ignore_for_file: camel_case_types, non_constant_identifier_names + +exclude-all-by-default: true + +unions: + dependency-only: opaque + +typedefs: + include: + - CXIndex + - CXTranslationUnit + - CXDiagnostic + - CXClientData + - CXEvalResult + - CXFile + +structs: + dependency-only: opaque + +silence-enum-warning: true +enums: + include: + - CXChildVisitResult + - CXCursorKind + - CXTypeKind + - CXDiagnosticDisplayOptions + - CXDiagnosticSeverity + - CXTranslationUnit_Flags + - CXEvalResultKind + - CXObjCPropertyAttrKind + - CXTypeNullabilityKind + - CXTypeLayoutError + - CX_StorageClass + as-int: + include: + - CXChildVisitResult + - CXCursorKind + - CXTypeKind + - CXDiagnosticDisplayOptions + - CXDiagnosticSeverity + - CXTranslationUnit_Flags + - CXEvalResultKind + - CXObjCPropertyAttrKind + - CXTypeNullabilityKind + - CXTypeLayoutError + - CX_StorageClass + +functions: + include: + - clang_createIndex + - clang_disposeIndex + - clang_parseTranslationUnit + - clang_disposeTranslationUnit + - clang_getNumDiagnostics + - clang_getDiagnostic + - clang_getDiagnosticSeverity + - clang_disposeDiagnostic + - clang_EvalResult_getKind + - clang_EvalResult_getAsLongLong + - clang_EvalResult_getAsDouble + - clang_EvalResult_getAsStr + - clang_EvalResult_dispose + - clang_getCString_wrap + - clang_disposeString_wrap + - clang_getClangVersion_wrap + - clang_getCursorKind_wrap + - clang_getCursorDefinition_wrap + - clang_getCursorKindSpelling_wrap + - clang_getCursorType_wrap + - clang_getTypeSpelling_wrap + - clang_getTypeKindSpelling_wrap + - clang_getResultType_wrap + - clang_getPointeeType_wrap + - clang_getCanonicalType_wrap + - clang_Type_getModifiedType_wrap + - clang_Type_getNullability_wrap + - clang_Type_getNamedType_wrap + - clang_Type_getAlignOf_wrap + - clang_getTypeDeclaration_wrap + - clang_getTypedefName_wrap + - clang_getTypedefDeclUnderlyingType_wrap + - clang_getCursorSpelling_wrap + - clang_getCursorUSR_wrap + - clang_getTranslationUnitCursor_wrap + - clang_formatDiagnostic_wrap + - clang_visitChildren_wrap + - clang_getArgType_wrap + - clang_getNumArgTypes_wrap + - clang_getEnumConstantDeclValue_wrap + - clang_equalRanges_wrap + - clang_Cursor_Evaluate_wrap + - clang_Cursor_getArgument_wrap + - clang_Cursor_getNumArguments_wrap + - clang_Cursor_getCommentRange_wrap + - clang_Cursor_getRawCommentText_wrap + - clang_Cursor_getBriefCommentText_wrap + - clang_Cursor_getStorageClass_wrap + - clang_getFieldDeclBitWidth_wrap + - clang_Cursor_hasAttrs_wrap + - clang_Cursor_isFunctionInlined_wrap + - clang_Cursor_isAnonymous_wrap + - clang_Cursor_isAnonymousRecordDecl_wrap + - clang_Cursor_isNull_wrap + - clang_Cursor_isMacroFunctionLike_wrap + - clang_Cursor_isMacroBuiltin_wrap + - clang_Cursor_getObjCPropertyAttributes_wrap + - clang_Cursor_isObjCOptional_wrap + - clang_Cursor_getObjCPropertyGetterName_wrap + - clang_Cursor_getObjCPropertySetterName_wrap + - clang_getCursorResultType_wrap + - clang_isFunctionTypeVariadic_wrap + - clang_getCursorLocation_wrap + - clang_getEnumDeclIntegerType_wrap + - clang_getFileLocation_wrap + - clang_getFileName_wrap + - clang_getNumElements_wrap + - clang_getArrayElementType_wrap + - clang_isConstQualifiedType_wrap + - clang_Location_isInSystemHeader_wrap + # Helper functions + - getCXTypeKind + +type-map: + "native-types": + "char": + "lib": "ffi" + "c-type": "Uint8" + "dart-type": "int" + "unsigned int": + "lib": "ffi" + "c-type": "Uint32" + "dart-type": "int" + "int": + "lib": "ffi" + "c-type": "Int32" + "dart-type": "int" + "long long": + "lib": "ffi" + "c-type": "Int64" + "dart-type": "int" + "unsigned long long": + "lib": "ffi" + "c-type": "Uint64" + "dart-type": "int" diff --git a/pkgs/ffigenpad/tool/setup.dart b/pkgs/ffigenpad/tool/setup.dart new file mode 100644 index 0000000000..f73de4230c --- /dev/null +++ b/pkgs/ffigenpad/tool/setup.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Downloads required files needed to build ffigenpad + +import 'dart:io'; +import 'package:path/path.dart' as p; + +const llvmCompiledRelease = + 'https://github.com/TheComputerM/libclang-wasm/releases/download/v0/llvm-build.tar.gz'; + +Future main(List args) async { + final libclangDir = p.joinAll( + [p.dirname(Platform.script.path), '..', 'third_party', 'libclang'], + ); + final llvmDir = p.join(libclangDir, 'llvm-project'); + + if (args.contains('-f') && await Directory(llvmDir).exists()) { + await Directory(llvmDir).delete(recursive: true); + } + + if (await Directory(llvmDir).exists()) { + print('Compiled LLVM archives already exist.'); + print('Use `-f` to forcefully download archives.'); + return; + } + print('Downloading compiled LLVM archives'); + + // Download .tar.gz file + + final tempFileName = 'llvm-build.tar.gz'; + final tempFile = File(p.join(libclangDir, tempFileName)); + + final httpClient = HttpClient(); + final request = await httpClient.getUrl(Uri.parse(llvmCompiledRelease)); + final response = await request.close(); + final sink = tempFile.openWrite(); + await response.pipe(sink); + await sink.flush(); + await sink.close(); + httpClient.close(); + + print('Extracting LLVM archives to $llvmDir'); + + // Extract file to Config.llvmDir + + await Directory(llvmDir).create(recursive: true); + final result = await Process.run( + 'tar', + ['-xzf', tempFileName, '-C', llvmDir], + workingDirectory: libclangDir, + ); + if (result.exitCode >= 0) { + print('Archive files extracted successfully.'); + } else { + print('Error: ${result.stderr}'); + return; + } + + // remove temp .tar.gz file + await tempFile.delete(); +} diff --git a/pkgs/ffigenpad/web/.gitignore b/pkgs/ffigenpad/web/.gitignore new file mode 100644 index 0000000000..fa147c3e81 --- /dev/null +++ b/pkgs/ffigenpad/web/.gitignore @@ -0,0 +1,28 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +## Panda +styled-system +styled-system-studio \ No newline at end of file diff --git a/pkgs/ffigenpad/web/README.md b/pkgs/ffigenpad/web/README.md new file mode 100644 index 0000000000..9b7f9c70dd --- /dev/null +++ b/pkgs/ffigenpad/web/README.md @@ -0,0 +1,19 @@ +# FFIgenPad Web Interface + +## Setup + +Make sure you build *libclang.wasm* and *ffigenpad.wasm* and they are present in `/bin`. + +```bash +$ bun install +``` + +You can then run the dev server with the following command, any changes you make to the website while dev mode is active will be hot-reloaded to the preview. + +```bash +$ bun dev +``` + +## Developing + +FFIgenPad's online interface uses the [SolidJS](https://www.solidjs.com/) framework, [codemirror](https://codemirror.net/) for the code editors and [park-ui](https://park-ui.com/) for the UI components. diff --git a/pkgs/ffigenpad/web/bun.lock b/pkgs/ffigenpad/web/bun.lock new file mode 100644 index 0000000000..8e7bbf0c34 --- /dev/null +++ b/pkgs/ffigenpad/web/bun.lock @@ -0,0 +1,1622 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "web", + "dependencies": { + "@ark-ui/solid": "^3.7.0", + "@codemirror/lang-cpp": "^6.0.2", + "@codemirror/lang-yaml": "^6.1.2", + "@codemirror/language": "^6.10.8", + "@codemirror/legacy-modes": "^6.4.2", + "@codemirror/state": "^6.5.2", + "@codemirror/theme-one-dark": "^6.1.2", + "@fontsource-variable/reddit-mono": "^5.1.1", + "codemirror": "^6.0.1", + "pathe": "^1.1.2", + "solid-js": "^1.9.4", + }, + "devDependencies": { + "@babel/types": "^7.26.8", + "@iconify-json/tabler": "^1.2.16", + "@pandacss/dev": "^0.53.0", + "@park-ui/panda-preset": "^0.43.1", + "@types/node": "^22.13.1", + "typescript": "^5.7.3", + "unplugin-icons": "^22.0.0", + "vite": "^6.1.0", + "vite-plugin-solid": "^2.11.1", + "vite-tsconfig-paths": "^5.1.4", + }, + }, + }, + "packages": { + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@antfu/install-pkg": ["@antfu/install-pkg@0.5.0", "", { "dependencies": { "package-manager-detector": "^0.2.5", "tinyexec": "^0.3.1" } }, "sha512-dKnk2xlAyC7rvTkpkHmu+Qy/2Zc3Vm/l8PtNyIOGDBtXPY3kThfU4ORNEp3V7SXw5XSOb+tOJaUYpfquPzL/Tg=="], + + "@antfu/utils": ["@antfu/utils@0.7.10", "", {}, "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww=="], + + "@ark-ui/anatomy": ["@ark-ui/anatomy@3.5.0", "", { "dependencies": { "@zag-js/accordion": "0.62.1", "@zag-js/anatomy": "0.62.1", "@zag-js/avatar": "0.62.1", "@zag-js/carousel": "0.62.1", "@zag-js/checkbox": "0.62.1", "@zag-js/clipboard": "0.62.1", "@zag-js/collapsible": "0.62.1", "@zag-js/color-picker": "0.62.1", "@zag-js/color-utils": "0.62.1", "@zag-js/combobox": "0.62.1", "@zag-js/date-picker": "0.62.1", "@zag-js/date-utils": "0.62.1", "@zag-js/dialog": "0.62.1", "@zag-js/editable": "0.62.1", "@zag-js/file-upload": "0.62.1", "@zag-js/hover-card": "0.62.1", "@zag-js/menu": "0.62.1", "@zag-js/number-input": "0.62.1", "@zag-js/pagination": "0.62.1", "@zag-js/pin-input": "0.62.1", "@zag-js/popover": "0.62.1", "@zag-js/presence": "0.62.1", "@zag-js/progress": "0.62.1", "@zag-js/qr-code": "0.62.1", "@zag-js/radio-group": "0.62.1", "@zag-js/rating-group": "0.62.1", "@zag-js/select": "0.62.1", "@zag-js/signature-pad": "0.62.1", "@zag-js/slider": "0.62.1", "@zag-js/splitter": "0.62.1", "@zag-js/switch": "0.62.1", "@zag-js/tabs": "0.62.1", "@zag-js/tags-input": "0.62.1", "@zag-js/time-picker": "0.62.1", "@zag-js/toast": "0.62.1", "@zag-js/toggle-group": "0.62.1", "@zag-js/tooltip": "0.62.1", "@zag-js/tree-view": "0.62.1" } }, "sha512-KoROLVVT23BvFHcye/GYhG8NJ2CH0C+CaoJhXrkEjvk8pbEx80Xk5NIUy5gL7xmX+LDD7kY5t3NotBqCu+2L2w=="], + + "@ark-ui/solid": ["@ark-ui/solid@3.13.0", "", { "dependencies": { "@internationalized/date": "3.5.5", "@zag-js/accordion": "0.71.0", "@zag-js/anatomy": "0.71.0", "@zag-js/avatar": "0.71.0", "@zag-js/carousel": "0.71.0", "@zag-js/checkbox": "0.71.0", "@zag-js/clipboard": "0.71.0", "@zag-js/collapsible": "0.71.0", "@zag-js/color-picker": "0.71.0", "@zag-js/combobox": "0.71.0", "@zag-js/date-picker": "0.71.0", "@zag-js/dialog": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/editable": "0.71.0", "@zag-js/file-upload": "0.71.0", "@zag-js/file-utils": "0.71.0", "@zag-js/highlight-word": "0.71.0", "@zag-js/hover-card": "0.71.0", "@zag-js/i18n-utils": "0.71.0", "@zag-js/menu": "0.71.0", "@zag-js/number-input": "0.71.0", "@zag-js/pagination": "0.71.0", "@zag-js/pin-input": "0.71.0", "@zag-js/popover": "0.71.0", "@zag-js/presence": "0.71.0", "@zag-js/progress": "0.71.0", "@zag-js/qr-code": "0.71.0", "@zag-js/radio-group": "0.71.0", "@zag-js/rating-group": "0.71.0", "@zag-js/select": "0.71.0", "@zag-js/signature-pad": "0.71.0", "@zag-js/slider": "0.71.0", "@zag-js/solid": "0.71.0", "@zag-js/splitter": "0.71.0", "@zag-js/steps": "0.71.0", "@zag-js/switch": "0.71.0", "@zag-js/tabs": "0.71.0", "@zag-js/tags-input": "0.71.0", "@zag-js/time-picker": "0.71.0", "@zag-js/timer": "0.71.0", "@zag-js/toast": "0.71.0", "@zag-js/toggle-group": "0.71.0", "@zag-js/tooltip": "0.71.0", "@zag-js/tree-view": "0.71.0", "@zag-js/types": "0.71.0" }, "peerDependencies": { "solid-js": ">=1.6.0" } }, "sha512-1zCkFKHKkVidZTSoiYOPGDlUgusQprMmNn6ZyxISwtb7tUkYu1gISjOY6NN32fpGEfNKlOM3XZ/Cr2ASJUTA3w=="], + + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/compat-data": ["@babel/compat-data@7.26.8", "", {}, "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ=="], + + "@babel/core": ["@babel/core@7.26.8", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.8", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.7", "@babel/parser": "^7.26.8", "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", "@types/gensync": "^1.0.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ=="], + + "@babel/generator": ["@babel/generator@7.26.8", "", { "dependencies": { "@babel/parser": "^7.26.8", "@babel/types": "^7.26.8", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.26.5", "", { "dependencies": { "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], + + "@babel/helpers": ["@babel/helpers@7.26.7", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/types": "^7.26.7" } }, "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A=="], + + "@babel/parser": ["@babel/parser@7.26.8", "", { "dependencies": { "@babel/types": "^7.26.8" }, "bin": "./bin/babel-parser.js" }, "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA=="], + + "@babel/template": ["@babel/template@7.26.8", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.26.8", "@babel/types": "^7.26.8" } }, "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q=="], + + "@babel/traverse": ["@babel/traverse@7.26.8", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.8", "@babel/parser": "^7.26.8", "@babel/template": "^7.26.8", "@babel/types": "^7.26.8", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA=="], + + "@babel/types": ["@babel/types@7.26.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA=="], + + "@clack/core": ["@clack/core@0.4.1", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-Pxhij4UXg8KSr7rPek6Zowm+5M22rbd2g1nfojHJkxp5YkFqiZ2+YLEM/XGVIzvGOcM0nqjIFxrpDwWRZYWYjA=="], + + "@clack/prompts": ["@clack/prompts@0.9.1", "", { "dependencies": { "@clack/core": "0.4.1", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-JIpyaboYZeWYlyP0H+OoPPxd6nqueG/CmN6ixBiNFsIDHREevjIf0n0Ohh5gr5C8pEDknzgvz+pIJ8dMhzWIeg=="], + + "@codemirror/autocomplete": ["@codemirror/autocomplete@6.18.5", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-1e0/GALpdgVEcM6jUIrFuhznnwaCzxJNbZ4yiOjVluS2dvz+D0r6k4nBjL+TJZeHRemnBpTUdnEnqd5f0/+D0w=="], + + "@codemirror/commands": ["@codemirror/commands@6.8.0", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ=="], + + "@codemirror/lang-cpp": ["@codemirror/lang-cpp@6.0.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/cpp": "^1.0.0" } }, "sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg=="], + + "@codemirror/lang-yaml": ["@codemirror/lang-yaml@6.1.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.0.0", "@lezer/yaml": "^1.0.0" } }, "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw=="], + + "@codemirror/language": ["@codemirror/language@6.10.8", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw=="], + + "@codemirror/legacy-modes": ["@codemirror/legacy-modes@6.4.2", "", { "dependencies": { "@codemirror/language": "^6.0.0" } }, "sha512-HsvWu08gOIIk303eZQCal4H4t65O/qp1V4ul4zVa3MHK5FJ0gz3qz3O55FIkm+aQUcshUOjBx38t2hPiJwW5/g=="], + + "@codemirror/lint": ["@codemirror/lint@6.8.4", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A=="], + + "@codemirror/search": ["@codemirror/search@6.5.8", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "crelt": "^1.0.5" } }, "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig=="], + + "@codemirror/state": ["@codemirror/state@6.5.2", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA=="], + + "@codemirror/theme-one-dark": ["@codemirror/theme-one-dark@6.1.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/highlight": "^1.0.0" } }, "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA=="], + + "@codemirror/view": ["@codemirror/view@6.36.2", "", { "dependencies": { "@codemirror/state": "^6.5.0", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA=="], + + "@csstools/postcss-cascade-layers": ["@csstools/postcss-cascade-layers@4.0.6", "", { "dependencies": { "@csstools/selector-specificity": "^3.1.1", "postcss-selector-parser": "^6.0.13" }, "peerDependencies": { "postcss": "^8.4" } }, "sha512-Xt00qGAQyqAODFiFEJNkTpSUz5VfYqnDLECdlA/Vv17nl/OIV5QfTRHGAXrBGG5YcJyHpJ+GF9gF/RZvOQz4oA=="], + + "@csstools/selector-specificity": ["@csstools/selector-specificity@3.1.1", "", { "peerDependencies": { "postcss-selector-parser": "^6.0.13" } }, "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + + "@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.6.11", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.8" } }, "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + + "@fontsource-variable/reddit-mono": ["@fontsource-variable/reddit-mono@5.1.1", "", {}, "sha512-4PXQ8tX0Lrz9iVd44LkuC9dHoV++PmcdmV5LBXoskDdw67Oz1SZLCZHaE3TexZN843qEeUf7syaRmbX2+DDxVg=="], + + "@iconify-json/tabler": ["@iconify-json/tabler@1.2.16", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-gjvKz38+aOxfZtRvycYrASYipCsHRbCZ/Df49T0tfPntT0ur+qsgJ7PxCM4JF/Xs6+n3JkaFdiUz/N4ZZxDKdQ=="], + + "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], + + "@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="], + + "@internationalized/date": ["@internationalized/date@3.5.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ=="], + + "@internationalized/number": ["@internationalized/number@3.5.3", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-rd1wA3ebzlp0Mehj5YTuTI50AQEx80gWFyHcQu+u91/5NgdwBecO8BH6ipPfE+lmQ9d63vpB3H9SHoIUiupllw=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@lezer/common": ["@lezer/common@1.2.3", "", {}, "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="], + + "@lezer/cpp": ["@lezer/cpp@1.1.2", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ=="], + + "@lezer/highlight": ["@lezer/highlight@1.2.1", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA=="], + + "@lezer/lr": ["@lezer/lr@1.4.2", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA=="], + + "@lezer/yaml": ["@lezer/yaml@1.0.3", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.4.0" } }, "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA=="], + + "@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.2", "", {}, "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@pandacss/config": ["@pandacss/config@0.53.0", "", { "dependencies": { "@pandacss/logger": "0.53.0", "@pandacss/preset-base": "0.53.0", "@pandacss/preset-panda": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/types": "0.53.0", "bundle-n-require": "1.1.1", "escalade": "3.1.2", "merge-anything": "5.1.7", "microdiff": "1.3.2", "typescript": "5.6.2" } }, "sha512-e1rW392ezNQLL5FrczsUB59sqF/bkiLTW+Mp5Yd3UpQOGMbWlJpTwZR29QNUNX1JGq2JbmvczDSSZjJGtNRFYw=="], + + "@pandacss/core": ["@pandacss/core@0.53.0", "", { "dependencies": { "@csstools/postcss-cascade-layers": "4.0.6", "@pandacss/is-valid-prop": "^0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/token-dictionary": "0.53.0", "@pandacss/types": "0.53.0", "browserslist": "4.23.3", "hookable": "5.5.3", "lightningcss": "1.25.1", "lodash.merge": "4.6.2", "outdent": "0.8.0", "postcss": "8.4.49", "postcss-discard-duplicates": "7.0.1", "postcss-discard-empty": "7.0.0", "postcss-merge-rules": "7.0.4", "postcss-minify-selectors": "7.0.4", "postcss-nested": "6.0.1", "postcss-normalize-whitespace": "7.0.0", "postcss-selector-parser": "6.1.2", "ts-pattern": "5.0.8" } }, "sha512-VuLby1C7rPorsvOPPCrlV+9cD46DeyT7igeXamuFLO337/4B7Nll2XtDjhNz5QUNt7occ7ThryYHxmf9/pHhIA=="], + + "@pandacss/dev": ["@pandacss/dev@0.53.0", "", { "dependencies": { "@clack/prompts": "0.9.1", "@pandacss/config": "0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/node": "0.53.0", "@pandacss/postcss": "0.53.0", "@pandacss/preset-panda": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/token-dictionary": "0.53.0", "@pandacss/types": "0.53.0", "cac": "6.7.14" }, "bin": { "panda": "bin.js", "pandacss": "bin.js" } }, "sha512-zLoYiQo3QJPKhtvpUO4NIBq/OqqINwQ6k6n0n3HDK3ggd7U/q3kYIpOJqBrkkiIlPVgwfTccxk7lQlAb8tt0Iw=="], + + "@pandacss/extractor": ["@pandacss/extractor@0.53.0", "", { "dependencies": { "@pandacss/shared": "0.53.0", "ts-evaluator": "1.2.0", "ts-morph": "24.0.0" } }, "sha512-ujubixsMChBYLqldX8eWtUUFi+jLAv2gKe/OlyUlxzoA2eYF9ZRpErhLbT+79OevWb4xYt6XmZorzoPdCwk5AQ=="], + + "@pandacss/generator": ["@pandacss/generator@0.53.0", "", { "dependencies": { "@pandacss/core": "0.53.0", "@pandacss/is-valid-prop": "^0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/token-dictionary": "0.53.0", "@pandacss/types": "0.53.0", "javascript-stringify": "2.1.0", "outdent": " ^0.8.0", "pluralize": "8.0.0", "postcss": "8.4.49", "ts-pattern": "5.0.8" } }, "sha512-W9/vtpC7i/4dHndPYgF7UQIWlcN7zifEsX0g3eMMsBtLNnKW8TFXh/ebET76x57Jd3ccOMnLoX+cx9OEmgZeQw=="], + + "@pandacss/is-valid-prop": ["@pandacss/is-valid-prop@0.53.0", "", {}, "sha512-SIJiyDrAOpmf68EnkAA3myOUmy8aXLDL5SUDrbyrzy+2Gt6kDpuy0MU8b5qYF7t4sg4JJdXZzO2ghlSZUDOWDQ=="], + + "@pandacss/logger": ["@pandacss/logger@0.53.0", "", { "dependencies": { "@pandacss/types": "0.53.0", "kleur": "4.1.5" } }, "sha512-EByzeVHlGWYZCICczLcp7t6ljFNex8cakK9sz+ixSKHnfCQCxQGv7UXuPyjoa6dVK6h5/ETc+aaZZBl0kAxAIA=="], + + "@pandacss/node": ["@pandacss/node@0.53.0", "", { "dependencies": { "@pandacss/config": "0.53.0", "@pandacss/core": "0.53.0", "@pandacss/generator": "0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/parser": "0.53.0", "@pandacss/reporter": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/token-dictionary": "0.53.0", "@pandacss/types": "0.53.0", "browserslist": "4.23.3", "chokidar": "4.0.3", "fast-glob": "3.3.3", "fs-extra": "11.2.0", "glob-parent": "6.0.2", "is-glob": "4.0.3", "lodash.merge": "4.6.2", "look-it-up": "2.1.0", "outdent": " ^0.8.0", "package-manager-detector": "0.1.0", "perfect-debounce": "1.0.0", "pkg-types": "1.0.3", "pluralize": "8.0.0", "postcss": "8.4.49", "prettier": "3.2.5", "ts-morph": "24.0.0", "ts-pattern": "5.0.8", "tsconfck": "3.0.2" } }, "sha512-krDXFphRqiYwhj1WJSCPR/8QniyeZjFgL46a1yC6dsTLZgNPI+WKlrU0zeuoAJh5KRZM8NB6VFCpBhcS529LYA=="], + + "@pandacss/parser": ["@pandacss/parser@0.53.0", "", { "dependencies": { "@pandacss/config": "^0.53.0", "@pandacss/core": "^0.53.0", "@pandacss/extractor": "0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/types": "0.53.0", "@vue/compiler-sfc": "3.4.19", "magic-string": "0.30.17", "ts-morph": "24.0.0", "ts-pattern": "5.0.8" } }, "sha512-e60qXFvZEOpEqkXJ8CZ+6lXZBky6YFaoaWFEcI5QWRekR4ukd5lvsy4irU3RCWLVoKnFVzAPK/XFR/Xoy8lfPQ=="], + + "@pandacss/postcss": ["@pandacss/postcss@0.53.0", "", { "dependencies": { "@pandacss/node": "0.53.0", "postcss": "8.4.49" } }, "sha512-Cg/JYA8RquPlRIAS8ZPZ7eQKajFtcy2uf+LW+NkNVDCK+LisKWMysdhipy+qhx5K4n9H9oDxiO12dwNCq8HXdA=="], + + "@pandacss/preset-base": ["@pandacss/preset-base@0.53.0", "", { "dependencies": { "@pandacss/types": "0.53.0" } }, "sha512-tguvdWIImJp6qsnJDTNz53oBSgA3Jrrjv5md/DaY73xNavQ8h1qlhqHOsO2AbsZJN5pm8Yc3T0IRU8bhoUcQ/g=="], + + "@pandacss/preset-panda": ["@pandacss/preset-panda@0.53.0", "", { "dependencies": { "@pandacss/types": "0.53.0" } }, "sha512-/AyoQRYefXzUwPhee7JJIpf4ygnSU7hGPITugbLYv4jAr9D7/WTJhKfyjFTpw14mABjjfEWzxDtw10pLvYVfgw=="], + + "@pandacss/reporter": ["@pandacss/reporter@0.53.0", "", { "dependencies": { "@pandacss/core": "0.53.0", "@pandacss/generator": "0.53.0", "@pandacss/logger": "0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/types": "0.53.0", "table": "6.9.0", "wordwrapjs": "5.1.0" } }, "sha512-y0P5psLeg8wYySIr4SrQuhE7bPmZtByPapFItble7/mtLZMRdJ53/ZEVYfa3T7q+QXTdlX/O8CW2KhjE5SRwqg=="], + + "@pandacss/shared": ["@pandacss/shared@0.53.0", "", {}, "sha512-BmFovfEHJvlxamA206fK9FD8cioUJZxO3P5Tp6gfoQ7d3sV66Edh1WOen3ypkcUPPR4WTW5Fl0cG5qhsqq047Q=="], + + "@pandacss/token-dictionary": ["@pandacss/token-dictionary@0.53.0", "", { "dependencies": { "@pandacss/logger": "^0.53.0", "@pandacss/shared": "0.53.0", "@pandacss/types": "0.53.0", "ts-pattern": "5.0.8" } }, "sha512-8SMVouacoLCa6bRcfOK2HprhGwJcQd0DCkmdnZK8q47KsxtbGVqchZ0e+8SiDrZD3SVXbFsb4HZeW1VLhZADtA=="], + + "@pandacss/types": ["@pandacss/types@0.53.0", "", {}, "sha512-iEXXhZytGWU4Z/7THuWTMft1sRGMprSk5FjILZu9zkyxj0cLTjHcKKka80zOtFYAg0zRF7B8ZYXLQx96dwtzEg=="], + + "@park-ui/panda-preset": ["@park-ui/panda-preset@0.43.1", "", { "dependencies": { "@ark-ui/anatomy": "3.5.0", "effect": "3.10.15" }, "peerDependencies": { "@pandacss/dev": ">0.22.0" } }, "sha512-kcO1ewx8zU9wHuTjZ/nqPCqjzL9AXkpzDnDrpcZ2unKR/UE3hHpP+Y1F0grTBaluPHLomjfZz3GebczJvoShBQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.6", "", { "os": "android", "cpu": "arm" }, "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.6", "", { "os": "android", "cpu": "arm64" }, "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.6", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.6", "", { "os": "linux", "cpu": "arm" }, "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.6", "", { "os": "linux", "cpu": "arm" }, "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.6", "", { "os": "linux", "cpu": "none" }, "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.6", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.6", "", { "os": "linux", "cpu": "none" }, "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.6", "", { "os": "linux", "cpu": "s390x" }, "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.6", "", { "os": "linux", "cpu": "x64" }, "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.6", "", { "os": "linux", "cpu": "x64" }, "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.6", "", { "os": "win32", "cpu": "x64" }, "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w=="], + + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], + + "@ts-morph/common": ["@ts-morph/common@0.25.0", "", { "dependencies": { "minimatch": "^9.0.4", "path-browserify": "^1.0.1", "tinyglobby": "^0.2.9" } }, "sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg=="], + + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], + + "@types/babel__generator": ["@types/babel__generator@7.6.8", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw=="], + + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], + + "@types/babel__traverse": ["@types/babel__traverse@7.20.6", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/gensync": ["@types/gensync@1.0.4", "", {}, "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA=="], + + "@types/node": ["@types/node@22.13.1", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew=="], + + "@vue/compiler-core": ["@vue/compiler-core@3.4.19", "", { "dependencies": { "@babel/parser": "^7.23.9", "@vue/shared": "3.4.19", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.4.19", "", { "dependencies": { "@vue/compiler-core": "3.4.19", "@vue/shared": "3.4.19" } }, "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA=="], + + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.4.19", "", { "dependencies": { "@babel/parser": "^7.23.9", "@vue/compiler-core": "3.4.19", "@vue/compiler-dom": "3.4.19", "@vue/compiler-ssr": "3.4.19", "@vue/shared": "3.4.19", "estree-walker": "^2.0.2", "magic-string": "^0.30.6", "postcss": "^8.4.33", "source-map-js": "^1.0.2" } }, "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg=="], + + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.4.19", "", { "dependencies": { "@vue/compiler-dom": "3.4.19", "@vue/shared": "3.4.19" } }, "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw=="], + + "@vue/shared": ["@vue/shared@3.4.19", "", {}, "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="], + + "@zag-js/accordion": ["@zag-js/accordion@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-kImRcnhjhJt435RHcqjPfgIXu1x9WtuTjUgp56Xm4iKSJQSs8IUK5vDT8AeYwlMIorAn3Zg3x8houn14w7CtPw=="], + + "@zag-js/anatomy": ["@zag-js/anatomy@0.71.0", "", {}, "sha512-Vx9Tuk5J0q0P9ZMCaBsnS3xZyEG5XQfrfudmd/4eOekSwifVIxcRDIszNVjqvNc9ukr16E67YDv4CyEQdi2wOQ=="], + + "@zag-js/aria-hidden": ["@zag-js/aria-hidden@0.71.0", "", { "dependencies": { "aria-hidden": "1.2.4" } }, "sha512-R2G2qWgkUB3dIrOa1w3QB3S6MGKcZ4YOcZIBLVMAzHZSc4DjEo9OVARHS0HpS+w1N8kA+iKo/DWxywoCXLfDGA=="], + + "@zag-js/auto-resize": ["@zag-js/auto-resize@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0" } }, "sha512-n6UVeYC6/GwfF8mSXkHm4xXsz2B2CJQIypSzcUZc0gm+XgeRZOKGqzpg39jWQixRPEVgHvOxoQQy5/k9QpTJxA=="], + + "@zag-js/avatar": ["@zag-js/avatar@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-KBqircTN2W5JKU4mGKdY20TYGX6RwWAXAC1Mfikm40PIO62MJ20QS8bOiSKZY6gF6ZQHvGA8EV+hYDsSy+/+Wg=="], + + "@zag-js/carousel": ["@zag-js/carousel@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-PaNbf/j4MwDwZ8J9P+/kRgAY970tdkQh+8E98lZ4BDy1dnAmhM9fZIiZreQZSSwWpNFSKNK/+aQjBhB+/yKG7A=="], + + "@zag-js/checkbox": ["@zag-js/checkbox@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/focus-visible": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-wcn6qDu9aEAqj8HIp2UuYx5Sz1+kRCyOgFVfWNi1DtTnlHRj9ElBk8CHlPgojEgqsGoRzK2qXlTFnqh4AtM6sw=="], + + "@zag-js/clipboard": ["@zag-js/clipboard@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-uehbcS1Xoiea/tIsVrSUEvIrzwVth9/Ctn27Y8UMf3ezH4pxKGR9hj+CrvEDTHt5AJfh3UGLrpvSSPWAu/XvsQ=="], + + "@zag-js/collapsible": ["@zag-js/collapsible@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-LVPXlUgtnyzKih847DI93gpY1Wvp+N+8lDFzdfOGNO9raAc6mltvXsADvyOXxYK+kN/ck2b12JqSXrbRofjo2w=="], + + "@zag-js/collection": ["@zag-js/collection@0.71.0", "", { "dependencies": { "@zag-js/utils": "0.71.0" } }, "sha512-bOfr/zxNmu1k5aHB1cOfZS4f6XlXeVKl64SqVzYKN0CQ3jWlK8TF52xvim0xkth1XjeCMzroNcXvqC5qzCAwhQ=="], + + "@zag-js/color-picker": ["@zag-js/color-picker@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/color-utils": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/text-selection": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-uGEaf8PYpvBFenq+Dgdw8EBt8lOE/rv4WxlzvSAbCzZMxvkDKUz/SF/FJ7sV06eTc4Cysta/I2tr1ZJr+Ljs9A=="], + + "@zag-js/color-utils": ["@zag-js/color-utils@0.62.1", "", { "dependencies": { "@zag-js/numeric-range": "0.62.1" } }, "sha512-uXsEA0xsI4NT7YFwWZldy7LXsk32Ta+41MrckhzbSA766v+bW4sFDUYmJxwLkN4nl1QzlLAlGghhauXmW9Fs8g=="], + + "@zag-js/combobox": ["@zag-js/combobox@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/aria-hidden": "0.71.0", "@zag-js/collection": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-cInxLRgeGwNaI1Bks5whDxFNXOM1SFrosff64W/DfzFdHmCpNjhaJJWHPAM4oXd5mW3+K2oY4CyetYYlOMn0IQ=="], + + "@zag-js/core": ["@zag-js/core@0.71.0", "", { "dependencies": { "@zag-js/store": "0.71.0", "@zag-js/utils": "0.71.0", "klona": "2.0.6" } }, "sha512-MWnz4Gib4UVTI4vyiOXpYn63oBsb9DjWWUaSn8mjpk1lFI1+Uor88LMYTb4KaDEvx5kHZyi70984RJCnSy55ZA=="], + + "@zag-js/date-picker": ["@zag-js/date-picker@0.71.0", "", { "dependencies": { "@internationalized/date": "3.5.5", "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/date-utils": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/live-region": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/text-selection": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-k6lIF813Jb9tBOFqYuS4g5PluRNfmP5uRr1Lhx/U1hx3PzEZr/8c07JQkKNMBv7qyU+67FbElMapeyyZnwSuTw=="], + + "@zag-js/date-utils": ["@zag-js/date-utils@0.62.1", "", { "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "sha512-YBqT5YRtHOCDS2IcCZtrq7BfzBkU5c+Sc2pVTncf06/3jxjE6l6YbBncMPu5a3uWKjNld1wOTFszhSoPKZfrJA=="], + + "@zag-js/dialog": ["@zag-js/dialog@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/aria-hidden": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/remove-scroll": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0", "focus-trap": "7.6.0" } }, "sha512-DBWfqEQuAQsbxdfKs//2q8v4OnJy3ecaEpe/IPhKdV6EiNXgL9MX+dsUlT2X4SQmZ25HGZssPP/T6QnPWdjz+Q=="], + + "@zag-js/dismissable": ["@zag-js/dismissable@0.71.0", "", { "dependencies": { "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/interact-outside": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-6i9Uc6TOhS2wE0E7bNgWWjqaGr13gbk8CQudtMjUpcPHx0CMRUAeww5M9LDnNzPZFVTbTN80Bl+YYJSauQRdrA=="], + + "@zag-js/dom-event": ["@zag-js/dom-event@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0", "@zag-js/text-selection": "0.71.0", "@zag-js/types": "0.71.0" } }, "sha512-HG1W2bLTWGFRgtrApHxuQNn6b5YEm3Rxor0yFTtdLrkAEd2Bskf/FkguxyHOyjbBlGHGm5HXGhuR9U0cy9cE6g=="], + + "@zag-js/dom-query": ["@zag-js/dom-query@0.71.0", "", {}, "sha512-PntZJu3EqAVAcOIbjxN091La4hhouH3Q0VwDu5QzOjB9CaAxM3yuhYpHjF+w/7fw7pXe6F3zd+FwhR4hZOd/UQ=="], + + "@zag-js/editable": ["@zag-js/editable@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/interact-outside": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-2JmvIx5XuN2MHbc22dUFk7coV4CCFN9of14KnR3iqqgdSEnXDpZdZDHQlmrPvRWSuraFV8wHwpXo9nNdgVdX5A=="], + + "@zag-js/element-rect": ["@zag-js/element-rect@0.71.0", "", {}, "sha512-50yuD7lpNctvcWNdESDGd2bePT7V1OWOHzsPljiy1ztMvL/U69sZ8NBm6ZFBpYs1rHWh/r3cIixcjVY0FCGHtw=="], + + "@zag-js/element-size": ["@zag-js/element-size@0.71.0", "", {}, "sha512-4Kf2h7+HEJ/b8yKJ+SX8skyNqFSRYImziIzv5QPsgeOD43YrfXpvvpE2iylD6aX9TN/C/nkNA74WQGHe76SiIQ=="], + + "@zag-js/file-upload": ["@zag-js/file-upload@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/file-utils": "0.71.0", "@zag-js/i18n-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-RYy6ygCvbYbPpUSfEWEkgJy/dcnmnLyI7VLjNb6EAdD+cNLcfsxtb+K9EcgDv6LcjoCYEi00ym00n7YpNtwb4w=="], + + "@zag-js/file-utils": ["@zag-js/file-utils@0.71.0", "", { "dependencies": { "@zag-js/i18n-utils": "0.71.0" } }, "sha512-kkDRbt5kZBXfosCkLlc93E+u/bYT+aaN9SH2NL+jvJghve673HcV6FnPbXjcrwV3k/iGKzHwdEW4e6JFh9K2FQ=="], + + "@zag-js/focus-visible": ["@zag-js/focus-visible@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0" } }, "sha512-+MyA3QNw7LGVanm0zOYA1TgRpGmvlpbmDBDQJREre7PC5dTmnE7bpw1Qs0aq6i5oX4x1VIbRhJjCl6PssH3Xzw=="], + + "@zag-js/form-utils": ["@zag-js/form-utils@0.71.0", "", {}, "sha512-ZDeWtp8QRxkA+Fy6PCZyT3/LTbb7ekCctxma9GYuxrXSe3N/BdqdQRF5Tf1a+dZDC/C/BNaBHFCJQVnfKZC5Qw=="], + + "@zag-js/highlight-word": ["@zag-js/highlight-word@0.71.0", "", {}, "sha512-afO+0KVgwcGYnqflJfsTY2+BLz+mMjRnvOxtX2cpYzP601YPJz76b/CfdD4RYH5CUX9SgWL9o8y+mcuA6bp/tA=="], + + "@zag-js/hover-card": ["@zag-js/hover-card@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-nDWEHH4jMAi9Z2Dxi0cYziue4+sqpGza4rqzKR35uht6DAsLlg4Ch2RneUWzbGvOGWKUqd8OE8D2PRDt7P9VEg=="], + + "@zag-js/i18n-utils": ["@zag-js/i18n-utils@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0" } }, "sha512-TMO3o1TME8bheQZ7b/sZWltVb4iFd6Xd5IhyrRLH6AAsJpimZd1ptDYrGoMNXtWRPjF35uF4Leio4vlLMGdlWw=="], + + "@zag-js/interact-outside": ["@zag-js/interact-outside@0.71.0", "", { "dependencies": { "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-DuCCOBpFxkoZ4TFiyiBw/sWy6gBcxTZ+DaszlfxaYXo5tGE6ta4jvnYLVomXru2PLbSlGm3/uWNG39BngK8oYg=="], + + "@zag-js/live-region": ["@zag-js/live-region@0.71.0", "", {}, "sha512-n+bbvjUK6e0EHA7EZ/xy9WaVsy/fa4UCZ3uK/yLQI/G7THVedzr1GXuSTFAUkF3uuq//rPvP8ELJosiMjOIWww=="], + + "@zag-js/menu": ["@zag-js/menu@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/rect-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-824dLMM9MEvpZeX/Ig4jVIoeUuhhAO64/nqrRwj5yROsILVdHOIbn/bSN4wi2Uc4x2Ft59Cu/QV9/QokRCyHMQ=="], + + "@zag-js/number-input": ["@zag-js/number-input@0.71.0", "", { "dependencies": { "@internationalized/number": "3.5.3", "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/number-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-39SjO9R44DXhfCl3R71pIDfS7fJJ/BCrEKH/acZS5UDVjNWCykuOuLJ9D/dMO8r3OyM3I5B8ffCpAdmlaVj0Pw=="], + + "@zag-js/number-utils": ["@zag-js/number-utils@0.71.0", "", {}, "sha512-GC2blJSlAEjH8xDrt6ycWUX/0aHXd7YxCwe6T78UaboRUwwt9oFkLet49Zjv9U+T9ePJERVBK5RB8lry30FsSw=="], + + "@zag-js/numeric-range": ["@zag-js/numeric-range@0.71.0", "", {}, "sha512-FvinriNKzrUeKHUsERMxUQ7HEKMlZn9JGyhXNCRhJIegPlY4hnQFukQGVYxVoaJ98nnX9XjrG/ZnghGixfYRiQ=="], + + "@zag-js/pagination": ["@zag-js/pagination@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-x//i35SMMZ2A2U3db5wd+ICe0/cycSBbaaQ6AYQZktt3/sikBT3Jte7HdK1yhRRjdIjIOB1FOLGGU5DjTYnfvw=="], + + "@zag-js/pin-input": ["@zag-js/pin-input@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-lj7X2JoJH3DUqCGBmDU7jWO614WhXZh9DvkxE0s7/kDw5jrWenOw072k8OA612954/mWm5xDcINiVCb+L+cCGQ=="], + + "@zag-js/popover": ["@zag-js/popover@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/aria-hidden": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/remove-scroll": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0", "focus-trap": "7.6.0" } }, "sha512-GTsT24NBeeByhvFW4HV0+8PLcrseuQ+YpJteOPiEsr28LfjTgXkq42EsvWHE/au/ilkquWH/lUv9i7t0yMLltg=="], + + "@zag-js/popper": ["@zag-js/popper@0.71.0", "", { "dependencies": { "@floating-ui/dom": "1.6.11", "@zag-js/dom-query": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-C+L2zcBxZ/fikiLaonk+r4yvCHtDetk2qrpyrBOPZv52D/4aE4gQDzI5Kn985XI2IsvlODgFXebKkgEYX+IPGw=="], + + "@zag-js/presence": ["@zag-js/presence@0.71.0", "", { "dependencies": { "@zag-js/core": "0.71.0", "@zag-js/types": "0.71.0" } }, "sha512-cqfcIroednr5k3AFRY9+3+CYRXWuP3mA233zgHAae2sbbjv/0qrtT/Tlk+Pw+c7zI+nFoYIi5mdetYlGVUnaKw=="], + + "@zag-js/progress": ["@zag-js/progress@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-a2fZkRl59hv2YZGHY85ZghTj8mfAPpsBRTX49McPTt48IsturA1a8JePhiEguXonxLyaNRO1qXGC3tzBzuNGwg=="], + + "@zag-js/qr-code": ["@zag-js/qr-code@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0", "proxy-memoize": "3.0.1", "uqr": "0.1.2" } }, "sha512-o8jyXrEbDK5mR+qDIHMhnycymJX/JUnoJpK/2wvq7qeqTEKVgRaoGhIBHLrDnoSwKkpxUxNj2fJfgLuWoMONYg=="], + + "@zag-js/radio-group": ["@zag-js/radio-group@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/element-rect": "0.71.0", "@zag-js/focus-visible": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-l2e5wwRSqEOTOY2uBGpAmeXxTK0PTxfQZF4BGq28Bz2Cp3kRqVXnSS57dcdqhefgQcgo5DzIeR0kSS8EJ/phsQ=="], + + "@zag-js/rating-group": ["@zag-js/rating-group@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-qgYJs6DMGe2ofNLWv70hBVQkwNTvmI5mZmYNJyqGKY0kqzDoS3MOaMX9EZ0RlEGmB45u0PrHBzTbDaxWlxGEJQ=="], + + "@zag-js/rect-utils": ["@zag-js/rect-utils@0.71.0", "", {}, "sha512-61O6eTEQRex2MtYc8/hdBBtuyvVKW9d0kAVedLJyrvNnNaDcNF9eb9Ucq2BoZ7SO90SKCcsyvPn4XV6tcCqVhw=="], + + "@zag-js/remove-scroll": ["@zag-js/remove-scroll@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0" } }, "sha512-QmmnYNgthaq/b9ml5HYoVNmT2Ev/8Uz5dAF9pTUj1EUlbF1LLgenZwzBg8lb4LUFXpG7tFuXYJ2wE4B/yGKE6w=="], + + "@zag-js/select": ["@zag-js/select@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/collection": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-97EU4Ojp7HLSQNQzBlfpHh2uqyQRfWReF+6MeGUuj1isWfk81vha2NZ4wkmQKRa8oIVAAmDej8+B05HdWevWlg=="], + + "@zag-js/signature-pad": ["@zag-js/signature-pad@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0", "perfect-freehand": "^1.2.2" } }, "sha512-A6+CpnhOBW3CPPDHkRRxM/tSzXiSguWlS4yvEHJ4Ax1jERaIgFpaLoxmqs5rQHSzdUw9hDwK38VRGQ7Xg1F6pw=="], + + "@zag-js/slider": ["@zag-js/slider@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/element-size": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/numeric-range": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-HgvoS0CTsZjdlNvF9GQwfj/Q0VnBU3wiDjOfAHN3pexfuRUgyxKihUaYGpvr28kS1jMzx7a6wMw9qB/hZsMD3g=="], + + "@zag-js/solid": ["@zag-js/solid@0.71.0", "", { "dependencies": { "@zag-js/core": "0.71.0", "@zag-js/store": "0.71.0", "@zag-js/types": "0.71.0" }, "peerDependencies": { "solid-js": ">=1.1.3" } }, "sha512-hP2UxxyLQhm2anKFzTIEZ3J5AphL8cbzktlMDgjhkKLbofacMbgyQVUHCdzpVf8YqKKp3MbVysKrJS5nFlnXeQ=="], + + "@zag-js/splitter": ["@zag-js/splitter@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/number-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-1iDeRtcqMCmiEeBCdK6x7kyZi0UZpV1UiI7DB7I0tfTZAggliOT6VxHiU7hwazRoEcJVDgWJAz2w0/Mq8X4aEQ=="], + + "@zag-js/steps": ["@zag-js/steps@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-ThdV6oqSvabmg3hBX6GGK0stdXhxK8LnE6TsnAaFI9cwBfL+HOhdyilHWvynSjnxyS0fRDLyUqQlHix/Y/8jig=="], + + "@zag-js/store": ["@zag-js/store@0.71.0", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-LjnpYn2pJMqaG3OjFwMNBIjEByClneHm8lRbgnGHZX7c3hFAbSWsDYX6unpmet/f5v2k3khGrMzCsjYjlgiMcg=="], + + "@zag-js/switch": ["@zag-js/switch@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/focus-visible": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-835iMEllFxlh76MpJ89YaBigRv5PG+i2nD57S1xr0TacuAJfVWMqXxlEb9OLZmC+nVOk9/GrZ6LNIY+GjQNTIA=="], + + "@zag-js/tabs": ["@zag-js/tabs@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/element-rect": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-z3vcgVz2tQtOfqPpk1mAl5l60VqZBlqrYgP1kZNu9WFiGZeWq3bWY+N1t2cudAlXKCkRqavSGk1jD5+yUKbd8w=="], + + "@zag-js/tags-input": ["@zag-js/tags-input@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/auto-resize": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/form-utils": "0.71.0", "@zag-js/interact-outside": "0.71.0", "@zag-js/live-region": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-oV4KTAYPAKfDhNHOw6olbwWcH/mOyJlcY/popFp19hf4BG8/gteGz/+kzOXBd6O/3ILHGZVNC3fJoQhWoFftYA=="], + + "@zag-js/text-selection": ["@zag-js/text-selection@0.71.0", "", { "dependencies": { "@zag-js/dom-query": "0.71.0" } }, "sha512-th61RGV9HuWNMGoWsTqMFyRTiCBuVw7gB2gjje7UbMa0zecK1hqtaudqiEArbp1i5g/9pkdPV3a060pP3/NaOQ=="], + + "@zag-js/time-picker": ["@zag-js/time-picker@0.71.0", "", { "dependencies": { "@internationalized/date": "3.5.5", "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "^0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-OlOqZhCkYiSG0SLQ1x+j2Ll6LGYT7O67WohAf4N21cmWmskxxgLvv7wHiXurNVSuUGpqbAvJtywUleXY162Eyg=="], + + "@zag-js/timer": ["@zag-js/timer@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-Fq80XxDGh0Uc5VxJMTnetMfwf2ziZ+jwXD5oH9TGr2aMA865GO53kYN84qBZM5oUFOJMQiufvzZKYKpZI52GNQ=="], + + "@zag-js/toast": ["@zag-js/toast@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dismissable": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-4GxAiMdRCLSSGnYuTklUkMlxtC7d3ZK5ZCnNtYNGYO4vcrK8ooaFoCpgG2D3jaON/b0sfpsRUEk6C1zOnkpgLQ=="], + + "@zag-js/toggle-group": ["@zag-js/toggle-group@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-TiBJ5DQHl0r6PRXdv041RZFxdil9ZSSGYfMKj6r29hz2PF2aS0LUmFdfYn3w00wiU76yh65r2nriowb7gXMvIQ=="], + + "@zag-js/tooltip": ["@zag-js/tooltip@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/focus-visible": "0.71.0", "@zag-js/popper": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-ZjxWtFsIFxxx4SkkoY1irQwLbqFeAXnq6okHIC1QkagyQb9U9HXgtBcDXf1vYa9wZQBfaRetAt/Hw0qygAzCcw=="], + + "@zag-js/tree-view": ["@zag-js/tree-view@0.71.0", "", { "dependencies": { "@zag-js/anatomy": "0.71.0", "@zag-js/core": "0.71.0", "@zag-js/dom-event": "0.71.0", "@zag-js/dom-query": "0.71.0", "@zag-js/types": "0.71.0", "@zag-js/utils": "0.71.0" } }, "sha512-2JElMhcuy1pT9Sa+xnAVDy6ZkR47o+ai+nVvhYKSZAym1ioA58j/+hPQA8IyiSrFccDJaJgFo+OBJCh5ZvEGsQ=="], + + "@zag-js/types": ["@zag-js/types@0.71.0", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-3laLExMsOgznfyULiJzX8cA4yCZbDEwX6iiFKaYyH/SU8ficy2sDuq0JjwIWUShlpsXGrUK+l/FQo0eTm9l46g=="], + + "@zag-js/utils": ["@zag-js/utils@0.71.0", "", {}, "sha512-Lax6Muzc0Y9XNZaCgH7WDAYalGZrcTb246MJC8PAdJPdEc/CT/SSC4jVfi8cuD3eqFXWwGJ9KWq8GiZoRBG22Q=="], + + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="], + + "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], + + "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.39.6", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-HMkTn5A3NyydEgG7HKmm48YcnsQQyqeT6SKNWh2TrS6nn5rOLeHDfg5hPbrRUCFUqaT9WGn5NInQfMc3qne3Dg=="], + + "babel-preset-solid": ["babel-preset-solid@1.9.3", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.39.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-jvlx5wDp8s+bEF9sGFw/84SInXOA51ttkUEroQziKMbxplXThVKt83qB6bDTa1HuLNatdU9FHpFOiQWs1tLQIg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], + + "bundle-n-require": ["bundle-n-require@1.1.1", "", { "dependencies": { "esbuild": "^0.20.0", "node-eval": "^2.0.0" } }, "sha512-EB2wFjXF106LQLe/CYnKCMCdLeTW47AtcEtUfiqAOgr2a08k0+YgRklur2aLfEYHlhz6baMskZ8L2U92Hh0vyA=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001699", "", {}, "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w=="], + + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="], + + "codemirror": ["codemirror@6.0.1", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/lint": "^6.0.0", "@codemirror/search": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="], + + "crosspath": ["crosspath@2.0.0", "", { "dependencies": { "@types/node": "^17.0.36" } }, "sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "cssnano-utils": ["cssnano-utils@5.0.0", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + + "effect": ["effect@3.10.15", "", { "dependencies": { "fast-check": "^3.21.0" } }, "sha512-LdczPAFbtij3xGr9i+8PyDtuWdlXjSY5UJ8PKrYrr0DClKfR/OW3j8sxtambWYljzJAYD865KFhv7LdbWdG7VQ=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.97", "", {}, "sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + + "escalade": ["escalade@3.1.2", "", {}, "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], + + "fastq": ["fastq@1.19.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA=="], + + "fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "focus-trap": ["focus-trap@7.6.0", "", { "dependencies": { "tabbable": "^6.2.0" } }, "sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ=="], + + "fs-extra": ["fs-extra@11.2.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@15.14.0", "", {}, "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig=="], + + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "javascript-stringify": ["javascript-stringify@2.1.0", "", {}, "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + + "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="], + + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + + "lightningcss": ["lightningcss@1.25.1", "", { "dependencies": { "detect-libc": "^1.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.25.1", "lightningcss-darwin-x64": "1.25.1", "lightningcss-freebsd-x64": "1.25.1", "lightningcss-linux-arm-gnueabihf": "1.25.1", "lightningcss-linux-arm64-gnu": "1.25.1", "lightningcss-linux-arm64-musl": "1.25.1", "lightningcss-linux-x64-gnu": "1.25.1", "lightningcss-linux-x64-musl": "1.25.1", "lightningcss-win32-x64-msvc": "1.25.1" } }, "sha512-V0RMVZzK1+rCHpymRv4URK2lNhIRyO8g7U7zOFwVAhJuat74HtkjIQpQRKNCwFEYkRGpafOpmXXLoaoBcyVtBg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.25.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-G4Dcvv85bs5NLENcu/s1f7ehzE3D5ThnlWSDwE190tWXRQCQaqwcuHe+MGSVI/slm0XrxnaayXY+cNl3cSricw=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.25.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-dYWuCzzfqRueDSmto6YU5SoGHvZTMU1Em9xvhcdROpmtOQLorurUZz8+xFxZ51lCO2LnYbfdjZ/gCqWEkwixNg=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.25.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hXoy2s9A3KVNAIoKz+Fp6bNeY+h9c3tkcx1J3+pS48CqAt+5bI/R/YY4hxGL57fWAIquRjGKW50arltD6iRt/w=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.25.1", "", { "os": "linux", "cpu": "arm" }, "sha512-tWyMgHFlHlp1e5iW3EpqvH5MvsgoN7ZkylBbG2R2LWxnvH3FuWCJOhtGcYx9Ks0Kv0eZOBud789odkYLhyf1ng=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.25.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Xjxsx286OT9/XSnVLIsFEDyDipqe4BcLeB4pXQ/FEA5+2uWCCuAEarUNQumRucnj7k6ftkAHUEph5r821KBccQ=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.25.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-IhxVFJoTW8wq6yLvxdPvyHv4NjzcpN1B7gjxrY3uaykQNXPHNIpChLB52+wfH+yS58zm1PL4LemUp8u9Cfp6Bw=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.25.1", "", { "os": "linux", "cpu": "x64" }, "sha512-RXIaru79KrREPEd6WLXfKfIp4QzoppZvD3x7vuTKkDA64PwTzKJ2jaC43RZHRt8BmyIkRRlmywNhTRMbmkPYpA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.25.1", "", { "os": "linux", "cpu": "x64" }, "sha512-TdcNqFsAENEEFr8fJWg0Y4fZ/nwuqTRsIr7W7t2wmDUlA8eSXVepeeONYcb+gtTj1RaXn/WgNLB45SFkz+XBZA=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.25.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9KZZkmmy9oGDSrnyHuxP6iMhbsgChUiu/NSgOx+U1I/wTngBStDf2i2aGRCHvFqj19HqqBEI4WuGVQBa2V6e0A=="], + + "local-pkg": ["local-pkg@0.5.1", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.2.1" } }, "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ=="], + + "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "lodash.truncate": ["lodash.truncate@4.4.2", "", {}, "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw=="], + + "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], + + "look-it-up": ["look-it-up@2.1.0", "", {}, "sha512-nMoGWW2HurtuJf6XAL56FWTDCWLOTSsanrgwOyaR5Y4e3zfG5N/0cU5xWZSEU3tBxhQugRbV1xL9jb+ug7yZww=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "magic-string": ["magic-string@0.30.11", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A=="], + + "merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "microdiff": ["microdiff@1.3.2", "", {}, "sha512-pKy60S2febliZIbwdfEQKTtL5bLNxOyiRRmD400gueYl9XcHyNGxzHSlJWn9IMHwYXT0yohPYL08+bGozVk8cQ=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + + "node-eval": ["node-eval@2.0.0", "", { "dependencies": { "path-is-absolute": "1.0.1" } }, "sha512-Ap+L9HznXAVeJj3TJ1op6M6bg5xtTq8L5CU/PJxtkhea/DrIxdTknGKIECKd/v/Lgql95iuMAYvIzBNd0pmcMg=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "object-path": ["object-path@0.11.8", "", {}, "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA=="], + + "outdent": ["outdent@0.8.0", "", {}, "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A=="], + + "package-manager-detector": ["package-manager-detector@0.1.0", "", {}, "sha512-qRwvZgEE7geMY6xPChI3T0qrM0PL4s/AKiLnNVjhg3GdN2/fUUSrpGA5Z8mejMXauT1BS6RJIgWvSGAdqg8NnQ=="], + + "parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="], + + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "perfect-freehand": ["perfect-freehand@1.2.2", "", {}, "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pkg-types": ["pkg-types@1.0.3", "", { "dependencies": { "jsonc-parser": "^3.2.0", "mlly": "^1.2.0", "pathe": "^1.1.0" } }, "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A=="], + + "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], + + "postcss": ["postcss@8.5.2", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA=="], + + "postcss-discard-duplicates": ["postcss-discard-duplicates@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ=="], + + "postcss-discard-empty": ["postcss-discard-empty@7.0.0", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA=="], + + "postcss-merge-rules": ["postcss-merge-rules@7.0.4", "", { "dependencies": { "browserslist": "^4.23.3", "caniuse-api": "^3.0.0", "cssnano-utils": "^5.0.0", "postcss-selector-parser": "^6.1.2" }, "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg=="], + + "postcss-minify-selectors": ["postcss-minify-selectors@7.0.4", "", { "dependencies": { "cssesc": "^3.0.0", "postcss-selector-parser": "^6.1.2" }, "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA=="], + + "postcss-nested": ["postcss-nested@6.0.1", "", { "dependencies": { "postcss-selector-parser": "^6.0.11" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ=="], + + "postcss-normalize-whitespace": ["postcss-normalize-whitespace@7.0.0", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "prettier": ["prettier@3.2.5", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A=="], + + "proxy-compare": ["proxy-compare@3.0.1", "", {}, "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q=="], + + "proxy-memoize": ["proxy-memoize@3.0.1", "", { "dependencies": { "proxy-compare": "^3.0.0" } }, "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g=="], + + "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "readdirp": ["readdirp@4.1.1", "", {}, "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], + + "rollup": ["rollup@4.34.6", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.6", "@rollup/rollup-android-arm64": "4.34.6", "@rollup/rollup-darwin-arm64": "4.34.6", "@rollup/rollup-darwin-x64": "4.34.6", "@rollup/rollup-freebsd-arm64": "4.34.6", "@rollup/rollup-freebsd-x64": "4.34.6", "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", "@rollup/rollup-linux-arm-musleabihf": "4.34.6", "@rollup/rollup-linux-arm64-gnu": "4.34.6", "@rollup/rollup-linux-arm64-musl": "4.34.6", "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", "@rollup/rollup-linux-riscv64-gnu": "4.34.6", "@rollup/rollup-linux-s390x-gnu": "4.34.6", "@rollup/rollup-linux-x64-gnu": "4.34.6", "@rollup/rollup-linux-x64-musl": "4.34.6", "@rollup/rollup-win32-arm64-msvc": "4.34.6", "@rollup/rollup-win32-ia32-msvc": "4.34.6", "@rollup/rollup-win32-x64-msvc": "4.34.6", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "seroval": ["seroval@1.2.1", "", {}, "sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw=="], + + "seroval-plugins": ["seroval-plugins@1.2.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="], + + "solid-js": ["solid-js@1.9.4", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ipQl8FJ31bFUoBNScDQTG3BjN6+9Rg+Q+f10bUbnO6EOTTf5NGerJeHc7wyu5I4RMHEl/WwZwUmy/PTRgxxZ8g=="], + + "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "style-mod": ["style-mod@4.1.2", "", {}, "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="], + + "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], + + "table": ["table@6.9.0", "", { "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1" } }, "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A=="], + + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "tinyglobby": ["tinyglobby@0.2.10", "", { "dependencies": { "fdir": "^6.4.2", "picomatch": "^4.0.2" } }, "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "ts-evaluator": ["ts-evaluator@1.2.0", "", { "dependencies": { "ansi-colors": "^4.1.3", "crosspath": "^2.0.0", "object-path": "^0.11.8" }, "peerDependencies": { "jsdom": ">=14.x || >=15.x || >=16.x || >=17.x || >=18.x || >=19.x || >=20.x || >=21.x || >=22.x", "typescript": ">=3.2.x || >= 4.x || >= 5.x" }, "optionalPeers": ["jsdom"] }, "sha512-ncSGek1p92bj2ifB7s9UBgryHCkU9vwC5d+Lplt12gT9DH+e41X8dMoHRQjIMeAvyG7j9dEnuHmwgOtuRIQL+Q=="], + + "ts-morph": ["ts-morph@24.0.0", "", { "dependencies": { "@ts-morph/common": "~0.25.0", "code-block-writer": "^13.0.3" } }, "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw=="], + + "ts-pattern": ["ts-pattern@5.0.8", "", {}, "sha512-aafbuAQOTEeWmA7wtcL94w6I89EgLD7F+IlWkr596wYxeb0oveWDO5dQpv85YP0CGbxXT/qXBIeV6IYLcoZ2uA=="], + + "tsconfck": ["tsconfck@3.1.5", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + + "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "unplugin": ["unplugin@2.2.0", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw=="], + + "unplugin-icons": ["unplugin-icons@22.0.0", "", { "dependencies": { "@antfu/install-pkg": "^0.5.0", "@antfu/utils": "^0.7.10", "@iconify/utils": "^2.2.1", "debug": "^4.4.0", "kolorist": "^1.8.0", "local-pkg": "^0.5.1", "unplugin": "^2.1.0" }, "peerDependencies": { "@svgr/core": ">=7.0.0", "@svgx/core": "^1.0.1", "@vue/compiler-sfc": "^3.0.2 || ^2.7.0", "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0", "vue-template-compiler": "^2.6.12", "vue-template-es2015-compiler": "^1.9.0" }, "optionalPeers": ["@svgr/core", "@svgx/core", "@vue/compiler-sfc", "svelte", "vue-template-compiler", "vue-template-es2015-compiler"] }, "sha512-+1jIt2wynxL+GISehNok8MIb9RaCufIZCHJs0HKbxOljJL9m4NtOhva+dZhNtSKtfQ62Hwd/RRbniSVuuD4Xow=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], + + "uqr": ["uqr@0.1.2", "", {}, "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "validate-html-nesting": ["validate-html-nesting@1.2.2", "", {}, "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg=="], + + "vite": ["vite@6.1.0", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.5.1", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ=="], + + "vite-plugin-solid": ["vite-plugin-solid@2.11.1", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-X9vbbK6AOOA6yxSsNl1VTuUq5y4BG9AR6Z5F/J1ZC2VO7ll8DlSCbOL+RcZXlRbxn0ptE6OI5832nGQhq4yXKQ=="], + + "vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="], + + "vitefu": ["vitefu@1.0.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA=="], + + "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], + + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], + + "wordwrapjs": ["wordwrapjs@5.1.0", "", {}, "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg=="], + + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "@antfu/install-pkg/package-manager-detector": ["package-manager-detector@0.2.9", "", {}, "sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q=="], + + "@ark-ui/anatomy/@zag-js/accordion": ["@zag-js/accordion@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-1lMKuD1GbiMuemOHOu+24BSAAG8iTD6l/4zYrQRBCTsxXzHhWqTtLF7okGgmSAs8iyNfOuWefCfaJJ3BJNSh5A=="], + + "@ark-ui/anatomy/@zag-js/anatomy": ["@zag-js/anatomy@0.62.1", "", {}, "sha512-1JiPQOyVlO1jHwLTSNJpyfy1R1UYoaVU1mKSUww5+htAuT/1txjs04pr+8vTF/L/UVzNEZZYepB1tTabyb9LYg=="], + + "@ark-ui/anatomy/@zag-js/avatar": ["@zag-js/avatar@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-J+IRqJlpL4S9ikCQle/FHj6p8uT8Ee/D88u4k7m/An4Ot1FcrfKqfC3INB5YOI+d8hkIQVtEIAC8Yt/s4OzAMg=="], + + "@ark-ui/anatomy/@zag-js/carousel": ["@zag-js/carousel@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-0YQ2jJjzaS1zFLVnPBslVKI8/fY2Z6aOrcJbBjxozG27iSS6zEqmbsz3OOtcYJRlB8jLboZutpMBs3PGh5zg5Q=="], + + "@ark-ui/anatomy/@zag-js/checkbox": ["@zag-js/checkbox@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-xiubQLhRXedlZe4Vc6zxaDFWLSpRdGEG0jTrF3OXovYZLN7bmq0iXiYcWqsLa012+2dYN9w5B1zfQQlzf4sk2w=="], + + "@ark-ui/anatomy/@zag-js/clipboard": ["@zag-js/clipboard@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-gEhCGLkAlrgNWkd7ZqF4p4yNKsR54+0YQPevEv7iX9oio8T/F8OWaDmDjA4NsXxqRe6hr5KLJbVp8dYRop30TQ=="], + + "@ark-ui/anatomy/@zag-js/collapsible": ["@zag-js/collapsible@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-M4hsuqf6dVra6RvKaxQjgQjZ+iYj3XH84w6QOnt/SXbJauQoE6nfy77RI/A8O2pPuP6uLq0h2E9Eo3ftcbGBoQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker": ["@zag-js/color-picker@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/color-utils": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-GLeADGcoMLcVS+UM6rn/c1BmBgSB2uTc5AWBkuKoH7TktsKo6+T/v3/QZIU7/b69qBAp3/vWZti99Flw42IDdw=="], + + "@ark-ui/anatomy/@zag-js/combobox": ["@zag-js/combobox@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/aria-hidden": "0.62.1", "@zag-js/collection": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-EovqyFqD61YmYJYc42qKH2OE7GxMm3gamWLU/lvZe/3eyZt6TsxFe2xeP7WSsvq2v90myMajAnUb0DOpvYaCKw=="], + + "@ark-ui/anatomy/@zag-js/date-picker": ["@zag-js/date-picker@0.62.1", "", { "dependencies": { "@internationalized/date": "3.5.5", "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/date-utils": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/live-region": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-Wl6yzMtrTy7XgDFbYJaRO8M5dkxLPBvAo3ilDvFBicbJViJCZ9pg1AJYh+xGaK/gfAd7O9wBdYJdHxfESlmlDg=="], + + "@ark-ui/anatomy/@zag-js/dialog": ["@zag-js/dialog@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/aria-hidden": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/remove-scroll": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1", "focus-trap": "7.5.4" } }, "sha512-7YRvWZ9UMUjFz0q537/uaTMBljLimWISfVHkUSa2ngbXB8LPYYbqYv5Vio2rvRFqy3nJR3HTO4cGZJGDjO655g=="], + + "@ark-ui/anatomy/@zag-js/editable": ["@zag-js/editable@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-BkPLV8T9ixdhz3IxvseV24a1pBNmYhR1np+JUKap0C8thtFbDoF361haEQjCqTCfHDv+j5l1rtq/+H/TF3eEIg=="], + + "@ark-ui/anatomy/@zag-js/file-upload": ["@zag-js/file-upload@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/file-utils": "0.62.1", "@zag-js/i18n-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-Wh33acYMJLNRIV2y0GdSZqoN3aX/t/uzIBWh3rVsN7tpjDYWXLYIsXQttkGLFf0sgICK+3PVD+LLaIpiGDh4+Q=="], + + "@ark-ui/anatomy/@zag-js/hover-card": ["@zag-js/hover-card@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-ryiNHQmmHpiDiZ5nuk9nvGUgnT017q8hYf+wLSI5OJ+klHPjrHObb7I7v/fUmKzWNtIOhaL0uw9afzjRt3bLEw=="], + + "@ark-ui/anatomy/@zag-js/menu": ["@zag-js/menu@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/rect-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-l/PartHj6//NMlENYNBmUmeYG9K0SbjbnnIudv+rK+oyrUoX/MDCJ7bdy7ZMYxWTR127WdZlLHBxsgMe86lBqQ=="], + + "@ark-ui/anatomy/@zag-js/number-input": ["@zag-js/number-input@0.62.1", "", { "dependencies": { "@internationalized/number": "3.5.3", "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/number-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-THizFB4Qwq4erMk6mI82voIo/PbbrAOSQXyPF8NPyGupSzqYntS1XPEdyqFH677PhHweelxQnvtZEm5alm1HLw=="], + + "@ark-ui/anatomy/@zag-js/pagination": ["@zag-js/pagination@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-fyDXNnAGyRsQEugvNR1kfEO8hGeesOV6l2rEACdvNN6G9Cqktqd52aaWVIf805G3Ig72igW2SybI9md/rDflzQ=="], + + "@ark-ui/anatomy/@zag-js/pin-input": ["@zag-js/pin-input@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-CTAOyQCLaNSWH29bhc4XruEkvnYFJN1QF/x5axtHV+cir05zcdB3L7Sna4D6nUBSwd0tOGnUmPlviyP7zkpgBA=="], + + "@ark-ui/anatomy/@zag-js/popover": ["@zag-js/popover@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/aria-hidden": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/remove-scroll": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1", "focus-trap": "7.5.4" } }, "sha512-cT6okb5Yq69YWx6G1vonNEnEg4MlBXRbXLflLBqOP1PTwhk6RwlndXGV2uCdlnR0mUJa/RKldzdUcwOQesJaag=="], + + "@ark-ui/anatomy/@zag-js/presence": ["@zag-js/presence@0.62.1", "", { "dependencies": { "@zag-js/core": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-qjnr1WpW5yetRp2j2V0ocRvr6X6TuWNxjL2DyJAusodcsSElF2V0UuFOLT/xIZA8BVIbgcyCvcPB01PHugC5Ww=="], + + "@ark-ui/anatomy/@zag-js/progress": ["@zag-js/progress@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-7FyeP/wCiJ2dao1y/4RzhrLeIse305YtRMTDaVE5EnOJK3nit2Rrl+z8kGx5aqrGQcGsLH/rh5QYFp689Nx57Q=="], + + "@ark-ui/anatomy/@zag-js/qr-code": ["@zag-js/qr-code@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1", "proxy-memoize": "3.0.1", "uqr": "0.1.2" } }, "sha512-648qXQduIqq4CZWN07D1UOcczZrdp3UjBSHFEi4PQHTz1Vg08pH0BIZDqiqpupG9niYJEB/GPLGofRQQYoIoDw=="], + + "@ark-ui/anatomy/@zag-js/radio-group": ["@zag-js/radio-group@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/element-rect": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-VVGTUkHgD27vBTYeP7hPYi+eDRXkq7xtlv6Ml062t3gcTWBhc/2eaI6iZ7awlxTl9052sflzbawrrDysPREuAQ=="], + + "@ark-ui/anatomy/@zag-js/rating-group": ["@zag-js/rating-group@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-gXvHofr3gfZcaMh7Y3FU+wyj7ge1R0BgsuPJWFUShlAlxjnnE7e3AqjSGlzuvpkWMkc6KKDyKRJlMVWLCv94OA=="], + + "@ark-ui/anatomy/@zag-js/select": ["@zag-js/select@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/collection": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-dgU65imBSeB8+QfHkN68j7Xqd/d6wsF42itJ0AeRSdgnCHgTWdN9rRCK5EDbNkJue51oMkdsnJ7XG1k+oCgiAg=="], + + "@ark-ui/anatomy/@zag-js/signature-pad": ["@zag-js/signature-pad@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1", "perfect-freehand": "^1.2.2" } }, "sha512-hWZSWT9J9V1kbImkj8qXHCqS0TYm7nms9oAhcQ2QNIiGO38wqW8Yswos8sqAj8VtzHxkSMIeL1by7Zgy3Xjq9g=="], + + "@ark-ui/anatomy/@zag-js/slider": ["@zag-js/slider@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/element-size": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/numeric-range": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-v5rgPJF3fh7bBPu0wzEGpN4EcXpK5cSw4OAwxatmbtkYsg2Udwv6WL26CB5Q2zVwYIR6R532b/bjFqicfVs+SA=="], + + "@ark-ui/anatomy/@zag-js/splitter": ["@zag-js/splitter@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/number-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-Ni93ZaprnbctAsbuot8sEw9DDfNMgkelnd5xQfAiwpgjwUgnY8733LRbWydC5OUPoJ/cCs3XiNKa0CHwclcq6Q=="], + + "@ark-ui/anatomy/@zag-js/switch": ["@zag-js/switch@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-uh0yy3NuZqHF+jPVZ2oMcAtPx32eTnBebiROBGBDgj1A5yZBirfQm8j/vZLSILhDq9TdktHS9/gITJ7TvgV4cQ=="], + + "@ark-ui/anatomy/@zag-js/tabs": ["@zag-js/tabs@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/element-rect": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-BpY6oA2nmZLpYu8nQrpi+zTF4txTiMYIMB31CmbFmbJ3hMVkEqk8sgNzNQY3LrzkkSemDRBHxPZ5H+YKaQrEdg=="], + + "@ark-ui/anatomy/@zag-js/tags-input": ["@zag-js/tags-input@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/auto-resize": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/form-utils": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/live-region": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-8gJ4ckQQ0BB3oUGgIEGkmB6wIKSf7xx0q6e3tqTbfZnPhmWP4hpli38XAOYjsBQyNXmQW89H/Rp8/8W1A/Vpow=="], + + "@ark-ui/anatomy/@zag-js/time-picker": ["@zag-js/time-picker@0.62.1", "", { "dependencies": { "@internationalized/date": "3.5.5", "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "^0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-THNASHp9Fu5f4/LC3t3qJfsYD6FqjhbP7HrjIDDFOcdNGRzOTfbEpKF3JtJgmM6F+/fuQKhe6FUbcluMd9zo8Q=="], + + "@ark-ui/anatomy/@zag-js/toast": ["@zag-js/toast@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dismissable": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-Kb+OiFx7KUG0fAExIL06xWEfhxeMRJACvP6q4B4FNuFX+6N06RbV/PZtLbPbffOodd7VhSk1W37T7t6Np32mvg=="], + + "@ark-ui/anatomy/@zag-js/toggle-group": ["@zag-js/toggle-group@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-h7jQtWJt11uws6IYBd3kQzOyOemtZ5CqR7lt4XZdni3J1EtymKRJNha2JIukIETZS9/0VU1fPcuDkQeCXcGHgQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip": ["@zag-js/tooltip@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/popper": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-318EJU6B4FR0nMNU79qMAgdOiVM6vbDiRWBHjGLDBK3z5No3lKfo4TZb/NqBmmi2W7ZFPiPwvLFsTql+H0xDbA=="], + + "@ark-ui/anatomy/@zag-js/tree-view": ["@zag-js/tree-view@0.62.1", "", { "dependencies": { "@zag-js/anatomy": "0.62.1", "@zag-js/core": "0.62.1", "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/types": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-Y7qj16X18uElsD5jA9l03+rKEg1/5JIGRutO+NlEbs9Ffb7y34vqcEWquA+YgDfqXVWk2b5v9xcU1iKuKhOagQ=="], + + "@babel/helper-compilation-targets/browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@csstools/postcss-cascade-layers/postcss-selector-parser": ["postcss-selector-parser@6.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg=="], + + "@iconify/utils/@antfu/install-pkg": ["@antfu/install-pkg@1.0.0", "", { "dependencies": { "package-manager-detector": "^0.2.8", "tinyexec": "^0.3.2" } }, "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw=="], + + "@iconify/utils/@antfu/utils": ["@antfu/utils@8.1.0", "", {}, "sha512-XPR7Jfwp0FFl/dFYPX8ZjpmU4/1mIXTjnZ1ba48BLMyKOV62/tiRjdsFcPs2hsYcSud4tzk7w3a3LjX8Fu3huA=="], + + "@iconify/utils/local-pkg": ["local-pkg@1.0.0", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.3.0" } }, "sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg=="], + + "@pandacss/config/typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], + + "@pandacss/core/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], + + "@pandacss/generator/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], + + "@pandacss/node/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], + + "@pandacss/node/tsconfck": ["tsconfck@3.0.2", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-6lWtFjwuhS3XI4HsX4Zg0izOI3FU/AI9EGVlPEUMDIhvLPMD4wkiof0WCoDgW7qY+Dy198g4d9miAqUHWHFH6Q=="], + + "@pandacss/parser/magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "@pandacss/postcss/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], + + "@zag-js/color-picker/@zag-js/color-utils": ["@zag-js/color-utils@0.71.0", "", { "dependencies": { "@zag-js/numeric-range": "0.71.0" } }, "sha512-H/CeRE7fjLecLYBinOTRGpiLTI3e60KnMEQceBx4ZbyxRW2LD+MoOQMmkgudrXLS1tG1x5Ng/4IWYfpzFV26Rg=="], + + "@zag-js/color-utils/@zag-js/numeric-range": ["@zag-js/numeric-range@0.62.1", "", {}, "sha512-R4/II5MvS+eJ880srPuIlexqRH7kVsGomcsDlB5yyhHsradm7OJfC5L6osvKj1DNAitfFh8901BZFaWmQe8O1w=="], + + "@zag-js/date-picker/@zag-js/date-utils": ["@zag-js/date-utils@0.71.0", "", { "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "sha512-4BQRBY8hAKK9H5sV+7k1il34Cou4GrBGJSlv3XzwNYRzYhGRK1J2fByGgIdoBxAnb0KHmUftP+XTJdVSLz5Ymw=="], + + "@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], + + "bundle-n-require/esbuild": ["esbuild@0.20.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.20.2", "@esbuild/android-arm": "0.20.2", "@esbuild/android-arm64": "0.20.2", "@esbuild/android-x64": "0.20.2", "@esbuild/darwin-arm64": "0.20.2", "@esbuild/darwin-x64": "0.20.2", "@esbuild/freebsd-arm64": "0.20.2", "@esbuild/freebsd-x64": "0.20.2", "@esbuild/linux-arm": "0.20.2", "@esbuild/linux-arm64": "0.20.2", "@esbuild/linux-ia32": "0.20.2", "@esbuild/linux-loong64": "0.20.2", "@esbuild/linux-mips64el": "0.20.2", "@esbuild/linux-ppc64": "0.20.2", "@esbuild/linux-riscv64": "0.20.2", "@esbuild/linux-s390x": "0.20.2", "@esbuild/linux-x64": "0.20.2", "@esbuild/netbsd-x64": "0.20.2", "@esbuild/openbsd-x64": "0.20.2", "@esbuild/sunos-x64": "0.20.2", "@esbuild/win32-arm64": "0.20.2", "@esbuild/win32-ia32": "0.20.2", "@esbuild/win32-x64": "0.20.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g=="], + + "caniuse-api/browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "crosspath/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "local-pkg/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "postcss-merge-rules/browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "postcss-nested/postcss-selector-parser": ["postcss-selector-parser@6.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg=="], + + "tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "update-browserslist-db/escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/aria-hidden": ["@zag-js/aria-hidden@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-vVV8bwZhNU+AOOf/USEGV/n9zuTID+spHeC9ZAj29ibWAMmaiq2bx4t1kO4v9eKqKXULUBPPrZQ7CX7oiU616A=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/collection": ["@zag-js/collection@0.62.1", "", { "dependencies": { "@zag-js/utils": "0.62.1" } }, "sha512-Qg3OvGCvcoeV4u8IcQmNCu4dChRttVyQ9DF8Ab0qlyrjRDF+w8vMAcNcgNqn10/xX4A7B743cz023LooVsW6VA=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/live-region": ["@zag-js/live-region@0.62.1", "", {}, "sha512-Giu7d5UWc2Sqb3/T0tSzqSwxJ4mVrNN+MTu06J7EaD4khK5RgX4GRpQ9rpwOS/GJT+8nc6YBhWTi7tqKN/+iHQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/aria-hidden": ["@zag-js/aria-hidden@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-vVV8bwZhNU+AOOf/USEGV/n9zuTID+spHeC9ZAj29ibWAMmaiq2bx4t1kO4v9eKqKXULUBPPrZQ7CX7oiU616A=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/remove-scroll": ["@zag-js/remove-scroll@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-7xpX6HUrOEq/TNLIWojYnQf7kj20bk8ueOKpu7cTZmoN0LSL6cS09uil+NOqb+SzZsiRmQKvzd3fQBNwbdab5Q=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/dialog/focus-trap": ["focus-trap@7.5.4", "", { "dependencies": { "tabbable": "^6.2.0" } }, "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/file-utils": ["@zag-js/file-utils@0.62.1", "", { "dependencies": { "@zag-js/i18n-utils": "0.62.1" } }, "sha512-p363S2pqz29wf1shcSfoY2GI9wWrJkKamNiwuehqoYFh2b8isrcWFVL3VYxm937N1/m5+rtMATQbn0a9j9sggA=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/i18n-utils": ["@zag-js/i18n-utils@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-ipzx0W6VK5x+w/PnUrN8z5SULJuLqvdzsPVBJ2iGHrMcTPC/y9JDt82nJV9fUYmG898pOZUx7vysfLLPNEAFTQ=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/rect-utils": ["@zag-js/rect-utils@0.62.1", "", {}, "sha512-6w56LuRD382Oa2FXi4AfKQqgtUPS/nc/mZzXiaqKz9b5aFA1CXtmEwNC2GaiXhkqJp5DyxHwujDfQP1WXACnRQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/number-utils": ["@zag-js/number-utils@0.62.1", "", {}, "sha512-ktnGSYKKLG9No14ivlboEzq4+jiOIWU+8yeoRrZmfdCG58g4s9JF0lBDRf3ts9vhUdofJ+vUFMPqkk2eCWyQlA=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/aria-hidden": ["@zag-js/aria-hidden@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-vVV8bwZhNU+AOOf/USEGV/n9zuTID+spHeC9ZAj29ibWAMmaiq2bx4t1kO4v9eKqKXULUBPPrZQ7CX7oiU616A=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/remove-scroll": ["@zag-js/remove-scroll@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-7xpX6HUrOEq/TNLIWojYnQf7kj20bk8ueOKpu7cTZmoN0LSL6cS09uil+NOqb+SzZsiRmQKvzd3fQBNwbdab5Q=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/popover/focus-trap": ["focus-trap@7.5.4", "", { "dependencies": { "tabbable": "^6.2.0" } }, "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w=="], + + "@ark-ui/anatomy/@zag-js/presence/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/presence/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/element-rect": ["@zag-js/element-rect@0.62.1", "", {}, "sha512-SefRp1IeiENoUkl7yxGzUIdxtQqgKlI+G1qlgx9MZgchH2VZCpqi+EuZgLEKzz7REMabOYqbgs6EEIxGIyNueg=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/collection": ["@zag-js/collection@0.62.1", "", { "dependencies": { "@zag-js/utils": "0.62.1" } }, "sha512-Qg3OvGCvcoeV4u8IcQmNCu4dChRttVyQ9DF8Ab0qlyrjRDF+w8vMAcNcgNqn10/xX4A7B743cz023LooVsW6VA=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/element-size": ["@zag-js/element-size@0.62.1", "", {}, "sha512-QCtVeIJ611hJPorKEkdfrWWcMohadplZoW8xQW/2PLSmKUhTNLfHsZLyeoYKyj5Jk4X8OAN4onnMVETFw232EA=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/numeric-range": ["@zag-js/numeric-range@0.62.1", "", {}, "sha512-R4/II5MvS+eJ880srPuIlexqRH7kVsGomcsDlB5yyhHsradm7OJfC5L6osvKj1DNAitfFh8901BZFaWmQe8O1w=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/number-utils": ["@zag-js/number-utils@0.62.1", "", {}, "sha512-ktnGSYKKLG9No14ivlboEzq4+jiOIWU+8yeoRrZmfdCG58g4s9JF0lBDRf3ts9vhUdofJ+vUFMPqkk2eCWyQlA=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/element-rect": ["@zag-js/element-rect@0.62.1", "", {}, "sha512-SefRp1IeiENoUkl7yxGzUIdxtQqgKlI+G1qlgx9MZgchH2VZCpqi+EuZgLEKzz7REMabOYqbgs6EEIxGIyNueg=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/auto-resize": ["@zag-js/auto-resize@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-nznVkAsZGS+L+VhNO8hPnEyvagNhTezkb64SSPa8E49hJHS2DEN3T5hKCx86tDuiCMd0EdjwUCCQq3pnbzbnCQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/form-utils": ["@zag-js/form-utils@0.62.1", "", {}, "sha512-GJWRRtEpro8TNEUuEWMhIOWmVFXqiHNTTrrRLxijxUIWbsPrPdPiKL7qwBAESYoZQCmN0hU99S0w2Xmm7Q05Zg=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/live-region": ["@zag-js/live-region@0.62.1", "", {}, "sha512-Giu7d5UWc2Sqb3/T0tSzqSwxJ4mVrNN+MTu06J7EaD4khK5RgX4GRpQ9rpwOS/GJT+8nc6YBhWTi7tqKN/+iHQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/dismissable": ["@zag-js/dismissable@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/interact-outside": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-muGTBISpjQEWLCrsYa9wAFaGXlVxYtyMaDgpcPpQdQPwZF86b445y4d8h9FjwkESdJ6Zcdjn21pu5CWD28T3uQ=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/popper": ["@zag-js/popper@0.62.1", "", { "dependencies": { "@floating-ui/dom": "1.6.8", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-tyLEdYIsv3cgnWCWzPPv9f72hzmQDQcObDIczIZt+OQr89qgyhGHt5jR1f0Qxsz9zZlSPsEftccyXRQYInQtxQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/core": ["@zag-js/core@0.62.1", "", { "dependencies": { "@zag-js/store": "0.62.1", "klona": "2.0.6" } }, "sha512-ZSjqnV5vcGDassjmZ/lxWbG244A0i+IHImVZ/a4/0JkjkH126ly+At4FC+HI571pNKiNlrqYmGzRRSBMqm37yQ=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/dom-query": ["@zag-js/dom-query@0.62.1", "", {}, "sha512-sI/urNd3QX/WI7Sii+X1Z/OTWNisn7EaW3T0X9Rbn41u79DC4KeUnP+wpIq1igSJNH2zQWIWBLJ1OGhAjuSl5g=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/types": ["@zag-js/types@0.62.1", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wjJvasoxg/rsFhMTaGLJEjYnSGaXz7DymtO+wWOIfa+O6y44flHc8wRQ1l6ZRRetCz4RALTuwhZI+0ESZ1Bpwg=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/utils": ["@zag-js/utils@0.62.1", "", {}, "sha512-90sk7Li2mqoMCAfZbns1xrySEg4PIFPwLpiRO/T2kvKpc9z/qsq2WqDFpS8eqHfYRmkLnmQa0Bw1LzItYYsGVQ=="], + + "@iconify/utils/@antfu/install-pkg/package-manager-detector": ["package-manager-detector@0.2.9", "", {}, "sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q=="], + + "@iconify/utils/local-pkg/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "bundle-n-require/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.20.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g=="], + + "bundle-n-require/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.20.2", "", { "os": "android", "cpu": "arm" }, "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w=="], + + "bundle-n-require/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.20.2", "", { "os": "android", "cpu": "arm64" }, "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg=="], + + "bundle-n-require/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.20.2", "", { "os": "android", "cpu": "x64" }, "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg=="], + + "bundle-n-require/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.20.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA=="], + + "bundle-n-require/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.20.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA=="], + + "bundle-n-require/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.20.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw=="], + + "bundle-n-require/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.20.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw=="], + + "bundle-n-require/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.20.2", "", { "os": "linux", "cpu": "arm" }, "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg=="], + + "bundle-n-require/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.20.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A=="], + + "bundle-n-require/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.20.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig=="], + + "bundle-n-require/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.20.2", "", { "os": "linux", "cpu": "none" }, "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ=="], + + "bundle-n-require/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.20.2", "", { "os": "linux", "cpu": "none" }, "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA=="], + + "bundle-n-require/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.20.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg=="], + + "bundle-n-require/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.20.2", "", { "os": "linux", "cpu": "none" }, "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg=="], + + "bundle-n-require/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.20.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ=="], + + "bundle-n-require/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.20.2", "", { "os": "linux", "cpu": "x64" }, "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw=="], + + "bundle-n-require/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.20.2", "", { "os": "none", "cpu": "x64" }, "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ=="], + + "bundle-n-require/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.20.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ=="], + + "bundle-n-require/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.20.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w=="], + + "bundle-n-require/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.20.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ=="], + + "bundle-n-require/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.20.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ=="], + + "bundle-n-require/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.20.2", "", { "os": "win32", "cpu": "x64" }, "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ=="], + + "local-pkg/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/dismissable/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/dismissable/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/dismissable/@zag-js/dom-event": ["@zag-js/dom-event@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1", "@zag-js/text-selection": "0.62.1", "@zag-js/types": "0.62.1" } }, "sha512-/+okVW69Xdoot7dutJVMz0iciwWM6DvAeLWr7LB5DZsUQMu93oqV/8BE2JArDxEcg5C208HNThGStcWlTaddgA=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/presence/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/dismissable/@zag-js/interact-outside": ["@zag-js/interact-outside@0.62.1", "", { "dependencies": { "@zag-js/dom-event": "0.62.1", "@zag-js/dom-query": "0.62.1", "@zag-js/utils": "0.62.1" } }, "sha512-V5N+kr2Uv97HWYL0U5ZVS//NMQu87XGLtI7Ae5EtHrdAEKxO2NpPwf50Gzza4zc1VEVYYFqobTlkNQ3hrrL6VQ=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/popper/@floating-ui/dom": ["@floating-ui/dom@1.6.8", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.5" } }, "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/core/@zag-js/store": ["@zag-js/store@0.62.1", "", { "dependencies": { "proxy-compare": "3.0.0" } }, "sha512-0xkz7b/Rs9cHeI5CB3UH4yMlVzys3l+IsJU3KRWZwqWohDjTEqRyzcuFD6AH28WAcJPjIgOQYnRYzYSoMGZtDQ=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@iconify/utils/local-pkg/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "@ark-ui/anatomy/@zag-js/accordion/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/avatar/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/carousel/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/checkbox/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/clipboard/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/collapsible/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/color-picker/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/combobox/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/date-picker/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/dialog/@zag-js/dismissable/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/editable/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/file-upload/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/hover-card/@zag-js/dismissable/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/menu/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/number-input/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/pagination/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/pin-input/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/popover/@zag-js/dismissable/@zag-js/dom-event/@zag-js/text-selection": ["@zag-js/text-selection@0.62.1", "", { "dependencies": { "@zag-js/dom-query": "0.62.1" } }, "sha512-0b049CnWN/Nyp/F/nbeU6G8BI/fzwlSQTTDWK81yRFADDFTZ2mWpVAWJF/fY0rKjsn4ucDykCS7GXMIo5rYILQ=="], + + "@ark-ui/anatomy/@zag-js/presence/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/progress/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/qr-code/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/radio-group/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/rating-group/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/select/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/signature-pad/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/slider/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/splitter/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/switch/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/tabs/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/tags-input/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/time-picker/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/toast/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/toggle-group/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/tooltip/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + + "@ark-ui/anatomy/@zag-js/tree-view/@zag-js/core/@zag-js/store/proxy-compare": ["proxy-compare@3.0.0", "", {}, "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w=="], + } +} diff --git a/pkgs/ffigenpad/web/index.html b/pkgs/ffigenpad/web/index.html new file mode 100644 index 0000000000..b6eed543c0 --- /dev/null +++ b/pkgs/ffigenpad/web/index.html @@ -0,0 +1,13 @@ + + + + + + + FFIgenPad + + +
+ + + diff --git a/pkgs/ffigenpad/web/package.json b/pkgs/ffigenpad/web/package.json new file mode 100644 index 0000000000..c615385ad8 --- /dev/null +++ b/pkgs/ffigenpad/web/package.json @@ -0,0 +1,40 @@ +{ + "name": "web", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "prepare": "panda codegen", + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@ark-ui/solid": "^3.7.0", + "@codemirror/lang-cpp": "^6.0.2", + "@codemirror/lang-yaml": "^6.1.2", + "@codemirror/language": "^6.10.8", + "@codemirror/legacy-modes": "^6.4.2", + "@codemirror/state": "^6.5.2", + "@codemirror/theme-one-dark": "^6.1.2", + "@fontsource-variable/reddit-mono": "^5.1.1", + "codemirror": "^6.0.1", + "pathe": "^1.1.2", + "solid-js": "^1.9.4" + }, + "devDependencies": { + "@babel/types": "^7.26.8", + "@iconify-json/tabler": "^1.2.16", + "@pandacss/dev": "^0.53.0", + "@park-ui/panda-preset": "^0.43.1", + "@types/node": "^22.13.1", + "typescript": "^5.7.3", + "unplugin-icons": "^22.0.0", + "vite": "^6.1.0", + "vite-plugin-solid": "^2.11.1", + "vite-tsconfig-paths": "^5.1.4" + }, + "engines": { + "node": ">=20.17.0" + } +} diff --git a/pkgs/ffigenpad/web/panda.config.ts b/pkgs/ffigenpad/web/panda.config.ts new file mode 100644 index 0000000000..7be753c85b --- /dev/null +++ b/pkgs/ffigenpad/web/panda.config.ts @@ -0,0 +1,47 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { defineConfig } from "@pandacss/dev"; +import { createPreset } from "@park-ui/panda-preset"; +import blue from "@park-ui/panda-preset/colors/blue"; +import slate from "@park-ui/panda-preset/colors/slate"; + +export default defineConfig({ + preflight: true, + presets: [ + "@pandacss/preset-base", + createPreset({ + accentColor: blue, + grayColor: slate, + radius: "sm" + }), + ], + include: ["./src/**/*.{js,jsx,ts,tsx,vue}", "./third_party/**/*.{js,jsx,ts,tsx,vue}"], + jsxFramework: "solid", + outdir: "styled-system", + theme: { + extend: { + slotRecipes: { + treeView: { + base: { + tree: { gap: "0.5" }, + }, + }, + tabs: { + base: { + root: { height: "full", flexGrow: 1, gap: "1" }, + content: { height: "full", flexGrow: 1, overflow: "auto" }, + }, + compoundVariants: [ + { + size: "md", + variant: "enclosed", + css: { content: { p: "unset" } }, + }, + ], + }, + }, + }, + }, +}); diff --git a/pkgs/ffigenpad/web/park-ui.json b/pkgs/ffigenpad/web/park-ui.json new file mode 100644 index 0000000000..3f03b3ec32 --- /dev/null +++ b/pkgs/ffigenpad/web/park-ui.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://park-ui.com/registry/latest/schema.json", + "jsFramework": "solid", + "outputPath": "./third_party/ui" +} diff --git a/pkgs/ffigenpad/web/postcss.config.cjs b/pkgs/ffigenpad/web/postcss.config.cjs new file mode 100644 index 0000000000..1bfc8f1deb --- /dev/null +++ b/pkgs/ffigenpad/web/postcss.config.cjs @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + "@pandacss/dev/postcss": {}, + }, +}; diff --git a/pkgs/ffigenpad/web/src/App.tsx b/pkgs/ffigenpad/web/src/App.tsx new file mode 100644 index 0000000000..40184eef7d --- /dev/null +++ b/pkgs/ffigenpad/web/src/App.tsx @@ -0,0 +1,186 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import TablerCopy from '~icons/tabler/copy' +import TablerExternalLink from '~icons/tabler/external-link' +import { + createResource, + createSignal, + lazy, + onMount, + Show, + Suspense, +} from "solid-js"; +import { Center, Flex, HStack, Stack } from "styled-system/jsx"; +import * as dart from "../../bin/ffigenpad.mjs"; +import dartWasm from "../../bin/ffigenpad.wasm?url"; +import createLibClang from "../../bin/libclang.mjs"; +import { BindingsViewer } from "./components/bindings-viewer"; +import { ConfigEditor } from "./components/config-editor"; +import { HeaderEditor } from "./components/header-editor"; +import { Navbar } from "./components/navbar"; +import { Button } from "third_party/ui/button"; +import { Spinner } from "third_party/ui/spinner"; +import { Splitter } from "third_party/ui/splitter"; +import { Tabs } from "third_party/ui/tabs"; +import { Text } from "third_party/ui/text"; +import { $bindings } from "./lib/bindings"; +import { $ffigenConfig } from "./lib/ffigen-config"; +import { registerMemFSListeners } from "./lib/filesystem"; +import { $logs } from "./lib/log"; + +const FileExplorer = lazy(() => import("./components/file-explorer")); +const LogsViewer = lazy(() => import("./components/logs-viewer")); + +/** + * Core app which is loaded after all the wasm files are loaded + */ +function FFIGenPad({ ffigenpad }: { ffigenpad: WebAssembly.Instance }) { + const [logs, setLogs] = $logs; + const [ffigenConfig] = $ffigenConfig; + const [bindings, setBindings] = $bindings; + const [loading, setLoading] = createSignal(false); + + registerMemFSListeners(); + + function generate() { + setLoading(true); + // need to wrap in a timeout to show the loading spinner + setTimeout(() => { + setLogs([]); + dart.invoke(ffigenpad, ffigenConfig()); + setBindings(globalThis.FS.readFile("/output.dart", { encoding: "utf8" })); + setLoading(false); + }, 0); + } + + // generate bindings for default settings on load + onMount(generate); + + function copyBindings() { + navigator.clipboard.writeText(bindings()); + } + + return ( + + + + + + }> + + + + Headers + Config + + + + + + + + + + + + + + + + + + + + + + ); +} + +/** + * THE APP + */ +function App() { + const [ffigenpad] = createResource(async () => { + const libclang = await createLibClang(); + globalThis.FS = libclang.FS; + globalThis.addFunction = libclang.addFunction; + globalThis.removeFunction = libclang.removeFunction; + globalThis.setLogs = $logs[1]; + + const module = new WebAssembly.Module( + await (await fetch(dartWasm)).arrayBuffer(), + ); + const instance: WebAssembly.Instance = await dart.instantiate(module, { + ffi: { + malloc: libclang.wasmExports.malloc, + free: libclang.wasmExports.free, + memory: libclang.wasmMemory, + }, + libclang: libclang.wasmExports, + }); + return instance; + }); + + return ( + + + + + + ffigenpad might take some time to load + + + } + > + + + + ); +} + +export default App; diff --git a/pkgs/ffigenpad/web/src/components/bindings-viewer.tsx b/pkgs/ffigenpad/web/src/components/bindings-viewer.tsx new file mode 100644 index 0000000000..93cd0596cc --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/bindings-viewer.tsx @@ -0,0 +1,62 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { StreamLanguage } from "@codemirror/language"; +import { dart } from "@codemirror/legacy-modes/mode/clike"; +import { EditorState } from "@codemirror/state"; +import { basicSetup, EditorView } from "codemirror"; +import { createEffect, onMount } from "solid-js"; +import { Box } from "styled-system/jsx"; +import { $bindings } from "~/lib/bindings"; +import { $theme, editorThemeConfig } from "~/lib/theme"; + +/** + * Displays output generated by ffigen in a read only codemirror editor + */ +export const BindingsViewer = () => { + const [bindings] = $bindings; + + let editorRef: HTMLDivElement; + let editor: EditorView; + + onMount(() => { + editor = new EditorView({ + doc: bindings(), + extensions: [ + basicSetup, + StreamLanguage.define(dart), + editorThemeConfig.of([$theme.editorTheme()]), + EditorView.theme({ + "&": { + height: "100%", + }, + }), + // set readOnly true + EditorState.readOnly.of(true), + ], + parent: editorRef!, + }); + + return () => { + editor.destroy(); + }; + }); + + createEffect(() => { + if (editor) { + // change the content whenever the generated bindings are updated + editor.dispatch({ + changes: { from: 0, to: editor.state.doc.length, insert: bindings() }, + }); + } + }); + + createEffect(() => { + if (editor) { + editor.dispatch($theme.editorThemeTransaction()); + } + }); + + return ; +}; diff --git a/pkgs/ffigenpad/web/src/components/config-editor.tsx b/pkgs/ffigenpad/web/src/components/config-editor.tsx new file mode 100644 index 0000000000..9e5ad232a1 --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/config-editor.tsx @@ -0,0 +1,55 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { yaml } from "@codemirror/lang-yaml"; +import { basicSetup, EditorView } from "codemirror"; +import { createEffect, onMount } from "solid-js"; +import { Box } from "styled-system/jsx"; +import { $ffigenConfig } from "~/lib/ffigen-config"; +import { $theme, editorThemeConfig } from "~/lib/theme"; + +/** + * Codemirror editor used for editing ffigen config yaml file + */ +export const ConfigEditor = () => { + let editorRef: HTMLDivElement; + let editor: EditorView; + + const [ffigenConfig, setFfigenConfig] = $ffigenConfig; + + onMount(() => { + editor = new EditorView({ + doc: ffigenConfig(), + extensions: [ + basicSetup, + yaml(), + EditorView.domEventHandlers({ + // update the config when editor is not in focus to prevent frequent updates + blur: (_, view) => { + setFfigenConfig(view.state.doc.toString()); + }, + }), + editorThemeConfig.of([$theme.editorTheme()]), + EditorView.theme({ + "&": { + height: "100%", + }, + }), + ], + parent: editorRef!, + }); + + return () => { + editor.destroy(); + }; + }); + + createEffect(() => { + if (editor) { + editor.dispatch($theme.editorThemeTransaction()); + } + }); + + return ; +}; diff --git a/pkgs/ffigenpad/web/src/components/file-explorer.tsx b/pkgs/ffigenpad/web/src/components/file-explorer.tsx new file mode 100644 index 0000000000..fac2935ed2 --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/file-explorer.tsx @@ -0,0 +1,373 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { basename, dirname, join } from "pathe"; +import TablerChevronRight from '~icons/tabler/chevron-right' +import TablerFileDots from '~icons/tabler/file-dots' +import TablerFilePlus from '~icons/tabler/file-plus' +import TablerFileUpload from '~icons/tabler/file-upload' +import TablerFolderPlus from '~icons/tabler/folder-plus' +import TablerTrash from '~icons/tabler/trash' +import { createSignal, For, Show } from "solid-js"; +import { Portal } from "solid-js/web"; +import { HStack, Stack } from "styled-system/jsx"; +import { treeView } from "styled-system/recipes"; +import { $filesystem, type FSNode } from "~/lib/filesystem"; +import { Button } from "third_party/ui/button"; +import { Dialog } from "third_party/ui/dialog"; +import { Drawer } from "third_party/ui/drawer"; +import { Editable } from "third_party/ui/editable"; +import { FileUpload } from "third_party/ui/file-upload"; +import { IconButton } from "third_party/ui/icon-button"; +import { Input } from "third_party/ui/input"; +import * as StyledTreeView from "third_party/ui/styled/tree-view"; +import { Text } from "third_party/ui/text"; + +// need to include recipe to add styles for some reason +treeView(); + +/** + * Displays MemFS files located at /home/web_user as file tree with the ability + * to create, rename, delete files and folders + */ +const FileTree = () => { + const { fileTree, helpers } = $filesystem; + const [_, setSelectedFile] = $filesystem.selectedFile; + + // adds a file with the default name as 'file*.h' + const addFile = (parentPathParts: string[], content = "") => { + // get the contents of the folder where the files is being created + const parentContents = helpers.getNode(parentPathParts) as FSNode; + // find possible default name for new file + let i = 1; + while (`file${i}.h` in parentContents) i++; + const name = `file${i}.h`; + globalThis.FS.writeFile( + join("/home/web_user", ...parentPathParts, name), + content, + ); + }; + + // adds a folder with the default name as 'file*.h' + const addFolder = (parentPathParts: string[]) => { + // get the contents of the parent folder + const parentContents = helpers.getNode(parentPathParts) as FSNode; + // find possible default name for new folder + let i = 1; + while (`folder${i}` in parentContents) i++; + const name = `folder${i}`; + globalThis.FS.mkdir(join("/home/web_user", ...parentPathParts, name)); + }; + + const deleteFile = (filePath: string) => { + globalThis.FS.unlink(join("/home/web_user", filePath)); + }; + + // recursively deleted child files and folders + const deleteFolder = (folderPath: string) => { + // get the contents of the folder being deleted + const contents = globalThis.FS.readdir( + join("/home/web_user", folderPath), + ).slice(2); + // recursively delete all content in the folder so it is empty + for (const node of contents) { + const treeValue = `${folderPath}/${node}`; + const mode = globalThis.FS.stat(join("/home/web_user/", treeValue)).mode; + if (globalThis.FS.isFile(mode)) { + deleteFile(treeValue); + } else if (globalThis.FS.isDir(mode)) { + deleteFolder(treeValue); + } + } + // finally remove the empty folder + globalThis.FS.rmdir(join("/home/web_user", folderPath)); + }; + + // renames a file or a folder + const renameEntity = (oldPath: string, newName: string) => { + globalThis.FS.rename( + join("/home/web_user", oldPath), + join("/home/web_user", dirname(oldPath), newName), + ); + }; + + /** + * + * @param node Object in the fileTree represented as a [key, value] array + * @param parentPathParts array of names of parent nodes + */ + const renderNode = ( + node: [string, FSNode | string], + parentPathParts: string[], + ) => { + const [name, children] = node; + // ensures that all values are relative + const pathParts = + name === "/home/web_user" ? [] : [...parentPathParts, name]; + // it is path relative to /home/web_user in MemFS + const path = pathParts.join("/"); + + return ( + + + renameEntity(path, value)} + > + + + ( + + )} + /> + + + + + deleteFile(path)} + > + + + + } + > + {/* rendered when node is a folder and children is an object */} + + + + + + + renameEntity(path, value)} + > + + + ( + + )} + /> + + + + + addFile(pathParts)} + > + + + addFolder(pathParts)} + > + + + deleteFolder(path)} + > + + + + + + + {(child) => renderNode(child, pathParts)} + + + + + ); + }; + + return ( + { + // only open file in editor if the filename ends with .h + if (selectedValue[0].endsWith(".h")) { + setSelectedFile(`/home/web_user/${selectedValue[0]}`); + } + }} + > + + {/* /home/web_user should be used as the base for the tree */} + + {(child) => renderNode(child, [])} + + + + ); +}; + +/* + * A dialog box to upload multiple files from user at once to a specific directory + */ +function UploadFiles() { + const [files, setFiles] = createSignal([]); + const [directory, setDirectory] = createSignal(""); + const [isLoading, setIsLoading] = createSignal(false); + + async function onConfirm() { + setIsLoading(true); + const directoryParts = directory() + .split("/") + .filter((p) => p.trim() !== ""); + let parentPath = "/home/web_user"; + + for (const folder of directoryParts) { + parentPath = join(parentPath, folder); + globalThis.FS.mkdir(parentPath); + } + + for (const file of files()) { + const filePath = join(parentPath, file.name); + globalThis.FS.writeFile(filePath, ""); + globalThis.FS.writeFile(filePath, await file.text()); + } + setIsLoading(false); + } + + return ( + + ( + + )} + /> + + + + + setFiles(files)} + > + + Drop your header files here + ( + + )} + /> + + + + {(fileUpload) => ( + + {(file) => ( + + + + ( + + + + )} + /> + + )} + + )} + + + + + + /home/web_user/ + setDirectory(e.target.value)} + value={directory()} + /> + + + ( + + )} + /> + + + + + + + ); +} + +/** + * Drawer that handles emscripten's MemFS filesystem as a tree + */ +const FileExplorer = () => { + const [selectedFile] = $filesystem.selectedFile; + return ( + + ( + + )} + /> + + + + + Virtual FileSystem + + tip: double click to rename + + + + + + + + + + + + + ); +}; + +export default FileExplorer; diff --git a/pkgs/ffigenpad/web/src/components/header-editor.tsx b/pkgs/ffigenpad/web/src/components/header-editor.tsx new file mode 100644 index 0000000000..668250a9ea --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/header-editor.tsx @@ -0,0 +1,72 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { cpp } from "@codemirror/lang-cpp"; +import { basicSetup, EditorView } from "codemirror"; +import { createEffect, onMount } from "solid-js"; +import { Box } from "styled-system/jsx"; +import { $filesystem } from "~/lib/filesystem"; +import { $theme, editorThemeConfig } from "~/lib/theme"; + +/** + * Codemirror editor for header files, modifying the file that is currently selected + */ +export const HeaderEditor = () => { + let editorRef: HTMLDivElement; + let editor: EditorView; + + const [selectedFile] = $filesystem.selectedFile; + + /** + * file content of the selected file read from MemFS + */ + const selectedFileContent = () => + globalThis.FS.readFile(selectedFile(), { encoding: "utf8" }); + + onMount(() => { + editor = new EditorView({ + doc: selectedFileContent(), + extensions: [ + basicSetup, + cpp(), + EditorView.domEventHandlers({ + // write to MemFS file on editor blur to prevent frequent updates + blur: (_, view) => { + globalThis.FS.writeFile(selectedFile(), view.state.doc.toString()); + }, + }), + editorThemeConfig.of([$theme.editorTheme()]), + EditorView.theme({ + "&": { + height: "100%", + }, + }), + ], + parent: editorRef!, + }); + + return () => { + editor.destroy(); + }; + }); + + createEffect(() => { + if (editor) { + // update the editor content whenever a new file is selected. + editor.dispatch({ + changes: { + from: 0, + to: editor.state.doc.length, + insert: selectedFileContent(), + }, + }); + } + }); + + createEffect(() => { + if (editor) editor.dispatch($theme.editorThemeTransaction()); + }); + + return ; +}; diff --git a/pkgs/ffigenpad/web/src/components/logs-viewer.tsx b/pkgs/ffigenpad/web/src/components/logs-viewer.tsx new file mode 100644 index 0000000000..6d79c1cfa3 --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/logs-viewer.tsx @@ -0,0 +1,98 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import { createSignal, For } from "solid-js"; +import { $logs } from "~/lib/log"; +import { Select } from "third_party/ui/select"; +import { Table } from "third_party/ui/table"; +import TablerSelector from '~icons/tabler/selector' + +/** + * level and label pairs as defined by package:logging in dart + */ +const loggingLevels: [number, string][] = [ + [0, "ALL"], + [3, "FINEST"], + [4, "FINER"], + [5, "FINE"], + [7, "CONFIG"], + [8, "INFO"], + [9, "WARNING"], + [10, "SEVERE"], +]; + +const levelLabelMap = new Map(loggingLevels); + +/** + *Dropdown select to set filter for the logs displayed + */ +const LevelSelect = (props: { + level: number; + onLevelChange: (level: number) => void; +}) => { + return ( + item[0].toString()} + itemToString={(item) => item[1]} + onValueChange={({ value }) => { + props.onLevelChange(parseInt(value[0])); + }} + > + + + + + + + + + + {(item) => ( + + {item[1]} + + )} + + + + + ); +}; + +const LogsViewer = () => { + const [logs] = $logs; + + // set default log level to INFO + const [levelFilter, setLevelFilter] = createSignal(8); + const filteredLogs = () => + logs().filter(({ level }) => level >= levelFilter()); + + return ( + + + + + + + Message + + + + + {(log) => ( + + {levelLabelMap.get(log.level)} + {log.message} + + )} + + + + ); +}; + +export default LogsViewer; diff --git a/pkgs/ffigenpad/web/src/components/navbar.tsx b/pkgs/ffigenpad/web/src/components/navbar.tsx new file mode 100644 index 0000000000..c8b2ce3282 --- /dev/null +++ b/pkgs/ffigenpad/web/src/components/navbar.tsx @@ -0,0 +1,76 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import TablerBrandGithub from '~icons/tabler/brand-github' +import TablerBug from '~icons/tabler/bug' +import TablerMoon from '~icons/tabler/moon' +import TablerSun from '~icons/tabler/sun' + +import { Show } from "solid-js"; +import { Divider, HStack } from "styled-system/jsx"; +import { $theme } from "~/lib/theme"; +import { Badge } from "third_party/ui/badge"; +import { Button } from "third_party/ui/button"; +import { Heading } from "third_party/ui/heading"; +import { IconButton } from "third_party/ui/icon-button"; + +/* + * Button that switches the theme + */ +const ThemeSwitcher = () => { + const [darkMode, setDarkMode] = $theme.darkMode; + + return ( + setDarkMode((x) => !x)} variant="ghost"> + }> + + + + ); +}; + +export const Navbar = () => { + return ( + + + + FFIgenPad + + ffigen 14.0.0-wip + libclang 18.1.8 + + +