@@ -12,119 +12,148 @@ on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212express or implied. See the License for the specific language governing
1313permissions and limitations under the License.
1414*/
15- 'use strict' ;
16-
17- import * as path from 'path' ;
18- import * as fs from 'fs' ;
19- import { workspace , ExtensionContext , window , WebviewPanel , Uri , commands , ViewColumn , window as VsCodeWindow } from 'vscode' ;
20- import { LanguageClient , LanguageClientOptions , ServerOptions , TransportKind } from 'vscode-languageclient/node' ;
15+ "use strict" ;
16+
17+ import * as path from "path" ;
18+ import * as fs from "fs" ;
19+ import {
20+ workspace ,
21+ ExtensionContext ,
22+ window ,
23+ WebviewPanel ,
24+ Uri ,
25+ commands ,
26+ ViewColumn ,
27+ window as VsCodeWindow ,
28+ } from "vscode" ;
29+ import {
30+ LanguageClient ,
31+ LanguageClientOptions ,
32+ ServerOptions ,
33+ TransportKind ,
34+ } from "vscode-languageclient/node" ;
2135
2236let previews : { [ index : string ] : WebviewPanel } = { } ;
2337let languageClient : LanguageClient ;
2438
2539export async function activate ( context : ExtensionContext ) {
26-
27- // The server is implemented in node
28- let serverModule = context . asAbsolutePath ( path . join ( 'server' , 'out' , 'server.js' ) ) ;
29- // The debug options for the server
30- let debugOptions = { execArgv : [ "--nolazy" , "--inspect=6010" ] } ;
31-
32- // If the extension is launched in debug mode then the debug server options are used
33- // Otherwise the run options are used
34- let serverOptions : ServerOptions = {
35- run : { module : serverModule , transport : TransportKind . ipc } ,
36- debug : { module : serverModule , transport : TransportKind . ipc , options : debugOptions }
37- } ;
38-
39- // Options to control the language client
40- let clientOptions : LanguageClientOptions = {
41- // Register the server for plain text documents
42- documentSelector : [
43- { scheme : 'file' , language : 'yaml' } ,
44- { scheme : 'file' , language : 'json' } ,
45- ] ,
46- synchronize : {
47- // Synchronize the setting section 'languageServerExample' to the server
48- configurationSection : 'cfnLint' ,
49- // Notify the server about file changes to '.clientrc files contain in the workspace
50- fileEvents : [
51- workspace . createFileSystemWatcher ( '**/.clientrc' ) ,
52- workspace . createFileSystemWatcher ( '**/*.?(e)y?(a)ml' ) ,
53- ]
54- }
55- } ;
56-
57- // Create the language client and start the client.
58- languageClient = new LanguageClient ( 'cfnLint' , 'CloudFormation linter Language Server' , serverOptions , clientOptions ) ;
59- await languageClient . start ( ) ;
60-
61- languageClient . onNotification ( 'cfn/busy' , ( ) => {
62- window . showInformationMessage ( "Linter is already running. Please try again." ) ;
63- } ) ;
64- languageClient . onNotification ( 'cfn/previewIsAvailable' , ( uri ) => {
65- reloadSidePreview ( uri , languageClient ) ;
66- } ) ;
67- languageClient . onNotification ( 'cfn/isPreviewable' , ( value ) => {
68- commands . executeCommand ( 'setContext' , 'isPreviewable' , value ) ;
69- } ) ;
70- languageClient . onNotification ( 'cfn/fileclosed' , ( uri ) => {
71- // if the user closed the template itself, we close the preview
72- if ( previews [ uri ] ) {
73- previews [ uri ] . dispose ( ) ;
74- }
75- } ) ;
76-
77- let previewDisposable = commands . registerCommand ( 'extension.sidePreview' , ( ) => {
78-
79- if ( window . activeTextEditor . document ) {
80- let uri = Uri . file ( window . activeTextEditor . document . fileName ) . toString ( ) ;
81-
82- languageClient . sendNotification ( 'cfn/requestPreview' , uri ) ;
83- }
84-
85- } ) ;
86-
87- context . subscriptions . push ( previewDisposable ) ;
88-
40+ // The server is implemented in node
41+ let serverModule = context . asAbsolutePath (
42+ path . join ( "server" , "out" , "server.js" )
43+ ) ;
44+ // The debug options for the server
45+ let debugOptions = { execArgv : [ "--nolazy" , "--inspect=6010" ] } ;
46+
47+ // If the extension is launched in debug mode then the debug server options are used
48+ // Otherwise the run options are used
49+ let serverOptions : ServerOptions = {
50+ run : { module : serverModule , transport : TransportKind . ipc } ,
51+ debug : {
52+ module : serverModule ,
53+ transport : TransportKind . ipc ,
54+ options : debugOptions ,
55+ } ,
56+ } ;
57+
58+ // Options to control the language client
59+ let clientOptions : LanguageClientOptions = {
60+ // Register the server for plain text documents
61+ documentSelector : [
62+ { scheme : "file" , language : "yaml" } ,
63+ { scheme : "file" , language : "json" } ,
64+ ] ,
65+ synchronize : {
66+ // Synchronize the setting section 'languageServerExample' to the server
67+ configurationSection : "cfnLint" ,
68+ // Notify the server about file changes to '.clientrc files contain in the workspace
69+ fileEvents : [
70+ workspace . createFileSystemWatcher ( "**/.clientrc" ) ,
71+ workspace . createFileSystemWatcher ( "**/*.?(e)y?(a)ml" ) ,
72+ ] ,
73+ } ,
74+ } ;
75+
76+ // Create the language client and start the client.
77+ languageClient = new LanguageClient (
78+ "cfnLint" ,
79+ "CloudFormation linter Language Server" ,
80+ serverOptions ,
81+ clientOptions
82+ ) ;
83+ await languageClient . start ( ) ;
84+
85+ languageClient . onNotification ( "cfn/busy" , ( ) => {
86+ window . showInformationMessage (
87+ "Linter is already running. Please try again."
88+ ) ;
89+ } ) ;
90+ languageClient . onNotification ( "cfn/previewIsAvailable" , ( uri ) => {
91+ reloadSidePreview ( uri , languageClient ) ;
92+ } ) ;
93+ languageClient . onNotification ( "cfn/isPreviewable" , ( value ) => {
94+ commands . executeCommand ( "setContext" , "isPreviewable" , value ) ;
95+ } ) ;
96+ languageClient . onNotification ( "cfn/fileclosed" , ( uri ) => {
97+ // if the user closed the template itself, we close the preview
98+ if ( previews [ uri ] ) {
99+ previews [ uri ] . dispose ( ) ;
100+ }
101+ } ) ;
102+
103+ let previewDisposable = commands . registerCommand (
104+ "extension.sidePreview" ,
105+ ( ) => {
106+ if ( window . activeTextEditor . document ) {
107+ let uri = Uri . file (
108+ window . activeTextEditor . document . fileName
109+ ) . toString ( ) ;
110+
111+ languageClient . sendNotification ( "cfn/requestPreview" , uri ) ;
112+ }
113+ }
114+ ) ;
115+
116+ context . subscriptions . push ( previewDisposable ) ;
89117}
90118
91119function reloadSidePreview ( file : string , languageClient : LanguageClient ) {
92- let uri = Uri . parse ( file ) ;
93- let stringifiedUri = uri . toString ( ) ;
94- let dotFile = uri . fsPath + ".dot" ;
95-
96- if ( ! fs . existsSync ( dotFile ) ) {
97- window . showErrorMessage ( "Error previewing graph. Please run `pip3 install cfn-lint pydot --upgrade`" ) ;
98- return ;
99- }
100- let content = fs . readFileSync ( dotFile , 'utf8' ) ;
101-
102- if ( ! previews [ stringifiedUri ] ) {
103- previews [ stringifiedUri ] = VsCodeWindow . createWebviewPanel (
104- 'cfnLintPreview' , // Identifies the type of the webview. Used internally
105- 'Template: ' + dotFile . slice ( 0 , - 4 ) , // Title of the panel displayed to the user
106- ViewColumn . Two , // Editor column to show the new webview panel in.
107- {
108- enableScripts : true ,
109- }
110- ) ;
111- previews [ stringifiedUri ] . onDidDispose ( ( ) => {
112- // if the user closed the preview
113- delete previews [ stringifiedUri ] ;
114- fs . unlinkSync ( dotFile ) ;
115- languageClient . sendNotification ( 'cfn/previewClosed' , stringifiedUri ) ;
116- } ) ;
117- }
118-
119- const panel = previews [ stringifiedUri ] ;
120- panel . webview . html = getPreviewContent ( content ) ;
120+ let uri = Uri . parse ( file ) ;
121+ let stringifiedUri = uri . toString ( ) ;
122+ let dotFile = uri . fsPath + ".dot" ;
123+
124+ if ( ! fs . existsSync ( dotFile ) ) {
125+ window . showErrorMessage (
126+ "Error previewing graph. Please run `pip3 install cfn-lint pydot --upgrade`"
127+ ) ;
128+ return ;
129+ }
130+ let content = fs . readFileSync ( dotFile , "utf8" ) ;
131+
132+ if ( ! previews [ stringifiedUri ] ) {
133+ previews [ stringifiedUri ] = VsCodeWindow . createWebviewPanel (
134+ "cfnLintPreview" , // Identifies the type of the webview. Used internally
135+ "Template: " + dotFile . slice ( 0 , - 4 ) , // Title of the panel displayed to the user
136+ ViewColumn . Two , // Editor column to show the new webview panel in.
137+ {
138+ enableScripts : true ,
139+ }
140+ ) ;
141+ previews [ stringifiedUri ] . onDidDispose ( ( ) => {
142+ // if the user closed the preview
143+ delete previews [ stringifiedUri ] ;
144+ fs . unlinkSync ( dotFile ) ;
145+ languageClient . sendNotification ( "cfn/previewClosed" , stringifiedUri ) ;
146+ } ) ;
147+ }
148+
149+ const panel = previews [ stringifiedUri ] ;
150+ panel . webview . html = getPreviewContent ( content ) ;
121151}
122152
123153function getPreviewContent ( content : String ) : string {
124-
125- let multilineString = "`" + content + "`" ;
126- // FIXME is there a better way of converting from dot to svg that is not using cdn urls?
127- return `
154+ let multilineString = "`" + content + "`" ;
155+ // FIXME is there a better way of converting from dot to svg that is not using cdn urls?
156+ return `
128157 <!DOCTYPE html>
129158 <body>
130159 <script src="https://cdn.jsdelivr.net/npm/[email protected] /dist/d3.min.js" integrity="sha256-Xb6SSzhH3wEPC4Vy3W70Lqh9Y3Du/3KxPqI2JHQSpTw=" crossorigin="anonymous"></script> @@ -143,8 +172,8 @@ function getPreviewContent(content: String): string {
143172}
144173
145174export function deactivate ( ) : Thenable < void > | undefined {
146- if ( ! languageClient ) {
147- return undefined ;
148- }
149- return languageClient . stop ( ) ;
150- }
175+ if ( ! languageClient ) {
176+ return undefined ;
177+ }
178+ return languageClient . stop ( ) ;
179+ }
0 commit comments