123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import _ from 'lodash';
- const schema = [
- {
- enum: ['always', 'always-multiline', 'only-multiline', 'never'],
- type: 'string',
- },
- {
- enum: ['always', 'always-multiline', 'only-multiline', 'never'],
- type: 'string',
- },
- {
- enum: ['always', 'always-multiline', 'only-multiline', 'never'],
- type: 'string',
- },
- ];
- // required for reporting the correct position
- const getLast = (property, indexer) => {
- if (!property) {
- return indexer;
- }
- if (!indexer) {
- return property;
- }
- if (property.loc.end.line > indexer.loc.end.line) {
- return property;
- }
- if (indexer.loc.end.line > property.loc.end.line) {
- return indexer;
- }
- if (property.loc.end.column > indexer.loc.end.column) {
- return property;
- }
- return indexer;
- };
- const create = (context) => {
- const option = context.options[0] || 'never';
- const interfaceOption = context.options[1] || option;
- const inexactNotationOption = context.options[2] || 'never';
- const sourceCode = context.getSourceCode();
- const getNodeOption = (node) => {
- if (node.parent.type === 'InterfaceDeclaration') {
- return interfaceOption;
- }
- if (node.inexact) {
- return inexactNotationOption;
- }
- return option;
- };
- const reporter = (node, message, fix) => () => {
- context.report({
- fix,
- message,
- node,
- });
- };
- const makeReporters = (node, tokenToFix) => ({
- dangle: reporter(node, 'Unexpected trailing delimiter', (fixer) => fixer.replaceText(tokenToFix, '')),
- noDangle: reporter(node, 'Missing trailing delimiter', (fixer) => fixer.insertTextAfter(tokenToFix, ',')),
- });
- const evaluate = (node, lastChildNode) => {
- if (!lastChildNode && !node.inexact) {
- return;
- }
- const [penultimateToken, lastToken] = sourceCode.getLastTokens(node, 2);
- const isDangling = [';', ','].includes(penultimateToken.value);
- const isMultiLine = penultimateToken.loc.start.line !== lastToken.loc.start.line;
- // Use the object node if it's inexact since there's no child node for the inexact notation
- const report = makeReporters(node.inexact ? node : lastChildNode, penultimateToken);
- const nodeOption = getNodeOption(node);
- if (nodeOption === 'always' && !isDangling) {
- report.noDangle();
- return;
- }
- if (nodeOption === 'never' && isDangling) {
- report.dangle();
- return;
- }
- if (nodeOption === 'always-multiline' && !isDangling && isMultiLine) {
- report.noDangle();
- return;
- }
- if (nodeOption === 'always-multiline' && isDangling && !isMultiLine) {
- report.dangle();
- return;
- }
- if (nodeOption === 'only-multiline' && isDangling && !isMultiLine) {
- report.dangle();
- }
- };
- return {
- ObjectTypeAnnotation(node) {
- evaluate(node, getLast(_.last(node.properties), _.last(node.indexers)));
- },
- TupleTypeAnnotation(node) {
- evaluate(node, _.last(node.types));
- },
- };
- };
- export default {
- create,
- meta: {
- fixable: 'code',
- },
- schema,
- };
|