Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make indentation in buffers composable #162

Merged
merged 12 commits into from
Feb 22, 2024
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
npm install
npm run test

- name: Run Integration Tests
run: |
npm install
npm run test:integration
# - name: Run Integration Tests
# run: |
# npm install
# npm run test:integration
10 changes: 3 additions & 7 deletions lib/components/enum.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,9 @@ const { normalise } = require('./identifier')
function printEnum(buffer, name, kvs, options = {}) {
const opts = {...{export: true}, ...options}
buffer.add('// enum')
buffer.add(`${opts.export ? 'export ' : ''}const ${name} = {`)
buffer.indent()
for (const [k, v] of kvs) {
buffer.add(`${normalise(k)}: ${v},`)
}
buffer.outdent()
buffer.add('} as const;')
buffer.addIndentedBlock(`${opts.export ? 'export ' : ''}const ${name} = {`, () =>
kvs.forEach(([k, v]) => buffer.add(`${normalise(k)}: ${v},`))
, '} as const;')
buffer.add(`${opts.export ? 'export ' : ''}type ${name} = ${stringifyEnumType(kvs)}`)
buffer.add('')
}
Expand Down
4 changes: 3 additions & 1 deletion lib/csn.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,12 @@ function amendCSN(csn) {
*/
const isView = entity => entity.query && !entity.projection

const isDraftEnabled = entity => entity['@odata.draft.enabled'] === true

/**
* @see isView
* Unresolved entities have to be looked up from inferred csn.
*/
const isUnresolved = entity => entity._unresolved === true

module.exports = { amendCSN, isView, isUnresolved, propagateForeignKeys }
module.exports = { amendCSN, isView, isDraftEnabled, isUnresolved, propagateForeignKeys }
65 changes: 64 additions & 1 deletion lib/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,13 @@ class Library extends File {
* Source file containing several buffers.
*/
class SourceFile extends File {
/**
* @param {string | Path} path
*/
constructor(path) {
super()
/** @type {Path} */
this.path = new Path(path.split('.'))
this.path = path instanceof Path ? path : new Path(path.split('.'))
/** @type {Object} */
this.imports = {}
/** @type {Buffer} */
Expand Down Expand Up @@ -480,6 +483,33 @@ class Buffer {
add(part) {
this.parts.push(this.currentIndent + part)
}

/**
* Adds an element to the buffer with one level of indent.
* @param {string | (() => void)} part either a string or a function. If it is a string, it is added to the buffer.
* If not, it is expected to be a function that manipulates the buffer as a side effect.
*/
addIndented(part) {
this.indent()
if (typeof part === 'function') {
part()
} else if (Array.isArray(part)) {
part.forEach(p => this.add(p))
}
this.outdent()
}

/**
* Adds an element to a buffer with one level of indent and and opener and closer surrounding it.
* @param {string} opener the string to put before the indent
* @param {string} content the content to indent (see {@link addIndented})
* @param {string} closer the string to put after the indent
*/
addIndentedBlock(opener, content, closer) {
this.add(opener)
this.addIndented(content)
this.add(closer)
}
}

/**
Expand Down Expand Up @@ -548,6 +578,38 @@ class Path {
}
}

// TODO: having the repository pattern in place we can separate (some of) the printing logic from the visitor.
// Most of it hinges primarily on resolving specific files. We can now pass the repository and the resolver to a printer.
class FileRepository {
#files = {}

/**
* @param {string} name
* @param {SourceFile} file
*/
add(name, file) {
this.#files[name] = file
}

/**
* Determines the file corresponding to the namespace.
* If no such file exists yet, it is created first.
* @param {string | Path} path the name of the namespace (foo.bar.baz)
* @returns {SourceFile} the file corresponding to that namespace name
*/
getNamespaceFile(path) {
const key = path instanceof Path ? path.asNamespace() : path
return (this.#files[key] ??= new SourceFile(path))
}

/**
* @returns {SourceFile[]}
*/
getFiles() {
return Object.values(this.#files)
}
}

/**
* Base definitions used throughout the typing process,
* such as Associations and Compositions.
Expand Down Expand Up @@ -618,6 +680,7 @@ module.exports = {
Library,
Buffer,
File,
FileRepository,
SourceFile,
Path,
writeout,
Expand Down
Loading
Loading