Skip to content

Commit

Permalink
feature: goldstein: keyword-export-no-const: add
Browse files Browse the repository at this point in the history
  • Loading branch information
coderaiser committed Dec 12, 2024
1 parent f86a939 commit 01d6d6f
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,19 @@ The same as:
const a = require('a');
```

### Export without `const`

```gs
export x = () => {};
```

The same as:

```js
export const x = () => {};
```


## How to contribute?

Clone the registry, create a new keyword with a prefix `keyword-`, then create directory `fixture` and put there two files with extensions `.js` and `.gs`. Half way done 🥳!
Expand Down
14 changes: 14 additions & 0 deletions packages/goldstein/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,17 @@ test('goldstein: compile: missing comma', (t) => {
t.equal(result, expected);
t.end();
});

test('goldstein: compile: export-no-const', (t) => {
const source = montag`
export x = () => {};
`;

const result = compile(source);
const expected = montag`
export const x = () => {};\n
`;

t.equal(result, expected);
t.end();
});
2 changes: 2 additions & 0 deletions packages/goldstein/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import keywordUselessSemicolon from '../keyword-useless-semicolon/index.js';
import keywordAssignFrom from '../keyword-assign-from/index.js';
import internalParseMaybeAssign from '../internal-parse-maybe-assign/index.js';
import operatorSafeAssignment from '../operator-safe-assignment/index.js';
import keywordExportNoConst from '../keyword-export-no-const/index.js';

const {values} = Object;

Expand All @@ -41,6 +42,7 @@ const defaultKeywords = {
keywordUselessComma,
keywordUselessSemicolon,
keywordAssignFrom,
keywordExportNoConst,
operatorSafeAssignment,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export x = () => {};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const x = () => {};
88 changes: 88 additions & 0 deletions packages/keyword-export-no-const/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {types} from 'putout';
import {tokTypes as tt} from '../operator/index.js';

const {
VariableDeclaration,
VariableDeclarator,
} = types;

export default function keywordExportNoConst(Parser) {
return class extends Parser {
shouldParseExportStatement() {
if (!this.type.keyword)
return true;

return super.shouldParseExportStatement();
}

parseExport(node, exports) {
this.next();

/* c8 ignore start */
// export * from '...'
if (this.eat(tt.star))
return this.parseExportAllDeclaration(node, exports);
/* c8 ignore end */

/* c8 ignore start */
if (this.eat(tt._default)) {
// export default ...
this.checkExport(exports, 'default', this.lastTokStart);
node.declaration = this.parseExportDefaultDeclaration();

return this.finishNode(node, 'ExportDefaultDeclaration');
}

/* c8 ignore end */
// export var|const|let|function|class ...
if (this.shouldParseExportStatement()) {
node.declaration = this.parseExportDeclaration(node);

if (node.declaration.type === 'VariableDeclaration')
this.checkVariableExport(exports, node.declaration.declarations);

if (node.declaration.type === 'ExpressionStatement')
node.declaration = VariableDeclaration('const', [
VariableDeclarator(node.declaration.expression.left, node.declaration.expression.right),
]);
else
this.checkExport(exports, node.declaration.id, node.declaration.id.start);

node.specifiers = [];
node.source = null;
} else {
// export { x, y as z } [from '...']
node.declaration = null;
node.specifiers = this.parseExportSpecifiers(exports);

if (this.eatContextual('from')) {
if (this.type !== tt.string)
this.unexpected();

node.source = this.parseExprAtom();

if (this.options.ecmaVersion >= 16)
node.attributes = this.parseWithClause();
} else {
for (let i = 0, list = node.specifiers; i < list.length; ++i) {
// check for keywords used as local names
const spec = list[i];

this.checkUnreserved(spec.local);
// check if export is defined
this.checkLocalExport(spec.local);

if (spec.local.type === 'Literal')
this.raise(spec.local.start, 'A string literal cannot be used as an exported binding without `from`.');
}

node.source = null;
}

this.semicolon();
}

return this.finishNode(node, 'ExportNamedDeclaration');
}
};
}
9 changes: 9 additions & 0 deletions packages/keyword-export-no-const/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {createTest} from '../test/index.js';
import keywordExportNoConst from './index.js';

const test = createTest(import.meta.url, keywordExportNoConst);

test('goldstein: keyword: export-no-const', (t) => {
t.compile('export-no-const');
t.end();
});

0 comments on commit 01d6d6f

Please sign in to comment.