1
1
import { ShowHierarchyBase } from './showHierarchyBase' ;
2
2
import { ModuleManager } from '@src' ;
3
- import { ArrowType , Component , Edge , GraphState , Node , NodeType , Project } from '@model' ;
3
+ import { ArrowType , Component , Edge , GraphState , NamedEntity , Node , NodeType , Project } from '@model' ;
4
4
import * as fs from 'fs' ;
5
5
import * as path from 'path' ;
6
6
import * as vscode from 'vscode' ;
7
7
8
8
export class GenerateDependencyInjectionGraph extends ShowHierarchyBase {
9
- static get commandName ( ) { return 'generateDependencyInjectionGraph' ; }
10
- public execute ( webview : vscode . Webview ) {
11
- this . checkForOpenWorkspace ( ) ;
12
- webview . onDidReceiveMessage (
13
- message => {
14
- switch ( message . command ) {
15
- case 'saveAsPng' : {
16
- this . saveAsPng ( this . config . dependencyInjectionPngFilename , message . text ) ;
17
- return ;
18
- }
19
- case 'saveAsDgml' : {
20
- this . saveAsDgml ( this . config . dependencyInjectionDgmlGraphFilename , message . text , `'The components hierarchy has been analyzed and a Directed Graph Markup Language (dgml) file '${ this . config . dependencyInjectionDgmlGraphFilename } ' has been created'` ) ;
21
- return ;
22
- }
23
- case 'saveAsDot' : {
24
- this . saveAsDot ( this . config . dependencyInjectionDotGraphFilename , message . text , 'dependencyInjectionGraph' , `'The components hierarchy has been analyzed and a GraphViz (dot) file '${ this . config . dependencyInjectionDotGraphFilename } ' has been created'` ) ;
25
- return ;
26
- }
27
- case 'setGraphState' : {
28
- const newGraphState : GraphState = JSON . parse ( message . text ) ;
29
- this . graphState = newGraphState ;
30
- this . setNewState ( this . graphState ) ;
31
- this . nodes . forEach ( node => {
32
- node . position = this . graphState . nodePositions [ node . id ] ;
33
- } ) ;
34
- this . addNodesAndEdges ( project , this . appendNodes , this . appendEdges ) ;
35
- this . generateAndSaveJavascriptContent ( ( ) => { } ) ;
36
- return ;
37
- }
38
- case 'openFile' : {
39
- const filename = message . text ;
40
- if ( this . fsUtils . fileExists ( filename ) ) {
41
- var openPath = vscode . Uri . parse ( "file:///" + filename ) ;
42
- vscode . workspace . openTextDocument ( openPath ) . then ( doc => {
43
- vscode . window . showTextDocument ( doc ) ;
44
- } ) ;
45
- }
46
- return ;
47
- }
9
+ static get commandName ( ) { return 'generateDependencyInjectionGraph' ; }
10
+ public execute ( webview : vscode . Webview ) {
11
+ this . checkForOpenWorkspace ( ) ;
12
+ webview . onDidReceiveMessage (
13
+ message => {
14
+ switch ( message . command ) {
15
+ case 'saveAsPng' : {
16
+ this . saveAsPng ( this . config . dependencyInjectionPngFilename , message . text ) ;
17
+ return ;
18
+ }
19
+ case 'saveAsDgml' : {
20
+ this . saveAsDgml ( this . config . dependencyInjectionDgmlGraphFilename , message . text , `'The components hierarchy has been analyzed and a Directed Graph Markup Language (dgml) file '${ this . config . dependencyInjectionDgmlGraphFilename } ' has been created'` ) ;
21
+ return ;
22
+ }
23
+ case 'saveAsDot' : {
24
+ this . saveAsDot ( this . config . dependencyInjectionDotGraphFilename , message . text , 'dependencyInjectionGraph' , `'The components hierarchy has been analyzed and a GraphViz (dot) file '${ this . config . dependencyInjectionDotGraphFilename } ' has been created'` ) ;
25
+ return ;
26
+ }
27
+ case 'setGraphState' : {
28
+ const newGraphState : GraphState = JSON . parse ( message . text ) ;
29
+ this . graphState = newGraphState ;
30
+ this . setNewState ( this . graphState ) ;
31
+ this . nodes . forEach ( node => {
32
+ node . position = this . graphState . nodePositions [ node . id ] ;
33
+ } ) ;
34
+ this . addNodesAndEdges ( project ) ;
35
+ this . generateAndSaveJavascriptContent ( ( ) => { } ) ;
36
+ return ;
37
+ }
38
+ case 'openFile' : {
39
+ const filename = message . text ;
40
+ if ( this . fsUtils . fileExists ( filename ) ) {
41
+ var openPath = vscode . Uri . parse ( "file:///" + filename ) ;
42
+ vscode . workspace . openTextDocument ( openPath ) . then ( doc => {
43
+ vscode . window . showTextDocument ( doc ) ;
44
+ } ) ;
45
+ }
46
+ return ;
47
+ }
48
+ }
49
+ } ,
50
+ undefined ,
51
+ this . extensionContext . subscriptions
52
+ ) ;
53
+ var workspaceFolder = this . fsUtils . getWorkspaceFolder ( ) ;
54
+ const errors : string [ ] = [ ] ;
55
+ const project : Project = ModuleManager . scanProject ( workspaceFolder , errors , this . isTypescriptFile ) ;
56
+ this . nodes = [ ] ;
57
+ this . edges = [ ] ;
58
+ this . addNodesAndEdges ( project ) ;
59
+ let htmlContent = this . generateHtmlContent ( webview , this . showModuleHierarchyJsFilename ) ;
60
+ // this.fsUtils.writeFile(this.extensionContext?.asAbsolutePath(path.join('out', GenerateDependencyInjectionGraph.commandName + '.html')), htmlContent, () => { }); // For debugging
61
+ this . generateAndSaveJavascriptContent ( ( ) => { webview . html = htmlContent ; } ) ;
62
+ if ( errors . length > 0 ) {
63
+ this . showErrors ( errors , `Parsing of ${ errors . length > 1 ? 'some' : 'one' } of the project files failed.\n` ) ;
48
64
}
49
- } ,
50
- undefined ,
51
- this . extensionContext . subscriptions
52
- ) ;
53
- var workspaceFolder = this . fsUtils . getWorkspaceFolder ( ) ;
54
- const errors : string [ ] = [ ] ;
55
- const project : Project = ModuleManager . scanProject ( workspaceFolder , errors , this . isTypescriptFile ) ;
56
- this . nodes = [ ] ;
57
- this . edges = [ ] ;
58
- this . addNodesAndEdges ( project , this . appendNodes , this . appendEdges ) ;
59
- let htmlContent = this . generateHtmlContent ( webview , this . showModuleHierarchyJsFilename ) ;
60
- // this.fsUtils.writeFile(this.extensionContext?.asAbsolutePath(path.join('out', GenerateDependencyInjectionGraph.commandName + '.html')), htmlContent, () => { }); // For debugging
61
- this . generateAndSaveJavascriptContent ( ( ) => { webview . html = htmlContent ; } ) ;
62
- if ( errors . length > 0 ) {
63
- this . showErrors ( errors , `Parsing of ${ errors . length > 1 ? 'some' : 'one' } of the project files failed.\n` ) ;
64
65
}
65
- }
66
66
67
- private generateAndSaveJavascriptContent ( callback : ( ) => any ) {
68
- const nodesJson = this . nodes
69
- . map ( node => { return node . toJsonString ( ) ; } )
70
- . join ( ',\n' ) ;
71
- const edgesJson = this . edges
72
- . map ( edge => { return edge . toJsonString ( ) ; } )
73
- . join ( ',\n' ) ;
67
+ private generateAndSaveJavascriptContent ( callback : ( ) => any ) {
68
+ const nodesJson = this . nodes
69
+ . map ( node => { return node . toJsonString ( ) ; } )
70
+ . join ( ',\n' ) ;
71
+ const edgesJson = this . edges
72
+ . map ( edge => { return edge . toJsonString ( ) ; } )
73
+ . join ( ',\n' ) ;
74
74
75
- try {
76
- const jsContent = this . generateJavascriptContent ( nodesJson , edgesJson ) ;
77
- this . fsUtils . writeFile (
78
- this . extensionContext ?. asAbsolutePath ( path . join ( '.' , this . showModuleHierarchyJsFilename ) ) ,
79
- jsContent ,
80
- callback
81
- ) ;
82
- }
83
- catch ( ex ) {
84
- console . log ( 'Angular Tools Exception:' + ex ) ;
75
+ try {
76
+ const jsContent = this . generateJavascriptContent ( nodesJson , edgesJson ) ;
77
+ this . fsUtils . writeFile (
78
+ this . extensionContext ?. asAbsolutePath ( path . join ( '.' , this . showModuleHierarchyJsFilename ) ) ,
79
+ jsContent ,
80
+ callback
81
+ ) ;
82
+ }
83
+ catch ( ex ) {
84
+ console . log ( 'Angular Tools Exception:' + ex ) ;
85
+ }
85
86
}
86
- }
87
87
88
- generatedComponentNode ( component : Component ) : string {
89
- let nodeContent : string = '' ;
90
- nodeContent = `<b>${ component . name } </b>` ;
91
- if ( component . inputs . length > 0 ) {
92
- const inputs = component . inputs . map ( i => i . name ) . join ( ", " ) ;
93
- nodeContent += `\\n<b>Inputs: </b> ${ inputs } ` ;
94
- }
95
- if ( component . outputs . length > 0 ) {
96
- const outputs = component . outputs . map ( i => i . name ) . join ( ", " ) ;
97
- nodeContent += `\\n<b>Outputs: </b> ${ outputs } ` ;
98
- }
99
- if ( component . viewChilds . length > 0 ) {
100
- const viewchilds = component . viewChilds . map ( i => i . name ) . join ( ", " ) ;
101
- nodeContent += `\\n<b>Viewchilds: </b> ${ viewchilds } ` ;
102
- }
103
- if ( component . viewChildren . length > 0 ) {
104
- const viewchildren = component . viewChildren . map ( i => i . name ) . join ( ", " ) ;
105
- nodeContent += `\\n<b>Viewchildren: </b> ${ viewchildren } ` ;
106
- }
107
- if ( component . contentChilds . length > 0 ) {
108
- const contentchilds = component . contentChilds . map ( i => i . name ) . join ( ", " ) ;
109
- nodeContent += `\\n<b>Contentchilds: </b> ${ contentchilds } ` ;
88
+ private getNodeLabel ( entity : Component | NamedEntity ) : string {
89
+ let nodeContent : string = '' ;
90
+ nodeContent = `<b>${ entity . name } </b>` ;
91
+ if ( entity instanceof Component ) {
92
+ if ( entity . inputs . length > 0 ) {
93
+ const inputs = entity . inputs . map ( i => i . name ) . join ( ", " ) ;
94
+ nodeContent += `\\n<b>Inputs: </b> ${ inputs } ` ;
95
+ }
96
+ if ( entity . outputs . length > 0 ) {
97
+ const outputs = entity . outputs . map ( i => i . name ) . join ( ", " ) ;
98
+ nodeContent += `\\n<b>Outputs: </b> ${ outputs } ` ;
99
+ }
100
+ if ( entity . viewChilds . length > 0 ) {
101
+ const viewchilds = entity . viewChilds . map ( i => i . name ) . join ( ", " ) ;
102
+ nodeContent += `\\n<b>Viewchilds: </b> ${ viewchilds } ` ;
103
+ }
104
+ if ( entity . viewChildren . length > 0 ) {
105
+ const viewchildren = entity . viewChildren . map ( i => i . name ) . join ( ", " ) ;
106
+ nodeContent += `\\n<b>Viewchildren: </b> ${ viewchildren } ` ;
107
+ }
108
+ if ( entity . contentChilds . length > 0 ) {
109
+ const contentchilds = entity . contentChilds . map ( i => i . name ) . join ( ", " ) ;
110
+ nodeContent += `\\n<b>Contentchilds: </b> ${ contentchilds } ` ;
111
+ }
112
+ if ( entity . contentChildren . length > 0 ) {
113
+ const contentchildren = entity . contentChildren . map ( i => i . name ) . join ( ", " ) ;
114
+ nodeContent += `\\n<b>Contentchildren: </b> ${ contentchildren } ` ;
115
+ }
116
+ }
117
+ return nodeContent ;
110
118
}
111
- if ( component . contentChildren . length > 0 ) {
112
- const contentchildren = component . contentChildren . map ( i => i . name ) . join ( ", " ) ;
113
- nodeContent += `\\n<b>Contentchildren: </b> ${ contentchildren } ` ;
119
+
120
+ private addNodesAndEdges ( project : Project ) {
121
+ this . addNamedEntityNodeAndEdges ( project . components , NodeType . component , ArrowType . injectable ) ;
122
+ this . addNamedEntityNodeAndEdges ( project . injectables , NodeType . injectable , ArrowType . injectable ) ;
123
+ this . addNamedEntityNodeAndEdges ( project . directives , NodeType . directive , ArrowType . injectable ) ;
124
+ this . addNamedEntityNodeAndEdges ( project . pipes , NodeType . pipe , ArrowType . injectable ) ;
114
125
}
115
- return nodeContent ;
116
- }
117
126
118
- addNodesAndEdges ( project : Project , appendNodes : ( nodeList : Node [ ] ) => void , appendEdges : ( edgeList : Edge [ ] ) => void ) {
119
- project . components . forEach ( component => {
120
- let componentFilename = component . filename . replace ( this . workspaceDirectory , '.' ) ;
121
- componentFilename = componentFilename . split ( '\\' ) . join ( '/' ) ;
122
- const componentPosition = this . graphState . nodePositions [ component . name ] ;
123
- appendNodes ( [ new Node ( component . name , this . generatedComponentNode ( component ) , componentFilename , component . filename , false , NodeType . component , componentPosition ) ] ) ;
124
- component . dependencies . forEach ( injectable => {
125
- const injectablePosition = this . graphState . nodePositions [ injectable . name ] ;
126
- appendNodes ( [ new Node ( injectable . name , injectable . name , injectable . filename . replace ( this . workspaceDirectory , '' ) , injectable . filename , false , NodeType . injectable , injectablePosition ) ] ) ;
127
- appendEdges ( [ new Edge ( ( this . edges . length + 1 ) . toString ( ) , injectable . name , component . name , ArrowType . injectable ) ] ) ;
127
+ private addNamedEntityNodeAndEdges ( namedEntityMap : Map < string , Component | NamedEntity > , noteType : NodeType , arrowType : ArrowType ) {
128
+ namedEntityMap . forEach ( namedEntity => {
129
+ let namedEntityFilename = namedEntity . filename . replace ( this . workspaceDirectory , '.' ) ;
130
+ namedEntityFilename = namedEntityFilename . split ( '\\' ) . join ( '/' ) ;
131
+ const entityPosition = this . graphState . nodePositions [ namedEntity . name ] ;
132
+ this . appendNodes ( [ new Node ( namedEntity . name , this . getNodeLabel ( namedEntity ) , namedEntityFilename , namedEntity . filename , false , noteType , entityPosition ) ] ) ;
133
+ namedEntity . dependencies . forEach ( dependency => {
134
+ const dependencyPosition = this . graphState . nodePositions [ dependency . name ] ;
135
+ this . appendNodes ( [ new Node ( dependency . name , dependency . name , dependency . filename . replace ( this . workspaceDirectory , '' ) , dependency . filename , false , NodeType . injectable , dependencyPosition ) ] ) ;
136
+ this . appendEdges ( [ new Edge ( ( this . edges . length + 1 ) . toString ( ) , dependency . name , namedEntity . name , arrowType ) ] ) ;
137
+ } ) ;
128
138
} ) ;
129
- } ) ;
130
- project . injectables . forEach ( injectable => {
131
- injectable . dependencies . forEach ( dependency => {
132
- const dependencyPosition = this . graphState . nodePositions [ dependency . name ] ;
133
- appendNodes ( [ new Node ( dependency . name , dependency . name , dependency . filename . replace ( this . workspaceDirectory , '' ) , dependency . filename , false , NodeType . injectable , dependencyPosition ) ] ) ;
134
- appendEdges ( [ new Edge ( ( this . edges . length + 1 ) . toString ( ) , dependency . name , injectable . name , ArrowType . injectable ) ] ) ;
135
- } ) ;
136
- } ) ;
137
- }
139
+ }
138
140
139
- generateJavascriptContent ( nodesJson : string , edgesJson : string ) {
140
- let template = fs . readFileSync ( this . extensionContext ?. asAbsolutePath ( path . join ( 'templates' , this . templateJsFilename ) ) , 'utf8' ) ;
141
- let jsContent = template . replace ( 'const nodes = new vis.DataSet([]);' , `var nodes = new vis.DataSet([${ nodesJson } ]);` ) ;
142
- jsContent = jsContent . replace ( 'const edges = new vis.DataSet([]);' , `var edges = new vis.DataSet([${ edgesJson } ]);` ) ;
143
- jsContent = jsContent . replace ( 'type: "triangle" // edge arrow to type' , `type: "${ this . config . dependencyInjectionEdgeArrowToType } " // edge arrow to type}` ) ;
144
- jsContent = jsContent . replace ( 'ctx.strokeStyle = \'blue\'; // graph selection guideline color' , `ctx.strokeStyle = '${ this . config . graphSelectionGuidelineColor } '; // graph selection guideline color` ) ;
145
- jsContent = jsContent . replace ( 'ctx.lineWidth = 1; // graph selection guideline width' , `ctx.lineWidth = ${ this . config . graphSelectionGuidelineWidth } ; // graph selection guideline width` ) ;
146
- jsContent = jsContent . replace ( 'selectionCanvasContext.strokeStyle = \'red\';' , `selectionCanvasContext.strokeStyle = '${ this . config . graphSelectionColor } ';` ) ;
147
- jsContent = jsContent . replace ( 'selectionCanvasContext.lineWidth = 2;' , `selectionCanvasContext.lineWidth = ${ this . config . graphSelectionWidth } ;` ) ;
148
- jsContent = jsContent . replace ( 'let showHierarchicalOptionsCheckboxChecked = false;' , `let showHierarchicalOptionsCheckboxChecked = ${ this . graphState . showHierarchicalOptions } ;` ) ;
149
- jsContent = jsContent . replace ( 'let hierarchicalOptionsDirectionSelectValue = undefined;' , `let hierarchicalOptionsDirectionSelectValue = '${ this . graphState . graphDirection } ';` ) ;
150
- jsContent = jsContent . replace ( 'let hierarchicalOptionsSortMethodSelectValue = undefined;' , `let hierarchicalOptionsSortMethodSelectValue = '${ this . graphState . graphLayout } ';` ) ;
151
- jsContent = this . setGraphState ( jsContent ) ;
152
- return jsContent ;
153
- }
141
+ private generateJavascriptContent ( nodesJson : string , edgesJson : string ) {
142
+ let template = fs . readFileSync ( this . extensionContext ?. asAbsolutePath ( path . join ( 'templates' , this . templateJsFilename ) ) , 'utf8' ) ;
143
+ let jsContent = template . replace ( 'const nodes = new vis.DataSet([]);' , `var nodes = new vis.DataSet([${ nodesJson } ]);` ) ;
144
+ jsContent = jsContent . replace ( 'const edges = new vis.DataSet([]);' , `var edges = new vis.DataSet([${ edgesJson } ]);` ) ;
145
+ jsContent = jsContent . replace ( 'type: "triangle" // edge arrow to type' , `type: "${ this . config . dependencyInjectionEdgeArrowToType } " // edge arrow to type}` ) ;
146
+ jsContent = jsContent . replace ( 'ctx.strokeStyle = \'blue\'; // graph selection guideline color' , `ctx.strokeStyle = '${ this . config . graphSelectionGuidelineColor } '; // graph selection guideline color` ) ;
147
+ jsContent = jsContent . replace ( 'ctx.lineWidth = 1; // graph selection guideline width' , `ctx.lineWidth = ${ this . config . graphSelectionGuidelineWidth } ; // graph selection guideline width` ) ;
148
+ jsContent = jsContent . replace ( 'selectionCanvasContext.strokeStyle = \'red\';' , `selectionCanvasContext.strokeStyle = '${ this . config . graphSelectionColor } ';` ) ;
149
+ jsContent = jsContent . replace ( 'selectionCanvasContext.lineWidth = 2;' , `selectionCanvasContext.lineWidth = ${ this . config . graphSelectionWidth } ;` ) ;
150
+ jsContent = jsContent . replace ( 'let showHierarchicalOptionsCheckboxChecked = false;' , `let showHierarchicalOptionsCheckboxChecked = ${ this . graphState . showHierarchicalOptions } ;` ) ;
151
+ jsContent = jsContent . replace ( 'let hierarchicalOptionsDirectionSelectValue = undefined;' , `let hierarchicalOptionsDirectionSelectValue = '${ this . graphState . graphDirection } ';` ) ;
152
+ jsContent = jsContent . replace ( 'let hierarchicalOptionsSortMethodSelectValue = undefined;' , `let hierarchicalOptionsSortMethodSelectValue = '${ this . graphState . graphLayout } ';` ) ;
153
+ jsContent = this . setGraphState ( jsContent ) ;
154
+ return jsContent ;
155
+ }
154
156
}
0 commit comments