Skip to content

Commit

Permalink
feat: Improve error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
pnevyk committed Oct 5, 2017
1 parent 687f82b commit b95dd31
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 43 deletions.
54 changes: 42 additions & 12 deletions src/rules/arrayStyle/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,71 @@ const schema = [
}
];

const fixShorthand = (context, node) => {
const fixShorthand = (node, type) => {
return (fixer) => {
const rawElementType = context.getSourceCode().getText(node.elementType);

return fixer.replaceText(node, 'Array<' + rawElementType + '>');
return fixer.replaceText(node, 'Array<' + type + '>');
};
};

const fixVerbose = (context, node) => {
const fixVerbose = (node, type, elementTypeNode) => {
return (fixer) => {
const elementTypeNode = node.typeParameters.params[0];
const rawElementType = context.getSourceCode().getText(elementTypeNode);

if (needWrap(elementTypeNode)) {
return fixer.replaceText(node, '(' + rawElementType + ')[]');
return fixer.replaceText(node, '(' + type + ')[]');
} else {
return fixer.replaceText(node, rawElementType + '[]');
return fixer.replaceText(node, type + '[]');
}
};
};

const inlineType = (type) => {
const inlined = type.replace(/\s+/g, ' ');

if (inlined.length <= 50) {
return inlined;
} else {
return 'Type';
}
};

export default (defaultConfig, shorthandHandler, verboseHandler) => {
const create = (context) => {
const verbose = (context.options[0] || defaultConfig) === 'verbose';

return {
// shorthand
ArrayTypeAnnotation (node) {
shorthandHandler(isSimpleType(node.elementType), verbose, context, node, fixShorthand(context, node));
const rawElementType = context.getSourceCode().getText(node.elementType);
const inlinedType = inlineType(rawElementType);
const wrappedInlinedType = needWrap(node.elementType) ? '(' + inlinedType + ')' : inlinedType;

shorthandHandler(
isSimpleType(node.elementType),
verbose,
context,
node,
fixShorthand(node, rawElementType),
inlinedType,
wrappedInlinedType
);
},
// verbose
GenericTypeAnnotation (node) {
if (node.id.name === 'Array') {
if (node.typeParameters.params.length === 1) {
verboseHandler(isSimpleType(node.typeParameters.params[0]), verbose, context, node, fixVerbose(context, node));
const elementTypeNode = node.typeParameters.params[0];
const rawElementType = context.getSourceCode().getText(elementTypeNode);
const inlinedType = inlineType(rawElementType);
const wrappedInlinedType = needWrap(elementTypeNode) ? '(' + inlinedType + ')' : inlinedType;

verboseHandler(
isSimpleType(elementTypeNode),
verbose,
context,
node,
fixVerbose(node, rawElementType, elementTypeNode),
inlinedType,
wrappedInlinedType
);
}
}
}
Expand Down
16 changes: 12 additions & 4 deletions src/rules/arrayStyleComplexType.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import makeArrayStyleRule from './arrayStyle';

const shorthandHandler = (isSimpleType, verbose, context, node, fix) => {
const shorthandHandler = (isSimpleType, verbose, context, node, fix, inlinedType, wrappedInlinedType) => {
if (!isSimpleType && verbose) {
context.report({
data: {
type: inlinedType,
wrappedType: wrappedInlinedType
},
fix,
message: 'Use "Array<ComplexType>", not "ComplexType[]"',
message: 'Use "Array<{{ type }}>", not "{{ wrappedType }}[]"',
node
});
}
};

const verboseHandler = (isSimpleType, verbose, context, node, fix) => {
const verboseHandler = (isSimpleType, verbose, context, node, fix, inlinedType, wrappedInlinedType) => {
if (!isSimpleType && !verbose) {
context.report({
data: {
type: inlinedType,
wrappedType: wrappedInlinedType
},
fix,
message: 'Use "ComplexType[]", not "Array<ComplexType>"',
message: 'Use "{{ wrappedType }}[]", not "Array<{{ type }}>"',
node
});
}
Expand Down
16 changes: 12 additions & 4 deletions src/rules/arrayStyleSimpleType.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import makeArrayStyleRule from './arrayStyle';

const shorthandHandler = (isSimpleType, verbose, context, node, fix) => {
const shorthandHandler = (isSimpleType, verbose, context, node, fix, inlinedType, wrappedInlinedType) => {
if (isSimpleType && verbose) {
context.report({
data: {
type: inlinedType,
wrappedType: wrappedInlinedType
},
fix,
message: 'Use "Array<SimpleType>", not "SimpleType[]"',
message: 'Use "Array<{{ type }}>", not "{{ wrappedType }}[]"',
node
});
}
};

const verboseHandler = (isSimpleType, verbose, context, node, fix) => {
const verboseHandler = (isSimpleType, verbose, context, node, fix, inlinedType, wrappedInlinedType) => {
if (isSimpleType && !verbose) {
context.report({
data: {
type: inlinedType,
wrappedType: wrappedInlinedType
},
fix,
message: 'Use "SimpleType[]", not "Array<SimpleType>"',
message: 'Use "{{ wrappedType }}[]", not "Array<{{ type }}>"',
node
});
}
Expand Down
28 changes: 19 additions & 9 deletions tests/rules/assertions/arrayStyleComplexType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,61 @@ export default {
invalid: [
{
code: 'type X = (?string)[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<?string>", not "(?string)[]"'}],
output: 'type X = Array<?string>'
},
{
code: 'type X = (?string)[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<?string>", not "(?string)[]"'}],
options: ['verbose'],
output: 'type X = Array<?string>'
},
{
code: 'type X = Array<?string>',
errors: [{message: 'Use "ComplexType[]", not "Array<ComplexType>"'}],
errors: [{message: 'Use "(?string)[]", not "Array<?string>"'}],
options: ['shorthand'],
output: 'type X = (?string)[]'
},
{
code: 'type X = Array<{foo: string}>',
errors: [{message: 'Use "ComplexType[]", not "Array<ComplexType>"'}],
errors: [{message: 'Use "{foo: string}[]", not "Array<{foo: string}>"'}],
options: ['shorthand'],
output: 'type X = {foo: string}[]'
},
{
code: 'type X = (string | number)[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<string | number>", not "(string | number)[]"'}],
output: 'type X = Array<string | number>'
},
{
code: 'type X = (string & number)[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<string & number>", not "(string & number)[]"'}],
output: 'type X = Array<string & number>'
},
{
code: 'type X = [string, number][]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<[string, number]>", not "[string, number][]"'}],
output: 'type X = Array<[string, number]>'
},
{
code: 'type X = {foo: string}[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<{foo: string}>", not "{foo: string}[]"'}],
output: 'type X = Array<{foo: string}>'
},
{
code: 'type X = (string => number)[]',
errors: [{message: 'Use "Array<ComplexType>", not "ComplexType[]"'}],
errors: [{message: 'Use "Array<string => number>", not "(string => number)[]"'}],
output: 'type X = Array<string => number>'
},
{
code: 'type X = {\n foo: string,\n bar: number\n}[]',
errors: [{message: 'Use "Array<{ foo: string, bar: number }>", not "{ foo: string, bar: number }[]"'}],
output: 'type X = Array<{\n foo: string,\n bar: number\n}>'
},
{
code: 'type X = {\n foo: string,\n bar: number,\n quo: boolean,\n hey: Date\n}[]',
errors: [{message: 'Use "Array<Type>", not "Type[]"'}],
output: 'type X = Array<{\n foo: string,\n bar: number,\n quo: boolean,\n hey: Date\n}>'
}
],
misconfigured: [
Expand Down
38 changes: 24 additions & 14 deletions tests/rules/assertions/arrayStyleSimpleType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,72 @@ export default {
invalid: [
{
code: 'type X = string[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<string>", not "string[]"'}],
output: 'type X = Array<string>'
},
{
code: 'type X = string[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<string>", not "string[]"'}],
options: ['verbose'],
output: 'type X = Array<string>'
},
{
code: 'type X = Array<string>',
errors: [{message: 'Use "SimpleType[]", not "Array<SimpleType>"'}],
errors: [{message: 'Use "string[]", not "Array<string>"'}],
options: ['shorthand'],
output: 'type X = string[]'
},
{
code: 'type X = Date[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<Date>", not "Date[]"'}],
output: 'type X = Array<Date>'
},
{
code: 'type X = Promise<string>[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<Promise<string>>", not "Promise<string>[]"'}],
output: 'type X = Array<Promise<string>>'
},
{
code: 'type X = $Keys<{ foo: string }>[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
output: 'type X = Array<$Keys<{ foo: string }>>'
code: 'type X = $Keys<{foo: string}>[]',
errors: [{message: 'Use "Array<$Keys<{foo: string}>>", not "$Keys<{foo: string}>[]"'}],
output: 'type X = Array<$Keys<{foo: string}>>'
},
{
code: 'type X = any[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<any>", not "any[]"'}],
output: 'type X = Array<any>'
},
{
code: 'type X = mixed[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<mixed>", not "mixed[]"'}],
output: 'type X = Array<mixed>'
},
{
code: 'type X = void[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<void>", not "void[]"'}],
output: 'type X = Array<void>'
},
{
code: 'type X = null[]',
errors: [{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}],
errors: [{message: 'Use "Array<null>", not "null[]"'}],
output: 'type X = Array<null>'
},
{
code: 'type X = string[][]',
errors: [
{message: 'Use "Array<SimpleType>", not "SimpleType[]"'},
{message: 'Use "Array<SimpleType>", not "SimpleType[]"'}
{message: 'Use "Array<string[]>", not "string[][]"'},
{message: 'Use "Array<string>", not "string[]"'}
]
},
{
code: 'type X = Promise<{\n foo: string,\n bar: number\n}>[]',
errors: [{message: 'Use "Array<Promise<{ foo: string, bar: number }>>", not "Promise<{ foo: string, bar: number }>[]"'}],
output: 'type X = Array<Promise<{\n foo: string,\n bar: number\n}>>'
},
{
code: 'type X = Promise<{\n foo: string,\n bar: number,\n quo: boolean\n}>[]',
errors: [{message: 'Use "Array<Type>", not "Type[]"'}],
output: 'type X = Array<Promise<{\n foo: string,\n bar: number,\n quo: boolean\n}>>'
}
],
misconfigured: [
Expand Down

0 comments on commit b95dd31

Please sign in to comment.