Skip to content

Commit

Permalink
Fix generated code not building when conflicing names
Browse files Browse the repository at this point in the history
  • Loading branch information
stwiname committed Dec 12, 2023
1 parent 27fa096 commit 0142bd9
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 26 deletions.
69 changes: 64 additions & 5 deletions packages/common-cosmos/src/codegen/codegen-controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,28 @@ describe('Codegen cosmos', () => {
{
'osmosis.gamm.v1beta1': {
file: './proto/osmosis/gamm/v1beta1/tx.proto',

messages: ['MsgSwapExactAmountIn'],
},
},
{
'osmosis.poolmanager.v1beta1': {
file: './proto/osmosis/poolmanager/v1beta1/swap_route.proto',
messages: ['SwapAmountInRoute'],
messages: ['MsgSwapAmountInRoute'],
},
},
];
expect(prepareProtobufRenderProps(mockChainTypes, PROJECT_PATH)).toStrictEqual([
{
messageNames: ['MsgSwapExactAmountIn'],
namespace: 'osmosis.gamm.v1beta1.tx',
name: 'OsmosisGammV1beta1Tx',
path: './proto-interfaces/osmosis/gamm/v1beta1/tx',
},
{
messageNames: ['SwapAmountInRoute'],
messageNames: ['MsgSwapAmountInRoute'],
namespace: 'osmosis.poolmanager.v1beta1.swap_route',
name: 'OsmosisPoolmanagerV1beta1Swap_route',
path: './proto-interfaces/osmosis/poolmanager/v1beta1/swap_route',
},
]);
Expand All @@ -61,14 +66,16 @@ describe('Codegen cosmos', () => {
{
'osmosis.poolmanager.v1beta1': {
file: './proto/osmosis/poolmanager/v1beta1/swap_route.proto',
messages: ['SwapAmountInRoute'],
messages: ['MsgSwapAmountInRoute'],
},
},
undefined,
];
expect(prepareProtobufRenderProps(mixedMockChainTypes, PROJECT_PATH)).toStrictEqual([
{
messageNames: ['SwapAmountInRoute'],
messageNames: ['MsgSwapAmountInRoute'],
name: 'OsmosisPoolmanagerV1beta1Swap_route',
namespace: 'osmosis.poolmanager.v1beta1.swap_route',
path: './proto-interfaces/osmosis/poolmanager/v1beta1/swap_route',
},
]);
Expand Down Expand Up @@ -104,6 +111,58 @@ describe('Codegen cosmos', () => {
expect(v.toString()).toBe('fake proto');
await promisify(rimraf)(tp);
});

it('renders correct codegen from ejs', async () => {
const job = {
props: {
proto: [
{
messageNames: ['MsgSwapExactAmountIn'],
namespace: 'osmosis.gamm.v1beta1.tx',
name: 'OsmosisGammV1beta1Tx',
path: './proto-interfaces/osmosis/gamm/v1beta1/tx',
},
{
messageNames: ['SwapAmountInRoute'],
namespace: 'osmosis.poolmanager.v1beta1.swap_route',
name: 'OsmosisPoolmanagerV1beta1Swap_route',
path: './proto-interfaces/osmosis/poolmanager/v1beta1/swap_route',
},
],
},
helper: {upperFirst},
};

const output = await ejs.renderFile(path.resolve(__dirname, '../../templates/proto-interface.ts.ejs'), job);

// await fs.promises.writeFile(path.join(PROJECT_PATH, 'test.ts'), data);
const expectCodegen = `// SPDX-License-Identifier: Apache-2.0
// Auto-generated , DO NOT EDIT
import {CosmosMessage} from "@subql/types-cosmos";
import * as OsmosisGammV1beta1Tx from "./proto-interfaces/osmosis/gamm/v1beta1/tx";
import * as OsmosisPoolmanagerV1beta1Swap_route from "./proto-interfaces/osmosis/poolmanager/v1beta1/swap_route";
export namespace osmosis.gamm.v1beta1.tx {
export type MsgSwapExactAmountInMessage = CosmosMessage<OsmosisGammV1beta1Tx.MsgSwapExactAmountIn>;
}
export namespace osmosis.poolmanager.v1beta1.swap_route {
export type SwapAmountInRouteMessage = CosmosMessage<OsmosisPoolmanagerV1beta1Swap_route.SwapAmountInRoute>;
}
`;

expect(output).toEqual(expectCodegen);
// const output = await fs.promises.readFile(path.join(PROJECT_PATH, 'test.ts'));
// expect(output.toString()).toMatch(expectCodegen);
// await promisify(rimraf)(path.join(PROJECT_PATH, 'test.ts'));
});
});

describe('CosmWasm codegen', () => {
Expand Down Expand Up @@ -162,7 +221,7 @@ describe('Codegen cosmos', () => {
},
]);
});
it('render correct codegen from ejs', async () => {
it('renders correct codegen from ejs', async () => {
const mockJob = {
contract: 'Cw20',
messages: {
Expand Down
75 changes: 58 additions & 17 deletions packages/common-cosmos/src/codegen/codegen-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {makeTempDir} from '@subql/common';
import {CosmosChaintypes, CustomModule, CosmosRuntimeDatasource} from '@subql/types-cosmos';
import {Data} from 'ejs';
import {copySync} from 'fs-extra';
import {upperFirst} from 'lodash';
import {IDLObject} from 'wasm-ast-types';
import {isRuntimeCosmosDs} from '../project';
import {COSMWASM_OPTS, TELESCOPE_OPTS} from './constants';
Expand All @@ -26,6 +27,18 @@ const COSMWASM_INTERFACE_WRAPPER_PATH = '/src/types/cosmwasm-interface-wrappers'
const COSMWASM_INTERFACE_TEMPLATE_PATH = path.resolve(__dirname, '../../templates/cosmwasm-interfaces.ts.ejs');

interface ProtobufRenderProps {
/**
* The dot notation format of the path without PROTO dir
* @exmaple
* 'cosmos.auth.v1beta1.tx'
* */
namespace: string;
/**
* The camel case format of the path without PROTO dir
* @example
* 'CosmosAuthV1Beta1Tx'
* */
name: string;
messageNames: string[]; // all messages
path: string; // should process the file Path and concat with PROTO dir
}
Expand All @@ -42,6 +55,20 @@ export function processProtoFilePath(path: string): string {
return `./proto-interfaces/${path.replace(/^\.\/proto\/|\.proto$/g, '').replace(/\./g, '/')}`;
}

function pathToNamespace(path: string): string {
return path
.replace(/^\.\/proto\/|\.proto$/g, '')
.split(/(?<=\\\\)\/|(?<!\\)\//)
.join('.');
}

function pathToName(path: string): string {
return pathToNamespace(path)
.split('.')
.map((p) => upperFirst(p))
.join('');
}

export function isProtoPath(filePath: string, projectPath: string): boolean {
// check if the protobuf files are under ./proto directory
return !!path.join(projectPath, filePath).startsWith(path.join(projectPath, './proto/'));
Expand Down Expand Up @@ -151,24 +178,36 @@ export function prepareProtobufRenderProps(
return [];
}
return chaintypes.filter(Boolean).flatMap((chaintype) => {
return Object.entries(chaintype).map(([key, value]) => {
const filePath = path.join(projectPath, value.file);
if (!fs.existsSync(filePath)) {
throw new Error(`Error: chainType ${key}, file ${value.file} does not exist`);
}
if (!isProtoPath(value.file, projectPath)) {
console.error(
`Codegen will not apply for this file: ${value.file} Please ensure it is under the ./proto directory if you want to run codegen on it`
);
}
return {
messageNames: value.messages,
path: processProtoFilePath(value.file),
};
});
return Object.entries(chaintype)
.map(([key, value]) => {
const filePath = path.join(projectPath, value.file);
if (!fs.existsSync(filePath)) {
throw new Error(`Error: chainType ${key}, file ${value.file} does not exist`);
}
if (!isProtoPath(value.file, projectPath)) {
console.error(
`Codegen will not apply for this file: ${value.file} Please ensure it is under the ./proto directory if you want to run codegen on it`
);
}

// We only need to generate for RPC messages that are always prefixed with Msg
const messages = value.messages.filter((m: string) => m.indexOf('Msg') === 0);
if (!messages.length) return;

return {
messageNames: messages,
namespace: pathToNamespace(value.file),
name: pathToName(value.file),
path: processProtoFilePath(value.file),
};
})
.filter(Boolean);
});
}

/**
* Makes a temporaray directory and populates it with some core protobufs used by all projects, then copies over the projects protobufs
* */
export async function tempProtoDir(projectPath: string): Promise<string> {
const tmpDir = await makeTempDir();
const userProto = path.join(projectPath, './proto');
Expand Down Expand Up @@ -198,11 +237,12 @@ export async function generateProto(
prepareDirPath: (path: string, recreate: boolean) => Promise<void>,
renderTemplate: (templatePath: string, outputPath: string, templateData: Data) => Promise<void>,
upperFirst: (string?: string) => string,
mkdirProto: (projectPath: string) => Promise<string>
/** @deprecated */
mkdirProto?: (projectPath: string) => Promise<string>

Check warning on line 241 in packages/common-cosmos/src/codegen/codegen-controller.ts

View workflow job for this annotation

GitHub Actions / code-style

'mkdirProto' is defined but never used
): Promise<void> {
let tmpPath: string;
try {
tmpPath = await mkdirProto(projectPath);
tmpPath = await tempProtoDir(projectPath);
const protobufRenderProps = prepareProtobufRenderProps(chaintypes, projectPath);
const outputPath = path.join(projectPath, PROTO_INTERFACES_ROOT_DIR);
await prepareDirPath(path.join(projectPath, PROTO_INTERFACES_ROOT_DIR), true);
Expand All @@ -227,6 +267,7 @@ export async function generateProto(
const errorMessage = e.message.startsWith('Dependency')
? `Please add the missing protobuf file to ./proto directory`
: '';
console.log('ERRROR', e);
throw new Error(`Failed to generate from protobufs. ${e.message}, ${errorMessage}`);
} finally {
fs.rmSync(tmpPath, {recursive: true, force: true});
Expand Down
11 changes: 7 additions & 4 deletions packages/common-cosmos/templates/proto-interface.ts.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
// Auto-generated , DO NOT EDIT
import {CosmosMessage} from "@subql/types-cosmos";
<% props.proto.forEach(function(proto) { %>
import {<% proto.messageNames.forEach(function(msg, index) { %><%= helper.upperFirst(msg) %><% if (index < proto.messageNames.length - 1) { %>,<% } %><% }); %>} from "<%= proto.path %>";
import * as <%= proto.name %> from "<%= proto.path %>";
<% }); %>
<% props.proto.forEach(function(proto) { %>
export namespace <%= proto.namespace %> {
<% proto.messageNames.forEach(function(msg) { %>
export type <%= helper.upperFirst(msg) %>Message = CosmosMessage<<%= proto.name %>.<%= helper.upperFirst(msg) %>>;<% }); %>
}
<% }); %>
<% props.proto.forEach(function(proto) { %><% proto.messageNames.forEach(function(msg) { %>
export type <%= helper.upperFirst(msg) %>Message = CosmosMessage<<%= helper.upperFirst(msg) %>>;<% }); %>
<% }); %>

0 comments on commit 0142bd9

Please sign in to comment.