1- // Deal with debugging flag
2-
1+ // Deal with debugging flag.
32exports . activate = function ( ) {
43 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
5- console . log ( "LSL extension is activated." ) ;
4+ console . info ( "LSL extension is activated." ) ;
65 }
76}
87
98exports . deactivate = function ( ) {
109 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
11- console . log ( "LSL extension is being deactivated." ) ;
10+ console . info ( "LSL extension is being deactivated." ) ;
1211 }
1312}
1413
15- // Register menu items
16-
14+ // Register menu items.
1715nova . commands . register ( "gwynethllewelyn.LindenScriptingLanguage.search" , ( editor ) => {
1816 var query = editor . getTextInRange ( editor . selectedRanges [ 0 ] ) . trim ( ) ;
1917
@@ -26,13 +24,24 @@ nova.commands.register("gwynethllewelyn.LindenScriptingLanguage.search", (editor
2624} ) ;
2725
2826nova . commands . register ( "gwynethllewelyn.LindenScriptingLanguage.lint" , ( editor ) => {
29- console . log ( 'Not really implemented yet, I think' ) ;
27+ var what = editor . documentText . MD5 ( ) ;
28+
29+ console . log ( 'Not really implemented yet, I think; MD5 is' , what ) ;
3030} ) ;
3131
3232// Create main class and activate it
3333class LSLinter {
34- constructor ( ) { }
34+ constructor ( ) {
35+ if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
36+ console . info ( "Entering LSLint constructor..." ) ;
37+ }
38+ }
3539
40+ /**
41+ * Constructs the path to the executable, based on existing path data.
42+ *
43+ * @returns {string } Path name to the executable.
44+ */
3645 getExecutablePath ( ) {
3746 let globalExecutable = nova . config
3847 . get ( "gwynethllewelyn.LindenScriptingLanguage.executablePath" , "string" )
@@ -53,17 +62,23 @@ class LSLinter {
5362 ) ;
5463 }
5564
56- let path = globalExecutable || bundledExecutable ;
65+ let execPath = bundledExecutable ?? globalExecutable ;
5766
5867 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
59- console . log ( "lslint executable path:" , path ) ;
68+ console . info ( 'getExecutablePath() will return path: "%s"' , execPath ) ;
6069 }
6170
62- return path ;
71+ return execPath ;
6372 }
6473
74+ /**
75+ * Returns either the path to the user-defined builtins.txt, or constructs the path to
76+ * the extension-provided builtins.txt.
77+ *
78+ * @returns {string } Path name to builtins.txt.
79+ */
6580 getBuiltins ( ) {
66- let customBuiltins = nova . config . get (
81+ var customBuiltins = nova . config . get (
6782 'gwynethllewelyn.LindenScriptingLanguage.builtins' ,
6883 'string'
6984 ) ;
@@ -74,55 +89,114 @@ class LSLinter {
7489 "builtins.txt"
7590 ) ;
7691
77- customBuiltins = nova . fs . stat ( customBuiltins ) != undefined ?
78- customBuiltins :
79- null ;
92+ if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
93+ console . info ( 'getBuiltins() constructed defaultBuiltins = "%s"' , defaultBuiltins ) ;
94+ }
95+ try {
96+ customBuiltins = nova . fs . stat ( customBuiltins ) != undefined ?
97+ customBuiltins :
98+ null ;
99+ } catch ( error ) {
100+ console . warn ( "getBuiltins() could not find a valid builtins.txt path '%s' — throws: '%s'" , customBuiltins , error . toString ( ) ) ;
101+ }
80102
81- let selectedBuiltins = customBuiltins || defaultBuiltins ;
103+ let selectedBuiltins = customBuiltins ?? defaultBuiltins ;
82104
83105 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
84- console . log ( "Linting builtins path: " + selectedBuiltins ) ;
106+ console . log ( 'getBuiltins() will return path: "%s"' , selectedBuiltins ) ;
85107 }
86108
87109 return selectedBuiltins ;
88110 }
89111
90112 provideIssues ( editor ) {
91- let issues = [ ] ;
92113 let self = this ;
93114
94115 return new Promise ( function ( resolve ) {
116+ /**
117+ * Randomly generated filename, to be used as scrap (so we don't
118+ * break anything).
119+ *
120+ * @type {string }
121+ */
95122 let fileName = Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) +
96123 Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) +
97124 ".lsl" ;
125+ // Get the whole document. This makes sense, because the LSLinter cannot
126+ // work just on LSL fragments. (gwyneth 20240214)
98127 let range = new Range ( 0 , editor . document . length ) ;
128+ /**
129+ * Full document text.
130+ * @type {string }
131+ */
99132 let documentText = editor . getTextInRange ( range ) ;
100133 let output = "" ;
101134
102135 try {
103136 nova . fs . mkdir ( nova . extension . workspaceStoragePath )
104137 } catch ( error ) {
105- // fail silently
138+ console . error ( "Nova couldn't mkdir directory '%s'" , nova . extension . workspaceStoragePath )
139+ return resolve ( [ ] ) ;
140+ }
141+
142+ /** Name of the scrap file.
143+ * @type {string }
144+ */
145+ let scrapFileName = nova . path . join ( nova . extension . workspaceStoragePath , fileName ) ;
146+ try {
147+ var lintFile = nova . fs . open ( scrapFileName , "w" ) ;
148+
149+ lintFile . write ( documentText ) ;
150+ lintFile . close ( ) ;
151+ } catch ( error ) {
152+ console . error ( "Scrap filename at '%s' could not be written!" , scrapFileName ) ;
106153 }
107154
108- let lintFile = nova . fs . open ( nova . path . join ( nova . extension . workspaceStoragePath , fileName ) , "w" ) ;
155+ /**
156+ * Path to executable; hopefully, well defined.
157+ * @type {string }
158+ */
159+ var execPath = self . getExecutablePath ( ) ;
160+
161+ /**
162+ * Path to builtins.txt.
163+ * @type {string }
164+ */
165+ var builtinsPath = self . getBuiltins ( ) ;
109166
110- lintFile . write ( documentText ) ;
111- lintFile . close ( ) ;
167+ if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
168+ console . group ( "Pre-Process() paths" ) ;
169+ console . info ( "Executable path: '%s'" , execPath ) ;
170+ console . info ( "builtins.txt path: '%s'" , builtinsPath ) ;
171+ console . info ( "Path to temporary file: '%s'" , scrapFileName ) ;
172+ console . groupEnd ( ) ;
173+ }
112174
113175 try {
114- let linter = new Process (
115- self . getExecutablePath ( ) ,
116- {
176+ // create linter with var, or else we lose scope
177+ var linter = new Process ( '/usr/bin/env' , {
117178 args : [
179+ execPath ,
118180 '-l' ,
119181 '-d' ,
120- self . getBuiltins ( )
182+ builtinsPath ,
183+ scrapFileName
121184 ] ,
122- shell : false ,
185+ shell : true ,
123186 }
124187 ) ;
188+ } catch ( error ) {
189+ console . group ( "LSLint Process activation" ) ;
190+ console . error ( "Error during LSLint Process() activation" ) ;
191+ console . info ( "Exec path: '%s'" , execPath ) ;
192+ console . info ( "Path to builtins.txt: '%s'" , builtinsPath ) ;
193+ console . info ( "Path to temporary file: '%s'" , scrapFileName ) ;
194+ console . error ( "Process() throws:" , error ) ;
195+ console . groupEnd ( ) ;
196+ return resolve ( [ ] ) ;
197+ }
125198
199+ try {
126200 // Capture LSLint output, line by line
127201 linter . onStdout ( function ( line ) {
128202 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
@@ -131,53 +205,72 @@ class LSLinter {
131205
132206 output += line ;
133207 } ) ;
208+ } catch ( error ) {
209+ console . error ( "error during linter.onStdout - " , error ) ;
210+ return resolve ( [ ] ) ;
211+ }
134212
213+ // should not throw errors!
214+ try {
135215 linter . onStderr ( function ( line ) {
136216 console . error ( 'LSLint error: ' + line ) ;
217+ return resolve ( [ ] ) ;
137218 } ) ;
219+ } catch ( error ) {
220+ console . error ( "error during linter.onStderr - " , error ) ;
221+ return resolve ( [ ] ) ;
222+ }
138223
224+ try {
139225 linter . onDidExit ( function ( ) {
140226 output = output . trim ( ) ;
141227
142228 if ( output . length === 0 ) {
143229 return resolve ( [ ] ) ;
144230 }
145231
146- if ( ! self . outputIsJson ( output ) ) {
147- console . error ( output ) ;
148-
149- return resolve ( [ ] ) ;
150- }
232+ // This might be required at some point, i.e. how to deal with
233+ // errors from the output? Easy when the errors come in a different format.
234+ // if (!self.outputIsJson(output)) {
235+ // console.error(output);
236+ // return resolve([]);
237+ // }
151238
152239 resolve ( self . parseLinterOutput ( output ) ) ;
153240
154241 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
155- console . log ( "Finished linting." ) ;
242+ console . info ( "Finished linting." ) ;
156243 }
157244
158- nova . fs . remove ( lintFile . path ) ;
245+ nova . fs . remove ( scrapFileName ) ;
159246 } ) ;
247+ } catch ( error ) {
248+ console . error ( "error during processing - " , error ) ;
249+ return resolve ( [ ] ) ;
250+ }
160251
252+ try {
161253 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
162- console . log ( "Started linting." ) ;
254+ console . info ( "Started linting." ) ;
163255 console . log ( `Running command: ${ self . getExecutablePath ( ) } -l -d ${ self . getBuiltins ( ) } ` ) ;
164256 }
165-
257+ // Execution starts here.
166258 linter . start ( ) ;
167259 } catch ( error ) {
168- console . error ( "error during processing " , error ) ;
260+ console . error ( "error during actual execution - " , error ) ;
169261 }
170262 } ) ;
171263 }
172264
173- // probably not required
174- outputIsJson ( output ) {
175- try {
176- return ( JSON . parse ( output ) && ! ! output ) ;
177- } catch ( error ) {
178- return false ;
179- }
180- }
265+ // // probably not required
266+ // outputIsJson(output) {
267+ // try {
268+ // return (JSON.parse(output) && !!output);
269+ // } catch (error) {
270+ // return false;
271+ // }
272+ // }
273+ //
181274 /*
182275 LSLint output is something like this:
183276
@@ -195,7 +288,7 @@ class LSLinter {
195288 // Split by newlines first:
196289 var lints = output . split ( / \r \n | \n / ) ;
197290 for ( var lint = 0 ; lint < lints . length - 1 ; lint ++ ) {
198- let matches = lint . match ( / ^ \W * ( \w + ) : : \s * \( \s * ( \d * ) , \s * ( \d * ) \) - \( \s * ( \d * ) , \s * ( \d * ) \) : \s * ( .* ) $ / gmi) ;
291+ let matches = lints [ lint ] . match ( / ^ \W * ( \w + ) : : \s * \( \s * ( \d * ) , \s * ( \d * ) \) - \( \s * ( \d * ) , \s * ( \d * ) \) : \s * ( .* ) $ / gmi) ;
199292
200293 if (
201294 matches === null ||
@@ -233,9 +326,9 @@ class LSLinter {
233326 issue . endColumn = matches [ 5 ] ;
234327 issue . message = matches [ 6 ] ;
235328
236- console . log ( lint + ' --> ' + issue ) ;
237329 if ( nova . config . get ( 'gwynethllewelyn.LindenScriptingLanguage.debugging' , 'boolean' ) ) {
238- console . log ( "Found lslint:" ) ;
330+ // console.log(lint + ' --> ' + issue);
331+ console . log ( "Found lslint #%d:" , lint ) ;
239332 console . log ( "===========" ) ;
240333 console . log ( "Line: " + issue . line ) ;
241334 console . log ( "Severity: " + issue . severity ) ;
0 commit comments