Skip to content

Commit a9bee14

Browse files
alan-agius4vikerman
authored andcommitted
fix(@schematics/angular): appendValueInAstArray should not break JSON when using different formatting
Fixes: #16024, fixes: #15462 and fixes: #14776
1 parent 5bc0b9d commit a9bee14

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

packages/schematics/angular/utility/json-utils.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ export function removePropertyInAstObject(
143143

144144
recorder.remove(start.offset, end.offset - start.offset);
145145
if (!nextProp) {
146-
147146
recorder.insertRight(start.offset, '\n');
148147
}
149148
}
@@ -155,21 +154,39 @@ export function appendValueInAstArray(
155154
value: JsonValue,
156155
indent = 4,
157156
) {
158-
const indentStr = _buildIndent(indent);
157+
let indentStr = _buildIndent(indent);
159158
let index = node.start.offset + 1;
159+
// tslint:disable-next-line: no-any
160+
let newNodes: any[] | undefined;
161+
160162
if (node.elements.length > 0) {
161163
// Insert comma.
162-
const last = node.elements[node.elements.length - 1];
163-
recorder.insertRight(last.end.offset, ',');
164-
index = indent ? last.end.offset + 1 : last.end.offset;
164+
const { end } = node.elements[node.elements.length - 1];
165+
const isClosingOnSameLine = node.end.offset - end.offset === 1;
166+
167+
if (isClosingOnSameLine && indent) {
168+
// Reformat the entire array
169+
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
170+
newNodes = [
171+
...node.elements.map(({ value }) => value),
172+
value,
173+
];
174+
index = node.start.offset;
175+
// In case we are generating the entire node we need to reduce the spacing as
176+
// otherwise we'd end up having incorrect double spacing
177+
indent = indent - 2;
178+
indentStr = _buildIndent(indent);
179+
} else {
180+
recorder.insertRight(end.offset, ',');
181+
index = end.offset;
182+
}
165183
}
166184

167185
recorder.insertRight(
168186
index,
169-
(node.elements.length === 0 && indent ? '\n' : '')
170-
+ ' '.repeat(indent)
171-
+ _stringifyContent(value, indentStr)
172-
+ indentStr.slice(0, -indent),
187+
(newNodes ? '' : indentStr)
188+
+ _stringifyContent(newNodes || value, indentStr)
189+
+ (node.elements.length === 0 && indent ? indentStr.substr(0, -indent) + '\n' : ''),
173190
);
174191
}
175192

packages/schematics/angular/utility/json-utils_spec.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
removePropertyInAstObject,
1616
} from './json-utils';
1717

18+
// tslint:disable-next-line: no-big-function
1819
describe('json-utils', () => {
1920
const a = 'a';
2021
const b = 'b';
@@ -199,6 +200,35 @@ describe('json-utils', () => {
199200
expect(JSON.parse(got)).toEqual(want);
200201
}
201202
});
202-
});
203203

204+
it('should insert multiple props with different indentations in Object literal', () => {
205+
const cases: Array<[string[], string, {}, number]> = [
206+
// initial | value | want | indent
207+
[[], z, [z], 0],
208+
[[z], m, [z, m], 0],
209+
[[m, z], a, [m, z, a], 0],
210+
[[a, m, z], b, [a, m, z, b], 0],
211+
// todo: investigate how to do this this of addition with the correct formatting
212+
// [[], z, [z], 2],
213+
[[z], m, [z, m], 2],
214+
[[m, z], a, [m, z, a], 2],
215+
[[a, m, z], b, [a, m, z, b], 2],
216+
// todo: investigate how to do this this of addition with the correct formatting
217+
// [[], z, [z], 4],
218+
[[z], m, [z, m], 4],
219+
[[m, z], a, [m, z, a], 4],
220+
[[a, m, z], b, [a, m, z, b], 4],
221+
];
222+
for (const c of cases) {
223+
const [initial, value, want, indent] = c;
224+
const got = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
225+
expect(ast.properties[0].value.kind).toBe('array');
226+
appendValueInAstArray(rec, ast.properties[0].value as unknown as JsonAstArray, value, indent * 2);
227+
}, { data: initial }, indent);
228+
const wantData = { data: want };
229+
expect(got).toBe(JSON.stringify(wantData, null, indent));
230+
expect(JSON.parse(got)).toEqual(wantData);
231+
}
232+
});
233+
});
204234
});

0 commit comments

Comments
 (0)