Skip to content

Commit

Permalink
feat(go): emit indirect dependencies in go.mod (#2596)
Browse files Browse the repository at this point in the history
This helps IDEs (eg: GoLand from JetBrains, etc..) be more comfortable
with the codebase, as indirect dependencies are correctly mapped. This
generates code more in line with what `go mod` would have generated if
one had tried to manually generate those packages.
  • Loading branch information
RomainMuller authored Feb 23, 2021
1 parent 5b2fa9e commit 0f95a0b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 13 deletions.
49 changes: 47 additions & 2 deletions packages/@jsii/go-runtime/build-tools/gen-calc.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env npx ts-node

import { removeSync } from 'fs-extra';
import { join, resolve } from 'path';
import { readFileSync, removeSync, writeFileSync } from 'fs-extra';
import { join, relative, resolve } from 'path';

import { runtimeModules } from '../lib';
import { localRuntimeModules } from '../lib/local-runtime-modules';
import { runCommand } from './_constants';

const genRoot = join(__dirname, '..', 'jsii-calc');
Expand All @@ -22,3 +24,46 @@ runCommand(
],
{ stdio: 'inherit' },
);

// Inject "replaces" in the go.mod files so IDEs do not struggle too much...
const genModules = localRuntimeModules(genRoot);
const localModules = {
...genModules,
...runtimeModules,
};
for (const localPath of Object.values(genModules)) {
const goModFile = join(localPath, 'go.mod');
const goMod = readFileSync(goModFile, 'utf8');

const replaces = new Array<{
readonly dep: string;
readonly depPath: string;
}>();

let matches: ReturnType<RegExp['exec']>;
const depRegex = /([a-z0-9._~/-]+)\s+v\d/gi;
while ((matches = depRegex.exec(goMod)) != null) {
const [, dep] = matches;
if (dep in localModules) {
const depPath = localModules[dep];
replaces.push({ dep, depPath });
}
}

writeFileSync(
goModFile,
[
goMod.trim(),
'',
'// Injected by "yarn gen:calc", aka build-tools/gen-calc.ts',
'replace (',
...replaces
.map(
({ dep, depPath }) => `\t${dep} => ${relative(localPath, depPath)}`,
)
.sort(),
')',
'',
].join('\n'),
);
}
36 changes: 29 additions & 7 deletions packages/jsii-pacmak/lib/targets/go/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Assembly, Type, Submodule as JsiiSubmodule } from 'jsii-reflect';
import { basename, dirname, join } from 'path';
import * as semver from 'semver';

import { VERSION } from '../../version';
import { EmitContext } from './emit-context';
import { ReadmeFile } from './readme-file';
import {
Expand Down Expand Up @@ -253,17 +254,38 @@ export class RootPackage extends Package {
code.line();
code.open('require (');
// Strip " (build abcdef)" from the jsii version
code.line(
`${JSII_RT_MODULE_NAME} v${this.assembly.jsiiVersion.replace(
/ .*$/,
'',
)}`,
);
for (const dep of this.packageDependencies) {
code.line(`${JSII_RT_MODULE_NAME} v${VERSION}`);
const dependencies = this.packageDependencies;
for (const dep of dependencies) {
code.line(`${dep.goModuleName} v${dep.version}`);
}
indirectDependencies(
dependencies,
new Set(dependencies.map((dep) => dep.goModuleName)),
);
code.close(')');
code.closeFile(GOMOD_FILENAME);

/**
* Emits indirect dependency declarations, which are helpful to make IDEs at
* ease with the codebase.
*/
function indirectDependencies(
pkgs: RootPackage[],
alreadyEmitted: Set<string>,
): void {
for (const pkg of pkgs) {
const deps = pkg.packageDependencies;
for (const dep of deps) {
if (alreadyEmitted.has(dep.goModuleName)) {
continue;
}
alreadyEmitted.add(dep.goModuleName);
code.line(`${dep.goModuleName} v${dep.version} // indirect`);
}
indirectDependencies(deps, alreadyEmitted);
}
}
}

/*
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0f95a0b

Please sign in to comment.