mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-21 05:52:41 +08:00
refactor(@schematics/angular): remove unused json utils
This commit is contained in:
parent
93e2438954
commit
621f15aa18
@ -1,231 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
import {
|
|
||||||
JsonAstArray,
|
|
||||||
JsonAstKeyValue,
|
|
||||||
JsonAstNode,
|
|
||||||
JsonAstObject,
|
|
||||||
JsonValue,
|
|
||||||
} from '@angular-devkit/core';
|
|
||||||
import { UpdateRecorder } from '@angular-devkit/schematics';
|
|
||||||
|
|
||||||
export function appendPropertyInAstObject(
|
|
||||||
recorder: UpdateRecorder,
|
|
||||||
node: JsonAstObject,
|
|
||||||
propertyName: string,
|
|
||||||
value: JsonValue,
|
|
||||||
indent: number,
|
|
||||||
) {
|
|
||||||
const indentStr = _buildIndent(indent);
|
|
||||||
let index = node.start.offset + 1;
|
|
||||||
if (node.properties.length > 0) {
|
|
||||||
// Insert comma.
|
|
||||||
const last = node.properties[node.properties.length - 1];
|
|
||||||
const { text, end } = last;
|
|
||||||
const commaIndex = text.endsWith('\n') ? end.offset - 1 : end.offset;
|
|
||||||
recorder.insertRight(commaIndex, ',');
|
|
||||||
index = end.offset;
|
|
||||||
}
|
|
||||||
const content = _stringifyContent(value, indentStr);
|
|
||||||
recorder.insertRight(
|
|
||||||
index,
|
|
||||||
(node.properties.length === 0 && indent ? '\n' : '')
|
|
||||||
+ ' '.repeat(indent)
|
|
||||||
+ `"${propertyName}":${indent ? ' ' : ''}${content}`
|
|
||||||
+ indentStr.slice(0, -indent),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function insertPropertyInAstObjectInOrder(
|
|
||||||
recorder: UpdateRecorder,
|
|
||||||
node: JsonAstObject,
|
|
||||||
propertyName: string,
|
|
||||||
value: JsonValue,
|
|
||||||
indent: number,
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (node.properties.length === 0) {
|
|
||||||
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find insertion info.
|
|
||||||
let insertAfterProp: JsonAstKeyValue | null = null;
|
|
||||||
let prev: JsonAstKeyValue | null = null;
|
|
||||||
let isLastProp = false;
|
|
||||||
const last = node.properties[node.properties.length - 1];
|
|
||||||
for (const prop of node.properties) {
|
|
||||||
if (prop.key.value > propertyName) {
|
|
||||||
if (prev) {
|
|
||||||
insertAfterProp = prev;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (prop === last) {
|
|
||||||
isLastProp = true;
|
|
||||||
insertAfterProp = last;
|
|
||||||
}
|
|
||||||
prev = prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLastProp) {
|
|
||||||
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const indentStr = _buildIndent(indent);
|
|
||||||
const insertIndex = insertAfterProp === null
|
|
||||||
? node.start.offset + 1
|
|
||||||
: insertAfterProp.end.offset + 1;
|
|
||||||
const content = _stringifyContent(value, indentStr);
|
|
||||||
recorder.insertRight(
|
|
||||||
insertIndex,
|
|
||||||
indentStr
|
|
||||||
+ `"${propertyName}":${indent ? ' ' : ''}${content}`
|
|
||||||
+ ',',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removePropertyInAstObject(
|
|
||||||
recorder: UpdateRecorder,
|
|
||||||
node: JsonAstObject,
|
|
||||||
propertyName: string,
|
|
||||||
) {
|
|
||||||
// Find the property inside the object.
|
|
||||||
const propIdx = node.properties.findIndex(prop => prop.key.value === propertyName);
|
|
||||||
|
|
||||||
if (propIdx === -1) {
|
|
||||||
// There's nothing to remove.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.properties.length === 1) {
|
|
||||||
// This is a special case. Everything should be removed, including indentation.
|
|
||||||
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
|
|
||||||
recorder.insertRight(node.start.offset, '{}');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The AST considers commas and indentation to be part of the preceding property.
|
|
||||||
// To get around messy comma and identation management, we can work over the range between
|
|
||||||
// two properties instead.
|
|
||||||
const previousProp = node.properties[propIdx - 1];
|
|
||||||
const targetProp = node.properties[propIdx];
|
|
||||||
const nextProp = node.properties[propIdx + 1];
|
|
||||||
|
|
||||||
let start, end;
|
|
||||||
if (previousProp) {
|
|
||||||
// Given the object below, and intending to remove the `m` property:
|
|
||||||
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
|
|
||||||
// ^---------------^
|
|
||||||
// Removing the range above results in:
|
|
||||||
// "{\n \"a\": \"a\",\n \"z\": \"z\"\n}"
|
|
||||||
start = previousProp.end;
|
|
||||||
end = targetProp.end;
|
|
||||||
} else {
|
|
||||||
// If there's no previousProp there is a nextProp, since we've specialcased the 1 length case.
|
|
||||||
// Given the object below, and intending to remove the `a` property:
|
|
||||||
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
|
|
||||||
// ^---------------^
|
|
||||||
// Removing the range above results in:
|
|
||||||
// "{\n \"m\": \"m\",\n \"z\": \"z\"\n}"
|
|
||||||
start = targetProp.start;
|
|
||||||
end = nextProp.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
recorder.remove(start.offset, end.offset - start.offset);
|
|
||||||
if (!nextProp) {
|
|
||||||
recorder.insertRight(start.offset, '\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function appendValueInAstArray(
|
|
||||||
recorder: UpdateRecorder,
|
|
||||||
node: JsonAstArray,
|
|
||||||
value: JsonValue,
|
|
||||||
indent = 4,
|
|
||||||
) {
|
|
||||||
let indentStr = _buildIndent(indent);
|
|
||||||
let index = node.start.offset + 1;
|
|
||||||
// tslint:disable-next-line: no-any
|
|
||||||
let newNodes: any[] | undefined;
|
|
||||||
|
|
||||||
if (node.elements.length > 0) {
|
|
||||||
// Insert comma.
|
|
||||||
const { end } = node.elements[node.elements.length - 1];
|
|
||||||
const isClosingOnSameLine = node.end.offset - end.offset === 1;
|
|
||||||
|
|
||||||
if (isClosingOnSameLine && indent) {
|
|
||||||
// Reformat the entire array
|
|
||||||
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
|
|
||||||
newNodes = [
|
|
||||||
...node.elements.map(({ value }) => value),
|
|
||||||
value,
|
|
||||||
];
|
|
||||||
index = node.start.offset;
|
|
||||||
// In case we are generating the entire node we need to reduce the spacing as
|
|
||||||
// otherwise we'd end up having incorrect double spacing
|
|
||||||
indent = indent - 2;
|
|
||||||
indentStr = _buildIndent(indent);
|
|
||||||
} else {
|
|
||||||
recorder.insertRight(end.offset, ',');
|
|
||||||
index = end.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recorder.insertRight(
|
|
||||||
index,
|
|
||||||
(newNodes ? '' : indentStr)
|
|
||||||
+ _stringifyContent(newNodes || value, indentStr)
|
|
||||||
+ (node.elements.length === 0 && indent ? indentStr.substr(0, -indent) + '\n' : ''),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function findPropertyInAstObject(
|
|
||||||
node: JsonAstObject,
|
|
||||||
propertyName: string,
|
|
||||||
): JsonAstNode | null {
|
|
||||||
let maybeNode: JsonAstNode | null = null;
|
|
||||||
for (const property of node.properties) {
|
|
||||||
if (property.key.value == propertyName) {
|
|
||||||
maybeNode = property.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maybeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _buildIndent(count: number): string {
|
|
||||||
return count ? '\n' + ' '.repeat(count) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function _stringifyContent(value: JsonValue, indentStr: string): string {
|
|
||||||
// TODO: Add snapshot tests
|
|
||||||
|
|
||||||
// The 'space' value is 2, because we want to add 2 additional
|
|
||||||
// indents from the 'key' node.
|
|
||||||
|
|
||||||
// If we use the indent provided we will have double indents:
|
|
||||||
// "budgets": [
|
|
||||||
// {
|
|
||||||
// "type": "initial",
|
|
||||||
// "maximumWarning": "2mb",
|
|
||||||
// "maximumError": "5mb"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "type": "anyComponentStyle",
|
|
||||||
// 'maximumWarning": "5kb"
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
return JSON.stringify(value, null, 2).replace(/\n/g, indentStr);
|
|
||||||
}
|
|
@ -1,234 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
import { JsonAstArray, JsonAstObject, JsonValue, parseJsonAst } from '@angular-devkit/core';
|
|
||||||
import { HostTree, UpdateRecorder } from '@angular-devkit/schematics';
|
|
||||||
import { UnitTestTree } from '@angular-devkit/schematics/testing';
|
|
||||||
import {
|
|
||||||
appendPropertyInAstObject,
|
|
||||||
appendValueInAstArray,
|
|
||||||
insertPropertyInAstObjectInOrder,
|
|
||||||
removePropertyInAstObject,
|
|
||||||
} from './json-utils';
|
|
||||||
|
|
||||||
// tslint:disable-next-line: no-big-function
|
|
||||||
describe('json-utils', () => {
|
|
||||||
const a = 'a';
|
|
||||||
const b = 'b';
|
|
||||||
const m = 'm';
|
|
||||||
const z = 'z';
|
|
||||||
const filePath = '/temp';
|
|
||||||
let tree: UnitTestTree;
|
|
||||||
|
|
||||||
function runTest(testFn: Function, obj: JsonValue, indent: number): string {
|
|
||||||
const content = JSON.stringify(obj, null, indent);
|
|
||||||
tree.create(filePath, content);
|
|
||||||
const ast = parseJsonAst(content);
|
|
||||||
const rec = tree.beginUpdate(filePath);
|
|
||||||
testFn(rec, ast);
|
|
||||||
tree.commitUpdate(rec);
|
|
||||||
|
|
||||||
const result = tree.readContent(filePath);
|
|
||||||
// Clean up the tree by deleting the file.
|
|
||||||
tree.delete(filePath);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = new UnitTestTree(new HostTree());
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('appendPropertyInAstObject', () => {
|
|
||||||
it('should insert multiple props with different indentations', () => {
|
|
||||||
const cases: Array<[{}, string, {}, number]> = [
|
|
||||||
// initial | prop | want | indent
|
|
||||||
[{}, z, {z}, 0],
|
|
||||||
[{z}, m, {z, m}, 0],
|
|
||||||
[{m, z}, a, {m, z, a}, 0],
|
|
||||||
[{a, m, z}, b, {a, m, z, b}, 0],
|
|
||||||
[{}, z, {z}, 2],
|
|
||||||
[{z}, m, {z, m}, 2],
|
|
||||||
[{m, z}, a, {m, z, a}, 2],
|
|
||||||
[{a, m, z}, b, {a, m, z, b}, 2],
|
|
||||||
[{}, z, {z}, 4],
|
|
||||||
[{z}, m, {z, m}, 4],
|
|
||||||
[{m, z}, a, {m, z, a}, 4],
|
|
||||||
[{a, m, z}, b, {a, m, z, b}, 4],
|
|
||||||
];
|
|
||||||
for (const c of cases) {
|
|
||||||
const [initial, prop, want, indent] = c;
|
|
||||||
const got = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
appendPropertyInAstObject(rec, ast, prop, prop, indent);
|
|
||||||
}, initial, indent);
|
|
||||||
expect(got).toBe(JSON.stringify(want, null, indent));
|
|
||||||
expect(JSON.parse(got)).toEqual(want);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('insertPropertyInAstObjectInOrder', () => {
|
|
||||||
it('should insert a first prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
insertPropertyInAstObjectInOrder(rec, ast, a, a, indent);
|
|
||||||
}, {m, z}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({a, m, z}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({a, m, z});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should insert a middle prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
insertPropertyInAstObjectInOrder(rec, ast, m, m, indent);
|
|
||||||
}, {a, z}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({a, m, z}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({a, m, z});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should insert a last prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
insertPropertyInAstObjectInOrder(rec, ast, z, z, indent);
|
|
||||||
}, {a, m}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({a, m, z}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({a, m, z});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should insert multiple props with different indentations', () => {
|
|
||||||
const cases: Array<[{}, string, {}, number]> = [
|
|
||||||
// initial | prop | want | indent
|
|
||||||
[{}, z, {z}, 0],
|
|
||||||
[{z}, m, {m, z}, 0],
|
|
||||||
[{m, z}, a, {a, m, z}, 0],
|
|
||||||
[{a, m, z}, b, {a, b, m, z}, 0],
|
|
||||||
[{}, z, {z}, 2],
|
|
||||||
[{z}, m, {m, z}, 2],
|
|
||||||
[{m, z}, a, {a, m, z}, 2],
|
|
||||||
[{a, m, z}, b, {a, b, m, z}, 2],
|
|
||||||
[{}, z, {z}, 4],
|
|
||||||
[{z}, m, {m, z}, 4],
|
|
||||||
[{m, z}, a, {a, m, z}, 4],
|
|
||||||
[{a, m, z}, b, {a, b, m, z}, 4],
|
|
||||||
];
|
|
||||||
for (const c of cases) {
|
|
||||||
const [initial, prop, want, indent] = c;
|
|
||||||
const got = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
insertPropertyInAstObjectInOrder(rec, ast, prop, prop, indent);
|
|
||||||
}, initial, indent);
|
|
||||||
expect(got).toBe(JSON.stringify(want, null, indent));
|
|
||||||
expect(JSON.parse(got)).toEqual(want);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('removePropertyInAstObject', () => {
|
|
||||||
it('should remove a first prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
removePropertyInAstObject(rec, ast, a);
|
|
||||||
}, {a, m, z}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({m, z}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({m, z});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a middle prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
removePropertyInAstObject(rec, ast, m);
|
|
||||||
}, {a, m, z}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({a, z}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({a, z});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a last prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
removePropertyInAstObject(rec, ast, z);
|
|
||||||
}, {a, m, z}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({a, m}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({a, m});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove only prop', () => {
|
|
||||||
const indent = 2;
|
|
||||||
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.kind).toBe('object');
|
|
||||||
removePropertyInAstObject(rec, ast, a);
|
|
||||||
}, {a}, indent);
|
|
||||||
expect(result).toBe(JSON.stringify({}, null, indent));
|
|
||||||
expect(JSON.parse(result)).toEqual({});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('appendValueInAstArray', () => {
|
|
||||||
it('should insert multiple props with different indentations', () => {
|
|
||||||
const cases: Array<[string[], string, {}, number]> = [
|
|
||||||
// initial | value | want | indent
|
|
||||||
[[], z, [z], 0],
|
|
||||||
[[z], m, [z, m], 0],
|
|
||||||
[[m, z], a, [m, z, a], 0],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 0],
|
|
||||||
[[], z, [z], 2],
|
|
||||||
[[z], m, [z, m], 2],
|
|
||||||
[[m, z], a, [m, z, a], 2],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 2],
|
|
||||||
[[], z, [z], 4],
|
|
||||||
[[z], m, [z, m], 4],
|
|
||||||
[[m, z], a, [m, z, a], 4],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 4],
|
|
||||||
];
|
|
||||||
for (const c of cases) {
|
|
||||||
const [initial, value, want, indent] = c;
|
|
||||||
const got = runTest((rec: UpdateRecorder, ast: JsonAstArray) => {
|
|
||||||
expect(ast.kind).toBe('array');
|
|
||||||
appendValueInAstArray(rec, ast, value, indent);
|
|
||||||
}, initial, indent);
|
|
||||||
expect(got).toBe(JSON.stringify(want, null, indent));
|
|
||||||
expect(JSON.parse(got)).toEqual(want);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should insert multiple props with different indentations in Object literal', () => {
|
|
||||||
const cases: Array<[string[], string, {}, number]> = [
|
|
||||||
// initial | value | want | indent
|
|
||||||
[[], z, [z], 0],
|
|
||||||
[[z], m, [z, m], 0],
|
|
||||||
[[m, z], a, [m, z, a], 0],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 0],
|
|
||||||
// todo: investigate how to do this this of addition with the correct formatting
|
|
||||||
// [[], z, [z], 2],
|
|
||||||
[[z], m, [z, m], 2],
|
|
||||||
[[m, z], a, [m, z, a], 2],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 2],
|
|
||||||
// todo: investigate how to do this this of addition with the correct formatting
|
|
||||||
// [[], z, [z], 4],
|
|
||||||
[[z], m, [z, m], 4],
|
|
||||||
[[m, z], a, [m, z, a], 4],
|
|
||||||
[[a, m, z], b, [a, m, z, b], 4],
|
|
||||||
];
|
|
||||||
for (const c of cases) {
|
|
||||||
const [initial, value, want, indent] = c;
|
|
||||||
const got = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
|
|
||||||
expect(ast.properties[0].value.kind).toBe('array');
|
|
||||||
appendValueInAstArray(rec, ast.properties[0].value as unknown as JsonAstArray, value, indent * 2);
|
|
||||||
}, { data: initial }, indent);
|
|
||||||
const wantData = { data: want };
|
|
||||||
expect(got).toBe(JSON.stringify(wantData, null, indent));
|
|
||||||
expect(JSON.parse(got)).toEqual(wantData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user