Skip to content

Commit 81e3750

Browse files
authored
Merge pull request #529 from jpogran/puppet-module-hover
(GH-534) Puppet Module Metadata hover provider
2 parents ddb68b3 + 6804aab commit 81e3750

File tree

5 files changed

+116
-0
lines changed

5 files changed

+116
-0
lines changed

package-lock.json

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

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@
332332
"default": [],
333333
"description": "An array of strings of experimental features to enable in the Puppet Editor Service"
334334
},
335+
"puppet.editorService.hover.showMetadataInfo": {
336+
"type": "boolean",
337+
"default": true,
338+
"description": "Enable or disable showing Puppet Module version information in the metadata.json file"
339+
},
335340
"puppet.editorService.loglevel": {
336341
"type": "string",
337342
"default": "normal",
@@ -563,6 +568,7 @@
563568
"yargs": "^13.2.4"
564569
},
565570
"dependencies": {
571+
"jsonc-parser": "~2.1.0",
566572
"viz.js": "~1.7.0",
567573
"vscode-debugadapter": "^1.19.0",
568574
"vscode-debugprotocol": "^1.19.0",

src/extension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ILogger } from './logging';
2121
import { OutputChannelLogger } from './logging/outputchannel';
2222
import { legacySettings, SettingsFromWorkspace } from './settings';
2323
import { Reporter, reporter } from './telemetry/telemetry';
24+
import { PuppetModuleHoverFeature } from './feature/PuppetModuleHoverFeature';
2425

2526
const axios = require('axios');
2627

@@ -103,6 +104,10 @@ export function activate(context: vscode.ExtensionContext) {
103104
extensionFeatures.push(new NodeGraphFeature(puppetLangID, connectionHandler, logger, extContext));
104105
extensionFeatures.push(new PuppetResourceFeature(extContext, connectionHandler, logger));
105106
extensionFeatures.push(new DebuggingFeature(debugType, configSettings, extContext, logger));
107+
108+
if(settings.hover.showMetadataInfo){
109+
extensionFeatures.push(new PuppetModuleHoverFeature(extContext, logger));
110+
}
106111
}
107112

108113
export function deactivate() {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import * as vscode from 'vscode';
2+
import { getLocation } from 'jsonc-parser';
3+
import { IFeature } from '../feature';
4+
import { ILogger } from '../logging';
5+
6+
export class PuppetModuleHoverFeature implements IFeature {
7+
constructor(public context: vscode.ExtensionContext, public logger: ILogger) {
8+
let selector = [{ language: 'json', scheme: '*', pattern: '**/metadata.json' }];
9+
context.subscriptions.push(vscode.languages.registerHoverProvider(selector, new PuppetModuleHoverProvider(logger)));
10+
}
11+
12+
dispose() {}
13+
}
14+
15+
export class PuppetModuleHoverProvider implements vscode.HoverProvider {
16+
constructor(public logger: ILogger) {}
17+
18+
provideHover(
19+
document: vscode.TextDocument,
20+
position: vscode.Position,
21+
token: vscode.CancellationToken
22+
): Thenable<vscode.Hover> | null {
23+
const offset = document.offsetAt(position);
24+
const location = getLocation(document.getText(), offset);
25+
26+
if (location.isAtPropertyKey) {
27+
return;
28+
}
29+
30+
if (location.path[0] !== 'dependencies') {
31+
return;
32+
}
33+
34+
if (location.path[2] !== 'name') {
35+
return;
36+
}
37+
38+
const range = document.getWordRangeAtPosition(position);
39+
const word = document.getText(range);
40+
41+
this.logger.debug('Metadata hover info found ' + word + ' module');
42+
43+
let name = word
44+
.replace('"', '')
45+
.replace('"', '')
46+
.replace('/', '-');
47+
48+
return this.getModuleInfo(name).then(function(result: any) {
49+
let msg: string[] = [];
50+
msg.push(`### ${result.slug}`);
51+
52+
const releaseDate = new Date(result.releases[0].created_at);
53+
const dateformat = require('dateformat');
54+
msg.push(`\nLatest version: ${result.releases[0].version} (${dateformat(releaseDate, 'dS mmmm yyyy')})`);
55+
56+
if (result.endorsement !== null) {
57+
const endorsementCapitalized = result.endorsement.charAt(0).toUpperCase() + result.endorsement.slice(1);
58+
msg.push(`\nEndorsement: ${endorsementCapitalized}`);
59+
}
60+
61+
msg.push(`\nOwner: ${result.owner.slug}`);
62+
63+
const forgeUri = `https://forge.puppet.com/${result.owner.username}/${result.name}`;
64+
msg.push(`\nForge: \[${forgeUri}\](${forgeUri})\n`);
65+
66+
if (result.homepage_url !== null) {
67+
msg.push(`\nProject: \[${result.homepage_url}\](${result.homepage_url})\n`);
68+
}
69+
70+
let md = msg.join('\n');
71+
72+
return Promise.resolve(new vscode.Hover(new vscode.MarkdownString(md), range));
73+
});
74+
}
75+
76+
private getModuleInfo(name: string) {
77+
var options = {
78+
url: `https://forgeapi.puppet.com/v3/modules/${name}?exclude_fields=readme%20changelog%20license%20reference`
79+
};
80+
return new Promise(function(resolve, reject) {
81+
const request = require('request');
82+
request.get(options, function(err, resp, body) {
83+
if (err) {
84+
reject(err);
85+
} else {
86+
resolve(JSON.parse(body));
87+
}
88+
});
89+
});
90+
}
91+
}

src/settings.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export interface IEditorServiceSettings {
5353
export interface IFormatSettings {
5454
enable?: boolean;
5555
}
56+
export interface IHoverSettings {
57+
showMetadataInfo?: boolean;
58+
// showPuppetfileInfo?: boolean; Future use
59+
}
5660

5761
export interface ILintSettings {
5862
// Future Use
@@ -71,6 +75,7 @@ export interface INotificationSettings {
7175
export interface ISettings {
7276
editorService?: IEditorServiceSettings;
7377
format?: IFormatSettings;
78+
hover?: IHoverSettings;
7479
installDirectory?: string;
7580
installType?: PuppetInstallType;
7681
lint?: ILintSettings;
@@ -163,6 +168,9 @@ export function DefaultWorkspaceSettings(): ISettings {
163168
format: {
164169
enable: true
165170
},
171+
hover: {
172+
showMetadataInfo: true,
173+
},
166174
installDirectory: undefined,
167175
installType: PuppetInstallType.AUTO,
168176
lint: {
@@ -186,6 +194,7 @@ export function SettingsFromWorkspace(): ISettings {
186194
let settings = {
187195
editorService: workspaceConfig.get<IEditorServiceSettings>("editorService", defaults.editorService),
188196
format: workspaceConfig.get<IFormatSettings>("format", defaults.format),
197+
hover: workspaceConfig.get<IHoverSettings>("hover", defaults.hover),
189198
installDirectory: workspaceConfig.get<string>("installDirectory", defaults.installDirectory),
190199
installType: workspaceConfig.get<PuppetInstallType>("installType", defaults.installType),
191200
lint: workspaceConfig.get<ILintSettings>("lint", defaults.lint),

0 commit comments

Comments
 (0)