Skip to content

Commit df175f2

Browse files
committed
ci: add no circular dependency rule to tslint
And fix the linting issues.
1 parent dc1b9c5 commit df175f2

File tree

17 files changed

+2374
-2421
lines changed

17 files changed

+2374
-2421
lines changed

package-lock.json

Lines changed: 2114 additions & 2108 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
"zone.js": "^0.8.19"
163163
},
164164
"devDependencies": {
165-
"license-checker": "^16.0.0"
165+
"license-checker": "^16.0.0",
166+
"tslint-no-circular-imports": "^0.3.0"
166167
}
167168
}

packages/angular_devkit/architect/src/architect.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,6 @@ import {
2323
import { resolve as nodeResolve } from '@angular-devkit/core/node';
2424
import { Observable, forkJoin, of, throwError } from 'rxjs';
2525
import { concatMap, map, tap } from 'rxjs/operators';
26-
import {
27-
BuildEvent,
28-
Builder,
29-
BuilderConstructor,
30-
BuilderContext,
31-
BuilderDescription,
32-
BuilderPaths,
33-
BuilderPathsMap,
34-
} from './builder';
3526

3627
export class ProjectNotFoundException extends BaseException {
3728
constructor(projectName: string) {
@@ -68,6 +59,44 @@ export class BuilderNotFoundException extends BaseException {
6859
}
6960
}
7061

62+
export interface BuilderContext {
63+
logger: logging.Logger;
64+
host: virtualFs.Host<{}>;
65+
workspace: experimental.workspace.Workspace;
66+
architect: Architect;
67+
}
68+
69+
// TODO: use Build Event Protocol
70+
// https://docs.bazel.build/versions/master/build-event-protocol.html
71+
// https://github.com/googleapis/googleapis/tree/master/google/devtools/build/v1
72+
export interface BuildEvent {
73+
success: boolean;
74+
}
75+
76+
export interface Builder<OptionsT> {
77+
run(builderConfig: BuilderConfiguration<Partial<OptionsT>>): Observable<BuildEvent>;
78+
}
79+
80+
export interface BuilderPathsMap {
81+
builders: { [k: string]: BuilderPaths };
82+
}
83+
84+
export interface BuilderPaths {
85+
class: Path;
86+
schema: Path;
87+
description: string;
88+
}
89+
90+
export interface BuilderDescription {
91+
name: string;
92+
schema: JsonObject;
93+
description: string;
94+
}
95+
96+
export interface BuilderConstructor<OptionsT> {
97+
new(context: BuilderContext): Builder<OptionsT>;
98+
}
99+
71100
export interface BuilderConfiguration<OptionsT = {}> {
72101
root: Path;
73102
sourceRoot?: Path;

packages/angular_devkit/architect/src/builder.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.

packages/angular_devkit/architect/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@
77
*/
88

99
export * from './architect';
10-
export * from './builder';

packages/angular_devkit/schematics/src/engine/collection.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/angular_devkit/schematics/src/engine/engine.ts

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,31 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { BaseException, logging } from '@angular-devkit/core';
8+
import { BaseException, PriorityQueue, logging } from '@angular-devkit/core';
99
import { Observable, from as observableFrom } from 'rxjs';
1010
import { concatMap } from 'rxjs/operators';
1111
import { Url } from 'url';
1212
import { MergeStrategy } from '../tree/interface';
1313
import { NullTree } from '../tree/null';
1414
import { empty } from '../tree/static';
1515
import { Workflow } from '../workflow';
16-
import { CollectionImpl } from './collection';
1716
import {
1817
Collection,
1918
CollectionDescription,
2019
Engine,
2120
EngineHost,
2221
Schematic,
22+
SchematicContext,
2323
SchematicDescription,
2424
Source,
25-
TypedSchematicContext,
26-
} from './interface';
27-
import { SchematicImpl } from './schematic';
28-
import {
25+
TaskConfiguration,
2926
TaskConfigurationGenerator,
3027
TaskExecutor,
3128
TaskId,
32-
TaskScheduler,
33-
} from './task';
29+
TaskInfo,
30+
TypedSchematicContext,
31+
} from './interface';
32+
import { SchematicImpl } from './schematic';
3433

3534

3635
export class UnknownUrlSourceProtocol extends BaseException {
@@ -70,6 +69,95 @@ export class UnregisteredTaskException extends BaseException {
7069
}
7170
}
7271

72+
export class UnknownTaskDependencyException extends BaseException {
73+
constructor(id: TaskId) {
74+
super(`Unknown task dependency [ID: ${id.id}].`);
75+
}
76+
}
77+
78+
export class CollectionImpl<CollectionT extends object, SchematicT extends object>
79+
implements Collection<CollectionT, SchematicT> {
80+
constructor(private _description: CollectionDescription<CollectionT>,
81+
private _engine: SchematicEngine<CollectionT, SchematicT>,
82+
public readonly baseDescriptions?: Array<CollectionDescription<CollectionT>>) {
83+
}
84+
85+
get description() { return this._description; }
86+
get name() { return this.description.name || '<unknown>'; }
87+
88+
createSchematic(name: string, allowPrivate = false): Schematic<CollectionT, SchematicT> {
89+
return this._engine.createSchematic(name, this, allowPrivate);
90+
}
91+
92+
listSchematicNames(): string[] {
93+
return this._engine.listSchematicNames(this);
94+
}
95+
}
96+
97+
export class TaskScheduler {
98+
private _queue = new PriorityQueue<TaskInfo>((x, y) => x.priority - y.priority);
99+
private _taskIds = new Map<TaskId, TaskInfo>();
100+
private static _taskIdCounter = 1;
101+
102+
constructor(private _context: SchematicContext) {}
103+
104+
private _calculatePriority(dependencies: Set<TaskInfo>): number {
105+
if (dependencies.size === 0) {
106+
return 0;
107+
}
108+
109+
const prio = [...dependencies].reduce((prio, task) => prio + task.priority, 1);
110+
111+
return prio;
112+
}
113+
114+
private _mapDependencies(dependencies?: Array<TaskId>): Set<TaskInfo> {
115+
if (!dependencies) {
116+
return new Set();
117+
}
118+
119+
const tasks = dependencies.map(dep => {
120+
const task = this._taskIds.get(dep);
121+
if (!task) {
122+
throw new UnknownTaskDependencyException(dep);
123+
}
124+
125+
return task;
126+
});
127+
128+
return new Set(tasks);
129+
}
130+
131+
schedule<T>(taskConfiguration: TaskConfiguration<T>): TaskId {
132+
const dependencies = this._mapDependencies(taskConfiguration.dependencies);
133+
const priority = this._calculatePriority(dependencies);
134+
135+
const task = {
136+
id: TaskScheduler._taskIdCounter++,
137+
priority,
138+
configuration: taskConfiguration,
139+
context: this._context,
140+
};
141+
142+
this._queue.push(task);
143+
144+
const id = { id: task.id };
145+
this._taskIds.set(id, task);
146+
147+
return id;
148+
}
149+
150+
finalize(): ReadonlyArray<TaskInfo> {
151+
const tasks = this._queue.toArray();
152+
this._queue.clear();
153+
this._taskIds.clear();
154+
155+
return tasks;
156+
}
157+
158+
}
159+
160+
73161
export class SchematicEngine<CollectionT extends object, SchematicT extends object>
74162
implements Engine<CollectionT, SchematicT> {
75163

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
export * from './engine';
9+
export * from './interface';
10+
export * from './schematic';

packages/angular_devkit/schematics/src/engine/interface.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,37 @@ import { Observable } from 'rxjs';
1010
import { Url } from 'url';
1111
import { FileEntry, MergeStrategy, Tree } from '../tree/interface';
1212
import { Workflow } from '../workflow';
13-
import { TaskConfigurationGenerator, TaskExecutor, TaskId } from './task';
1413

1514

15+
export interface TaskConfiguration<T = {}> {
16+
name: string;
17+
dependencies?: Array<TaskId>;
18+
options?: T;
19+
}
20+
21+
export interface TaskConfigurationGenerator<T = {}> {
22+
toConfiguration(): TaskConfiguration<T>;
23+
}
24+
25+
export type TaskExecutor<T = {}>
26+
= (options: T | undefined, context: SchematicContext) => Promise<void> | Observable<void>;
27+
28+
export interface TaskExecutorFactory<T> {
29+
readonly name: string;
30+
create(options?: T): Promise<TaskExecutor> | Observable<TaskExecutor>;
31+
}
32+
33+
export interface TaskId {
34+
readonly id: number;
35+
}
36+
37+
export interface TaskInfo {
38+
readonly id: number;
39+
readonly priority: number;
40+
readonly configuration: TaskConfiguration;
41+
readonly context: SchematicContext;
42+
}
43+
1644
/**
1745
* The description (metadata) of a collection. This type contains every information the engine
1846
* needs to run. The CollectionMetadataT type parameter contains additional metadata that you

0 commit comments

Comments
 (0)