fabric8-analytics-lsp-server
Advanced tools
Comparing version 0.4.15 to 0.4.16
171
collector.js
@@ -6,5 +6,13 @@ /* -------------------------------------------------------------------------------------------- | ||
'use strict'; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.GomodDependencyCollector = exports.ReqDependencyCollector = exports.PomXmlDependencyCollector = exports.PackageJsonCollector = void 0; | ||
const Xml2Object = require("xml2object"); | ||
exports.GomodDependencyCollector = exports.ReqDependencyCollector = exports.PackageJsonCollector = void 0; | ||
const jsonAst = require("json-to-ast"); | ||
@@ -23,15 +31,2 @@ const types_1 = require("./types"); | ||
} | ||
/* Dependency class that can be created from `IKeyValueEntry` */ | ||
class Dependency { | ||
constructor(dependency) { | ||
this.name = { | ||
value: dependency.key, | ||
position: dependency.key_position | ||
}; | ||
this.version = { | ||
value: dependency.value.object, | ||
position: dependency.value_position | ||
}; | ||
} | ||
} | ||
class NaivePyParser { | ||
@@ -56,3 +51,3 @@ constructor(contents) { | ||
entry.value_position = { line: index + 1, column: req.indexOf(version) + 1 }; | ||
dependencies.push(new Dependency(entry)); | ||
dependencies.push(new types_1.Dependency(entry)); | ||
} | ||
@@ -72,5 +67,7 @@ return dependencies; | ||
} | ||
async collect(contents) { | ||
let parser = new NaivePyParser(contents); | ||
return parser.parse(); | ||
collect(contents) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let parser = new NaivePyParser(contents); | ||
return parser.parse(); | ||
}); | ||
} | ||
@@ -96,3 +93,3 @@ } | ||
replaceEntry.value_position = { line: index + 1, column: (replaceWithIndex + replaceWithVersion.index) }; | ||
const replaceDependency = new Dependency(replaceEntry); | ||
const replaceDependency = new types_1.Dependency(replaceEntry); | ||
const isReplaceToVersion = replaceToVersion && replaceToVersion.length > 0; | ||
@@ -140,3 +137,3 @@ return { key: replaceTo[0].trim() + (isReplaceToVersion ? ('@v' + replaceToVersion[0]) : ''), value: replaceDependency }; | ||
// Push all direct and indirect modules present in go.mod (manifest) | ||
dependencies.push(new Dependency(entry)); | ||
dependencies.push(new types_1.Dependency(entry)); | ||
} | ||
@@ -175,3 +172,3 @@ } | ||
entry.value_position = replaceDependency.version.position; | ||
goPackageDeps.push(new Dependency(entry)); | ||
goPackageDeps.push(new types_1.Dependency(entry)); | ||
} | ||
@@ -195,100 +192,28 @@ }); | ||
} | ||
async collect(contents) { | ||
let promiseExec = new Promise((resolve, reject) => { | ||
const vscodeRootpath = this.manifestFile.replace("file://", "").replace("/go.mod", ""); | ||
child_process_1.exec(utils_1.getGoLangImportsCmd(), { shell: process.env["SHELL"], windowsHide: true, cwd: vscodeRootpath, maxBuffer: 1024 * 1200 }, (error, stdout, stderr) => { | ||
if (error) { | ||
console.error(`Command failed, environment SHELL: [${process.env["SHELL"]}] PATH: [${process.env["PATH"]}] CWD: [${process.env["CWD"]}]`); | ||
if (error.code == 127) { // Invalid command, go executable not found | ||
reject(`Unable to locate '${config_1.config.golang_executable}'`); | ||
collect(contents) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let promiseExec = new Promise((resolve, reject) => { | ||
const vscodeRootpath = this.manifestFile.replace("file://", "").replace("/go.mod", ""); | ||
child_process_1.exec(utils_1.getGoLangImportsCmd(), { shell: process.env["SHELL"], windowsHide: true, cwd: vscodeRootpath, maxBuffer: 1024 * 1200 }, (error, stdout, stderr) => { | ||
if (error) { | ||
console.error(`Command failed, environment SHELL: [${process.env["SHELL"]}] PATH: [${process.env["PATH"]}] CWD: [${process.env["CWD"]}]`); | ||
if (error.code == 127) { // Invalid command, go executable not found | ||
reject(`Unable to locate '${config_1.config.golang_executable}'`); | ||
} | ||
else { | ||
reject(`Unable to execute '${config_1.config.golang_executable} list' command, run '${config_1.config.golang_executable} mod tidy' to know more`); | ||
} | ||
} | ||
else { | ||
reject(`Unable to execute '${config_1.config.golang_executable} list' command, run '${config_1.config.golang_executable} mod tidy' to know more`); | ||
resolve(new Set(stdout.toString().split("\n"))); | ||
} | ||
} | ||
else { | ||
resolve(new Set(stdout.toString().split("\n"))); | ||
} | ||
}); | ||
}); | ||
const goImports = yield promiseExec; | ||
let parser = new NaiveGomodParser(contents, goImports); | ||
return parser.parse(); | ||
}); | ||
const goImports = await promiseExec; | ||
let parser = new NaiveGomodParser(contents, goImports); | ||
return parser.parse(); | ||
} | ||
} | ||
exports.GomodDependencyCollector = GomodDependencyCollector; | ||
class NaivePomXmlSaxParser { | ||
constructor(stream) { | ||
this.dependencies = []; | ||
this.isDependency = false; | ||
this.versionStartLine = 0; | ||
this.versionStartColumn = 0; | ||
this.stream = stream; | ||
this.parser = this.createParser(); | ||
} | ||
createParser() { | ||
let parser = new Xml2Object(["dependency"], { strict: true, trackPosition: true }); | ||
let deps = this.dependencies; | ||
let versionLine = this.versionStartLine; | ||
let versionColumn = this.versionStartColumn; | ||
parser.on("object", function (name, obj) { | ||
if (obj.hasOwnProperty("groupId") && obj.hasOwnProperty("artifactId") && obj.hasOwnProperty("version") && | ||
(!obj.hasOwnProperty("scope") || (obj.hasOwnProperty("scope") && obj["scope"] != "test"))) { | ||
let ga = `${obj["groupId"]}:${obj["artifactId"]}`; | ||
let entry = new types_1.KeyValueEntry(ga, { line: 0, column: 0 }); | ||
entry.value = new types_1.Variant(types_1.ValueType.String, obj["version"]); | ||
entry.value_position = { line: versionLine, column: versionColumn }; | ||
let dep = new Dependency(entry); | ||
deps.push(dep); | ||
} | ||
}); | ||
parser.saxStream.on("opentag", function (node) { | ||
if (node.name == "dependency") { | ||
this.isDependency = true; | ||
} | ||
if (this.isDependency && node.name == "version") { | ||
versionLine = parser.saxStream._parser.line + 1; | ||
versionColumn = parser.saxStream._parser.column + 1; | ||
} | ||
}); | ||
parser.saxStream.on("closetag", function (nodeName) { | ||
// TODO: nested deps! | ||
if (nodeName == "dependency") { | ||
this.isDependency = false; | ||
} | ||
}); | ||
parser.on("error", function (e) { | ||
// the XML document doesn't have to be well-formed, that's fine | ||
parser.error = null; | ||
}); | ||
parser.on("end", function () { | ||
// the XML document doesn't have to be well-formed, that's fine | ||
// parser.error = null; | ||
this.dependencies = deps; | ||
}); | ||
return parser; | ||
} | ||
async parse() { | ||
return new Promise(resolve => { | ||
this.stream.pipe(this.parser.saxStream).on('end', (data) => { | ||
resolve(this.dependencies); | ||
}); | ||
}); | ||
} | ||
} | ||
class PomXmlDependencyCollector { | ||
constructor(classes = ["dependencies"]) { | ||
this.classes = classes; | ||
} | ||
async collect(contents) { | ||
const file = utils_1.stream_from_string(contents); | ||
let parser = new NaivePomXmlSaxParser(file); | ||
let dependencies; | ||
await parser.parse().then(data => { | ||
dependencies = data; | ||
}); | ||
return dependencies || []; | ||
} | ||
} | ||
exports.PomXmlDependencyCollector = PomXmlDependencyCollector; | ||
class PackageJsonCollector { | ||
@@ -298,12 +223,14 @@ constructor(classes = ["dependencies"]) { | ||
} | ||
async collect(contents) { | ||
const ast = jsonAst(contents); | ||
return ast.children. | ||
filter(c => this.classes.includes(c.key.value)). | ||
flatMap(c => c.value.children). | ||
map(c => { | ||
let entry = new types_1.KeyValueEntry(c.key.value, { line: c.key.loc.start.line, column: c.key.loc.start.column + 1 }); | ||
entry.value = new types_1.Variant(types_1.ValueType.String, c.value.value); | ||
entry.value_position = { line: c.value.loc.start.line, column: c.value.loc.start.column + 1 }; | ||
return new Dependency(entry); | ||
collect(contents) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const ast = jsonAst(contents); | ||
return ast.children. | ||
filter(c => this.classes.includes(c.key.value)). | ||
flatMap(c => c.value.children). | ||
map(c => { | ||
let entry = new types_1.KeyValueEntry(c.key.value, { line: c.key.loc.start.line, column: c.key.loc.start.column + 1 }); | ||
entry.value = new types_1.Variant(types_1.ValueType.String, c.value.value); | ||
entry.value_position = { line: c.value.loc.start.line, column: c.value.loc.start.column + 1 }; | ||
return new types_1.Dependency(entry); | ||
}); | ||
}); | ||
@@ -310,0 +237,0 @@ } |
{ | ||
"name": "fabric8-analytics-lsp-server", | ||
"description": "LSP Server for Dependency Analytics", | ||
"version": "0.4.15", | ||
"version": "0.4.16", | ||
"author": "Pavel Odvody", | ||
@@ -33,8 +33,9 @@ "contributors": [ | ||
"dependencies": { | ||
"@xml-tools/ast": "^5.0.0", | ||
"@xml-tools/parser": "^1.0.7", | ||
"compare-versions": "3.6.0", | ||
"json-to-ast": "^2.1.0", | ||
"node-fetch": "^2.6.0", | ||
"vscode-languageserver": "^5.3.0-next.9", | ||
"winston": "3.2.1", | ||
"xml2object": "0.1.2", | ||
"compare-versions": "3.6.0" | ||
"winston": "3.2.1" | ||
}, | ||
@@ -41,0 +42,0 @@ "devDependencies": { |
@@ -5,4 +5,5 @@ # Dependency Analytics LSP Server | ||
[![NPM Version](https://img.shields.io/npm/v/fabric8-analytics-lsp-server.svg)](https://www.npmjs.com/package/fabric8-analytics-lsp-server) | ||
![CI Build](https://github.com/fabric8-analytics/fabric8-analytics-lsp-server/workflows/CI%20Build/badge.svg) | ||
![CI Build](https://github.com/fabric8-analytics/fabric8-analytics-lsp-server/workflows/CI%20Build/badge.svg?branch=master) | ||
[![codecov](https://codecov.io/gh/fabric8-analytics/fabric8-analytics-lsp-server/branch/master/graph/badge.svg?token=aVThXjheDf)](https://codecov.io/gh/fabric8-analytics/fabric8-analytics-lsp-server) | ||
Language Server(LSP) that can analyze your dependencies specified in `package.json` and `pom.xml`. | ||
@@ -9,0 +10,0 @@ |
@@ -6,2 +6,11 @@ /* -------------------------------------------------------------------------------------------- | ||
'use strict'; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -12,2 +21,3 @@ const path = require("path"); | ||
const collector_1 = require("./collector"); | ||
const maven_collector_1 = require("./maven.collector"); | ||
const consumers_1 = require("./consumers"); | ||
@@ -146,3 +156,3 @@ const aggregators_1 = require("./aggregators"); | ||
/* Fetch Vulnerabilities by component-analysis batch api-call */ | ||
const fetchVulnerabilities = async (reqData) => { | ||
const fetchVulnerabilities = (reqData) => __awaiter(void 0, void 0, void 0, function* () { | ||
let url = config_1.config.server_url; | ||
@@ -163,3 +173,3 @@ if (config_1.config.three_scale_user_token) { | ||
try { | ||
const response = await node_fetch_1.default(url, { | ||
const response = yield node_fetch_1.default(url, { | ||
method: 'post', | ||
@@ -171,3 +181,3 @@ body: JSON.stringify(reqData), | ||
if (response.ok) { | ||
const respData = await response.json(); | ||
const respData = yield response.json(); | ||
return respData; | ||
@@ -183,3 +193,3 @@ } | ||
} | ||
}; | ||
}); | ||
/* Total Counts of #Known Security Vulnerability and #Security Advisory */ | ||
@@ -221,7 +231,10 @@ class TotalCount { | ||
const regexVersion = new RegExp(/^([a-zA-Z0-9]+\.)?([a-zA-Z0-9]+\.)?([a-zA-Z0-9]+\.)?([a-zA-Z0-9]+)$/); | ||
const sendDiagnostics = async (ecosystem, diagnosticFilePath, contents, collector) => { | ||
const sendDiagnostics = (ecosystem, diagnosticFilePath, contents, collector) => __awaiter(void 0, void 0, void 0, function* () { | ||
connection.sendNotification('caNotification', { data: caDefaultMsg, done: false, uri: diagnosticFilePath }); | ||
let deps = null; | ||
try { | ||
deps = await collector.collect(contents); | ||
const start = new Date().getTime(); | ||
deps = yield collector.collect(contents); | ||
const end = new Date().getTime(); | ||
connection.console.log(`manifest parse took ${end - start} ms`); | ||
} | ||
@@ -231,3 +244,3 @@ catch (error) { | ||
if (ecosystem == "golang") { | ||
connection.console.error(`Command execution failed with error: ${error}`); | ||
connection.console.warn(`Command execution failed with error: ${error}`); | ||
connection.sendNotification('caError', { data: error, uri: diagnosticFilePath }); | ||
@@ -254,7 +267,7 @@ connection.sendDiagnostics({ uri: diagnosticFilePath, diagnostics: [] }); | ||
const allRequests = slicePayload(requestPayload, batchSize, ecosystem).map(request => fetchVulnerabilities(request).then(response => runPipeline(response, diagnostics, packageAggregator, diagnosticFilePath, requestMapper, totalCount))); | ||
await Promise.allSettled(allRequests); | ||
yield Promise.allSettled(allRequests); | ||
const end = new Date().getTime(); | ||
connection.console.log('Time taken to fetch vulnerabilities: ' + ((end - start) / 1000).toFixed(1) + ' sec.'); | ||
connection.console.log(`fetch vulns took ${end - start} ms`); | ||
connection.sendNotification('caNotification', { data: getCAmsg(deps, diagnostics, totalCount), diagCount: diagnostics.length || 0, vulnCount: totalCount, depCount: deps.length || 0, done: true, uri: diagnosticFilePath }); | ||
}; | ||
}); | ||
files.on(EventStream.Diagnostics, "^package\\.json$", (uri, name, contents) => { | ||
@@ -264,3 +277,3 @@ sendDiagnostics('npm', uri, contents, new collector_1.PackageJsonCollector()); | ||
files.on(EventStream.Diagnostics, "^pom\\.xml$", (uri, name, contents) => { | ||
sendDiagnostics('maven', uri, contents, new collector_1.PomXmlDependencyCollector()); | ||
sendDiagnostics('maven', uri, contents, new maven_collector_1.PomXmlDependencyCollector()); | ||
}); | ||
@@ -267,0 +280,0 @@ files.on(EventStream.Diagnostics, "^requirements\\.txt$", (uri, name, contents) => { |
16
types.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ValueType = exports.Variant = exports.KeyValueEntry = void 0; | ||
exports.Dependency = exports.ValueType = exports.Variant = exports.KeyValueEntry = void 0; | ||
/* Determine what is the value */ | ||
@@ -34,2 +34,16 @@ var ValueType; | ||
exports.Variant = Variant; | ||
/* Dependency class that can be created from `IKeyValueEntry` */ | ||
class Dependency { | ||
constructor(dependency) { | ||
this.name = { | ||
value: dependency.key, | ||
position: dependency.key_position | ||
}; | ||
this.version = { | ||
value: dependency.value.object, | ||
position: dependency.value_position | ||
}; | ||
} | ||
} | ||
exports.Dependency = Dependency; | ||
//# sourceMappingURL=types.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
102770
22
1062
52
7
+ Added@xml-tools/ast@^5.0.0
+ Added@xml-tools/parser@^1.0.7
+ Added@xml-tools/ast@5.0.5(transitive)
+ Added@xml-tools/common@0.1.6(transitive)
+ Added@xml-tools/parser@1.0.11(transitive)
+ Addedchevrotain@7.1.1(transitive)
+ Addedregexp-to-ast@0.5.0(transitive)
- Removedxml2object@0.1.2
- Removedsax@1.4.1(transitive)
- Removedxml2object@0.1.2(transitive)