@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
132 lines (130 loc) • 5.7 kB
JavaScript
import { tsUtils } from '@neo-one/ts-utils';
import { utils } from '@neo-one/utils';
import ts from 'typescript';
import { DEFAULT_CONTRACT_PROPERTIES } from '../constants';
import { getABI, getAllPropInfos, getContractInfo, getContractProperties, getDebugInfo, } from '../contract';
import { DiagnosticCode } from '../DiagnosticCode';
import { DiagnosticMessage } from '../DiagnosticMessage';
import { BuiltinInstanceMemberAccessor, BuiltinInstanceMemberCallableProperty, BuiltinInstanceMemberMethod, BuiltinInstanceMemberStorageProperty, BuiltinInstanceMemberStructuredStorageProperty, } from './builtins';
const PARAMETERS = ['String', 'Array'];
const RETURN_TYPE = 'Buffer';
const getSmartContract = (context, sourceFile) => {
const classDecls = tsUtils.statement
.getStatements(sourceFile)
.filter(ts.isClassDeclaration)
.filter((decl) => tsUtils.modifier.isNamedExport(decl))
.filter((decl) => context.analysis.isSmartContract(decl));
if (classDecls.length === 0) {
return undefined;
}
if (classDecls.length === 1) {
return classDecls[0];
}
context.reportError(classDecls[1], DiagnosticCode.InvalidContract, DiagnosticMessage.InvalidContractMultipleInFile);
return classDecls[0];
};
const addOverrideSymbol = (context, contractInfo, overrideSymbol) => {
const superSymbol = context.analysis.getSymbol(contractInfo.smartContract);
if (superSymbol === undefined) {
return;
}
if (overrideSymbol !== undefined) {
context.builtins.addOverride(superSymbol, overrideSymbol);
}
const superSmartContract = contractInfo.superSmartContract;
if (superSmartContract !== undefined) {
addOverrideSymbol(context, superSmartContract, superSymbol);
}
};
const addContractInfo = (context, contractInfo) => {
const propertyNameToOverride = new Map();
getAllPropInfos(contractInfo).forEach((propInfo) => {
const symbol = context.analysis.getSymbol(propInfo.classDecl);
if (symbol !== undefined &&
propInfo.type !== 'deploy' &&
propInfo.type !== 'refundAssets' &&
propInfo.type !== 'upgrade' &&
propInfo.type !== 'completeSend') {
const memberSymbol = propInfo.symbol;
switch (propInfo.type) {
case 'function':
if (ts.isPropertyDeclaration(propInfo.decl)) {
context.builtins.addMember(symbol, memberSymbol, new BuiltinInstanceMemberCallableProperty(propInfo.decl));
}
else {
context.builtins.addMember(symbol, memberSymbol, new BuiltinInstanceMemberMethod(propInfo.decl));
}
break;
case 'accessor':
context.builtins.addMember(symbol, memberSymbol, new BuiltinInstanceMemberAccessor(propInfo.getter === undefined ? undefined : propInfo.getter.decl, propInfo.setter === undefined ? undefined : propInfo.setter.decl));
break;
case 'property':
if (propInfo.structuredStorageType === undefined) {
context.builtins.addMember(symbol, memberSymbol, new BuiltinInstanceMemberStorageProperty(propInfo.name));
}
else {
context.builtins.addMember(symbol, memberSymbol, new BuiltinInstanceMemberStructuredStorageProperty(propInfo.structuredStorageType, propInfo.name));
}
break;
default:
utils.assertNever(propInfo);
throw new Error('For TS');
}
const memberName = tsUtils.symbol.getName(memberSymbol);
const overrideSymbol = propertyNameToOverride.get(memberName);
if (overrideSymbol === undefined) {
propertyNameToOverride.set(memberName, memberSymbol);
}
else {
context.builtins.addOverride(memberSymbol, overrideSymbol);
}
}
});
addOverrideSymbol(context, contractInfo);
};
export const getSmartContractInfo = (context, sourceFile) => {
const smartContract = getSmartContract(context, sourceFile);
const contractInfo = smartContract === undefined ? undefined : getContractInfo(context, smartContract);
const properties = smartContract === undefined ? DEFAULT_CONTRACT_PROPERTIES : getContractProperties(context, smartContract);
const payable = contractInfo === undefined
? true
: contractInfo.propInfos.some((propInfo) => propInfo.type === 'function' && propInfo.receive);
if (contractInfo !== undefined) {
addContractInfo(context, contractInfo);
return {
contractInfo,
abi: getABI(context, contractInfo),
debugInfo: getDebugInfo(context, contractInfo),
contract: {
parameters: PARAMETERS,
returnType: RETURN_TYPE,
...properties,
storage: true,
dynamicInvoke: true,
payable,
},
};
}
return {
contractInfo,
abi: {
functions: [],
events: [],
},
debugInfo: {
entrypoint: '',
documents: [],
methods: [],
events: [],
},
contract: {
parameters: PARAMETERS,
returnType: RETURN_TYPE,
...properties,
storage: true,
dynamicInvoke: true,
payable,
},
};
};
//# sourceMappingURL=getSmartContractInfo.js.map