Home > database >  How to see the value of a top level empty getter without running the code in Swift?
How to see the value of a top level empty getter without running the code in Swift?

Time:06-08

public var O_RDONLY: Int32 { get }

When I'm looking at stuff inside Darwin.sys.* or Darwin.POSIX.* for example, a lot of these constants are defined as getters. But how does one see the actual value without evaluating the code?

CodePudding user response:

public var O_RDONLY: Int32 { get }

is what the Swift importer generates from the macro definition

#define O_RDONLY        0x0000          /* open for reading only */

in the <sys/fcntl.h> include file. Although this is a fixed value, known at compile time, the Swift importer does not show the value in the generated Swift interface.

Note also that a macro definition in a C header file may depend on other macros, and on other “variables” such as compiler flags, the processor architecture, etc.

I am not aware of a way to navigate to that C definition from a Swift file, or any other way to show the defined value in a pure Swift project. As a workaround, one can

  • add a C file to the project,
  • use the macro in some C function, and
  • “jump to definition” from there.

CodePudding user response:

I ended up with the following solution:

const fs = require('fs');
const { exec } = require("child_process");

const getterRegEx = /^(.*)public var (. ): (. ) { get }(.*)$/;

const code = String(fs.readFileSync('./generatedSwift.swift'));

const lines = code.split('\n').map((line, i) => {
  const arr = getterRegEx.exec(line);
  if (arr) {
    const [all, prefix, constant, type, suffix] = arr;
    return `print("let ${constant}: ${type} = ", ${constant}, separator: "")`;
  }
  return `print("""\n${line}\n""")`;
});
lines.unshift('import Foundation');

fs.writeFileSync('./regeneratedSwift.swift', lines.join('\n'));

exec('swift ./regeneratedSwift.swift', (err, stdout, stderr) => {
  if (err) {
    console.error(`exec error: ${err}`);
    return;
  }
  if (stderr) {
    console.log(`stderr: ${stderr}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
});

Copy definitions generated by the XCode and save into a file named generatedSwift.swift the run node index.js in the same folder.

The output will contain the Swift code where all public var Constant: Type { get } are replaced with let Constant = Value and all other lines will remain the same.

  • Related