mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 23:16:26 +00:00
refactor(bazel): Simplify parser output structure (#18270)
This commit is contained in:
parent
8b9259b0e9
commit
f2d85c16cd
3 changed files with 135 additions and 161 deletions
|
@ -1,8 +1,7 @@
|
||||||
import { logger } from '../../../logger';
|
|
||||||
import type { PackageDependency, PackageFile } from '../types';
|
import type { PackageDependency, PackageFile } from '../types';
|
||||||
import { parse } from './parser';
|
import { parse } from './parser';
|
||||||
import { extractDepFromFragment } from './rules';
|
import { extractDepFromFragment } from './rules';
|
||||||
import type { ArrayFragment } from './types';
|
import type { RecordFragment } from './types';
|
||||||
|
|
||||||
export function extractPackageFile(
|
export function extractPackageFile(
|
||||||
content: string,
|
content: string,
|
||||||
|
@ -10,19 +9,13 @@ export function extractPackageFile(
|
||||||
): PackageFile | null {
|
): PackageFile | null {
|
||||||
const deps: PackageDependency[] = [];
|
const deps: PackageDependency[] = [];
|
||||||
|
|
||||||
let parsed: ArrayFragment | null = null;
|
const fragments: RecordFragment[] | null = parse(content, packageFile);
|
||||||
try {
|
if (!fragments) {
|
||||||
parsed = parse(content);
|
|
||||||
} catch (err) /* istanbul ignore next */ {
|
|
||||||
logger.debug({ err, packageFile }, 'Bazel parsing error');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parsed) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let idx = 0; idx < parsed.children.length; idx += 1) {
|
for (let idx = 0; idx < fragments.length; idx += 1) {
|
||||||
const fragment = parsed.children[idx];
|
const fragment = fragments[idx];
|
||||||
|
|
||||||
const dep = extractDepFromFragment(fragment);
|
const dep = extractDepFromFragment(fragment);
|
||||||
if (!dep) {
|
if (!dep) {
|
||||||
|
|
|
@ -9,42 +9,36 @@ describe('modules/manager/bazel/parser', () => {
|
||||||
|
|
||||||
const res = parse(input);
|
const res = parse(input);
|
||||||
|
|
||||||
expect(res).toEqual({
|
expect(res).toEqual([
|
||||||
type: 'array',
|
{
|
||||||
value:
|
type: 'record',
|
||||||
'go_repository(name = "foo")\nmaybe(go_repository, name = "bar", deps = ["baz", "qux"])',
|
value: 'go_repository(name = "foo")',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
children: [
|
children: {
|
||||||
{
|
rule: { type: 'string', value: 'go_repository', offset: 0 },
|
||||||
type: 'record',
|
name: { type: 'string', value: 'foo', offset: 22 },
|
||||||
value: 'go_repository(name = "foo")',
|
},
|
||||||
offset: 0,
|
},
|
||||||
children: {
|
{
|
||||||
rule: { type: 'string', value: 'go_repository', offset: 0 },
|
type: 'record',
|
||||||
name: { type: 'string', value: 'foo', offset: 22 },
|
value: 'maybe(go_repository, name = "bar", deps = ["baz", "qux"])',
|
||||||
|
offset: 28,
|
||||||
|
children: {
|
||||||
|
rule: { type: 'string', value: 'go_repository', offset: 34 },
|
||||||
|
name: { type: 'string', value: 'bar', offset: 57 },
|
||||||
|
deps: {
|
||||||
|
type: 'array',
|
||||||
|
value: '["baz", "qux"]',
|
||||||
|
offset: 70,
|
||||||
|
children: [
|
||||||
|
{ type: 'string', value: 'baz', offset: 72 },
|
||||||
|
{ type: 'string', value: 'qux', offset: 79 },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
type: 'record',
|
]);
|
||||||
value: 'maybe(go_repository, name = "bar", deps = ["baz", "qux"])',
|
expect(res?.map(extract)).toMatchObject([
|
||||||
offset: 28,
|
|
||||||
children: {
|
|
||||||
rule: { type: 'string', value: 'go_repository', offset: 34 },
|
|
||||||
name: { type: 'string', value: 'bar', offset: 57 },
|
|
||||||
deps: {
|
|
||||||
type: 'array',
|
|
||||||
value: '["baz", "qux"]',
|
|
||||||
offset: 70,
|
|
||||||
children: [
|
|
||||||
{ type: 'string', value: 'baz', offset: 72 },
|
|
||||||
{ type: 'string', value: 'qux', offset: 79 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
expect(extract(res!)).toMatchObject([
|
|
||||||
{ rule: 'go_repository', name: 'foo' },
|
{ rule: 'go_repository', name: 'foo' },
|
||||||
{ rule: 'go_repository', name: 'bar', deps: ['baz', 'qux'] },
|
{ rule: 'go_repository', name: 'bar', deps: ['baz', 'qux'] },
|
||||||
]);
|
]);
|
||||||
|
@ -66,45 +60,44 @@ describe('modules/manager/bazel/parser', () => {
|
||||||
|
|
||||||
const res = parse(input);
|
const res = parse(input);
|
||||||
|
|
||||||
expect(res).toMatchObject({
|
expect(res).toMatchObject([
|
||||||
children: [
|
{
|
||||||
{
|
children: {
|
||||||
children: {
|
rule: { value: 'http_archive' },
|
||||||
rule: { value: 'http_archive' },
|
name: { value: 'aspect_rules_js' },
|
||||||
name: { value: 'aspect_rules_js' },
|
sha256: {
|
||||||
sha256: {
|
value:
|
||||||
value:
|
'db9f446752fe4100320cf8487e8fd476b9af0adf6b99b601bcfd70b289bb0598',
|
||||||
'db9f446752fe4100320cf8487e8fd476b9af0adf6b99b601bcfd70b289bb0598',
|
},
|
||||||
},
|
strip_prefix: { value: 'rules_js-1.1.2' },
|
||||||
strip_prefix: { value: 'rules_js-1.1.2' },
|
url: {
|
||||||
url: {
|
value:
|
||||||
value:
|
'https://github.com/aspect-build/rules_js/archive/refs/tags/v1.1.2.tar.gz',
|
||||||
'https://github.com/aspect-build/rules_js/archive/refs/tags/v1.1.2.tar.gz',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
children: {
|
{
|
||||||
rule: { value: 'http_archive' },
|
children: {
|
||||||
name: { value: 'rules_nodejs' },
|
rule: { value: 'http_archive' },
|
||||||
sha256: {
|
name: { value: 'rules_nodejs' },
|
||||||
value:
|
sha256: {
|
||||||
'5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
|
value:
|
||||||
},
|
'5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
|
||||||
urls: {
|
},
|
||||||
type: 'array',
|
urls: {
|
||||||
children: [
|
type: 'array',
|
||||||
{
|
children: [
|
||||||
value:
|
{
|
||||||
'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
|
value:
|
||||||
},
|
'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
|
||||||
],
|
},
|
||||||
},
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
]);
|
||||||
expect(extract(res!)).toMatchObject([
|
|
||||||
|
expect(res?.map(extract)).toMatchObject([
|
||||||
{
|
{
|
||||||
rule: 'http_archive',
|
rule: 'http_archive',
|
||||||
name: 'aspect_rules_js',
|
name: 'aspect_rules_js',
|
||||||
|
@ -134,25 +127,24 @@ describe('modules/manager/bazel/parser', () => {
|
||||||
|
|
||||||
const res = parse(input);
|
const res = parse(input);
|
||||||
|
|
||||||
expect(res).toMatchObject({
|
expect(res).toMatchObject([
|
||||||
children: [
|
{
|
||||||
{
|
children: {
|
||||||
children: {
|
name: { value: 'rules_nodejs' },
|
||||||
name: { value: 'rules_nodejs' },
|
rule: { value: 'http_archive' },
|
||||||
rule: { value: 'http_archive' },
|
sha256: {
|
||||||
sha256: {
|
value:
|
||||||
value:
|
'5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
|
||||||
'5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
|
},
|
||||||
},
|
url: {
|
||||||
url: {
|
value:
|
||||||
value:
|
'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
|
||||||
'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
]);
|
||||||
expect(extract(res!)).toMatchObject([
|
|
||||||
|
expect(res?.map(extract)).toMatchObject([
|
||||||
{
|
{
|
||||||
rule: 'http_archive',
|
rule: 'http_archive',
|
||||||
name: 'rules_nodejs',
|
name: 'rules_nodejs',
|
||||||
|
@ -176,37 +168,35 @@ describe('modules/manager/bazel/parser', () => {
|
||||||
|
|
||||||
const res = parse(input);
|
const res = parse(input);
|
||||||
|
|
||||||
expect(res).toMatchObject({
|
expect(res).toMatchObject([
|
||||||
children: [
|
{
|
||||||
{
|
children: {
|
||||||
children: {
|
name: { value: 'bazel_toolchains' },
|
||||||
name: { value: 'bazel_toolchains' },
|
rule: { value: 'http_archive' },
|
||||||
rule: { value: 'http_archive' },
|
sha256: {
|
||||||
sha256: {
|
value:
|
||||||
value:
|
'4b1468b254a572dbe134cc1fd7c6eab1618a72acd339749ea343bd8f55c3b7eb',
|
||||||
'4b1468b254a572dbe134cc1fd7c6eab1618a72acd339749ea343bd8f55c3b7eb',
|
},
|
||||||
},
|
strip_prefix: {
|
||||||
strip_prefix: {
|
value: 'bazel-toolchains-d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4',
|
||||||
value:
|
},
|
||||||
'bazel-toolchains-d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4',
|
urls: {
|
||||||
},
|
children: [
|
||||||
urls: {
|
{
|
||||||
children: [
|
value:
|
||||||
{
|
'https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4.tar.gz',
|
||||||
value:
|
},
|
||||||
'https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4.tar.gz',
|
{
|
||||||
},
|
value:
|
||||||
{
|
'https://github.com/bazelbuild/bazel-toolchains/archive/d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4.tar.gz',
|
||||||
value:
|
},
|
||||||
'https://github.com/bazelbuild/bazel-toolchains/archive/d665ccfa3e9c90fa789671bf4ef5f7c19c5715c4.tar.gz',
|
],
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
]);
|
||||||
expect(extract(res!)).toMatchObject([
|
|
||||||
|
expect(res?.map(extract)).toMatchObject([
|
||||||
{
|
{
|
||||||
name: 'bazel_toolchains',
|
name: 'bazel_toolchains',
|
||||||
rule: 'http_archive',
|
rule: 'http_archive',
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { lang, lexer, parser, query as q } from 'good-enough-parser';
|
import { lang, lexer, parser, query as q } from 'good-enough-parser';
|
||||||
import hasha from 'hasha';
|
import hasha from 'hasha';
|
||||||
|
import { logger } from '../../../logger';
|
||||||
import * as memCache from '../../../util/cache/memory';
|
import * as memCache from '../../../util/cache/memory';
|
||||||
import { supportedRulesRegex } from './rules/index';
|
import { supportedRulesRegex } from './rules/index';
|
||||||
import type {
|
import type {
|
||||||
ArrayFragment,
|
|
||||||
Fragment,
|
Fragment,
|
||||||
FragmentData,
|
FragmentData,
|
||||||
NestedFragment,
|
NestedFragment,
|
||||||
|
@ -12,6 +12,7 @@ import type {
|
||||||
|
|
||||||
interface Ctx {
|
interface Ctx {
|
||||||
readonly source: string;
|
readonly source: string;
|
||||||
|
results: RecordFragment[];
|
||||||
stack: NestedFragment[];
|
stack: NestedFragment[];
|
||||||
recordKey?: string;
|
recordKey?: string;
|
||||||
}
|
}
|
||||||
|
@ -19,14 +20,8 @@ interface Ctx {
|
||||||
function emptyCtx(source: string): Ctx {
|
function emptyCtx(source: string): Ctx {
|
||||||
return {
|
return {
|
||||||
source,
|
source,
|
||||||
stack: [
|
results: [],
|
||||||
{
|
stack: [],
|
||||||
type: 'array',
|
|
||||||
value: source,
|
|
||||||
offset: 0,
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,12 +134,8 @@ function ruleCall(search: q.QueryBuilder<Ctx>): q.QueryBuilder<Ctx> {
|
||||||
const frag = currentFragment(ctx);
|
const frag = currentFragment(ctx);
|
||||||
if (frag.type === 'record' && tree.type === 'wrapped-tree') {
|
if (frag.type === 'record' && tree.type === 'wrapped-tree') {
|
||||||
frag.value = extractTreeValue(ctx.source, tree, frag.offset);
|
frag.value = extractTreeValue(ctx.source, tree, frag.offset);
|
||||||
}
|
ctx.stack.pop();
|
||||||
|
ctx.results.push(frag);
|
||||||
ctx.stack.pop();
|
|
||||||
const parentFrag = currentFragment(ctx);
|
|
||||||
if (parentFrag.type === 'array') {
|
|
||||||
parentFrag.children.push(frag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
@ -152,17 +143,13 @@ function ruleCall(search: q.QueryBuilder<Ctx>): q.QueryBuilder<Ctx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function ruleStartHandler(ctx: Ctx, { value, offset }: lexer.Token): Ctx {
|
function ruleStartHandler(ctx: Ctx, { offset }: lexer.Token): Ctx {
|
||||||
const parentFragment = currentFragment(ctx);
|
ctx.stack.push({
|
||||||
if (parentFragment.type === 'array') {
|
type: 'record',
|
||||||
ctx.stack.push({
|
value: '',
|
||||||
type: 'record',
|
offset,
|
||||||
value: '',
|
children: {},
|
||||||
offset,
|
});
|
||||||
children: {},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,22 +204,26 @@ function getCacheKey(input: string): string {
|
||||||
|
|
||||||
const starlark = lang.createLang('starlark');
|
const starlark = lang.createLang('starlark');
|
||||||
|
|
||||||
export function parse(input: string): ArrayFragment | null {
|
export function parse(
|
||||||
|
input: string,
|
||||||
|
packageFile?: string
|
||||||
|
): RecordFragment[] | null {
|
||||||
const cacheKey = getCacheKey(input);
|
const cacheKey = getCacheKey(input);
|
||||||
|
|
||||||
const cachedResult = memCache.get<ArrayFragment | null>(cacheKey);
|
const cachedResult = memCache.get<RecordFragment[] | null>(cacheKey);
|
||||||
// istanbul ignore if
|
// istanbul ignore if
|
||||||
if (cachedResult === null || cachedResult) {
|
if (cachedResult === null || cachedResult) {
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: ArrayFragment | null = null;
|
let result: RecordFragment[] | null = null;
|
||||||
const parsedResult = starlark.query(input, query, emptyCtx(input));
|
try {
|
||||||
if (parsedResult) {
|
const parsedResult = starlark.query(input, query, emptyCtx(input));
|
||||||
const rootFragment = parsedResult.stack[0];
|
if (parsedResult) {
|
||||||
if (rootFragment.type === 'array') {
|
result = parsedResult.results;
|
||||||
result = rootFragment;
|
|
||||||
}
|
}
|
||||||
|
} catch (err) /* istanbul ignore next */ {
|
||||||
|
logger.debug({ err, packageFile }, 'Bazel parsing error');
|
||||||
}
|
}
|
||||||
|
|
||||||
memCache.set(cacheKey, result);
|
memCache.set(cacheKey, result);
|
||||||
|
|
Loading…
Reference in a new issue