Skip to content

Commit 30ef0db

Browse files
Merge pull request diffblue#566 from diffblue/bugfix/java-code-block
Fix bug in Block
2 parents 1f5f1fc + 321a128 commit 30ef0db

File tree

3 files changed

+232
-19
lines changed

3 files changed

+232
-19
lines changed

env-model-generator/src/env-model-generator.ts

+7-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as program from "commander";
66
import * as fs from "fs-extra";
77
import * as _ from "lodash";
88
import * as pathUtils from "path";
9-
import { BlankLine, Block, Class, FnCall, Method, Null, Return, Statement } from "./javaCode";
9+
import { BlankLine, CatchBlock, Class, FnCall, IfThenElse, Method, Null, Return, Statement, StringConstant, TryCatch } from "./javaCode";
1010
import * as model from "./model";
1111
import parseSpringConfigFiles from "./parserDriver";
1212
import { createPath } from "./utils";
@@ -64,14 +64,13 @@ async function transformConfigFiles(fileName: string, options: any) {
6464
new Method(
6565
"public Object getBean(String name)",
6666
[
67-
new Block(
68-
"try",
67+
new TryCatch(
6968
(<Statement[]>[]).concat(
7069
model.Repository.getNamed()
7170
.sort((a, b) => a.name < b.name ? -1 : a.name === b.name ? 0 : 1)
7271
.map((bean) =>
73-
new Block(
74-
`if (name.equals("${bean.name}"))`,
72+
new IfThenElse(
73+
new FnCall("name.equals", [ new StringConstant(bean.name) ]),
7574
[
7675
new Return(new FnCall(bean.getter, [])),
7776
])),
@@ -80,17 +79,14 @@ async function transformConfigFiles(fileName: string, options: any) {
8079
const bean = model.Repository.tryGet(beanId);
8180
if (bean === undefined)
8281
throw new Error("Found alias to bean that doesn't exist");
83-
return new Block(
84-
`if (name.equals("${alias}"))`,
82+
return new IfThenElse(
83+
new FnCall("name.equals", [ new StringConstant(alias) ]),
8584
[
8685
new Return(new FnCall(bean.getter, [])),
8786
]);
8887
}),
8988
),
90-
),
91-
new Block(
92-
"catch(Exception ex)",
93-
[]),
89+
[ new CatchBlock("Exception") ]),
9490
new Return(new Null()),
9591
],
9692
[],

env-model-generator/src/javaCode.ts

+212-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,55 @@ export class FnCall extends CodeElement implements Expression {
5858
}
5959
}
6060

61+
export class BinaryOperator extends CodeElement implements Expression {
62+
public isExpression: true = true;
63+
64+
private lhs: Expression;
65+
private operatorName: string;
66+
private rhs: Expression;
67+
68+
public constructor(lhs: Expression, operatorName: string, rhs: Expression) {
69+
super();
70+
this.lhs = lhs;
71+
this.operatorName = operatorName;
72+
this.rhs = rhs;
73+
}
74+
75+
public flatten(): string[] {
76+
const lhsInLines = this.lhs.flatten();
77+
const rhsInLines = this.rhs.flatten();
78+
if (lhsInLines.length === 1 && rhsInLines.length === 1) {
79+
const oneLine = `${lhsInLines[0]} ${this.operatorName} ${rhsInLines[0]}`;
80+
if (oneLine.length < maxLineLength) {
81+
return [ oneLine ];
82+
}
83+
}
84+
if (lhsInLines.length === 1) {
85+
const firstLine = `${lhsInLines[0]} ${this.operatorName}`;
86+
if (firstLine.length < maxLineLength) {
87+
return [
88+
firstLine,
89+
...rhsInLines.map(indent),
90+
];
91+
}
92+
}
93+
if (rhsInLines.length === 1) {
94+
const lastLine = indent(`${this.operatorName} ${rhsInLines[0]}`);
95+
if (lastLine.length < maxLineLength) {
96+
return [
97+
...lhsInLines,
98+
lastLine,
99+
];
100+
}
101+
}
102+
return [
103+
...lhsInLines,
104+
this.operatorName,
105+
...rhsInLines.map(indent),
106+
];
107+
}
108+
}
109+
61110
export class BraceInitialiser extends CodeElement implements Expression {
62111
public isExpression: true = true;
63112

@@ -254,7 +303,7 @@ class Braces extends CodeElement {
254303
public flatten(): string[] {
255304
return [
256305
this.intro ? this.intro + " {" : "{",
257-
..._.flatMap(this.body, (block) => block.flatten()).map(indent),
306+
..._.flatMap(this.body, (stmt) => stmt.flatten()).map(indent),
258307
"}",
259308
];
260309
}
@@ -286,6 +335,168 @@ export class Method extends Braces implements Member {
286335
}
287336
}
288337

338+
export class CatchBlock {
339+
private exceptionType: string;
340+
private body: Statement[];
341+
private exceptionName: string;
342+
343+
public constructor(exceptionType: string, body: Statement[] = [], exceptionName: string = "ex") {
344+
this.exceptionType = exceptionType;
345+
this.body = body;
346+
this.exceptionName = exceptionName;
347+
}
348+
349+
public flatten(): string[] {
350+
return [
351+
`} catch (${this.exceptionType} ${this.exceptionName}) {`,
352+
..._.flatMap(this.body, (stmt) => stmt.flatten()),
353+
];
354+
}
355+
}
356+
357+
export class TryCatch extends CodeElement implements Statement {
358+
public isStatement: true = true;
359+
360+
private tryBody: Statement[];
361+
private catchBlocks: CatchBlock[];
362+
private finallyBody?: Statement[];
363+
364+
public constructor(tryBody: Statement[] = [], catchBlocks: CatchBlock[] = [], finallyBody?: Statement[]) {
365+
super();
366+
this.tryBody = tryBody;
367+
this.catchBlocks = catchBlocks;
368+
this.finallyBody = finallyBody;
369+
}
370+
371+
private getFinallyLines(): string[] {
372+
if (this.finallyBody === undefined) {
373+
return [];
374+
}
375+
return [
376+
"} finally {",
377+
..._.flatMap(this.finallyBody, (stmt) => stmt.flatten()),
378+
];
379+
}
380+
381+
public flatten(): string[] {
382+
return [
383+
"try {",
384+
..._.flatMap(this.tryBody, (stmt) => stmt.flatten()).map(indent),
385+
..._.flatMap(this.catchBlocks, (catchBlock) => catchBlock.flatten()),
386+
...this.getFinallyLines(),
387+
"}",
388+
];
389+
}
390+
}
391+
392+
export class IfThenElse extends CodeElement implements Statement {
393+
public isStatement: true = true;
394+
395+
private guard: Expression;
396+
private thenBlock: Statement[];
397+
private elseBlock?: Statement[];
398+
399+
public constructor(guard: Expression, thenBlock: Statement[], elseBlock?: Statement[]) {
400+
super();
401+
this.guard = guard;
402+
this.thenBlock = thenBlock;
403+
this.elseBlock = elseBlock;
404+
}
405+
406+
private getGuardLines(): string[] {
407+
const guardInLines = this.guard.flatten();
408+
if (guardInLines.length === 1) {
409+
const oneLine = `if (${guardInLines[0]}) {`;
410+
if (oneLine.length < maxLineLength)
411+
return [ oneLine ];
412+
}
413+
guardInLines[guardInLines.length - 1] += ")";
414+
return [
415+
"if (",
416+
...guardInLines.map(indent),
417+
"{",
418+
];
419+
}
420+
421+
public flatten(): string[] {
422+
const thenLines = _.flatMap(this.thenBlock, (stmt) => stmt.flatten()).map(indent);
423+
if (this.elseBlock === undefined) {
424+
return [
425+
...this.getGuardLines(),
426+
...thenLines,
427+
"}",
428+
];
429+
} else {
430+
return [
431+
...this.getGuardLines(),
432+
...thenLines,
433+
"} else {",
434+
..._.flatMap(this.elseBlock, (stmt) => stmt.flatten()).map(indent),
435+
"}",
436+
];
437+
}
438+
}
439+
}
440+
441+
export class RangedFor extends CodeElement implements Statement {
442+
public isStatement: true = true;
443+
444+
private modifiedType: string;
445+
private rangeVariableName: string;
446+
private collection: Expression;
447+
private body: Statement[];
448+
449+
public constructor(modifiedType: string, rangeVariableName: string, collection: Expression, body: Statement[]) {
450+
super();
451+
this.modifiedType = modifiedType;
452+
this.rangeVariableName = rangeVariableName;
453+
this.collection = collection;
454+
this.body = body;
455+
}
456+
457+
private getForLines(): string[] {
458+
const collectionInLines = this.collection.flatten();
459+
if (collectionInLines.length === 1) {
460+
const oneLine = `for (${this.modifiedType} ${this.rangeVariableName} : ${collectionInLines[0]}) {`;
461+
if (oneLine.length < maxLineLength)
462+
return [ oneLine ];
463+
}
464+
collectionInLines[collectionInLines.length - 1] += ")";
465+
const forLine = `for (${this.modifiedType} ${this.rangeVariableName} :`;
466+
if (forLine.length < maxLineLength) {
467+
return [
468+
forLine,
469+
...collectionInLines.map(indent),
470+
"{",
471+
];
472+
}
473+
const rangeVariableLine = indent(`${this.modifiedType} ${this.rangeVariableName} :`);
474+
if (rangeVariableLine.length < maxLineLength) {
475+
return [
476+
"for (",
477+
rangeVariableLine,
478+
...collectionInLines.map(indent),
479+
"{",
480+
];
481+
}
482+
return [
483+
"for (",
484+
indent(this.modifiedType),
485+
indent(indent(`${this.rangeVariableName} :`)),
486+
...collectionInLines.map(indent),
487+
"{",
488+
];
489+
}
490+
491+
public flatten(): string[] {
492+
return [
493+
...this.getForLines(),
494+
..._.flatMap(this.body, (stmt) => stmt.flatten()).map(indent),
495+
"}",
496+
];
497+
}
498+
}
499+
289500
export class Class extends CodeElement {
290501
private modifiers: string;
291502
private name: string;

env-model-generator/src/model.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ import * as _ from "lodash";
22
import { ConfigParseError } from "./configParseError";
33
import {
44
Assignment,
5+
BinaryOperator,
56
BlankLine,
6-
Block,
77
BraceInitialiser,
88
Declaration,
99
Expression,
1010
FnCall,
1111
FnStatement,
12+
IfThenElse,
1213
Member,
1314
Method,
1415
Null,
16+
RangedFor,
1517
Return,
1618
Statement,
1719
StringConstant,
@@ -190,8 +192,8 @@ export class Bean implements IBean {
190192
this._javaMembers.push(new Method(
191193
`public static ${typeName} ${this.getter}()`,
192194
[
193-
new Block(
194-
`if (${variableName} == null)`,
195+
new IfThenElse(
196+
new BinaryOperator(new Symbol(variableName), "==", new Null()),
195197
[
196198
new Assignment(variableName, new FnCall(creatorFn, constructorArgs)),
197199
...initialisers,
@@ -432,8 +434,10 @@ export class PropertiesValue extends Value {
432434
"public static java.util.Properties listToProperties(java.util.List<java.util.AbstractMap.SimpleEntry<String, String>> properties)",
433435
[
434436
new Declaration("java.util.Properties", "result", new FnCall("new java.util.Properties", [])),
435-
new Block(
436-
"for (java.util.AbstractMap.SimpleEntry<String, String> prop : properties)",
437+
new RangedFor(
438+
"java.util.AbstractMap.SimpleEntry<String, String>",
439+
"prop",
440+
new Symbol("properties"),
437441
[
438442
new FnStatement(new FnCall("result.put", [ new FnCall("prop.getKey", []), new FnCall("prop.getValue", []) ])),
439443
]),
@@ -481,8 +485,10 @@ export class MapValue extends Value {
481485
"public static java.util.Map<String, String> listToMap(java.util.List<java.util.AbstractMap.SimpleEntry<String, String>> entries)",
482486
[
483487
new Declaration("java.util.Map<String, String>", "result", new FnCall("new java.util.HashMap<String, String>", [])),
484-
new Block(
485-
"for (java.util.AbstractMap.SimpleEntry<String, String> entry : entries)",
488+
new RangedFor(
489+
"java.util.AbstractMap.SimpleEntry<String, String>",
490+
"entry",
491+
new Symbol("entries"),
486492
[
487493
new FnStatement(new FnCall("result.put", [ new FnCall("entry.getKey", []), new FnCall("entry.getValue", []) ])),
488494
]),

0 commit comments

Comments
 (0)