@@ -182,46 +182,38 @@ export class PackageJSONContribution implements IJSONContribution {
182182 return Promise . resolve ( null ) ;
183183 }
184184
185- public collectValueSuggestions (
186- _fileName : string ,
187- location : Location ,
188- result : ISuggestionsCollector
189- ) : Thenable < any > | null {
185+ public async collectValueSuggestions ( _fileName : string , location : Location , result : ISuggestionsCollector ) : Promise < any > {
190186 if ( ! this . onlineEnabled ( ) ) {
191187 return null ;
192188 }
193189
194190 if ( ( location . matches ( [ 'dependencies' , '*' ] ) || location . matches ( [ 'devDependencies' , '*' ] ) || location . matches ( [ 'optionalDependencies' , '*' ] ) || location . matches ( [ 'peerDependencies' , '*' ] ) ) ) {
195191 const currentKey = location . path [ location . path . length - 1 ] ;
196192 if ( typeof currentKey === 'string' ) {
197- return this . npmView ( currentKey ) . then ( info => {
198- const latest = info . distTagsLatest ;
199- if ( latest ) {
200- let name = JSON . stringify ( latest ) ;
201- let proposal = new CompletionItem ( name ) ;
202- proposal . kind = CompletionItemKind . Property ;
203- proposal . insertText = name ;
204- proposal . documentation = localize ( 'json.npm.latestversion' , 'The currently latest version of the package' ) ;
205- result . add ( proposal ) ;
193+ const info = await this . fetchPackageInfo ( currentKey ) ;
194+ if ( info && info . distTagsLatest ) {
206195
207- name = JSON . stringify ( '^' + latest ) ;
208- proposal = new CompletionItem ( name ) ;
209- proposal . kind = CompletionItemKind . Property ;
210- proposal . insertText = name ;
211- proposal . documentation = localize ( 'json.npm.majorversion ' , 'Matches the most recent major version (1.x.x) ' ) ;
212- result . add ( proposal ) ;
196+ let name = JSON . stringify ( info . distTagsLatest ) ;
197+ let proposal = new CompletionItem ( name ) ;
198+ proposal . kind = CompletionItemKind . Property ;
199+ proposal . insertText = name ;
200+ proposal . documentation = localize ( 'json.npm.latestversion ' , 'The currently latest version of the package ' ) ;
201+ result . add ( proposal ) ;
213202
214- name = JSON . stringify ( '~' + latest ) ;
215- proposal = new CompletionItem ( name ) ;
216- proposal . kind = CompletionItemKind . Property ;
217- proposal . insertText = name ;
218- proposal . documentation = localize ( 'json.npm.minorversion' , 'Matches the most recent minor version (1.2.x)' ) ;
219- result . add ( proposal ) ;
220- }
221- return 0 ;
222- } , ( ) => {
223- return 0 ;
224- } ) ;
203+ name = JSON . stringify ( '^' + info . distTagsLatest ) ;
204+ proposal = new CompletionItem ( name ) ;
205+ proposal . kind = CompletionItemKind . Property ;
206+ proposal . insertText = name ;
207+ proposal . documentation = localize ( 'json.npm.majorversion' , 'Matches the most recent major version (1.x.x)' ) ;
208+ result . add ( proposal ) ;
209+
210+ name = JSON . stringify ( '~' + info . distTagsLatest ) ;
211+ proposal = new CompletionItem ( name ) ;
212+ proposal . kind = CompletionItemKind . Property ;
213+ proposal . insertText = name ;
214+ proposal . documentation = localize ( 'json.npm.minorversion' , 'Matches the most recent minor version (1.2.x)' ) ;
215+ result . add ( proposal ) ;
216+ }
225217 }
226218 }
227219 return null ;
@@ -243,39 +235,75 @@ export class PackageJSONContribution implements IJSONContribution {
243235 return null ;
244236 }
245237
246- private getInfo ( pack : string ) : Thenable < string [ ] > {
247- return this . npmView ( pack ) . then ( info => {
238+ private async getInfo ( pack : string ) : Promise < string [ ] > {
239+ let info = await this . fetchPackageInfo ( pack ) ;
240+ if ( info ) {
248241 const result : string [ ] = [ ] ;
249242 result . push ( info . description || '' ) ;
250243 result . push ( info . distTagsLatest ? localize ( 'json.npm.version.hover' , 'Latest version: {0}' , info . distTagsLatest ) : '' ) ;
251244 result . push ( info . homepage || '' ) ;
252245 return result ;
253- } , ( ) => {
254- return [ ] ;
255- } ) ;
246+ }
247+
248+ return [ ] ;
249+ }
250+
251+ private async fetchPackageInfo ( pack : string ) : Promise < ViewPackageInfo | undefined > {
252+ let info = await this . npmView ( pack ) ;
253+ if ( ! info ) {
254+ info = await this . npmjsView ( pack ) ;
255+ }
256+ return info ;
256257 }
257258
258- private npmView ( pack : string ) : Promise < ViewPackageInfo > {
259- return new Promise ( ( resolve , reject ) => {
259+
260+ private npmView ( pack : string ) : Promise < ViewPackageInfo | undefined > {
261+ return new Promise ( ( resolve , _reject ) => {
260262 const command = 'npm view --json ' + pack + ' description dist-tags.latest homepage' ;
261263 cp . exec ( command , ( error , stdout ) => {
262- if ( error ) {
263- return reject ( ) ;
264- }
265- try {
266- const content = JSON . parse ( stdout ) ;
267- resolve ( {
268- description : content [ 'description' ] ,
269- distTagsLatest : content [ 'dist-tags.latest' ] ,
270- homepage : content [ 'homepage' ]
271- } ) ;
272- } catch ( e ) {
273- reject ( ) ;
264+ if ( ! error ) {
265+ try {
266+ const content = JSON . parse ( stdout ) ;
267+ resolve ( {
268+ description : content [ 'description' ] ,
269+ distTagsLatest : content [ 'dist-tags.latest' ] ,
270+ homepage : content [ 'homepage' ]
271+ } ) ;
272+ return ;
273+ } catch ( e ) {
274+ // ignore
275+ }
274276 }
277+ resolve ( undefined ) ;
275278 } ) ;
276279 } ) ;
277280 }
278281
282+ private async npmjsView ( pack : string ) : Promise < ViewPackageInfo | undefined > {
283+ const queryUrl = 'https://registry.npmjs.org/' + encodeURIComponent ( pack ) . replace ( / % 4 0 / g, '@' ) ;
284+ try {
285+ const success = await this . xhr ( {
286+ url : queryUrl ,
287+ agent : USER_AGENT
288+ } ) ;
289+ const obj = JSON . parse ( success . responseText ) ;
290+ if ( obj ) {
291+ const latest = obj && obj [ 'dist-tags' ] && obj [ 'dist-tags' ] [ 'latest' ] ;
292+ if ( latest ) {
293+ return {
294+ description : obj . description || '' ,
295+ distTagsLatest : latest ,
296+ homepage : obj . homepage || ''
297+ } ;
298+ }
299+ }
300+ }
301+ catch ( e ) {
302+ //ignore
303+ }
304+ return undefined ;
305+ }
306+
279307 public getInfoContribution ( _fileName : string , location : Location ) : Thenable < MarkedString [ ] | null > | null {
280308 if ( ( location . matches ( [ 'dependencies' , '*' ] ) || location . matches ( [ 'devDependencies' , '*' ] ) || location . matches ( [ 'optionalDependencies' , '*' ] ) || location . matches ( [ 'peerDependencies' , '*' ] ) ) ) {
281309 const pack = location . path [ location . path . length - 1 ] ;
@@ -327,4 +355,4 @@ interface ViewPackageInfo {
327355 description : string ;
328356 distTagsLatest ?: string ;
329357 homepage ?: string ;
330- }
358+ }
0 commit comments