Merge pull request #3939 from ethereum/eslint

Eslint 2 spaces fix
pull/3824/head
bunsenstraat 1 year ago committed by GitHub
commit abc6101e34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      .eslintrc.json
  2. 88
      apps/remix-ide/ci/download_e2e_assets.js
  3. 12
      apps/remix-ide/ci/lint-targets.js
  4. 32
      apps/remix-ide/ci/splice_tests.js
  5. 86
      apps/remix-ide/src/app/components/main-panel.tsx
  6. 206
      apps/remix-ide/src/app/components/preload.tsx
  7. 4
      apps/remix-ide/src/app/components/vertical-icons.tsx
  8. 6
      apps/remix-ide/src/app/editor/editor.js
  9. 4
      apps/remix-ide/src/app/files/dgitProvider.js
  10. 22
      apps/remix-ide/src/app/files/fileManager.ts
  11. 104
      apps/remix-ide/src/app/files/fileSystem.ts
  12. 308
      apps/remix-ide/src/app/files/filesystems/fileSystemUtility.ts
  13. 156
      apps/remix-ide/src/app/files/filesystems/indexedDB.ts
  14. 98
      apps/remix-ide/src/app/files/filesystems/localStorage.ts
  15. 6
      apps/remix-ide/src/app/panels/layout.ts
  16. 6
      apps/remix-ide/src/app/panels/terminal.js
  17. 482
      apps/remix-ide/src/app/plugins/code-format.ts
  18. 64
      apps/remix-ide/src/app/plugins/code-format/index.ts
  19. 210
      apps/remix-ide/src/app/plugins/code-format/parser.ts
  20. 4
      apps/remix-ide/src/app/plugins/contractFlattener.tsx
  21. 118
      apps/remix-ide/src/app/plugins/file-decorator.ts
  22. 976
      apps/remix-ide/src/app/plugins/parser/code-parser.tsx
  23. 72
      apps/remix-ide/src/app/plugins/parser/services/antlr-worker.ts
  24. 410
      apps/remix-ide/src/app/plugins/parser/services/code-parser-antlr-service.ts
  25. 432
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  26. 112
      apps/remix-ide/src/app/plugins/parser/services/code-parser-gas-service.ts
  27. 130
      apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts
  28. 232
      apps/remix-ide/src/app/plugins/parser/types/antlr-types.ts
  29. 8
      apps/remix-ide/src/app/plugins/permission-handler-plugin.tsx
  30. 28
      apps/remix-ide/src/app/plugins/solidity-script.tsx
  31. 262
      apps/remix-ide/src/app/plugins/solidity-umlgen.tsx
  32. 32
      apps/remix-ide/src/app/providers/custom-vm-fork-provider.tsx
  33. 48
      apps/remix-ide/src/app/state/registry.ts
  34. 8
      apps/remix-ide/src/app/tabs/analysis-tab.js
  35. 44
      apps/remix-ide/src/app/tabs/search.tsx
  36. 2
      apps/remix-ide/src/app/tabs/theme-module.js
  37. 4
      apps/remix-ide/src/app/tabs/web3-provider.js
  38. 4
      apps/remix-ide/src/app/udapp/run-tab.js
  39. 6
      apps/remix-ide/src/app/ui/landing-page/landing-page.js
  40. 122
      apps/remix-ide/src/blockchain/blockchain.tsx
  41. 24
      apps/remix-ide/src/blockchain/helper.ts
  42. 2
      apps/remix-ide/src/blockchain/providers/injected.ts
  43. 2
      apps/remix-ide/src/blockchain/providers/node.ts
  44. 10
      apps/remix-ide/src/blockchain/providers/vm.ts
  45. 116
      apps/remix-ide/src/blockchain/providers/worker-vm.ts
  46. 2
      libs/ghaction-helper/src/methods.ts
  47. 82
      libs/ghaction-helper/src/signer.ts
  48. 32
      libs/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  49. 30
      libs/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
  50. 12
      libs/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts
  51. 2
      libs/remix-core-plugin/src/lib/compiler-artefacts.ts
  52. 4
      libs/remix-core-plugin/src/lib/compiler-content-imports.ts
  53. 8
      libs/remix-core-plugin/src/lib/compiler-metadata.ts
  54. 156
      libs/remix-core-plugin/src/lib/constants/uups.ts
  55. 4
      libs/remix-core-plugin/src/types/contract.ts
  56. 2
      libs/remix-debug/test.ts
  57. 16
      libs/remix-debug/test/decoder/localsTests/helper.ts
  58. 104
      libs/remix-debug/test/decoder/stateTests/mapping.ts
  59. 252
      libs/remix-debug/test/resources/ast.ts
  60. 26
      libs/remix-lib/src/execution/txFormat.ts
  61. 32
      libs/remix-lib/src/hash.ts
  62. 2
      libs/remix-lib/src/util.ts
  63. 4
      libs/remix-lib/test/txFormat.ts
  64. 66
      libs/remix-simulator/src/methods/blocks.ts
  65. 92
      libs/remix-solidity/src/compiler/compiler-abstract.ts
  66. 40
      libs/remix-solidity/src/compiler/compiler.ts
  67. 2
      libs/remix-solidity/src/compiler/types.ts
  68. 66
      libs/remix-solidity/src/lib/es-web-worker/compiler-worker.ts
  69. 12
      libs/remix-solidity/src/lib/es-web-worker/es-web-worker-handler.ts
  70. 44
      libs/remix-tests/src/logger.ts
  71. 50
      libs/remix-tests/tests/testRunner.cli.spec.ts
  72. 832
      libs/remix-tests/tests/testRunner.spec.ts
  73. 54
      libs/remix-ui/app/src/lib/remix-app/components/modals/modal-wrapper.tsx
  74. 134
      libs/remix-ui/app/src/lib/remix-app/reducer/modals.ts
  75. 36
      libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx
  76. 4
      libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx
  77. 20
      libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts
  78. 134
      libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx
  79. 2
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  80. 22
      libs/remix-ui/debugger-ui/src/lib/tx-browser/tx-browser.tsx
  81. 88
      libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts
  82. 88
      libs/remix-ui/debugger-ui/src/reducers/calldata.ts
  83. 38
      libs/remix-ui/drag-n-drop/src/lib/drag-n-drop.tsx
  84. 152
      libs/remix-ui/editor/src/lib/actions/editor.ts
  85. 18
      libs/remix-ui/editor/src/lib/helpers/retrieveNodesAtPosition.ts
  86. 74
      libs/remix-ui/editor/src/lib/providers/codeActionProvider.ts
  87. 1378
      libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts
  88. 744
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  89. 138
      libs/remix-ui/editor/src/lib/providers/definitionProvider.ts
  90. 56
      libs/remix-ui/editor/src/lib/providers/highlightProvider.ts
  91. 362
      libs/remix-ui/editor/src/lib/providers/hoverProvider.ts
  92. 26
      libs/remix-ui/editor/src/lib/providers/quickfixes.ts
  93. 66
      libs/remix-ui/editor/src/lib/providers/referenceProvider.ts
  94. 4
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  95. 454
      libs/remix-ui/editor/src/lib/web-types.ts
  96. 18
      libs/remix-ui/file-decorators/src/lib/components/file-decoration-icon.tsx
  97. 6
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-custom-icon.tsx
  98. 6
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-error-icon.tsx
  99. 2
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-tooltip.tsx
  100. 2
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-warning-icon.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -47,7 +47,8 @@
"eslint-disable-next-line no-empty": "off",
"no-empty": "off",
"jsx-a11y/anchor-is-valid": "off",
"@typescript-eslint/no-inferrable-types": "off"
"@typescript-eslint/no-inferrable-types": "off",
"indent": ["error", 2]
}
},
{
@ -58,7 +59,9 @@
"extends": [
"plugin:@nrwl/nx/javascript"
],
"rules": {}
"rules": {
"indent": ["error", 2]
}
}
],
"globals": {

@ -5,8 +5,8 @@ const { exit } = require('process');
const child = child_process.spawnSync('grep -r --include="*.json" --include="*.ts" --include="*.tsx" "+commit" apps/**/* libs/**/*', [], { encoding: 'utf8', cwd: process.cwd(), shell: true });
if (child.error) {
console.log("ERROR: ", child);
exit(1);
console.log("ERROR: ", child);
exit(1);
}
@ -15,63 +15,63 @@ let soljson =[];
const quotedVersionsRegex = /['"v]\d*\.\d*\.\d*\+commit\.[\d\w]*/g;
let quotedVersionsRegexMatch = child.stdout.match(quotedVersionsRegex)
if(quotedVersionsRegexMatch){
let soljson2 = quotedVersionsRegexMatch.map((item) => item.replace('\'', 'v').replace('"', 'v'))
console.log('non nightly soljson versions found: ', soljson2);
if(soljson2) soljson = soljson.concat(soljson2);
let soljson2 = quotedVersionsRegexMatch.map((item) => item.replace('\'', 'v').replace('"', 'v'))
console.log('non nightly soljson versions found: ', soljson2);
if(soljson2) soljson = soljson.concat(soljson2);
}
const nightlyVersionsRegex = /\d*\.\d*\.\d-nightly.*\+commit\.[\d\w]*/g
const nightlyVersionsRegexMatch = child.stdout.match(nightlyVersionsRegex)
if(nightlyVersionsRegexMatch){
let soljson3 = nightlyVersionsRegexMatch.map((item) => 'v' + item);
console.log('nightly soljson versions found: ', soljson3);
if(soljson3) soljson = soljson.concat(soljson3);
let soljson3 = nightlyVersionsRegexMatch.map((item) => 'v' + item);
console.log('nightly soljson versions found: ', soljson3);
if(soljson3) soljson = soljson.concat(soljson3);
}
if (soljson) {
// filter out duplicates
soljson = soljson.filter((item, index) => soljson.indexOf(item) === index);
// filter out duplicates
soljson = soljson.filter((item, index) => soljson.indexOf(item) === index);
// manually add some versions
soljson.push('v0.7.6+commit.7338295f');
// manually add some versions
soljson.push('v0.7.6+commit.7338295f');
console.log('soljson versions found: ', soljson, soljson.length);
console.log('soljson versions found: ', soljson, soljson.length);
for (let i = 0; i < soljson.length; i++) {
const version = soljson[i];
if (version) {
let url = ''
// if nightly
if (version.includes('nightly')) {
url = `https://binaries.soliditylang.org/bin/soljson-${version}.js`;
}else{
url = `https://binaries.soliditylang.org/wasm/soljson-${version}.js`;
}
const dir = './dist/apps/remix-ide/assets/js/soljson';
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
const path = `./dist/apps/remix-ide/assets/js/soljson/soljson-${version}.js`;
// check if the file exists
const exists = fs.existsSync(path);
if (!exists) {
console.log('URL:', url)
try {
// use curl to download the file
child_process.exec(`curl -o ${path} ${url}`, { encoding: 'utf8', cwd: process.cwd(), shell: true })
} catch (e) {
console.log('Failed to download soljson' + version + ' from ' + url)
}
}
for (let i = 0; i < soljson.length; i++) {
const version = soljson[i];
if (version) {
let url = ''
// if nightly
if (version.includes('nightly')) {
url = `https://binaries.soliditylang.org/bin/soljson-${version}.js`;
}else{
url = `https://binaries.soliditylang.org/wasm/soljson-${version}.js`;
}
const dir = './dist/apps/remix-ide/assets/js/soljson';
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
const path = `./dist/apps/remix-ide/assets/js/soljson/soljson-${version}.js`;
// check if the file exists
const exists = fs.existsSync(path);
if (!exists) {
console.log('URL:', url)
try {
// use curl to download the file
child_process.exec(`curl -o ${path} ${url}`, { encoding: 'utf8', cwd: process.cwd(), shell: true })
} catch (e) {
console.log('Failed to download soljson' + version + ' from ' + url)
}
}
}
}
}
}
}

@ -5,15 +5,15 @@ const file = fs.readFileSync('projects.json')
const projects = JSON.parse(file)
console.log(Object.keys(projects.graph.nodes))
for(let node of Object.keys(projects.graph.nodes)){
if(projects.graph.nodes[node].data.targets.lint){
if(projects.graph.nodes[node].data.targets.lint){
console.log(projects.graph.nodes[node].data.name)
const result = spawnSync('yarn', ['lint', projects.graph.nodes[node].data.name])
if(result.status == 0){
console.log('success')
console.log('success')
}else{
console.log(result.stdout.toString())
console.log(result.stderr.toString())
exit(1)
console.log(result.stdout.toString())
console.log(result.stderr.toString())
exit(1)
}
}
}
}

@ -7,21 +7,21 @@ let args = process.argv.slice(2)
const jobsize = args[0] || 10;
const job = args[1] || 0;
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.error(`error: ${error.message}`);
return;
}
if (error) {
console.error(`error: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
let files = stdout.split('\n').filter(f => f.includes('.test')).map(f => f.replace('dist/apps/remix-ide-e2e/src/tests/', '')).map(f => f.replace('.js', ''))
let splitIndex = Math.ceil(files.length / jobsize);
const parts = []
for (let i = 0; i < jobsize; i++) {
parts.push(files.slice(i * splitIndex, (i + 1) * splitIndex))
}
console.log(parts[job].join('\n'))
});
let files = stdout.split('\n').filter(f => f.includes('.test')).map(f => f.replace('dist/apps/remix-ide-e2e/src/tests/', '')).map(f => f.replace('.js', ''))
let splitIndex = Math.ceil(files.length / jobsize);
const parts = []
for (let i = 0; i < jobsize; i++) {
parts.push(files.slice(i * splitIndex, (i + 1) * splitIndex))
}
console.log(parts[job].join('\n'))
});

@ -13,56 +13,56 @@ const profile = {
}
export class MainPanel extends AbstractPanel {
element: HTMLDivElement
dispatch: React.Dispatch<any> = () => {}
constructor (config) {
super(profile)
this.element = document.createElement('div')
this.element.setAttribute('data-id', 'mainPanelPluginsContainer')
this.element.setAttribute('style', 'height: 100%; width: 100%;')
// this.config = config
}
element: HTMLDivElement
dispatch: React.Dispatch<any> = () => {}
constructor (config) {
super(profile)
this.element = document.createElement('div')
this.element.setAttribute('data-id', 'mainPanelPluginsContainer')
this.element.setAttribute('style', 'height: 100%; width: 100%;')
// this.config = config
}
setDispatch (dispatch: React.Dispatch<any>) {
this.dispatch = dispatch
}
setDispatch (dispatch: React.Dispatch<any>) {
this.dispatch = dispatch
}
onActivation () {
this.renderComponent()
}
onActivation () {
this.renderComponent()
}
focus (name) {
this.emit('focusChanged', name)
super.focus(name)
this.renderComponent()
}
focus (name) {
this.emit('focusChanged', name)
super.focus(name)
this.renderComponent()
}
addView (profile, view) {
super.addView(profile, view)
this.renderComponent()
}
addView (profile, view) {
super.addView(profile, view)
this.renderComponent()
}
removeView (profile) {
super.removeView(profile)
this.renderComponent()
}
removeView (profile) {
super.removeView(profile)
this.renderComponent()
}
async showContent (name) {
super.showContent(name)
this.renderComponent()
}
async showContent (name) {
super.showContent(name)
this.renderComponent()
}
renderComponent () {
this.dispatch({
plugins: this.plugins
})
}
renderComponent () {
this.dispatch({
plugins: this.plugins
})
}
render() {
return <div style={{height: '100%', width: '100%'}} data-id='mainPanelPluginsContainer'><PluginViewWrapper plugin={this} /></div>
}
render() {
return <div style={{height: '100%', width: '100%'}} data-id='mainPanelPluginsContainer'><PluginViewWrapper plugin={this} /></div>
}
updateComponent (state: any) {
return <RemixPluginPanel header={<></>} plugins={state.plugins}/>
}
updateComponent (state: any) {
return <RemixPluginPanel header={<></>} plugins={state.plugins}/>
}
}

@ -11,134 +11,134 @@ const _paq = window._paq = window._paq || []
export const Preload = () => {
const [supported, setSupported] = useState<boolean>(true)
const [error, setError] = useState<boolean>(false)
const [showDownloader, setShowDownloader] = useState<boolean>(false)
const remixFileSystems = useRef<fileSystems>(new fileSystems())
const remixIndexedDB = useRef<fileSystem>(new indexedDBFileSystem())
const localStorageFileSystem = useRef<fileSystem>(new localStorageFS())
// url parameters to e2e test the fallbacks and error warnings
const testmigrationFallback = useRef<boolean>(window.location.hash.includes('e2e_testmigration_fallback=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
const testmigrationResult = useRef<boolean>(window.location.hash.includes('e2e_testmigration=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
const testBlockStorage = useRef<boolean>(window.location.hash.includes('e2e_testblock_storage=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
const [supported, setSupported] = useState<boolean>(true)
const [error, setError] = useState<boolean>(false)
const [showDownloader, setShowDownloader] = useState<boolean>(false)
const remixFileSystems = useRef<fileSystems>(new fileSystems())
const remixIndexedDB = useRef<fileSystem>(new indexedDBFileSystem())
const localStorageFileSystem = useRef<fileSystem>(new localStorageFS())
// url parameters to e2e test the fallbacks and error warnings
const testmigrationFallback = useRef<boolean>(window.location.hash.includes('e2e_testmigration_fallback=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
const testmigrationResult = useRef<boolean>(window.location.hash.includes('e2e_testmigration=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
const testBlockStorage = useRef<boolean>(window.location.hash.includes('e2e_testblock_storage=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:')
function loadAppComponent() {
import('../../app').then((AppComponent) => {
const appComponent = new AppComponent.default()
appComponent.run().then(() => {
render(
<>
<RemixApp app={appComponent} />
</>,
document.getElementById('root')
)
})
}).catch(err => {
_paq.push(['trackEvent', 'Preload', 'error', err && err.message])
console.error('Error loading Remix:', err)
setError(true)
})
}
function loadAppComponent() {
import('../../app').then((AppComponent) => {
const appComponent = new AppComponent.default()
appComponent.run().then(() => {
render(
<>
<RemixApp app={appComponent} />
</>,
document.getElementById('root')
)
})
}).catch(err => {
_paq.push(['trackEvent', 'Preload', 'error', err && err.message])
console.error('Error loading Remix:', err)
setError(true)
})
}
const downloadBackup = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
await fsUtility.downloadBackup(remixFileSystems.current.fileSystems['localstorage'])
await migrateAndLoad()
}
const downloadBackup = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
await fsUtility.downloadBackup(remixFileSystems.current.fileSystems['localstorage'])
await migrateAndLoad()
}
const migrateAndLoad = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
const migrationResult = await fsUtility.migrate(localStorageFileSystem.current, remixIndexedDB.current)
_paq.push(['trackEvent', 'Migrate', 'result', migrationResult?'success' : 'fail'])
await setFileSystems()
}
const migrateAndLoad = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
const migrationResult = await fsUtility.migrate(localStorageFileSystem.current, remixIndexedDB.current)
_paq.push(['trackEvent', 'Migrate', 'result', migrationResult?'success' : 'fail'])
await setFileSystems()
}
const setFileSystems = async() => {
const fsLoaded = await remixFileSystems.current.setFileSystem([(testmigrationFallback.current || testBlockStorage.current)? null: remixIndexedDB.current, testBlockStorage.current? null:localStorageFileSystem.current])
if (fsLoaded) {
console.log(fsLoaded.name + ' activated')
_paq.push(['trackEvent', 'Storage', 'activate', fsLoaded.name])
loadAppComponent()
} else {
_paq.push(['trackEvent', 'Storage', 'error', 'no supported storage'])
setSupported(false)
}
const setFileSystems = async() => {
const fsLoaded = await remixFileSystems.current.setFileSystem([(testmigrationFallback.current || testBlockStorage.current)? null: remixIndexedDB.current, testBlockStorage.current? null:localStorageFileSystem.current])
if (fsLoaded) {
console.log(fsLoaded.name + ' activated')
_paq.push(['trackEvent', 'Storage', 'activate', fsLoaded.name])
loadAppComponent()
} else {
_paq.push(['trackEvent', 'Storage', 'error', 'no supported storage'])
setSupported(false)
}
}
const testmigration = async() => {
if (testmigrationResult.current) {
const fsUtility = new fileSystemUtility()
fsUtility.populateWorkspace(migrationTestData, remixFileSystems.current.fileSystems['localstorage'].fs)
}
const testmigration = async() => {
if (testmigrationResult.current) {
const fsUtility = new fileSystemUtility()
fsUtility.populateWorkspace(migrationTestData, remixFileSystems.current.fileSystems['localstorage'].fs)
}
}
useEffect(() => {
async function loadStorage() {
await remixFileSystems.current.addFileSystem(remixIndexedDB.current) || _paq.push(['trackEvent', 'Storage', 'error', 'indexedDB not supported'])
await remixFileSystems.current.addFileSystem(localStorageFileSystem.current) || _paq.push(['trackEvent', 'Storage', 'error', 'localstorage not supported'])
await testmigration()
remixIndexedDB.current.loaded && await remixIndexedDB.current.checkWorkspaces()
localStorageFileSystem.current.loaded && await localStorageFileSystem.current.checkWorkspaces()
remixIndexedDB.current.loaded && ( (remixIndexedDB.current.hasWorkSpaces || !localStorageFileSystem.current.hasWorkSpaces)? await setFileSystems():setShowDownloader(true))
!remixIndexedDB.current.loaded && await setFileSystems()
}
loadStorage()
}, [])
useEffect(() => {
async function loadStorage() {
await remixFileSystems.current.addFileSystem(remixIndexedDB.current) || _paq.push(['trackEvent', 'Storage', 'error', 'indexedDB not supported'])
await remixFileSystems.current.addFileSystem(localStorageFileSystem.current) || _paq.push(['trackEvent', 'Storage', 'error', 'localstorage not supported'])
await testmigration()
remixIndexedDB.current.loaded && await remixIndexedDB.current.checkWorkspaces()
localStorageFileSystem.current.loaded && await localStorageFileSystem.current.checkWorkspaces()
remixIndexedDB.current.loaded && ( (remixIndexedDB.current.hasWorkSpaces || !localStorageFileSystem.current.hasWorkSpaces)? await setFileSystems():setShowDownloader(true))
!remixIndexedDB.current.loaded && await setFileSystems()
}
loadStorage()
}, [])
return <>
<div className='preload-container'>
<div className='preload-logo pb-4'>
{logo}
<div className="info-secondary splash">
return <>
<div className='preload-container'>
<div className='preload-logo pb-4'>
{logo}
<div className="info-secondary splash">
REMIX IDE
<br />
<span className='version'> v{packageJson.version}</span>
</div>
</div>
{!supported ?
<div className='preload-info-container alert alert-warning'>
<br />
<span className='version'> v{packageJson.version}</span>
</div>
</div>
{!supported ?
<div className='preload-info-container alert alert-warning'>
Your browser does not support any of the filesystems required by Remix.
Either change the settings in your browser or use a supported browser.
</div> : null}
{error ?
<div className='preload-info-container alert alert-danger text-left'>
</div> : null}
{error ?
<div className='preload-info-container alert alert-danger text-left'>
An unknown error has occurred while loading the application.<br></br>
Doing a hard refresh might fix this issue:<br></br>
<div className='pt-2'>
<div className='pt-2'>
Windows:<br></br>
- Chrome: CTRL + F5 or CTRL + Reload Button<br></br>
- Firefox: CTRL + SHIFT + R or CTRL + F5<br></br>
</div>
<div className='pt-2'>
</div>
<div className='pt-2'>
MacOS:<br></br>
- Chrome & FireFox: CMD + SHIFT + R or SHIFT + Reload Button<br></br>
</div>
<div className='pt-2'>
</div>
<div className='pt-2'>
Linux:<br></br>
- Chrome & FireFox: CTRL + SHIFT + R<br></br>
</div>
</div> : null}
{showDownloader ?
<div className='preload-info-container alert alert-info'>
</div>
</div> : null}
{showDownloader ?
<div className='preload-info-container alert alert-info'>
This app will be updated now. Please download a backup of your files now to make sure you don't lose your work.
<br></br>
<br></br>
You don't need to do anything else, your files will be available when the app loads.
<div onClick={async () => { await downloadBackup() }} data-id='downloadbackup-btn' className='btn btn-primary mt-1'>download backup</div>
<div onClick={async () => { await migrateAndLoad() }} data-id='skipbackup-btn' className='btn btn-primary mt-1'>skip backup</div>
</div> : null}
{(supported && !error && !showDownloader) ?
<div>
<i className="fas fa-spinner fa-spin fa-2x"></i>
</div> : null}
</div>
</>
<div onClick={async () => { await downloadBackup() }} data-id='downloadbackup-btn' className='btn btn-primary mt-1'>download backup</div>
<div onClick={async () => { await migrateAndLoad() }} data-id='skipbackup-btn' className='btn btn-primary mt-1'>skip backup</div>
</div> : null}
{(supported && !error && !showDownloader) ?
<div>
<i className="fas fa-spinner fa-spin fa-2x"></i>
</div> : null}
</div>
</>
}
const logo = <svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100">
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z" />
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z" />
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z" />
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z" />
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z" />
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z" />
</svg>

@ -113,8 +113,8 @@ export class VerticalIcons extends Plugin {
updateComponent(state: any){
return <RemixUiVerticalIconsPanel
verticalIconsPlugin={state.verticalIconsPlugin}
icons={state.icons}
verticalIconsPlugin={state.verticalIconsPlugin}
icons={state.icons}
/>
}

@ -99,8 +99,8 @@ class Editor extends Plugin {
this.ref.clearDecorationsByPlugin = (filePath, plugin, typeOfDecoration) => this.clearDecorationsByPlugin(filePath, plugin, typeOfDecoration)
this.ref.keepDecorationsFor = (name, typeOfDecoration) => this.keepDecorationsFor(name, typeOfDecoration)
}} id='editorView'>
<PluginViewWrapper plugin={this} />
</div>
<PluginViewWrapper plugin={this} />
</div>
}
renderComponent () {
@ -293,7 +293,7 @@ class Editor extends Plugin {
* Get the text in the current session, if any.
* @param {string} url Address of the content to retrieve.
*/
getText (url) {
getText (url) {
if (this.sessions[url]) {
return this.sessions[url].getValue()
}

@ -110,7 +110,7 @@ class DGitProvider extends Plugin {
...cmd
})
if (refresh) {
setTimeout(async () => {
setTimeout(async () => {
await this.call('fileManager', 'refresh')
}, 1000)
}
@ -141,7 +141,7 @@ class DGitProvider extends Plugin {
...cmd
})
if (refresh) {
setTimeout(async () => {
setTimeout(async () => {
await this.call('fileManager', 'refresh')
}, 1000)
}

@ -361,15 +361,15 @@ class FileManager extends Plugin {
try {
const downloadFileName = helper.extractNameFromKey(path)
if (await this.isDirectory(path)) {
const zip = new JSZip()
await this.zipDir(path, zip)
const content = await zip.generateAsync({type: 'blob'})
saveAs(content, `${downloadFileName}.zip`)
} else {
path = this.normalize(path)
const content: any = await this.readFile(path)
saveAs(new Blob([content]), downloadFileName)
}
const zip = new JSZip()
await this.zipDir(path, zip)
const content = await zip.generateAsync({type: 'blob'})
saveAs(content, `${downloadFileName}.zip`)
} else {
path = this.normalize(path)
const content: any = await this.readFile(path)
saveAs(new Blob([content]), downloadFileName)
}
} catch (e) {
throw new Error(e)
}
@ -777,7 +777,7 @@ class FileManager extends Plugin {
provider.set(currentFile, oldContent)
return console.error(error)
} else {
this.emit('fileSaved', currentFile)
this.emit('fileSaved', currentFile)
}
})
})
@ -868,7 +868,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async moveFile(src: string, dest: string) {
async moveFile(src: string, dest: string) {
try {
src = this.normalize(src)
dest = this.normalize(dest)

@ -1,71 +1,71 @@
export class fileSystem {
name: string
enabled: boolean
available: boolean
fs: any
fsCallBack: any;
hasWorkSpaces: boolean
loaded: boolean
load: () => Promise<unknown>
test: () => Promise<unknown>
name: string
enabled: boolean
available: boolean
fs: any
fsCallBack: any;
hasWorkSpaces: boolean
loaded: boolean
load: () => Promise<unknown>
test: () => Promise<unknown>
constructor() {
this.available = false
this.enabled = false
this.hasWorkSpaces = false
this.loaded = false
}
constructor() {
this.available = false
this.enabled = false
this.hasWorkSpaces = false
this.loaded = false
}
checkWorkspaces = async () => {
try {
await this.fs.stat('.workspaces')
this.hasWorkSpaces = true
} catch (e) {
checkWorkspaces = async () => {
try {
await this.fs.stat('.workspaces')
this.hasWorkSpaces = true
} catch (e) {
}
}
}
set = async () => {
const w = (window as any)
if (!this.loaded) return false
w.remixFileSystem = this.fs
w.remixFileSystem.name = this.name
w.remixFileSystemCallback = this.fsCallBack
return true
}
set = async () => {
const w = (window as any)
if (!this.loaded) return false
w.remixFileSystem = this.fs
w.remixFileSystem.name = this.name
w.remixFileSystemCallback = this.fsCallBack
return true
}
}
export class fileSystems {
fileSystems: Record<string, fileSystem>
constructor() {
this.fileSystems = {}
}
fileSystems: Record<string, fileSystem>
constructor() {
this.fileSystems = {}
}
addFileSystem = async (fs: fileSystem): Promise<boolean> => {
try {
this.fileSystems[fs.name] = fs
await fs.test() && await fs.load()
console.log(fs.name + ' is loaded...')
return true
} catch (e) {
console.log(fs.name + ' not available...')
return false
}
addFileSystem = async (fs: fileSystem): Promise<boolean> => {
try {
this.fileSystems[fs.name] = fs
await fs.test() && await fs.load()
console.log(fs.name + ' is loaded...')
return true
} catch (e) {
console.log(fs.name + ' not available...')
return false
}
/**
}
/**
* sets filesystem using list as fallback
* @param {string[]} names
* @returns {Promise}
*/
setFileSystem = async (filesystems?: fileSystem[]): Promise<fileSystem> => {
for (const fs of filesystems) {
if (fs && this.fileSystems[fs.name]) {
const result = await this.fileSystems[fs.name].set()
if (result) return this.fileSystems[fs.name]
}
}
return null
setFileSystem = async (filesystems?: fileSystem[]): Promise<fileSystem> => {
for (const fs of filesystems) {
if (fs && this.fileSystems[fs.name]) {
const result = await this.fileSystems[fs.name].set()
if (result) return this.fileSystems[fs.name]
}
}
return null
}
}

@ -3,189 +3,189 @@ import JSZip from "jszip"
import { fileSystem } from "../fileSystem"
const _paq = window._paq = window._paq || []
export class fileSystemUtility {
migrate = async (fsFrom: fileSystem, fsTo: fileSystem) => {
try {
await fsFrom.checkWorkspaces()
await fsTo.checkWorkspaces()
if (fsTo.hasWorkSpaces) {
console.log(`${fsTo.name} already has files`)
return true
}
if (!fsFrom.hasWorkSpaces) {
console.log('no files to migrate')
return true
}
const fromFiles = await this.copyFolderToJson('/', null, null, fsFrom.fs)
await this.populateWorkspace(fromFiles, fsTo.fs)
const toFiles = await this.copyFolderToJson('/', null, null, fsTo.fs)
if (hashMessage(JSON.stringify(toFiles)) === hashMessage(JSON.stringify(fromFiles))) {
console.log('file migration successful')
return true
} else {
_paq.push(['trackEvent', 'Migrate', 'error', 'hash mismatch'])
console.log('file migration failed falling back to ' + fsFrom.name)
fsTo.loaded = false
return false
}
} catch (err) {
console.log(err)
_paq.push(['trackEvent', 'Migrate', 'error', err && err.message])
console.log('file migration failed falling back to ' + fsFrom.name)
fsTo.loaded = false
return false
}
migrate = async (fsFrom: fileSystem, fsTo: fileSystem) => {
try {
await fsFrom.checkWorkspaces()
await fsTo.checkWorkspaces()
if (fsTo.hasWorkSpaces) {
console.log(`${fsTo.name} already has files`)
return true
}
if (!fsFrom.hasWorkSpaces) {
console.log('no files to migrate')
return true
}
const fromFiles = await this.copyFolderToJson('/', null, null, fsFrom.fs)
await this.populateWorkspace(fromFiles, fsTo.fs)
const toFiles = await this.copyFolderToJson('/', null, null, fsTo.fs)
if (hashMessage(JSON.stringify(toFiles)) === hashMessage(JSON.stringify(fromFiles))) {
console.log('file migration successful')
return true
} else {
_paq.push(['trackEvent', 'Migrate', 'error', 'hash mismatch'])
console.log('file migration failed falling back to ' + fsFrom.name)
fsTo.loaded = false
return false
}
} catch (err) {
console.log(err)
_paq.push(['trackEvent', 'Migrate', 'error', err && err.message])
console.log('file migration failed falling back to ' + fsFrom.name)
fsTo.loaded = false
return false
}
downloadBackup = async (fs: fileSystem) => {
try {
const zip = new JSZip()
zip.file("readme.txt", "This is a Remix backup file.\nThis zip should be used by the restore backup tool in Remix.\nThe .workspaces directory contains your workspaces.")
await fs.checkWorkspaces()
await this.copyFolderToJson('/', null, null, fs.fs, ({ path, content }) => {
zip.file(path, content)
})
const blob = await zip.generateAsync({ type: 'blob' })
const today = new Date()
const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate()
const time = today.getHours() + 'h' + today.getMinutes() + 'min'
this.saveAs(blob, `remix-backup-at-${time}-${date}.zip`)
_paq.push(['trackEvent','Backup','download','preload'])
} catch (err) {
_paq.push(['trackEvent','Backup','error',err && err.message])
console.log(err)
}
}
downloadBackup = async (fs: fileSystem) => {
try {
const zip = new JSZip()
zip.file("readme.txt", "This is a Remix backup file.\nThis zip should be used by the restore backup tool in Remix.\nThe .workspaces directory contains your workspaces.")
await fs.checkWorkspaces()
await this.copyFolderToJson('/', null, null, fs.fs, ({ path, content }) => {
zip.file(path, content)
})
const blob = await zip.generateAsync({ type: 'blob' })
const today = new Date()
const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate()
const time = today.getHours() + 'h' + today.getMinutes() + 'min'
this.saveAs(blob, `remix-backup-at-${time}-${date}.zip`)
_paq.push(['trackEvent','Backup','download','preload'])
} catch (err) {
_paq.push(['trackEvent','Backup','error',err && err.message])
console.log(err)
}
populateWorkspace = async (json, fs) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await this.createDir(item, fs)
await this.populateWorkspace(json[item].children, fs)
} else {
await fs.writeFile(item, json[item].content, 'utf8')
}
}
}
populateWorkspace = async (json, fs) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await this.createDir(item, fs)
await this.populateWorkspace(json[item].children, fs)
} else {
await fs.writeFile(item, json[item].content, 'utf8')
}
}
}
/**
/**
* copy the folder recursively
* @param {string} path is the folder to be copied over
* @param {Function} visitFile is a function called for each visited files
* @param {Function} visitFolder is a function called for each visited folders
*/
copyFolderToJson = async (path, visitFile, visitFolder, fs, cb = null) => {
visitFile = visitFile || (() => { })
visitFolder = visitFolder || (() => { })
return await this._copyFolderToJsonInternal(path, visitFile, visitFolder, fs, cb)
}
copyFolderToJson = async (path, visitFile, visitFolder, fs, cb = null) => {
visitFile = visitFile || (() => { })
visitFolder = visitFolder || (() => { })
return await this._copyFolderToJsonInternal(path, visitFile, visitFolder, fs, cb)
}
/**
/**
* copy the folder recursively (internal use)
* @param {string} path is the folder to be copied over
* @param {Function} visitFile is a function called for each visited files
* @param {Function} visitFolder is a function called for each visited folders
*/
async _copyFolderToJsonInternal(path, visitFile, visitFolder, fs, cb) {
visitFile = visitFile || function () { /* do nothing. */ }
visitFolder = visitFolder || function () { /* do nothing. */ }
const json = {}
// path = this.removePrefix(path)
if (await fs.exists(path)) {
const items = await fs.readdir(path)
visitFolder({ path })
if (items.length !== 0) {
for (const item of items) {
const file: any = {}
const curPath = `${path}${path.endsWith('/') ? '' : '/'}${item}`
if ((await fs.stat(curPath)).isDirectory()) {
file.children = await this._copyFolderToJsonInternal(curPath, visitFile, visitFolder, fs, cb)
} else {
file.content = await fs.readFile(curPath, 'utf8')
if (cb) cb({ path: curPath, content: file.content })
visitFile({ path: curPath, content: file.content })
}
json[curPath] = file
}
}
}
return json
}
createDir = async (path, fs) => {
const paths = path.split('/')
if (paths.length && paths[0] === '') paths.shift()
let currentCheck = ''
for (const value of paths) {
currentCheck = currentCheck + (currentCheck ? '/' : '') + value
if (!await fs.exists(currentCheck)) {
await fs.mkdir(currentCheck)
}
async _copyFolderToJsonInternal(path, visitFile, visitFolder, fs, cb) {
visitFile = visitFile || function () { /* do nothing. */ }
visitFolder = visitFolder || function () { /* do nothing. */ }
const json = {}
// path = this.removePrefix(path)
if (await fs.exists(path)) {
const items = await fs.readdir(path)
visitFolder({ path })
if (items.length !== 0) {
for (const item of items) {
const file: any = {}
const curPath = `${path}${path.endsWith('/') ? '' : '/'}${item}`
if ((await fs.stat(curPath)).isDirectory()) {
file.children = await this._copyFolderToJsonInternal(curPath, visitFile, visitFolder, fs, cb)
} else {
file.content = await fs.readFile(curPath, 'utf8')
if (cb) cb({ path: curPath, content: file.content })
visitFile({ path: curPath, content: file.content })
}
json[curPath] = file
}
}
}
saveAs = (blob, name) => {
const node = document.createElement('a')
node.download = name
node.rel = 'noopener'
node.href = URL.createObjectURL(blob)
setTimeout(function () { URL.revokeObjectURL(node.href) }, 4E4) // 40s
setTimeout(function () {
try {
node.dispatchEvent(new MouseEvent('click'))
} catch (e) {
const evt = document.createEvent('MouseEvents')
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80,
20, false, false, false, false, 0, null)
node.dispatchEvent(evt)
}
}, 0) // 40s
return json
}
createDir = async (path, fs) => {
const paths = path.split('/')
if (paths.length && paths[0] === '') paths.shift()
let currentCheck = ''
for (const value of paths) {
currentCheck = currentCheck + (currentCheck ? '/' : '') + value
if (!await fs.exists(currentCheck)) {
await fs.mkdir(currentCheck)
}
}
}
saveAs = (blob, name) => {
const node = document.createElement('a')
node.download = name
node.rel = 'noopener'
node.href = URL.createObjectURL(blob)
setTimeout(function () { URL.revokeObjectURL(node.href) }, 4E4) // 40s
setTimeout(function () {
try {
node.dispatchEvent(new MouseEvent('click'))
} catch (e) {
const evt = document.createEvent('MouseEvents')
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80,
20, false, false, false, false, 0, null)
node.dispatchEvent(evt)
}
}, 0) // 40s
}
}
/* eslint-disable no-template-curly-in-string */
export const migrationTestData = {
'.workspaces': {
'.workspaces': {
children: {
'.workspaces/default_workspace': {
children: {
'.workspaces/default_workspace': {
children: {
'.workspaces/default_workspace/README.txt': {
content: 'TEST README'
}
}
},
'.workspaces/emptyspace': {
'.workspaces/default_workspace/README.txt': {
content: 'TEST README'
}
}
},
'.workspaces/emptyspace': {
},
'.workspaces/workspace_test': {
},
'.workspaces/workspace_test': {
children: {
'.workspaces/workspace_test/TEST_README.txt': {
content: 'TEST README'
},
'.workspaces/workspace_test/test_contracts': {
children: {
'.workspaces/workspace_test/test_contracts/1_Storage.sol': {
content: 'testing'
},
'.workspaces/workspace_test/test_contracts/artifacts': {
children: {
'.workspaces/workspace_test/TEST_README.txt': {
content: 'TEST README'
},
'.workspaces/workspace_test/test_contracts': {
children: {
'.workspaces/workspace_test/test_contracts/1_Storage.sol': {
content: 'testing'
},
'.workspaces/workspace_test/test_contracts/artifacts': {
children: {
'.workspaces/workspace_test/test_contracts/artifacts/Storage_metadata.json': {
content: '{ "test": "data" }'
}
}
}
}
}
'.workspaces/workspace_test/test_contracts/artifacts/Storage_metadata.json': {
content: '{ "test": "data" }'
}
}
}
}
}
}
}
}
}
}

@ -2,90 +2,90 @@ import LightningFS from "@isomorphic-git/lightning-fs"
import { fileSystem } from "../fileSystem"
export class IndexedDBStorage extends LightningFS {
base: LightningFS.PromisifedFS
addSlash: (file: string) => string
extended: { exists: (path: string) => Promise<unknown>; rmdir: (path: any) => Promise<void>; readdir: (path: any) => Promise<string[]>; unlink: (path: any) => Promise<void>; mkdir: (path: any) => Promise<void>; readFile: (path: any, options: any) => Promise<Uint8Array>; rename: (from: any, to: any) => Promise<void>; writeFile: (path: any, content: any, options: any) => Promise<void>; stat: (path: any) => Promise<import("fs").Stats>; init(name: string, opt?: LightningFS.FSConstructorOptions): void; activate(): Promise<void>; deactivate(): Promise<void>; lstat(filePath: string): Promise<import("fs").Stats>; readlink(filePath: string): Promise<string>; symlink(target: string, filePath: string): Promise<void> }
constructor(name: string) {
super(name)
this.addSlash = (file) => {
if (!file.startsWith('/')) file = '/' + file
return file
}
this.base = this.promises
this.extended = {
...this.promises,
exists: async (path: string) => {
return new Promise((resolve) => {
this.base.stat(this.addSlash(path)).then(() => resolve(true)).catch(() => resolve(false))
})
},
rmdir: async (path) => {
return this.base.rmdir(this.addSlash(path))
},
readdir: async (path) => {
return this.base.readdir(this.addSlash(path))
},
unlink: async (path) => {
return this.base.unlink(this.addSlash(path))
},
mkdir: async (path) => {
return this.base.mkdir(this.addSlash(path))
},
readFile: async (path, options) => {
return this.base.readFile(this.addSlash(path), options)
},
rename: async (from, to) => {
return this.base.rename(this.addSlash(from), this.addSlash(to))
},
writeFile: async (path, content, options) => {
return this.base.writeFile(this.addSlash(path), content, options)
},
stat: async (path) => {
return this.base.stat(this.addSlash(path))
}
}
base: LightningFS.PromisifedFS
addSlash: (file: string) => string
extended: { exists: (path: string) => Promise<unknown>; rmdir: (path: any) => Promise<void>; readdir: (path: any) => Promise<string[]>; unlink: (path: any) => Promise<void>; mkdir: (path: any) => Promise<void>; readFile: (path: any, options: any) => Promise<Uint8Array>; rename: (from: any, to: any) => Promise<void>; writeFile: (path: any, content: any, options: any) => Promise<void>; stat: (path: any) => Promise<import("fs").Stats>; init(name: string, opt?: LightningFS.FSConstructorOptions): void; activate(): Promise<void>; deactivate(): Promise<void>; lstat(filePath: string): Promise<import("fs").Stats>; readlink(filePath: string): Promise<string>; symlink(target: string, filePath: string): Promise<void> }
constructor(name: string) {
super(name)
this.addSlash = (file) => {
if (!file.startsWith('/')) file = '/' + file
return file
}
this.base = this.promises
this.extended = {
...this.promises,
exists: async (path: string) => {
return new Promise((resolve) => {
this.base.stat(this.addSlash(path)).then(() => resolve(true)).catch(() => resolve(false))
})
},
rmdir: async (path) => {
return this.base.rmdir(this.addSlash(path))
},
readdir: async (path) => {
return this.base.readdir(this.addSlash(path))
},
unlink: async (path) => {
return this.base.unlink(this.addSlash(path))
},
mkdir: async (path) => {
return this.base.mkdir(this.addSlash(path))
},
readFile: async (path, options) => {
return this.base.readFile(this.addSlash(path), options)
},
rename: async (from, to) => {
return this.base.rename(this.addSlash(from), this.addSlash(to))
},
writeFile: async (path, content, options) => {
return this.base.writeFile(this.addSlash(path), content, options)
},
stat: async (path) => {
return this.base.stat(this.addSlash(path))
}
}
}
}
export class indexedDBFileSystem extends fileSystem {
constructor() {
super()
this.name = 'indexedDB'
}
constructor() {
super()
this.name = 'indexedDB'
}
load = async () => {
return new Promise((resolve, reject) => {
try {
const fs = new IndexedDBStorage('RemixFileSystem')
fs.init('RemixFileSystem')
this.fs = fs.extended
this.fsCallBack = fs
this.loaded = true
resolve(true)
} catch (e) {
reject(e)
}
})
}
load = async () => {
return new Promise((resolve, reject) => {
try {
const fs = new IndexedDBStorage('RemixFileSystem')
fs.init('RemixFileSystem')
this.fs = fs.extended
this.fsCallBack = fs
this.loaded = true
resolve(true)
} catch (e) {
reject(e)
}
})
}
test = async () => {
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
this.available = false
reject('No indexedDB on window')
}
const request = window.indexedDB.open("RemixTestDataBase");
request.onerror = () => {
this.available = false
reject('Error creating test database')
};
request.onsuccess = () => {
window.indexedDB.deleteDatabase("RemixTestDataBase");
this.available = true
resolve(true)
};
})
}
test = async () => {
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
this.available = false
reject('No indexedDB on window')
}
const request = window.indexedDB.open("RemixTestDataBase");
request.onerror = () => {
this.available = false
reject('Error creating test database')
};
request.onsuccess = () => {
window.indexedDB.deleteDatabase("RemixTestDataBase");
this.available = true
resolve(true)
};
})
}
}

@ -2,56 +2,56 @@ import { fileSystem } from "../fileSystem";
export class localStorageFS extends fileSystem {
constructor() {
super()
this.name = 'localstorage'
}
load = async () => {
const me = this
return new Promise((resolve, reject) => {
try {
const w = window as any
w.BrowserFS.install(window)
w.BrowserFS.configure({
fs: 'LocalStorage'
}, async function (e) {
if (e) {
console.log('BrowserFS Error: ' + e)
reject(e)
} else {
me.fs = { ...window.require('fs') }
me.fsCallBack = window.require('fs')
me.fs.readdir = me.fs.readdirSync
me.fs.readFile = me.fs.readFileSync
me.fs.writeFile = me.fs.writeFileSync
me.fs.stat = me.fs.statSync
me.fs.unlink = me.fs.unlinkSync
me.fs.rmdir = me.fs.rmdirSync
me.fs.mkdir = me.fs.mkdirSync
me.fs.rename = me.fs.renameSync
me.fs.exists = me.fs.existsSync
me.loaded = true
resolve(true)
}
})
} catch (e) {
console.log('BrowserFS is not ready!')
reject(e)
}
constructor() {
super()
this.name = 'localstorage'
}
load = async () => {
const me = this
return new Promise((resolve, reject) => {
try {
const w = window as any
w.BrowserFS.install(window)
w.BrowserFS.configure({
fs: 'LocalStorage'
}, async function (e) {
if (e) {
console.log('BrowserFS Error: ' + e)
reject(e)
} else {
me.fs = { ...window.require('fs') }
me.fsCallBack = window.require('fs')
me.fs.readdir = me.fs.readdirSync
me.fs.readFile = me.fs.readFileSync
me.fs.writeFile = me.fs.writeFileSync
me.fs.stat = me.fs.statSync
me.fs.unlink = me.fs.unlinkSync
me.fs.rmdir = me.fs.rmdirSync
me.fs.mkdir = me.fs.mkdirSync
me.fs.rename = me.fs.renameSync
me.fs.exists = me.fs.existsSync
me.loaded = true
resolve(true)
}
})
}
} catch (e) {
console.log('BrowserFS is not ready!')
reject(e)
}
})
}
test = async () => {
return new Promise((resolve, reject) => {
const test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
resolve(true)
} catch(e) {
reject(e)
}
})
}
test = async () => {
return new Promise((resolve, reject) => {
const test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
resolve(true)
} catch(e) {
reject(e)
}
})
}
}

@ -61,9 +61,9 @@ export class Layout extends Plugin {
})
this.on('manager', 'activate', (profile: Profile) => {
switch (profile.name) {
case 'filePanel':
this.call('menuicons', 'select', 'filePanel')
break
case 'filePanel':
this.call('menuicons', 'select', 'filePanel')
break
}
})
this.on('sidePanel', 'focusChanged', async (name) => {

@ -114,9 +114,9 @@ class Terminal extends Plugin {
updateComponent(state) {
return <RemixUiTerminal
plugin={state.plugin}
onReady={state.onReady}
/>
plugin={state.plugin}
onReady={state.onReady}
/>
}
renderComponent () {

@ -8,279 +8,279 @@ import toml from 'toml'
import { filePathFilter, AnyFilter } from '@jsdevtools/file-path-filter'
const profile = {
name: 'codeFormatter',
desciption: 'prettier plugin for Remix',
methods: ['format'],
events: [''],
version: '0.0.1'
name: 'codeFormatter',
desciption: 'prettier plugin for Remix',
methods: ['format'],
events: [''],
version: '0.0.1'
}
const defaultOptions = {
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 80,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
}
},
{
"files": "*.yml",
"options": {
}
},
{
"files": "*.yaml",
"options": {
}
},
{
"files": "*.toml",
"options": {
}
},
{
"files": "*.json",
"options": {
}
},
{
"files": "*.js",
"options": {
}
},
{
"files": "*.ts",
"options": {
}
}
]
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 80,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
}
},
{
"files": "*.yml",
"options": {
}
},
{
"files": "*.yaml",
"options": {
}
},
{
"files": "*.toml",
"options": {
}
},
{
"files": "*.json",
"options": {
}
},
{
"files": "*.js",
"options": {
}
},
{
"files": "*.ts",
"options": {
}
}
]
}
export class CodeFormat extends Plugin {
prettier: any
ts: any
babel: any
espree: any
yml: any
sol: any
prettier: any
ts: any
babel: any
espree: any
yml: any
sol: any
constructor() {
super(profile)
}
constructor() {
super(profile)
}
async format(file: string) {
async format(file: string) {
// lazy load
if (!this.prettier) {
this.prettier = await import('prettier/standalone')
this.ts = await import('prettier/parser-typescript')
this.babel = await import('prettier/parser-babel')
this.espree = await import('prettier/parser-espree')
this.yml = await import('prettier/parser-yaml')
}
// lazy load
if (!this.prettier) {
this.prettier = await import('prettier/standalone')
this.ts = await import('prettier/parser-typescript')
this.babel = await import('prettier/parser-babel')
this.espree = await import('prettier/parser-espree')
this.yml = await import('prettier/parser-yaml')
}
try {
const content = await this.call('fileManager', 'readFile', file)
if (!content) return
let parserName = ''
let options: Options = {
}
switch (path.extname(file)) {
case '.sol':
parserName = 'solidity-parse'
break
case '.ts':
parserName = 'typescript'
options = {
...options,
trailingComma: 'all',
semi: false,
singleQuote: true,
quoteProps: 'as-needed',
bracketSpacing: true,
arrowParens: 'always',
}
break
case '.js':
parserName = "espree"
options = {
...options,
semi: false,
singleQuote: true,
}
break
case '.json':
parserName = 'json'
break
case '.yml':
parserName = 'yaml'
break
case '.yaml':
parserName = 'yaml'
break
}
try {
const content = await this.call('fileManager', 'readFile', file)
if (!content) return
let parserName = ''
let options: Options = {
}
switch (path.extname(file)) {
case '.sol':
parserName = 'solidity-parse'
break
case '.ts':
parserName = 'typescript'
options = {
...options,
trailingComma: 'all',
semi: false,
singleQuote: true,
quoteProps: 'as-needed',
bracketSpacing: true,
arrowParens: 'always',
}
break
case '.js':
parserName = "espree"
options = {
...options,
semi: false,
singleQuote: true,
}
break
case '.json':
parserName = 'json'
break
case '.yml':
parserName = 'yaml'
break
case '.yaml':
parserName = 'yaml'
break
}
if (file === '.prettierrc') {
parserName = 'json'
}
if (file === '.prettierrc') {
parserName = 'json'
}
const possibleFileNames = [
'.prettierrc',
'.prettierrc.json',
'.prettierrc.yaml',
'.prettierrc.yml',
'.prettierrc.toml',
'.prettierrc.js',
'.prettierrc.cjs',
'prettier.config.js',
'prettier.config.cjs',
'.prettierrc.json5',
]
const possibleFileNames = [
'.prettierrc',
'.prettierrc.json',
'.prettierrc.yaml',
'.prettierrc.yml',
'.prettierrc.toml',
'.prettierrc.js',
'.prettierrc.cjs',
'prettier.config.js',
'prettier.config.cjs',
'.prettierrc.json5',
]
const prettierConfigFile = await findAsync(possibleFileNames, async (fileName) => {
const exists = await this.call('fileManager', 'exists', fileName)
return exists
})
const prettierConfigFile = await findAsync(possibleFileNames, async (fileName) => {
const exists = await this.call('fileManager', 'exists', fileName)
return exists
})
let parsed = null
if (prettierConfigFile) {
let prettierConfig = await this.call('fileManager', 'readFile', prettierConfigFile)
if (prettierConfig) {
if (prettierConfigFile.endsWith('.yaml') || prettierConfigFile.endsWith('.yml')) {
try {
parsed = yaml.load(prettierConfig)
} catch (e) {
// do nothing
}
} else if (prettierConfigFile.endsWith('.toml')) {
try {
parsed = toml.parse(prettierConfig)
} catch (e) {
// do nothing
}
} else if (prettierConfigFile.endsWith('.json') || prettierConfigFile.endsWith('.json5')) {
try {
parsed = JSON.parse(prettierConfig)
} catch (e) {
// do nothing
}
} else if (prettierConfigFile === '.prettierrc') {
try {
parsed = JSON.parse(prettierConfig)
} catch (e) {
// do nothing
}
if (!parsed) {
try {
parsed = yaml.load(prettierConfig)
} catch (e) {
// do nothing
}
}
} else if (prettierConfigFile.endsWith('.js') || prettierConfigFile.endsWith('.cjs')) {
// remove any comments
prettierConfig = prettierConfig.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '')
// add quotes to keys
prettierConfig = prettierConfig.replace(/([a-zA-Z0-9_]+)(\s*):/g, '"$1"$2:')
// remove comma from last key
prettierConfig = prettierConfig.replace(/,(\s*})/g, '$1')
// remove any semi-colons
prettierConfig = prettierConfig.replace(/;/g, '')
// convert single quotes to double quotes
prettierConfig = prettierConfig.replace(/'/g, '"')
try {
parsed = JSON.parse(prettierConfig.replace('module.exports = ', '').replace('module.exports=', ''))
} catch (e) {
// do nothing
}
}
}
} else {
parsed = defaultOptions
await this.call('fileManager', 'writeFile', '.prettierrc.json', JSON.stringify(parsed, null, 2))
await this.call('notification', 'toast', 'A prettier config file has been created in the workspace.')
let parsed = null
if (prettierConfigFile) {
let prettierConfig = await this.call('fileManager', 'readFile', prettierConfigFile)
if (prettierConfig) {
if (prettierConfigFile.endsWith('.yaml') || prettierConfigFile.endsWith('.yml')) {
try {
parsed = yaml.load(prettierConfig)
} catch (e) {
// do nothing
}
if (!parsed && prettierConfigFile) {
this.call('notification', 'toast', `Error parsing prettier config file: ${prettierConfigFile}`)
} else if (prettierConfigFile.endsWith('.toml')) {
try {
parsed = toml.parse(prettierConfig)
} catch (e) {
// do nothing
}
} else if (prettierConfigFile.endsWith('.json') || prettierConfigFile.endsWith('.json5')) {
try {
parsed = JSON.parse(prettierConfig)
} catch (e) {
// do nothing
}
} else if (prettierConfigFile === '.prettierrc') {
try {
parsed = JSON.parse(prettierConfig)
} catch (e) {
// do nothing
}
if (!parsed) {
try {
parsed = yaml.load(prettierConfig)
} catch (e) {
// do nothing
}
}
} else if (prettierConfigFile.endsWith('.js') || prettierConfigFile.endsWith('.cjs')) {
// remove any comments
prettierConfig = prettierConfig.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '')
// add quotes to keys
prettierConfig = prettierConfig.replace(/([a-zA-Z0-9_]+)(\s*):/g, '"$1"$2:')
// remove comma from last key
prettierConfig = prettierConfig.replace(/,(\s*})/g, '$1')
// remove any semi-colons
prettierConfig = prettierConfig.replace(/;/g, '')
// convert single quotes to double quotes
prettierConfig = prettierConfig.replace(/'/g, '"')
try {
parsed = JSON.parse(prettierConfig.replace('module.exports = ', '').replace('module.exports=', ''))
} catch (e) {
// do nothing
}
}
}
} else {
parsed = defaultOptions
await this.call('fileManager', 'writeFile', '.prettierrc.json', JSON.stringify(parsed, null, 2))
await this.call('notification', 'toast', 'A prettier config file has been created in the workspace.')
}
if (!parsed && prettierConfigFile) {
this.call('notification', 'toast', `Error parsing prettier config file: ${prettierConfigFile}`)
}
// merge options
if (parsed) {
options = {
...options,
...parsed,
}
}
// search for overrides
if (parsed && parsed.overrides) {
const override = parsed.overrides.find((override) => {
if (override.files) {
const pathFilter: AnyFilter = {}
pathFilter.include = setGlobalExpression(override.files)
const filteredFiles = [file]
.filter(filePathFilter(pathFilter))
if (filteredFiles.length) {
return true
}
}
})
const validParsers = ['typescript', 'babel', 'espree', 'solidity-parse', 'json', 'yaml', 'solidity-parse']
if (override && override.options && override.options.parser) {
if (validParsers.includes(override.options.parser)) {
parserName = override.options.parser
} else {
this.call('notification', 'toast', `Invalid parser: ${override.options.parser}! Valid options are ${validParsers.join(', ')}`)
}
delete override.options.parser
}
// merge options
if (parsed) {
options = {
...options,
...parsed,
}
}
if (override) {
options = {
...options,
...override.options,
}
}
// search for overrides
if (parsed && parsed.overrides) {
const override = parsed.overrides.find((override) => {
if (override.files) {
const pathFilter: AnyFilter = {}
pathFilter.include = setGlobalExpression(override.files)
const filteredFiles = [file]
.filter(filePathFilter(pathFilter))
if (filteredFiles.length) {
return true
}
}
})
const validParsers = ['typescript', 'babel', 'espree', 'solidity-parse', 'json', 'yaml', 'solidity-parse']
if (override && override.options && override.options.parser) {
if (validParsers.includes(override.options.parser)) {
parserName = override.options.parser
} else {
this.call('notification', 'toast', `Invalid parser: ${override.options.parser}! Valid options are ${validParsers.join(', ')}`)
}
delete override.options.parser
}
const result = this.prettier.format(content, {
plugins: [sol as any, this.ts, this.babel, this.espree, this.yml],
parser: parserName,
...options
})
await this.call('fileManager', 'writeFile', file, result)
} catch (e) {
// do nothing
if (override) {
options = {
...options,
...override.options,
}
}
}
const result = this.prettier.format(content, {
plugins: [sol as any, this.ts, this.babel, this.espree, this.yml],
parser: parserName,
...options
})
await this.call('fileManager', 'writeFile', file, result)
} catch (e) {
// do nothing
}
}
}
//*.sol, **/*.txt, contracts/*
const setGlobalExpression = (paths: string) => {
const results = []
paths.split(',').forEach(path => {
path = path.trim()
if (path.startsWith('*.')) path = path.replace(/(\*\.)/g, '**/*.')
if (path.endsWith('/*') && !path.endsWith('/**/*'))
path = path.replace(/(\*)/g, '**/*.*')
results.push(path)
})
return results
const results = []
paths.split(',').forEach(path => {
path = path.trim()
if (path.startsWith('*.')) path = path.replace(/(\*\.)/g, '**/*.')
if (path.endsWith('/*') && !path.endsWith('/**/*'))
path = path.replace(/(\*)/g, '**/*.*')
results.push(path)
})
return results
}
async function findAsync(arr, asyncCallback) {
const promises = arr.map(asyncCallback);
const results = await Promise.all(promises);
const index = results.findIndex(result => result);
return arr[index];
const promises = arr.map(asyncCallback);
const results = await Promise.all(promises);
const index = results.findIndex(result => result);
return arr[index];
}

@ -8,54 +8,54 @@ import { parse } from './parser'
// https://prettier.io/docs/en/plugins.html#languages
// https://github.com/ikatyang/linguist-languages/blob/master/data/Solidity.json
const languages = [
{
linguistLanguageId: 237469032,
name: 'Solidity',
type: 'programming',
color: '#AA6746',
aceMode: 'text',
tmScope: 'source.solidity',
extensions: ['.sol'],
parsers: ['solidity-parse'],
vscodeLanguageIds: ['solidity']
}
{
linguistLanguageId: 237469032,
name: 'Solidity',
type: 'programming',
color: '#AA6746',
aceMode: 'text',
tmScope: 'source.solidity',
extensions: ['.sol'],
parsers: ['solidity-parse'],
vscodeLanguageIds: ['solidity']
}
];
// https://prettier.io/docs/en/plugins.html#parsers
const parser = { astFormat: 'solidity-ast', parse, ...loc };
const parsers = {
'solidity-parse': parser
'solidity-parse': parser
};
const canAttachComment = (node) =>
node.type && node.type !== 'BlockComment' && node.type !== 'LineComment';
node.type && node.type !== 'BlockComment' && node.type !== 'LineComment';
// https://prettier.io/docs/en/plugins.html#printers
const printers = {
'solidity-ast': {
canAttachComment,
handleComments: {
ownLine: handleComments.handleOwnLineComment,
endOfLine: handleComments.handleEndOfLineComment,
remaining: handleComments.handleRemainingComment
},
isBlockComment: handleComments.isBlockComment,
massageAstNode,
print,
printComment
}
'solidity-ast': {
canAttachComment,
handleComments: {
ownLine: handleComments.handleOwnLineComment,
endOfLine: handleComments.handleEndOfLineComment,
remaining: handleComments.handleRemainingComment
},
isBlockComment: handleComments.isBlockComment,
massageAstNode,
print,
printComment
}
};
// https://prettier.io/docs/en/plugins.html#defaultoptions
const defaultOptions = {
bracketSpacing: false,
tabWidth: 4
bracketSpacing: false,
tabWidth: 4
};
export default {
languages,
parsers,
printers,
options,
defaultOptions
languages,
parsers,
printers,
options,
defaultOptions
};

@ -80,113 +80,113 @@ export function parse(text, _parsers, options) {
},
BinaryOperation(ctx) {
switch (ctx.operator) {
case '+':
case '-':
ctx.left = tryHug(ctx.left, ['%']);
ctx.right = tryHug(ctx.right, ['%']);
break;
case '*':
ctx.left = tryHug(ctx.left, ['/', '%']);
break;
case '/':
ctx.left = tryHug(ctx.left, ['*', '%']);
break;
case '%':
ctx.left = tryHug(ctx.left, ['*', '/', '%']);
break;
case '**':
// If the compiler has not been given as an option using we leave a**b**c.
if (!compiler) break;
case '+':
case '-':
ctx.left = tryHug(ctx.left, ['%']);
ctx.right = tryHug(ctx.right, ['%']);
break;
case '*':
ctx.left = tryHug(ctx.left, ['/', '%']);
break;
case '/':
ctx.left = tryHug(ctx.left, ['*', '%']);
break;
case '%':
ctx.left = tryHug(ctx.left, ['*', '/', '%']);
break;
case '**':
// If the compiler has not been given as an option using we leave a**b**c.
if (!compiler) break;
if (semver.satisfies(compiler, '<0.8.0')) {
// If the compiler is less than 0.8.0 then a**b**c is formatted as
// (a**b)**c.
ctx.left = tryHug(ctx.left, ['**']);
break;
}
if (
ctx.left.type === 'BinaryOperation' &&
ctx.left.operator === '**'
) {
// the parser still organizes the a**b**c as (a**b)**c so we need
// to restructure it.
ctx.right = {
type: 'TupleExpression',
components: [
{
type: 'BinaryOperation',
operator: '**',
left: ctx.left.right,
right: ctx.right
}
],
isArray: false
};
ctx.left = ctx.left.left;
}
break;
case '<<':
case '>>':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**']);
break;
case '&':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**', '<<', '>>']);
break;
case '|':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
break;
case '^':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
break;
case '||':
ctx.left = tryHug(ctx.left, ['&&']);
ctx.right = tryHug(ctx.right, ['&&']);
break;
case '&&':
default:
if (semver.satisfies(compiler, '<0.8.0')) {
// If the compiler is less than 0.8.0 then a**b**c is formatted as
// (a**b)**c.
ctx.left = tryHug(ctx.left, ['**']);
break;
}
if (
ctx.left.type === 'BinaryOperation' &&
ctx.left.operator === '**'
) {
// the parser still organizes the a**b**c as (a**b)**c so we need
// to restructure it.
ctx.right = {
type: 'TupleExpression',
components: [
{
type: 'BinaryOperation',
operator: '**',
left: ctx.left.right,
right: ctx.right
}
],
isArray: false
};
ctx.left = ctx.left.left;
}
break;
case '<<':
case '>>':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**']);
break;
case '&':
ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']);
ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**', '<<', '>>']);
break;
case '|':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&',
'^'
]);
break;
case '^':
ctx.left = tryHug(ctx.left, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
ctx.right = tryHug(ctx.right, [
'+',
'-',
'*',
'/',
'**',
'<<',
'>>',
'&'
]);
break;
case '||':
ctx.left = tryHug(ctx.left, ['&&']);
ctx.right = tryHug(ctx.right, ['&&']);
break;
case '&&':
default:
break;
}
}
});

@ -61,8 +61,8 @@ export class ContractFlattener extends Plugin {
try{
dependencyGraph = getDependencyGraph(ast, filePath)
sorted = dependencyGraph.isEmpty()
? [filePath]
: dependencyGraph.sort().reverse()
? [filePath]
: dependencyGraph.sort().reverse()
sources = source.sources
result = concatSourceFiles(sorted, sources)
}catch(err){

@ -6,79 +6,79 @@ import { Plugin } from '@remixproject/engine'
import { fileDecoration } from '@remix-ui/file-decorators'
const profile = {
name: 'fileDecorator',
desciption: 'Keeps decorators of the files',
methods: ['setFileDecorators', 'clearFileDecorators', 'clearAllFileDecorators'],
events: ['fileDecoratorsChanged'],
version: '0.0.1'
name: 'fileDecorator',
desciption: 'Keeps decorators of the files',
methods: ['setFileDecorators', 'clearFileDecorators', 'clearAllFileDecorators'],
events: ['fileDecoratorsChanged'],
version: '0.0.1'
}
export class FileDecorator extends Plugin {
private _fileStates: fileDecoration[] = []
constructor() {
super(profile)
}
private _fileStates: fileDecoration[] = []
constructor() {
super(profile)
}
onActivation(): void {
this.on('filePanel', 'setWorkspace', async () => {
await this.clearAllFileDecorators()
})
}
onActivation(): void {
this.on('filePanel', 'setWorkspace', async () => {
await this.clearAllFileDecorators()
})
}
/**
/**
* @param fileStates Array of file states
*/
async setFileDecorators(fileStates: fileDecoration[] | fileDecoration) {
const { from } = this.currentRequest
const workspace = await this.call('filePanel', 'getCurrentWorkspace')
const fileStatesPayload = Array.isArray(fileStates) ? fileStates : [fileStates]
// clear all file states in the previous state of this owner on the files called
fileStatesPayload.forEach((state) => {
state.workspace = workspace
state.owner = from
})
const filteredState = this._fileStates.filter((state) => {
const index = fileStatesPayload.findIndex((payloadFileState: fileDecoration) => {
return from == state.owner && payloadFileState.path == state.path
})
return index == -1
})
const newState = [...filteredState, ...fileStatesPayload].sort(sortByPath)
async setFileDecorators(fileStates: fileDecoration[] | fileDecoration) {
const { from } = this.currentRequest
const workspace = await this.call('filePanel', 'getCurrentWorkspace')
const fileStatesPayload = Array.isArray(fileStates) ? fileStates : [fileStates]
// clear all file states in the previous state of this owner on the files called
fileStatesPayload.forEach((state) => {
state.workspace = workspace
state.owner = from
})
const filteredState = this._fileStates.filter((state) => {
const index = fileStatesPayload.findIndex((payloadFileState: fileDecoration) => {
return from == state.owner && payloadFileState.path == state.path
})
return index == -1
})
const newState = [...filteredState, ...fileStatesPayload].sort(sortByPath)
if (!deepequal(newState, this._fileStates)) {
this._fileStates = newState
this.emit('fileDecoratorsChanged', this._fileStates)
}
if (!deepequal(newState, this._fileStates)) {
this._fileStates = newState
this.emit('fileDecoratorsChanged', this._fileStates)
}
}
async clearFileDecorators(path?: string) {
const { from } = this.currentRequest
if (!from) return
async clearFileDecorators(path?: string) {
const { from } = this.currentRequest
if (!from) return
const filteredState = this._fileStates.filter((state) => {
if(state.owner != from) return true
if(path && state.path != path) return true
})
const newState = [...filteredState].sort(sortByPath)
if (!deepequal(newState, this._fileStates)) {
this._fileStates = newState
this.emit('fileDecoratorsChanged', this._fileStates)
}
const filteredState = this._fileStates.filter((state) => {
if(state.owner != from) return true
if(path && state.path != path) return true
})
const newState = [...filteredState].sort(sortByPath)
if (!deepequal(newState, this._fileStates)) {
this._fileStates = newState
this.emit('fileDecoratorsChanged', this._fileStates)
}
async clearAllFileDecorators() {
this._fileStates = []
this.emit('fileDecoratorsChanged', [])
}
}
async clearAllFileDecorators() {
this._fileStates = []
this.emit('fileDecoratorsChanged', [])
}
}
const sortByPath = (a: fileDecoration, b: fileDecoration) => {
if (a.path < b.path) {
return -1;
}
if (a.path > b.path) {
return 1;
}
return 0;
if (a.path < b.path) {
return -1;
}
if (a.path > b.path) {
return 1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

@ -1,45 +1,45 @@
let parser: any
self.onmessage = (e: MessageEvent) => {
const data: any = e.data
switch (data.cmd) {
case 'load':
{
(self as any).importScripts(e.data.url)
// @ts-ignore
parser = SolidityParser as any;
const data: any = e.data
switch (data.cmd) {
case 'load':
{
(self as any).importScripts(e.data.url)
// @ts-ignore
parser = SolidityParser as any;
self.postMessage({
cmd: 'loaded',
})
break
}
self.postMessage({
cmd: 'loaded',
})
break
}
case 'parse':
if (data.text && parser) {
case 'parse':
if (data.text && parser) {
try {
let startTime = performance.now()
const blocks = parser.parseBlock(data.text, { loc: true, range: true, tolerant: true })
const blockDuration = performance.now() - startTime
startTime = performance.now()
const ast = parser.parse(data.text, { loc: true, range: true, tolerant: true })
const endTime = performance.now()
try {
let startTime = performance.now()
const blocks = parser.parseBlock(data.text, { loc: true, range: true, tolerant: true })
const blockDuration = performance.now() - startTime
startTime = performance.now()
const ast = parser.parse(data.text, { loc: true, range: true, tolerant: true })
const endTime = performance.now()
self.postMessage({
cmd: 'parsed',
timestamp: data.timestamp,
ast,
text: data.text,
file: data.file,
duration: endTime - startTime,
blockDuration,
blocks
})
} catch (e) {
// do nothing
}
self.postMessage({
cmd: 'parsed',
timestamp: data.timestamp,
ast,
text: data.text,
file: data.file,
duration: endTime - startTime,
blockDuration,
blocks
})
} catch (e) {
// do nothing
}
}
break
}
break
}
}

@ -20,13 +20,13 @@ interface BlockDefinition {
}
export default class CodeParserAntlrService {
plugin: CodeParser
worker: Worker
parserStartTime: number = 0
workerTimer: NodeJS.Timer
parserThreshold: number = 10
parserThresholdSampleAmount = 3
cache: {
plugin: CodeParser
worker: Worker
parserStartTime: number = 0
workerTimer: NodeJS.Timer
parserThreshold: number = 10
parserThresholdSampleAmount = 3
cache: {
[name: string]: {
text: string,
ast: antlr.ParseResult | null,
@ -36,253 +36,253 @@ export default class CodeParserAntlrService {
blockDurations?: number[]
}
} = {};
constructor(plugin: CodeParser) {
this.plugin = plugin
this.createWorker()
}
constructor(plugin: CodeParser) {
this.plugin = plugin
this.createWorker()
}
createWorker() {
this.worker = new Worker(new URL('./antlr-worker', import.meta.url))
this.worker.postMessage({
cmd: 'load',
url: document.location.protocol + '//' + document.location.host + '/assets/js/parser/antlr.js',
});
const self = this
createWorker() {
this.worker = new Worker(new URL('./antlr-worker', import.meta.url))
this.worker.postMessage({
cmd: 'load',
url: document.location.protocol + '//' + document.location.host + '/assets/js/parser/antlr.js',
});
const self = this
this.worker.addEventListener('message', function (ev) {
switch (ev.data.cmd) {
case 'parsed':
if (ev.data.ast && self.parserStartTime === ev.data.timestamp) {
self.cache[ev.data.file] = {
...self.cache[ev.data.file],
text: ev.data.text,
ast: ev.data.ast,
duration: ev.data.duration,
blocks: ev.data.blocks,
blockDurations: self.cache[ev.data.file].blockDurations? [...self.cache[ev.data.file].blockDurations.slice(-self.parserThresholdSampleAmount), ev.data.blockDuration]: [ev.data.blockDuration]
}
self.setFileParsingState(ev.data.file)
}
break;
}
this.worker.addEventListener('message', function (ev) {
switch (ev.data.cmd) {
case 'parsed':
if (ev.data.ast && self.parserStartTime === ev.data.timestamp) {
self.cache[ev.data.file] = {
...self.cache[ev.data.file],
text: ev.data.text,
ast: ev.data.ast,
duration: ev.data.duration,
blocks: ev.data.blocks,
blockDurations: self.cache[ev.data.file].blockDurations? [...self.cache[ev.data.file].blockDurations.slice(-self.parserThresholdSampleAmount), ev.data.blockDuration]: [ev.data.blockDuration]
}
self.setFileParsingState(ev.data.file)
}
break;
}
});
}
});
}
setFileParsingState(file: string) {
if (this.cache[file]) {
if (this.cache[file].blockDurations && this.cache[file].blockDurations.length > this.parserThresholdSampleAmount) {
// calculate average of durations to determine if the parsing should be disabled
const values = [...this.cache[file].blockDurations]
const average = values.reduce((a, b) => a + b, 0) / values.length
if (average > this.parserThreshold) {
this.cache[file].parsingEnabled = false
} else {
this.cache[file].parsingEnabled = true
}
}
}
setFileParsingState(file: string) {
if (this.cache[file]) {
if (this.cache[file].blockDurations && this.cache[file].blockDurations.length > this.parserThresholdSampleAmount) {
// calculate average of durations to determine if the parsing should be disabled
const values = [...this.cache[file].blockDurations]
const average = values.reduce((a, b) => a + b, 0) / values.length
if (average > this.parserThreshold) {
this.cache[file].parsingEnabled = false
} else {
this.cache[file].parsingEnabled = true
}
}
}
}
enableWorker() {
if (!this.workerTimer) {
this.workerTimer = setInterval(() => {
this.setCurrentFileAST()
}, 5000)
}
enableWorker() {
if (!this.workerTimer) {
this.workerTimer = setInterval(() => {
this.setCurrentFileAST()
}, 5000)
}
}
disableWorker() {
clearInterval(this.workerTimer)
}
disableWorker() {
clearInterval(this.workerTimer)
}
async parseWithWorker(text: string, file: string) {
this.parserStartTime = Date.now()
this.worker.postMessage({
cmd: 'parse',
text,
timestamp: this.parserStartTime,
file,
parsingEnabled: (this.cache[file] && this.cache[file].parsingEnabled) || true
});
async parseWithWorker(text: string, file: string) {
this.parserStartTime = Date.now()
this.worker.postMessage({
cmd: 'parse',
text,
timestamp: this.parserStartTime,
file,
parsingEnabled: (this.cache[file] && this.cache[file].parsingEnabled) || true
});
}
}
async parseSolidity(text: string) {
const ast: antlr.ParseResult = (SolidityParser as any).parse(text, { loc: true, range: true, tolerant: true })
return ast
}
async parseSolidity(text: string) {
const ast: antlr.ParseResult = (SolidityParser as any).parse(text, { loc: true, range: true, tolerant: true })
return ast
}
/**
/**
* Tries to parse the current file or the given text and returns the AST
* If the parsing fails it returns the last successful AST for this file
* @param text
* @returns
*/
async setCurrentFileAST(text: string | null = null) {
try {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
if (!this.cache[this.plugin.currentFile]) {
this.cache[this.plugin.currentFile] = {
text: '',
ast: null,
parsingEnabled: true,
blockDurations: []
}
}
if (this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].text !== fileContent) {
try {
await this.parseWithWorker(fileContent, this.plugin.currentFile)
} catch (e) {
// do nothing
}
}
}
} catch (e) {
async setCurrentFileAST(text: string | null = null) {
try {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
if (!this.cache[this.plugin.currentFile]) {
this.cache[this.plugin.currentFile] = {
text: '',
ast: null,
parsingEnabled: true,
blockDurations: []
}
}
if (this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].text !== fileContent) {
try {
await this.parseWithWorker(fileContent, this.plugin.currentFile)
} catch (e) {
// do nothing
}
}
}
} catch (e) {
// do nothing
}
}
/**
/**
* Lists the AST nodes from the current file parser
* These nodes need to be changed to match the node types returned by the compiler
* @returns
*/
async listAstNodes() {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.cache[this.plugin.currentFile]) return
const nodes: AstNode[] = [];
(SolidityParser as any).visit(this.cache[this.plugin.currentFile].ast, {
StateVariableDeclaration: (node: antlr.StateVariableDeclaration) => {
if (node.variables) {
for (const variable of node.variables) {
nodes.push({ ...variable, nodeType: 'VariableDeclaration', id: null, src: null })
}
}
},
VariableDeclaration: (node: antlr.VariableDeclaration) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
UserDefinedTypeName: (node: antlr.UserDefinedTypeName) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
FunctionDefinition: (node: antlr.FunctionDefinition) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
ContractDefinition: (node: antlr.ContractDefinition) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
MemberAccess: function (node: antlr.MemberAccess) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
Identifier: function (node: antlr.Identifier) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
EventDefinition: function (node: antlr.EventDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
ModifierDefinition: function (node: antlr.ModifierDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
InvalidNode: function (node: antlr.InvalidNode) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
EnumDefinition: function (node: antlr.EnumDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
StructDefinition: function (node: antlr.StructDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
}
async listAstNodes() {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.cache[this.plugin.currentFile]) return
const nodes: AstNode[] = [];
(SolidityParser as any).visit(this.cache[this.plugin.currentFile].ast, {
StateVariableDeclaration: (node: antlr.StateVariableDeclaration) => {
if (node.variables) {
for (const variable of node.variables) {
nodes.push({ ...variable, nodeType: 'VariableDeclaration', id: null, src: null })
}
}
},
VariableDeclaration: (node: antlr.VariableDeclaration) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
UserDefinedTypeName: (node: antlr.UserDefinedTypeName) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
FunctionDefinition: (node: antlr.FunctionDefinition) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
ContractDefinition: (node: antlr.ContractDefinition) => {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
MemberAccess: function (node: antlr.MemberAccess) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
Identifier: function (node: antlr.Identifier) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
EventDefinition: function (node: antlr.EventDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
ModifierDefinition: function (node: antlr.ModifierDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
InvalidNode: function (node: antlr.InvalidNode) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
EnumDefinition: function (node: antlr.EnumDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
},
StructDefinition: function (node: antlr.StructDefinition) {
nodes.push({ ...node, nodeType: node.type, id: null, src: null })
}
})
return nodes
}
})
return nodes
}
/**
/**
*
* @param ast
* @returns
*/
async getLastNodeInLine(ast: string) {
let lastNode: any
const checkLastNode = (node: antlr.MemberAccess | antlr.Identifier) => {
if (lastNode && lastNode.range && lastNode.range[1]) {
if (node.range[1] > lastNode.range[1]) {
lastNode = node
}
} else {
lastNode = node
}
async getLastNodeInLine(ast: string) {
let lastNode: any
const checkLastNode = (node: antlr.MemberAccess | antlr.Identifier) => {
if (lastNode && lastNode.range && lastNode.range[1]) {
if (node.range[1] > lastNode.range[1]) {
lastNode = node
}
} else {
lastNode = node
}
}
(SolidityParser as any).visit(ast, {
MemberAccess: function (node: antlr.MemberAccess) {
checkLastNode(node)
},
Identifier: function (node: antlr.Identifier) {
checkLastNode(node)
}
})
if (lastNode && lastNode.expression) {
return lastNode.expression
}
return lastNode
(SolidityParser as any).visit(ast, {
MemberAccess: function (node: antlr.MemberAccess) {
checkLastNode(node)
},
Identifier: function (node: antlr.Identifier) {
checkLastNode(node)
}
})
if (lastNode && lastNode.expression) {
return lastNode.expression
}
/*
return lastNode
}
/*
* get the code blocks of the current file
*/
async getCurrentFileBlocks(text: string | null = null) {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.cache[this.plugin.currentFile]) {
if (!this.cache[this.plugin.currentFile].parsingEnabled) {
return
}
}
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
try {
const startTime = Date.now()
const blocks = (SolidityParser as any).parseBlock(fileContent, { loc: true, range: true, tolerant: true })
if(this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].blockDurations){
this.cache[this.plugin.currentFile].blockDurations = [...this.cache[this.plugin.currentFile].blockDurations.slice(-this.parserThresholdSampleAmount), Date.now() - startTime]
this.setFileParsingState(this.plugin.currentFile)
}
if (blocks) this.cache[this.plugin.currentFile].blocks = blocks
return blocks
} catch (e) {
// do nothing
}
async getCurrentFileBlocks(text: string | null = null) {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.cache[this.plugin.currentFile]) {
if (!this.cache[this.plugin.currentFile].parsingEnabled) {
return
}
}
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const fileContent = text || await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
try {
const startTime = Date.now()
const blocks = (SolidityParser as any).parseBlock(fileContent, { loc: true, range: true, tolerant: true })
if(this.cache[this.plugin.currentFile] && this.cache[this.plugin.currentFile].blockDurations){
this.cache[this.plugin.currentFile].blockDurations = [...this.cache[this.plugin.currentFile].blockDurations.slice(-this.parserThresholdSampleAmount), Date.now() - startTime]
this.setFileParsingState(this.plugin.currentFile)
}
if (blocks) this.cache[this.plugin.currentFile].blocks = blocks
return blocks
} catch (e) {
// do nothing
}
}
}
/**
/**
* Returns the block surrounding the given position
* For example if the position is in the middle of a function, it will return the function
* @param {position} position
* @param {string} text // optional
* @return {any}
* */
async getANTLRBlockAtPosition(position: any, text: string = null) {
const blocks: any[] = await this.getCurrentFileBlocks(text)
async getANTLRBlockAtPosition(position: any, text: string = null) {
const blocks: any[] = await this.getCurrentFileBlocks(text)
const walkAst = (blocks) => {
let nodeFound = null
for (const object of blocks) {
if (object.start <= position) {
nodeFound = object
break
}
}
return nodeFound
const walkAst = (blocks) => {
let nodeFound = null
for (const object of blocks) {
if (object.start <= position) {
nodeFound = object
break
}
if (!blocks) return
blocks.reverse()
const block = walkAst(blocks)
return block
}
return nodeFound
}
if (!blocks) return
blocks.reverse()
const block = walkAst(blocks)
return block
}
}

@ -34,253 +34,253 @@ type errorMarker = {
file: string
}
export default class CodeParserCompiler {
plugin: CodeParser
compiler: any // used to compile the current file seperately from the main compiler
onAstFinished: (success: any, data: CompilationResult, source: CompilationSourceCode, input: any, version: any) => Promise<void>;
errorState: boolean;
gastEstimateTimeOut: any
constructor(
plugin: CodeParser
compiler: any // used to compile the current file seperately from the main compiler
onAstFinished: (success: any, data: CompilationResult, source: CompilationSourceCode, input: any, version: any) => Promise<void>;
errorState: boolean;
gastEstimateTimeOut: any
constructor(
plugin: CodeParser
) {
this.plugin = plugin
}
init() {
) {
this.plugin = plugin
}
this.onAstFinished = async (success, data: CompilationResult, source: CompilationSourceCode, input: any, version) => {
this.plugin.call('editor', 'clearAnnotations')
this.errorState = true
const result = new CompilerAbstract('soljson', data, source, input)
let allErrors: errorMarker[] = []
if (data.errors || data.error) {
const file = await this.plugin.call('fileManager', 'getCurrentFile')
const currentFileContent = await this.plugin.call('fileManager', 'readFile', file)
const sources = result.getSourceCode().sources || []
if (data.error) {
if (data.error.formattedMessage) {
// mark this file as error
const errorMarker = await this.createErrorMarker(data.error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
}
} else {
for (const error of data.errors) {
if (!error.sourceLocation) {
// mark this file as error
const errorMarker = await this.createErrorMarker(error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
} else {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content)
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({
start: error.sourceLocation.start,
length: error.sourceLocation.end - error.sourceLocation.start
}, lineBreaks)
init() {
this.onAstFinished = async (success, data: CompilationResult, source: CompilationSourceCode, input: any, version) => {
this.plugin.call('editor', 'clearAnnotations')
this.errorState = true
const result = new CompilerAbstract('soljson', data, source, input)
let allErrors: errorMarker[] = []
if (data.errors || data.error) {
const file = await this.plugin.call('fileManager', 'getCurrentFile')
const currentFileContent = await this.plugin.call('fileManager', 'readFile', file)
const sources = result.getSourceCode().sources || []
if (data.error) {
if (data.error.formattedMessage) {
// mark this file as error
const errorMarker = await this.createErrorMarker(data.error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
}
} else {
for (const error of data.errors) {
if (!error.sourceLocation) {
// mark this file as error
const errorMarker = await this.createErrorMarker(error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
} else {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content)
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({
start: error.sourceLocation.start,
length: error.sourceLocation.end - error.sourceLocation.start
}, lineBreaks)
const filePath = error.sourceLocation.file
const fileTarget = await this.plugin.call('fileManager', 'getUrlFromPath', filePath)
const importFilePositions = await this.getPositionForImportErrors(fileTarget.file, currentFileContent)
for (const importFilePosition of importFilePositions) {
for (const line of importFilePosition.lines) {
allErrors = [...allErrors, await this.createErrorMarker(error, file, line.position)]
}
}
const filePath = error.sourceLocation.file
const fileTarget = await this.plugin.call('fileManager', 'getUrlFromPath', filePath)
allErrors = [...allErrors, await this.createErrorMarker(error, filePath, lineColumn)]
}
}
const importFilePositions = await this.getPositionForImportErrors(fileTarget.file, currentFileContent)
for (const importFilePosition of importFilePositions) {
for (const line of importFilePosition.lines) {
allErrors = [...allErrors, await this.createErrorMarker(error, file, line.position)]
}
}
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if (displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors)
this.addDecorators(allErrors, sources)
} else {
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources)
await this.clearDecorators(result.getSourceCode().sources)
allErrors = [...allErrors, await this.createErrorMarker(error, filePath, lineColumn)]
}
}
}
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if (displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors)
this.addDecorators(allErrors, sources)
} else {
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources)
await this.clearDecorators(result.getSourceCode().sources)
}
if (!data.sources) return
if (data.sources && Object.keys(data.sources).length === 0) return
this.plugin.compilerAbstract = new CompilerAbstract('soljson', data, source, input)
this.errorState = false
this.plugin.nodeIndex = {
declarations: {},
flatReferences: {},
nodesPerFile: {},
}
if (!data.sources) return
if (data.sources && Object.keys(data.sources).length === 0) return
this.plugin.compilerAbstract = new CompilerAbstract('soljson', data, source, input)
this.errorState = false
this.plugin.nodeIndex = {
declarations: {},
flatReferences: {},
nodesPerFile: {},
}
this.plugin._buildIndex(data, source)
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
await this.plugin.gasService.showGasEstimates()
this.plugin.emit('astFinished')
}
this.compiler = new Compiler((url, cb) => this.plugin.call('contentImport', 'resolveAndSave', url, undefined).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.compiler.event.register('compilationFinished', this.onAstFinished)
this.plugin._buildIndex(data, source)
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
await this.plugin.gasService.showGasEstimates()
this.plugin.emit('astFinished')
}
this.compiler = new Compiler((url, cb) => this.plugin.call('contentImport', 'resolveAndSave', url, undefined).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.compiler.event.register('compilationFinished', this.onAstFinished)
}
// COMPILER
// COMPILER
/**
/**
*
* @returns
*/
async compile() {
try {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const state = await this.plugin.call('solidity', 'getCompilerState')
this.compiler.set('optimize', state.optimize)
this.compiler.set('evmVersion', state.evmVersion)
this.compiler.set('language', state.language)
this.compiler.set('runs', state.runs)
this.compiler.set('useFileConfiguration', true)
this.compiler.set('compilerRetriggerMode', CompilerRetriggerMode.retrigger)
const configFileContent = {
"language": "Solidity",
"settings": {
"optimizer": {
"enabled": state.optimize,
"runs": state.runs
},
"outputSelection": {
"*": {
"": ["ast"],
"*": ["evm.gasEstimates"]
}
},
"evmVersion": state.evmVersion && state.evmVersion.toString() || "berlin",
}
}
this.compiler.set('configFileContent', JSON.stringify(configFileContent))
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.plugin.currentFile) return
const content = await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
const sources = { [this.plugin.currentFile]: { content } }
this.compiler.compile(sources, this.plugin.currentFile)
}
} catch (e) {
// do nothing
async compile() {
try {
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) {
const state = await this.plugin.call('solidity', 'getCompilerState')
this.compiler.set('optimize', state.optimize)
this.compiler.set('evmVersion', state.evmVersion)
this.compiler.set('language', state.language)
this.compiler.set('runs', state.runs)
this.compiler.set('useFileConfiguration', true)
this.compiler.set('compilerRetriggerMode', CompilerRetriggerMode.retrigger)
const configFileContent = {
"language": "Solidity",
"settings": {
"optimizer": {
"enabled": state.optimize,
"runs": state.runs
},
"outputSelection": {
"*": {
"": ["ast"],
"*": ["evm.gasEstimates"]
}
},
"evmVersion": state.evmVersion && state.evmVersion.toString() || "berlin",
}
}
}
async addDecorators(allErrors: errorMarker[], sources: any) {
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if (!displayErrors) return
const errorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const error of allErrors) {
if (!errorsPerFiles[error.file]) {
errorsPerFiles[error.file] = []
}
errorsPerFiles[error.file].push(error)
}
this.compiler.set('configFileContent', JSON.stringify(configFileContent))
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
if (!this.plugin.currentFile) return
const content = await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile)
const sources = { [this.plugin.currentFile]: { content } }
this.compiler.compile(sources, this.plugin.currentFile)
}
} catch (e) {
// do nothing
}
}
const errorPriority = {
'error': 0,
'warning': 1,
}
async addDecorators(allErrors: errorMarker[], sources: any) {
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if (!displayErrors) return
const errorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const error of allErrors) {
if (!errorsPerFiles[error.file]) {
errorsPerFiles[error.file] = []
}
errorsPerFiles[error.file].push(error)
}
// sort errorPerFiles by error priority
const sortedErrorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const fileName in errorsPerFiles) {
const errors = errorsPerFiles[fileName]
errors.sort((a, b) => {
return errorPriority[a.severity] - errorPriority[b.severity]
}
)
sortedErrorsPerFiles[fileName] = errors
}
const filesWithOutErrors = Object.keys(sources).filter((fileName) => !sortedErrorsPerFiles[fileName])
// add decorators
const decorators: fileDecoration[] = []
for (const fileName in sortedErrorsPerFiles) {
const errors = sortedErrorsPerFiles[fileName]
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileTarget.file,
isDirectory: false,
fileStateType: errors[0].severity == MarkerSeverity.Error ? fileDecorationType.Error : fileDecorationType.Warning,
fileStateLabelClass: errors[0].severity == MarkerSeverity.Error ? 'text-danger' : 'text-warning',
fileStateIconClass: '',
fileStateIcon: '',
text: errors.length.toString(),
owner: 'code-parser',
bubble: true,
comment: errors.map((error) => error.message),
}
decorators.push(decorator)
}
for (const fileName of filesWithOutErrors) {
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileTarget.file,
isDirectory: false,
fileStateType: fileDecorationType.None,
fileStateLabelClass: '',
fileStateIconClass: '',
fileStateIcon: '',
text: '',
owner: 'code-parser',
bubble: false
}
decorators.push(decorator)
}
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
await this.plugin.call('editor', 'clearErrorMarkers', filesWithOutErrors)
const errorPriority = {
'error': 0,
'warning': 1,
}
// sort errorPerFiles by error priority
const sortedErrorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const fileName in errorsPerFiles) {
const errors = errorsPerFiles[fileName]
errors.sort((a, b) => {
return errorPriority[a.severity] - errorPriority[b.severity]
}
)
sortedErrorsPerFiles[fileName] = errors
}
const filesWithOutErrors = Object.keys(sources).filter((fileName) => !sortedErrorsPerFiles[fileName])
// add decorators
const decorators: fileDecoration[] = []
for (const fileName in sortedErrorsPerFiles) {
const errors = sortedErrorsPerFiles[fileName]
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileTarget.file,
isDirectory: false,
fileStateType: errors[0].severity == MarkerSeverity.Error ? fileDecorationType.Error : fileDecorationType.Warning,
fileStateLabelClass: errors[0].severity == MarkerSeverity.Error ? 'text-danger' : 'text-warning',
fileStateIconClass: '',
fileStateIcon: '',
text: errors.length.toString(),
owner: 'code-parser',
bubble: true,
comment: errors.map((error) => error.message),
}
decorators.push(decorator)
}
for (const fileName of filesWithOutErrors) {
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileTarget.file,
isDirectory: false,
fileStateType: fileDecorationType.None,
fileStateLabelClass: '',
fileStateIconClass: '',
fileStateIcon: '',
text: '',
owner: 'code-parser',
bubble: false
}
decorators.push(decorator)
}
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
await this.plugin.call('editor', 'clearErrorMarkers', filesWithOutErrors)
async createErrorMarker(error: any, filePath: string, lineColumn): Promise<errorMarker> {
return {
message: error.formattedMessage,
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning,
position: {
start: {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1,
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1
},
end: {
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1,
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
}
}
, file: filePath
}
async createErrorMarker(error: any, filePath: string, lineColumn): Promise<errorMarker> {
return {
message: error.formattedMessage,
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning,
position: {
start: {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1,
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1
},
end: {
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1,
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
}
}
, file: filePath
}
}
async clearDecorators(sources: any) {
const decorators: fileDecoration[] = []
if (!sources) return
for (const fileName of Object.keys(sources)) {
const decorator: fileDecoration = {
path: fileName,
isDirectory: false,
fileStateType: fileDecorationType.None,
fileStateLabelClass: '',
fileStateIconClass: '',
fileStateIcon: '',
text: '',
owner: 'code-parser',
bubble: false
}
decorators.push(decorator)
}
async clearDecorators(sources: any) {
const decorators: fileDecoration[] = []
if (!sources) return
for (const fileName of Object.keys(sources)) {
const decorator: fileDecoration = {
path: fileName,
isDirectory: false,
fileStateType: fileDecorationType.None,
fileStateLabelClass: '',
fileStateIconClass: '',
fileStateIcon: '',
text: '',
owner: 'code-parser',
bubble: false
}
decorators.push(decorator)
}
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
}
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
}
async getPositionForImportErrors(importedFileName: string, text: string) {
const re = new RegExp(importedFileName, 'gi')
const result: SearchResultLine[] = findLinesInStringWithMatch(
text,
re
)
return result
}
async getPositionForImportErrors(importedFileName: string, text: string) {
const re = new RegExp(importedFileName, 'gi')
const result: SearchResultLine[] = findLinesInStringWithMatch(
text,
re
)
return result
}
}

@ -3,76 +3,76 @@ import { lineText } from '@remix-ui/editor'
import { lastCompilationResult } from '@remixproject/plugin-api';
export default class CodeParserGasService {
plugin: CodeParser
plugin: CodeParser
constructor(plugin: CodeParser) {
this.plugin = plugin
}
constructor(plugin: CodeParser) {
this.plugin = plugin
}
async getGasEstimates(fileName: string) {
if (!fileName) {
fileName = await this.plugin.currentFile
}
if (this.plugin.nodeIndex.nodesPerFile && this.plugin.nodeIndex.nodesPerFile[fileName] && this.plugin.nodeIndex.nodesPerFile[fileName].contracts) {
const estimates: any = []
for (const contract in this.plugin.nodeIndex.nodesPerFile[fileName].contracts) {
if (this.plugin.nodeIndex.nodesPerFile[fileName].contracts[contract].contractNodes) {
const nodes = this.plugin.nodeIndex.nodesPerFile[fileName].contracts[contract].contractNodes
for (const node of Object.values(nodes) as any[]) {
if (node.gasEstimate) {
estimates.push({
node,
range: await this.plugin.getLineColumnOfNode(node)
})
}
}
}
async getGasEstimates(fileName: string) {
if (!fileName) {
fileName = await this.plugin.currentFile
}
if (this.plugin.nodeIndex.nodesPerFile && this.plugin.nodeIndex.nodesPerFile[fileName] && this.plugin.nodeIndex.nodesPerFile[fileName].contracts) {
const estimates: any = []
for (const contract in this.plugin.nodeIndex.nodesPerFile[fileName].contracts) {
if (this.plugin.nodeIndex.nodesPerFile[fileName].contracts[contract].contractNodes) {
const nodes = this.plugin.nodeIndex.nodesPerFile[fileName].contracts[contract].contractNodes
for (const node of Object.values(nodes) as any[]) {
if (node.gasEstimate) {
estimates.push({
node,
range: await this.plugin.getLineColumnOfNode(node)
})
}
return estimates
}
}
}
return estimates
}
}
async showGasEstimates() {
const showGasConfig = await this.plugin.call('config', 'getAppParameter', 'show-gas')
if(!showGasConfig) {
await this.plugin.call('editor', 'discardLineTexts')
return
}
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = await this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
const gasEstimates = await this.getGasEstimates(this.plugin.currentFile)
async showGasEstimates() {
const showGasConfig = await this.plugin.call('config', 'getAppParameter', 'show-gas')
if(!showGasConfig) {
await this.plugin.call('editor', 'discardLineTexts')
return
}
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = await this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
const gasEstimates = await this.getGasEstimates(this.plugin.currentFile)
const friendlyNames = {
'executionCost': 'Estimated execution cost',
'codeDepositCost': 'Estimated code deposit cost',
'creationCost': 'Estimated creation cost',
const friendlyNames = {
'executionCost': 'Estimated execution cost',
'codeDepositCost': 'Estimated code deposit cost',
'creationCost': 'Estimated creation cost',
}
await this.plugin.call('editor', 'discardLineTexts')
if (gasEstimates) {
for (const estimate of gasEstimates) {
const linetext: lineText = {
content: Object.entries(estimate.node.gasEstimate).map(([, value]) => `${value} gas`).join(' '),
position: estimate.range,
hide: false,
className: 'text-muted small',
afterContentClassName: 'text-muted small fas fa-gas-pump pl-4',
from: 'codeParser',
hoverMessage: [{
value: `${Object.entries(estimate.node.gasEstimate).map(([key, value]) => `${friendlyNames[key]}: ${value} gas`).join(' ')}`,
},
],
}
await this.plugin.call('editor', 'discardLineTexts')
if (gasEstimates) {
for (const estimate of gasEstimates) {
const linetext: lineText = {
content: Object.entries(estimate.node.gasEstimate).map(([, value]) => `${value} gas`).join(' '),
position: estimate.range,
hide: false,
className: 'text-muted small',
afterContentClassName: 'text-muted small fas fa-gas-pump pl-4',
from: 'codeParser',
hoverMessage: [{
value: `${Object.entries(estimate.node.gasEstimate).map(([key, value]) => `${friendlyNames[key]}: ${value} gas`).join(' ')}`,
},
],
}
this.plugin.call('editor', 'addLineText', linetext, estimate.range.fileName)
this.plugin.call('editor', 'addLineText', linetext, estimate.range.fileName)
}
}
}
}
}
}

@ -8,81 +8,81 @@ export type CodeParserImportsData= {
}
export default class CodeParserImports {
plugin: CodeParser
plugin: CodeParser
data: CodeParserImportsData = {}
constructor(plugin: CodeParser) {
this.plugin = plugin
this.init()
}
data: CodeParserImportsData = {}
constructor(plugin: CodeParser) {
this.plugin = plugin
this.init()
}
async getImports(){
return this.data
}
async getImports(){
return this.data
}
async init() {
// @ts-ignore
const txt = await import('raw-loader!libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt')
this.data.modules = txt.default.split('\n')
.filter(x => x !== '')
.map(x => x.replace('./node_modules/', ''))
.filter(x => {
if(x.includes('@openzeppelin')) {
return !x.includes('mock')
}else{
return true
}
})
async init() {
// @ts-ignore
const txt = await import('raw-loader!libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt')
this.data.modules = txt.default.split('\n')
.filter(x => x !== '')
.map(x => x.replace('./node_modules/', ''))
.filter(x => {
if(x.includes('@openzeppelin')) {
return !x.includes('mock')
}else{
return true
}
})
// get unique first words of the values in the array
this.data.packages = [...new Set(this.data.modules.map(x => x.split('/')[0]))]
}
// get unique first words of the values in the array
this.data.packages = [...new Set(this.data.modules.map(x => x.split('/')[0]))]
}
setFileTree = async () => {
this.data.files = await this.getDirectory('/')
this.data.files = this.data.files.filter(x => x.endsWith('.sol') && !x.startsWith('.deps') && !x.startsWith('.git'))
}
setFileTree = async () => {
this.data.files = await this.getDirectory('/')
this.data.files = this.data.files.filter(x => x.endsWith('.sol') && !x.startsWith('.deps') && !x.startsWith('.git'))
}
getDirectory = async (dir: string) => {
let result = []
let files = {}
try {
if (await this.plugin.call('fileManager', 'exists', dir)) {
files = await this.plugin.call('fileManager', 'readdir', dir)
}
} catch (e) {}
getDirectory = async (dir: string) => {
let result = []
let files = {}
try {
if (await this.plugin.call('fileManager', 'exists', dir)) {
files = await this.plugin.call('fileManager', 'readdir', dir)
}
} catch (e) {}
const fileArray = this.normalize(files)
for (const fi of fileArray) {
if (fi) {
const type = fi.data.isDirectory
if (type === true) {
result = [...result, ...(await this.getDirectory(`${fi.filename}`))]
} else {
result = [...result, fi.filename]
}
}
const fileArray = this.normalize(files)
for (const fi of fileArray) {
if (fi) {
const type = fi.data.isDirectory
if (type === true) {
result = [...result, ...(await this.getDirectory(`${fi.filename}`))]
} else {
result = [...result, fi.filename]
}
return result
}
}
return result
}
normalize = filesList => {
const folders = []
const files = []
Object.keys(filesList || {}).forEach(key => {
if (filesList[key].isDirectory) {
folders.push({
filename: key,
data: filesList[key]
})
} else {
files.push({
filename: key,
data: filesList[key]
})
}
normalize = filesList => {
const folders = []
const files = []
Object.keys(filesList || {}).forEach(key => {
if (filesList[key].isDirectory) {
folders.push({
filename: key,
data: filesList[key]
})
return [...folders, ...files]
}
} else {
files.push({
filename: key,
data: filesList[key]
})
}
})
return [...folders, ...files]
}
}

@ -596,132 +596,132 @@ type ASTTypeMap = ASTMap<ASTNode>
export const astNodeTypes = [
'SourceUnit',
'PragmaDirective',
'ImportDirective',
'ContractDefinition',
'InheritanceSpecifier',
'StateVariableDeclaration',
'UsingForDeclaration',
'StructDefinition',
'ModifierDefinition',
'ModifierInvocation',
'FunctionDefinition',
'EventDefinition',
'CustomErrorDefinition',
'RevertStatement',
'EnumValue',
'EnumDefinition',
'VariableDeclaration',
'UserDefinedTypeName',
'Mapping',
'ArrayTypeName',
'FunctionTypeName',
'Block',
'ExpressionStatement',
'IfStatement',
'WhileStatement',
'ForStatement',
'InlineAssemblyStatement',
'DoWhileStatement',
'ContinueStatement',
'Break',
'Continue',
'BreakStatement',
'ReturnStatement',
'EmitStatement',
'ThrowStatement',
'VariableDeclarationStatement',
'ElementaryTypeName',
'FunctionCall',
'AssemblyBlock',
'AssemblyCall',
'AssemblyLocalDefinition',
'AssemblyAssignment',
'AssemblyStackAssignment',
'LabelDefinition',
'AssemblySwitch',
'AssemblyCase',
'AssemblyFunctionDefinition',
'AssemblyFunctionReturns',
'AssemblyFor',
'AssemblyIf',
'SubAssembly',
'TupleExpression',
'NameValueExpression',
'BooleanLiteral',
'NumberLiteral',
'Identifier',
'BinaryOperation',
'UnaryOperation',
'NewExpression',
'Conditional',
'StringLiteral',
'HexLiteral',
'HexNumber',
'DecimalNumber',
'MemberAccess',
'IndexAccess',
'IndexRangeAccess',
'NameValueList',
'UncheckedStatement',
'TryStatement',
'CatchClause',
'FileLevelConstant',
'AssemblyMemberAccess',
'TypeDefinition',
'InvalidNode'
'SourceUnit',
'PragmaDirective',
'ImportDirective',
'ContractDefinition',
'InheritanceSpecifier',
'StateVariableDeclaration',
'UsingForDeclaration',
'StructDefinition',
'ModifierDefinition',
'ModifierInvocation',
'FunctionDefinition',
'EventDefinition',
'CustomErrorDefinition',
'RevertStatement',
'EnumValue',
'EnumDefinition',
'VariableDeclaration',
'UserDefinedTypeName',
'Mapping',
'ArrayTypeName',
'FunctionTypeName',
'Block',
'ExpressionStatement',
'IfStatement',
'WhileStatement',
'ForStatement',
'InlineAssemblyStatement',
'DoWhileStatement',
'ContinueStatement',
'Break',
'Continue',
'BreakStatement',
'ReturnStatement',
'EmitStatement',
'ThrowStatement',
'VariableDeclarationStatement',
'ElementaryTypeName',
'FunctionCall',
'AssemblyBlock',
'AssemblyCall',
'AssemblyLocalDefinition',
'AssemblyAssignment',
'AssemblyStackAssignment',
'LabelDefinition',
'AssemblySwitch',
'AssemblyCase',
'AssemblyFunctionDefinition',
'AssemblyFunctionReturns',
'AssemblyFor',
'AssemblyIf',
'SubAssembly',
'TupleExpression',
'NameValueExpression',
'BooleanLiteral',
'NumberLiteral',
'Identifier',
'BinaryOperation',
'UnaryOperation',
'NewExpression',
'Conditional',
'StringLiteral',
'HexLiteral',
'HexNumber',
'DecimalNumber',
'MemberAccess',
'IndexAccess',
'IndexRangeAccess',
'NameValueList',
'UncheckedStatement',
'TryStatement',
'CatchClause',
'FileLevelConstant',
'AssemblyMemberAccess',
'TypeDefinition',
'InvalidNode'
] as const
export const binaryOpValues = [
'+',
'-',
'*',
'/',
'**',
'%',
'<<',
'>>',
'&&',
'||',
',,',
'&',
',',
'^',
'<',
'>',
'<=',
'>=',
'==',
'!=',
'=',
',=',
'^=',
'&=',
'<<=',
'>>=',
'+=',
'-=',
'*=',
'/=',
'%=',
'|',
'|=',
'+',
'-',
'*',
'/',
'**',
'%',
'<<',
'>>',
'&&',
'||',
',,',
'&',
',',
'^',
'<',
'>',
'<=',
'>=',
'==',
'!=',
'=',
',=',
'^=',
'&=',
'<<=',
'>>=',
'+=',
'-=',
'*=',
'/=',
'%=',
'|',
'|=',
] as const
export type BinOp = typeof binaryOpValues[number]
export const unaryOpValues = [
'-',
'+',
'++',
'--',
'~',
'after',
'delete',
'!',
'-',
'+',
'++',
'--',
'~',
'after',
'delete',
'!',
] as const
export type UnaryOp = typeof unaryOpValues[number]

@ -49,12 +49,12 @@ export class PermissionHandlerPlugin extends Plugin {
switchMode (from: Profile, to: Profile, method: string, set: boolean, sensitiveCall: boolean) {
if (sensitiveCall) {
set
? this.sessionPermissions[to.name][method][from.name] = {}
: delete this.sessionPermissions[to.name][method][from.name]
? this.sessionPermissions[to.name][method][from.name] = {}
: delete this.sessionPermissions[to.name][method][from.name]
} else {
set
? this.permissions[to.name][method][from.name] = {}
: delete this.permissions[to.name][method][from.name]
? this.permissions[to.name][method][from.name] = {}
: delete this.permissions[to.name][method][from.name]
}
}

@ -84,20 +84,20 @@ export class SolidityScript extends Plugin {
if (hhlogs && hhlogs.length) {
const finalLogs = <div><div><b>console.log:</b></div>
{
hhlogs.map((log) => {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
return <div>{formattedLog}</div>
})}
{
hhlogs.map((log) => {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
return <div>{formattedLog}</div>
})}
</div>
_paq.push(['trackEvent', 'udapp', 'hardhat', 'console.log'])
this.call('terminal', 'logHtml', finalLogs)

@ -16,39 +16,39 @@ const parser = (window as any).SolidityParser
const _paq = window._paq = window._paq || []
const profile = {
name: 'solidityumlgen',
displayName: 'Solidity UML Generator',
description: 'Generates UML diagram in svg format from last compiled contract',
location: 'mainPanel',
methods: ['showUmlDiagram', 'generateUml', 'generateCustomAction'],
events: [],
name: 'solidityumlgen',
displayName: 'Solidity UML Generator',
description: 'Generates UML diagram in svg format from last compiled contract',
location: 'mainPanel',
methods: ['showUmlDiagram', 'generateUml', 'generateCustomAction'],
events: [],
}
const themeCollection = [
{ themeName: 'HackerOwl', backgroundColor: '#011628', textColor: '#babbcc',
shapeColor: '#8694a1',fillColor: '#011C32'},
shapeColor: '#8694a1',fillColor: '#011C32'},
{ themeName: 'Cerulean', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8f9fa'},
shapeColor: '#343a40',fillColor: '#f8f9fa'},
{ themeName: 'Cyborg', backgroundColor: '#060606', textColor: '#adafae',
shapeColor: '#adafae', fillColor: '#222222'},
shapeColor: '#adafae', fillColor: '#222222'},
{ themeName: 'Dark', backgroundColor: '#222336', textColor: '#babbcc',
shapeColor: '#babbcc',fillColor: '#2a2c3f'},
shapeColor: '#babbcc',fillColor: '#2a2c3f'},
{ themeName: 'Flatly', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#7b8a8b',fillColor: '#ffffff'},
shapeColor: '#7b8a8b',fillColor: '#ffffff'},
{ themeName: 'Black', backgroundColor: '#1a1a1a', textColor: '#babbcc',
shapeColor: '#b5b4bc',fillColor: '#1f2020'},
shapeColor: '#b5b4bc',fillColor: '#1f2020'},
{ themeName: 'Light', backgroundColor: '#eef1f6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#ffffff'},
shapeColor: '#343a40',fillColor: '#ffffff'},
{ themeName: 'Midcentury', backgroundColor: '#DBE2E0', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#eeede9'},
shapeColor: '#343a40',fillColor: '#eeede9'},
{ themeName: 'Spacelab', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#333333', fillColor: '#eeeeee'},
shapeColor: '#333333', fillColor: '#eeeeee'},
{ themeName: 'Candy', backgroundColor: '#d5efff', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#fbe7f8' },
shapeColor: '#343a40',fillColor: '#fbe7f8' },
{ themeName: 'Violet', backgroundColor: '#f1eef6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#f8fafe' },
shapeColor: '#343a40',fillColor: '#f8fafe' },
{ themeName: 'Unicorn', backgroundColor: '#f1eef6', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8fafe' },
shapeColor: '#343a40',fillColor: '#f8fafe' },
]
/**
@ -121,7 +121,7 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
getThemeCssVariables(cssVars: string) {
return window.getComputedStyle(document.documentElement)
.getPropertyValue(cssVars)
.getPropertyValue(cssVars)
}
private handleThemeChange() {
@ -246,10 +246,10 @@ interface Sol2umlClassOptions extends ClassOptions {
import { dirname } from 'path'
import { convertClass2Dot } from 'sol2uml/lib/converterClass2Dot'
import {
Association,
ClassStereotype,
ReferenceType,
UmlClass,
Association,
ClassStereotype,
ReferenceType,
UmlClass,
} from 'sol2uml/lib/umlClass'
import { findAssociatedClass } from 'sol2uml/lib/associations'
@ -264,11 +264,11 @@ import { findAssociatedClass } from 'sol2uml/lib/associations'
* @return dotString Graphviz's DOT format for defining nodes, edges and clusters.
*/
export function convertUmlClasses2Dot(
umlClasses: UmlClass[],
clusterFolders: boolean = false,
classOptions: Sol2umlClassOptions = {}
umlClasses: UmlClass[],
clusterFolders: boolean = false,
classOptions: Sol2umlClassOptions = {}
): string {
let dotString: string = `
let dotString: string = `
digraph UmlClassDiagram {
rankdir=BT
arrowhead=open
@ -276,124 +276,124 @@ bgcolor="${classOptions.backColor}"
edge [color="${classOptions.shapeColor}"]
node [shape=record, style=filled, color="${classOptions.shapeColor}", fillcolor="${classOptions.fillColor}", fontcolor="${classOptions.textColor}"]`
// Sort UML Classes by folder of source file
const umlClassesSortedByCodePath = sortUmlClassesByCodePath(umlClasses)
// Sort UML Classes by folder of source file
const umlClassesSortedByCodePath = sortUmlClassesByCodePath(umlClasses)
let currentCodeFolder = ''
for (const umlClass of umlClassesSortedByCodePath) {
const codeFolder = dirname(umlClass.relativePath)
if (currentCodeFolder !== codeFolder) {
// Need to close off the last subgraph if not the first
if (currentCodeFolder != '') {
dotString += '\n}'
}
let currentCodeFolder = ''
for (const umlClass of umlClassesSortedByCodePath) {
const codeFolder = dirname(umlClass.relativePath)
if (currentCodeFolder !== codeFolder) {
// Need to close off the last subgraph if not the first
if (currentCodeFolder != '') {
dotString += '\n}'
}
dotString += `
dotString += `
subgraph ${getSubGraphName(clusterFolders)} {
label="${codeFolder}"`
currentCodeFolder = codeFolder
}
dotString += convertClass2Dot(umlClass, classOptions)
currentCodeFolder = codeFolder
}
dotString += convertClass2Dot(umlClass, classOptions)
}
// Need to close off the last subgraph if not the first
if (currentCodeFolder != '') {
dotString += '\n}'
}
// Need to close off the last subgraph if not the first
if (currentCodeFolder != '') {
dotString += '\n}'
}
dotString += addAssociationsToDot(umlClasses, classOptions)
dotString += addAssociationsToDot(umlClasses, classOptions)
// Need to close off the last the digraph
dotString += '\n}'
// Need to close off the last the digraph
dotString += '\n}'
// debug(dotString)
// debug(dotString)
return dotString
return dotString
}
let subGraphCount = 0
function getSubGraphName(clusterFolders: boolean = false) {
if (clusterFolders) {
return ` cluster_${subGraphCount++}`
}
return ` graph_${subGraphCount++}`
if (clusterFolders) {
return ` cluster_${subGraphCount++}`
}
return ` graph_${subGraphCount++}`
}
function sortUmlClassesByCodePath(umlClasses: UmlClass[]): UmlClass[] {
return umlClasses.sort((a, b) => {
if (a.relativePath < b.relativePath) {
return -1
}
if (a.relativePath > b.relativePath) {
return 1
}
return 0
})
return umlClasses.sort((a, b) => {
if (a.relativePath < b.relativePath) {
return -1
}
if (a.relativePath > b.relativePath) {
return 1
}
return 0
})
}
export function addAssociationsToDot(
umlClasses: UmlClass[],
classOptions: ClassOptions = {}
umlClasses: UmlClass[],
classOptions: ClassOptions = {}
): string {
let dotString: string = ''
// for each class
for (const sourceUmlClass of umlClasses) {
if (!classOptions.hideEnums) {
// for each enum in the class
sourceUmlClass.enums.forEach((enumId) => {
// Has the enum been filtered out? eg depth limited
const targetUmlClass = umlClasses.find((c) => c.id === enumId)
if (targetUmlClass) {
// Draw aggregated link from contract to contract level Enum
dotString += `\n${enumId} -> ${sourceUmlClass.id} [arrowhead=diamond, weight=2]`
}
})
let dotString: string = ''
// for each class
for (const sourceUmlClass of umlClasses) {
if (!classOptions.hideEnums) {
// for each enum in the class
sourceUmlClass.enums.forEach((enumId) => {
// Has the enum been filtered out? eg depth limited
const targetUmlClass = umlClasses.find((c) => c.id === enumId)
if (targetUmlClass) {
// Draw aggregated link from contract to contract level Enum
dotString += `\n${enumId} -> ${sourceUmlClass.id} [arrowhead=diamond, weight=2]`
}
if (!classOptions.hideStructs) {
// for each struct in the class
sourceUmlClass.structs.forEach((structId) => {
// Has the struct been filtered out? eg depth limited
const targetUmlClass = umlClasses.find((c) => c.id === structId)
if (targetUmlClass) {
// Draw aggregated link from contract to contract level Struct
dotString += `\n${structId} -> ${sourceUmlClass.id} [arrowhead=diamond, weight=2]`
}
})
})
}
if (!classOptions.hideStructs) {
// for each struct in the class
sourceUmlClass.structs.forEach((structId) => {
// Has the struct been filtered out? eg depth limited
const targetUmlClass = umlClasses.find((c) => c.id === structId)
if (targetUmlClass) {
// Draw aggregated link from contract to contract level Struct
dotString += `\n${structId} -> ${sourceUmlClass.id} [arrowhead=diamond, weight=2]`
}
})
}
// for each association in that class
for (const association of Object.values(sourceUmlClass.associations)) {
const targetUmlClass = findAssociatedClass(
association,
sourceUmlClass,
umlClasses
)
if (targetUmlClass) {
dotString += addAssociationToDot(
sourceUmlClass,
targetUmlClass,
association,
classOptions
)
}
}
// for each association in that class
for (const association of Object.values(sourceUmlClass.associations)) {
const targetUmlClass = findAssociatedClass(
association,
sourceUmlClass,
umlClasses
)
if (targetUmlClass) {
dotString += addAssociationToDot(
sourceUmlClass,
targetUmlClass,
association,
classOptions
)
}
}
}
return dotString
return dotString
}
function addAssociationToDot(
sourceUmlClass: UmlClass,
targetUmlClass: UmlClass,
association: Association,
classOptions: ClassOptions = {}
sourceUmlClass: UmlClass,
targetUmlClass: UmlClass,
association: Association,
classOptions: ClassOptions = {}
): string {
// do not include library or interface associations if hidden
// Or associations to Structs, Enums or Constants if they are hidden
if (
(classOptions.hideLibraries &&
// do not include library or interface associations if hidden
// Or associations to Structs, Enums or Constants if they are hidden
if (
(classOptions.hideLibraries &&
(sourceUmlClass.stereotype === ClassStereotype.Library ||
targetUmlClass.stereotype === ClassStereotype.Library)) ||
(classOptions.hideInterfaces &&
@ -408,28 +408,28 @@ function addAssociationToDot(
targetUmlClass.stereotype === ClassStereotype.Enum) ||
(classOptions.hideConstants &&
targetUmlClass.stereotype === ClassStereotype.Constant)
) {
return ''
}
) {
return ''
}
let dotString = `\n${sourceUmlClass.id} -> ${targetUmlClass.id} [`
let dotString = `\n${sourceUmlClass.id} -> ${targetUmlClass.id} [`
if (
association.referenceType == ReferenceType.Memory ||
if (
association.referenceType == ReferenceType.Memory ||
(association.realization &&
targetUmlClass.stereotype === ClassStereotype.Interface)
) {
dotString += 'style=dashed, '
}
) {
dotString += 'style=dashed, '
}
if (association.realization) {
dotString += 'arrowhead=empty, arrowsize=3, '
if (!targetUmlClass.stereotype) {
dotString += 'weight=4, '
} else {
dotString += 'weight=3, '
}
if (association.realization) {
dotString += 'arrowhead=empty, arrowsize=3, '
if (!targetUmlClass.stereotype) {
dotString += 'weight=4, '
} else {
dotString += 'weight=3, '
}
}
return dotString + ']'
return dotString + ']'
}

@ -29,23 +29,23 @@ export class CustomForkVMProvider extends BasicVMProvider {
const body = () => {
return <div>
<span>Please provide information about the custom fork. If the node URL is not provided, the VM will start with an empty state.</span>
<div>
<label className="mt-3 mb-1">Node URL</label>
<input data-id="CustomForkNodeUrl" name="nodeUrl" type="text" className="border form-control border-right-0" />
<div>
<label className="mt-3 mb-1">Node URL</label>
<input data-id="CustomForkNodeUrl" name="nodeUrl" type="text" className="border form-control border-right-0" />
</div>
<div>
<label className="mt-3 mb-1">Block number (or "latest")</label>
<input data-id="CustomForkBlockNumber" name="blockNumber" type="text" defaultValue="latest" placeholder='block number or "latest"' className="border form-control border-right-0" />
</div>
<div>
<label className="mt-3 mb-1">EVM</label>
<select data-id="CustomForkEvmType" name="evmType" defaultValue="merge" className="border form-control border-right-0">
{Object.keys(Hardfork).map((value, index) => {
return <option value={Hardfork[value]} key={index}>{value}</option>
})}
</select>
</div>
</div>
<div>
<label className="mt-3 mb-1">Block number (or "latest")</label>
<input data-id="CustomForkBlockNumber" name="blockNumber" type="text" defaultValue="latest" placeholder='block number or "latest"' className="border form-control border-right-0" />
</div>
<div>
<label className="mt-3 mb-1">EVM</label>
<select data-id="CustomForkEvmType" name="evmType" defaultValue="merge" className="border form-control border-right-0">
{Object.keys(Hardfork).map((value, index) => {
return <option value={Hardfork[value]} key={index}>{value}</option>
})}
</select>
</div>
</div>
}
const result = await ((): Promise<any> => {
return new Promise((resolve, reject) => {

@ -4,35 +4,35 @@ type registryEntry = {
}
export default class Registry {
private static instance: Registry;
private state: any
private static instance: Registry;
private state: any
private constructor () {
this.state = {}
}
public static getInstance (): Registry {
if (!Registry.instance) {
Registry.instance = new Registry()
}
private constructor () {
this.state = {}
}
return Registry.instance
public static getInstance (): Registry {
if (!Registry.instance) {
Registry.instance = new Registry()
}
public put (entry: registryEntry) {
if (this.state[entry.name]) return this.state[entry.name]
const server = {
return Registry.instance
}
public put (entry: registryEntry) {
if (this.state[entry.name]) return this.state[entry.name]
const server = {
// uid: serveruid,
api: entry.api
}
this.state[entry.name] = { server }
return server
api: entry.api
}
this.state[entry.name] = { server }
return server
}
public get (name: string) {
const state = this.state[name]
if (!state) return
const server = state.server
return server
}
public get (name: string) {
const state = this.state[name]
if (!state) return
const server = state.server
return server
}
}

@ -81,10 +81,10 @@ class AnalysisTab extends ViewPlugin {
updateComponent(state) {
return <RemixUiStaticAnalyser
registry={state.registry}
analysisModule={state.analysisModule}
event={state.event}
/>
registry={state.registry}
analysisModule={state.analysisModule}
event={state.event}
/>
}
renderComponent () {

@ -3,31 +3,31 @@ import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
import { SearchTab } from '@remix-ui/search'
const profile = {
name: 'search',
displayName: 'Search in files',
methods: [''],
events: [],
icon: 'assets/img/search_icon.webp',
description: 'Find and replace in file explorer',
kind: '',
location: 'sidePanel',
documentation: '',
version: packageJson.version,
maintainedBy: 'Remix'
}
name: 'search',
displayName: 'Search in files',
methods: [''],
events: [],
icon: 'assets/img/search_icon.webp',
description: 'Find and replace in file explorer',
kind: '',
location: 'sidePanel',
documentation: '',
version: packageJson.version,
maintainedBy: 'Remix'
}
export class SearchPlugin extends ViewPlugin {
constructor () {
super(profile)
}
constructor () {
super(profile)
}
render() {
return (
<div id='searchTab'>
<SearchTab plugin={this}></SearchTab>
</div>
);
}
render() {
return (
<div id='searchTab'>
<SearchTab plugin={this}></SearchTab>
</div>
);
}
}

@ -39,7 +39,7 @@ export class ThemeModule extends Plugin {
this.themes = {}
themes.map((theme) => {
this.themes[theme.name.toLocaleLowerCase()] = {
...theme,
...theme,
url: window.location.origin + ( window.location.pathname.startsWith('/address/') || window.location.pathname.endsWith('.sol') ? '/' : window.location.pathname ) + theme.url
}
})

@ -60,8 +60,8 @@ export class Web3ProviderModule extends Plugin {
reject(new Error('User denied permission'))
}
}).catch((e) => {
reject(e)
})
reject(e)
})
})
}

@ -136,8 +136,8 @@ export class RunTab extends ViewPlugin {
if (window && window.ethereum && !(window.ethereum.isTrustWallet || window.ethereum.selectedProvider?.isTrustWallet)) {
const displayNameInjected = `Injected Provider${(window && window.ethereum && !(window.ethereum.providers && !window.ethereum.selectedProvider)) ?
window.ethereum.isCoinbaseWallet || window.ethereum.selectedProvider?.isCoinbaseWallet ? ' - Coinbase' :
window.ethereum.isBraveWallet || window.ethereum.selectedProvider?.isBraveWallet ? ' - Brave' :
window.ethereum.isMetaMask || window.ethereum.selectedProvider?.isMetaMask ? ' - MetaMask' : '' : ''}`
window.ethereum.isBraveWallet || window.ethereum.selectedProvider?.isBraveWallet ? ' - Brave' :
window.ethereum.isMetaMask || window.ethereum.selectedProvider?.isMetaMask ? ' - MetaMask' : '' : ''}`
await addProvider('injected', displayNameInjected, true, false)
} else if (window && !window.ethereum) {
// we still add "injected" if there's no provider (just so it's visible to the user).

@ -31,7 +31,7 @@ export class LandingPage extends ViewPlugin {
render () {
return <div id='landingPageHomeContainer' className='remixui_homeContainer justify-content-between bg-light d-flex' data-id='landingPageHomeContainer'>
<RemixUiHomeTab plugin={this} />
</div>
}
<RemixUiHomeTab plugin={this} />
</div>
}
}

@ -312,52 +312,52 @@ export class Blockchain extends Plugin {
}
async saveDeployedContractStorageLayout (contractObject, proxyAddress, networkInfo) {
const { contractName, implementationAddress } = contractObject
const networkName = networkInfo.name === 'custom' ? networkInfo.name + '-' + networkInfo.id : networkInfo.name
const hasPreviousDeploys = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
// TODO: make deploys folder read only.
if (hasPreviousDeploys) {
const deployments = await this.call('fileManager', 'readFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
const parsedDeployments = JSON.parse(deployments)
const proxyDeployment = parsedDeployments.deployments[proxyAddress]
if (proxyDeployment) {
const oldImplementationAddress = proxyDeployment.implementationAddress
const hasPreviousBuild = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
if (hasPreviousBuild) await this.call('fileManager', 'remove', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
}
parsedDeployments.deployments[proxyAddress] = {
date: new Date().toISOString(),
contractName: contractName,
fork: networkInfo.currentFork,
implementationAddress: implementationAddress,
solcOutput: contractObject.compiler.data,
solcInput: contractObject.compiler.source
}
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/solc-${implementationAddress}.json`, JSON.stringify({
solcInput: contractObject.compiler.source,
solcOutput: contractObject.compiler.data
}, null, 2))
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`, JSON.stringify(parsedDeployments, null, 2))
} else {
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/solc-${implementationAddress}.json`, JSON.stringify({
solcInput: contractObject.compiler.source,
solcOutput: contractObject.compiler.data
}, null, 2))
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`, JSON.stringify({
id: networkInfo.id,
network: networkInfo.name,
deployments: {
[proxyAddress]: {
date: new Date().toISOString(),
contractName: contractName,
fork: networkInfo.currentFork,
implementationAddress: implementationAddress
}
}
}, null, 2))
const { contractName, implementationAddress } = contractObject
const networkName = networkInfo.name === 'custom' ? networkInfo.name + '-' + networkInfo.id : networkInfo.name
const hasPreviousDeploys = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
// TODO: make deploys folder read only.
if (hasPreviousDeploys) {
const deployments = await this.call('fileManager', 'readFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
const parsedDeployments = JSON.parse(deployments)
const proxyDeployment = parsedDeployments.deployments[proxyAddress]
if (proxyDeployment) {
const oldImplementationAddress = proxyDeployment.implementationAddress
const hasPreviousBuild = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
if (hasPreviousBuild) await this.call('fileManager', 'remove', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
}
parsedDeployments.deployments[proxyAddress] = {
date: new Date().toISOString(),
contractName: contractName,
fork: networkInfo.currentFork,
implementationAddress: implementationAddress,
solcOutput: contractObject.compiler.data,
solcInput: contractObject.compiler.source
}
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/solc-${implementationAddress}.json`, JSON.stringify({
solcInput: contractObject.compiler.source,
solcOutput: contractObject.compiler.data
}, null, 2))
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`, JSON.stringify(parsedDeployments, null, 2))
} else {
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/solc-${implementationAddress}.json`, JSON.stringify({
solcInput: contractObject.compiler.source,
solcOutput: contractObject.compiler.data
}, null, 2))
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`, JSON.stringify({
id: networkInfo.id,
network: networkInfo.name,
deployments: {
[proxyAddress]: {
date: new Date().toISOString(),
contractName: contractName,
fork: networkInfo.currentFork,
implementationAddress: implementationAddress
}
}
}, null, 2))
}
}
async getEncodedFunctionHex (args, funABI) {
@ -601,9 +601,9 @@ export class Blockchain extends Plugin {
if (viewEtherScanLink) {
this.call('terminal', 'logHtml',
(<a href={etherScanLink(network.name, txhash)} target="_blank">
(<a href={etherScanLink(network.name, txhash)} target="_blank">
view on etherscan
</a>))
</a>))
}
})
})
@ -808,20 +808,20 @@ export class Blockchain extends Plugin {
if (hhlogs && hhlogs.length) {
const finalLogs = <div><div><b>console.log:</b></div>
{
hhlogs.map((log) => {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
return <div>{formattedLog}</div>
})}
{
hhlogs.map((log) => {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
return <div>{formattedLog}</div>
})}
</div>
_paq.push(['trackEvent', 'udapp', 'hardhat', 'console.log'])
this.call('terminal', 'logHtml', finalLogs)

@ -1,14 +1,14 @@
const transactionDetailsLinks = {
Main: 'https://www.etherscan.io/tx/',
Rinkeby: 'https://rinkeby.etherscan.io/tx/',
Ropsten: 'https://ropsten.etherscan.io/tx/',
Kovan: 'https://kovan.etherscan.io/tx/',
Goerli: 'https://goerli.etherscan.io/tx/',
Sepolia: 'https://sepolia.etherscan.io/tx/'
}
Main: 'https://www.etherscan.io/tx/',
Rinkeby: 'https://rinkeby.etherscan.io/tx/',
Ropsten: 'https://ropsten.etherscan.io/tx/',
Kovan: 'https://kovan.etherscan.io/tx/',
Goerli: 'https://goerli.etherscan.io/tx/',
Sepolia: 'https://sepolia.etherscan.io/tx/'
}
export function etherScanLink (network: string, hash: string): string {
if (transactionDetailsLinks[network]) {
return transactionDetailsLinks[network] + hash
}
}
export function etherScanLink (network: string, hash: string): string {
if (transactionDetailsLinks[network]) {
return transactionDetailsLinks[network] + hash
}
}

@ -20,7 +20,7 @@ export class InjectedProvider {
}
async resetEnvironment () {
/* Do nothing. */
/* Do nothing. */
}
async getBalanceInEther (address) {

@ -30,7 +30,7 @@ export class NodeProvider {
}
async resetEnvironment () {
/* Do nothing. */
/* Do nothing. */
}
async getBalanceInEther (address) {

@ -59,12 +59,12 @@ export class VMProvider {
reject(new Error(msg.data.error))
}
} else if (msg.data.cmd === 'newAccountResult') {
if (this.newAccountCallback[msg.data.stamp]) {
this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result)
delete this.newAccountCallback[msg.data.stamp]
if (this.newAccountCallback[msg.data.stamp]) {
this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result)
delete this.newAccountCallback[msg.data.stamp]
}
}
}
})
})
this.worker.postMessage({ cmd: 'init', fork: this.executionContext.getCurrentFork(), nodeUrl: provider?.options['nodeUrl'], blockNumber: provider?.options['blockNumber']})
})
}

@ -4,74 +4,74 @@ let provider: Provider = null
self.onmessage = (e: MessageEvent) => {
const data = e.data
switch (data.cmd) {
case 'init':
{
provider = new Provider({ fork: data.fork, nodeUrl: data.nodeUrl, blockNumber: data.blockNumber })
provider.init().then(() => {
self.postMessage({
cmd: 'initiateResult',
stamp: data.stamp
})
}).catch((error) => {
case 'init':
{
provider = new Provider({ fork: data.fork, nodeUrl: data.nodeUrl, blockNumber: data.blockNumber })
provider.init().then(() => {
self.postMessage({
cmd: 'initiateResult',
stamp: data.stamp
})
}).catch((error) => {
self.postMessage({
cmd: 'initiateResult',
error,
stamp: data.stamp
})
})
break
}
case 'sendAsync':
{
if (provider) {
provider.sendAsync(data.query, (error, result) => {
self.postMessage({
cmd: 'initiateResult',
cmd: 'sendAsyncResult',
error,
result,
stamp: data.stamp
})
})
break
} else {
self.postMessage({
cmd: 'sendAsyncResult',
error: 'Provider not instantiated',
result: null,
stamp: data.stamp
})
}
case 'sendAsync':
{
if (provider) {
provider.sendAsync(data.query, (error, result) => {
self.postMessage({
cmd: 'sendAsyncResult',
error,
result,
stamp: data.stamp
})
})
} else {
self.postMessage({
cmd: 'sendAsyncResult',
error: 'Provider not instantiated',
result: null,
stamp: data.stamp
})
}
break
break
}
case 'addAccount':
{
if (provider) {
provider.Accounts._addAccount(data.privateKey, data.balance)
}
case 'addAccount':
{
if (provider) {
provider.Accounts._addAccount(data.privateKey, data.balance)
}
break
break
}
case 'newAccount':
{
if (provider) {
provider.Accounts.newAccount((error, address: string) => {
if (error) {
self.postMessage({
cmd: 'newAccountResult',
error,
stamp: data.stamp
})
} else {
self.postMessage({
cmd: 'newAccountResult',
result: address,
stamp: data.stamp
})
}
})
}
case 'newAccount':
{
if (provider) {
provider.Accounts.newAccount((error, address: string) => {
if (error) {
self.postMessage({
cmd: 'newAccountResult',
error,
stamp: data.stamp
})
} else {
self.postMessage({
cmd: 'newAccountResult',
result: address,
stamp: data.stamp
})
}
})
}
break
}
break
}
}
}

@ -198,7 +198,7 @@ const getContractAt = async (contractNameOrABI: ethers.ContractInterface, addres
if (result) {
return new ethers.Contract(address, result.abi, signer || provider.getSigner())
} else {
throw new Error('Contract artifacts not found')
throw new Error('Contract artifacts not found')
}
} else {
return new ethers.Contract(address, contractNameOrABI, signer || provider.getSigner())

@ -2,8 +2,8 @@
import { ethers } from "ethers"
export class SignerWithAddress extends ethers.Signer {
address: string
_signer: {
address: string
_signer: {
provider: any
signTransaction: (transaction: any) => any,
signMessage: (message: string) => any,
@ -11,43 +11,43 @@ export class SignerWithAddress extends ethers.Signer {
connect: (provider: any) => any,
_signTypedData: (...params: any) => any
}
provider: any
static async create(signer: any) {
return new SignerWithAddress(await signer.getAddress(), signer)
}
constructor(address: string, _signer: any) {
super()
this.address = address
this._signer = _signer
this.provider = _signer.provider
}
async getAddress() {
return this.address
}
signMessage(message: string){
return this._signer.signMessage(message)
}
signTransaction(transaction: any) {
return this._signer.signTransaction(transaction)
}
sendTransaction(transaction: any) {
return this._signer.sendTransaction(transaction)
}
connect(provider: any) {
return new SignerWithAddress(this.address, this._signer.connect(provider))
}
_signTypedData(...params: any) {
return this._signer._signTypedData(...params)
}
toJSON() {
return `<SignerWithAddress ${this.address}>`
}
provider: any
static async create(signer: any) {
return new SignerWithAddress(await signer.getAddress(), signer)
}
constructor(address: string, _signer: any) {
super()
this.address = address
this._signer = _signer
this.provider = _signer.provider
}
async getAddress() {
return this.address
}
signMessage(message: string){
return this._signer.signMessage(message)
}
signTransaction(transaction: any) {
return this._signer.signTransaction(transaction)
}
sendTransaction(transaction: any) {
return this._signer.sendTransaction(transaction)
}
connect(provider: any) {
return new SignerWithAddress(this.address, this._signer.connect(provider))
}
_signTypedData(...params: any) {
return this._signer._signTypedData(...params)
}
toJSON() {
return `<SignerWithAddress ${this.address}>`
}
}

@ -43,31 +43,31 @@ export default class lowLevelCalls implements AnalyzerModule {
let text = ''
let morehref = ''
switch (item.type) {
case lowLevelCallTypes.CALL:
text = `Use of "call": should be avoided whenever possible.
case lowLevelCallTypes.CALL:
text = `Use of "call": should be avoided whenever possible.
It can lead to unexpected behavior if return value is not handled properly.
Please use Direct Calls via specifying the called contract's interface.`
morehref = `https://solidity.readthedocs.io/en/${version}/control-structures.html?#external-function-calls`
break
case lowLevelCallTypes.CALLCODE:
text = `Use of "callcode": should be avoided whenever possible.
morehref = `https://solidity.readthedocs.io/en/${version}/control-structures.html?#external-function-calls`
break
case lowLevelCallTypes.CALLCODE:
text = `Use of "callcode": should be avoided whenever possible.
External code, that is called can change the state of the calling contract and send ether from the caller's balance.
If this is wanted behaviour, use the Solidity library feature if possible.`
morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break
case lowLevelCallTypes.DELEGATECALL:
text = `Use of "delegatecall": should be avoided whenever possible.
morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break
case lowLevelCallTypes.DELEGATECALL:
text = `Use of "delegatecall": should be avoided whenever possible.
External code, that is called can change the state of the calling contract and send ether from the caller's balance.
If this is wanted behaviour, use the Solidity library feature if possible.`
morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break
case lowLevelCallTypes.SEND:
text = `Use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly.
morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break
case lowLevelCallTypes.SEND:
text = `Use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly.
Use "transfer" whenever failure of the ether transfer should rollback the whole transaction.
Note: if you "send/transfer" ether to a contract the fallback function is called, the callees fallback function is very limited due to the limited amount of gas provided by "send/transfer".
No state changes are possible but the callee can log the event or revert the transfer. "send/transfer" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value.`
morehref = `https://solidity.readthedocs.io/en/${version}/security-considerations.html#sending-and-receiving-ether`
break
morehref = `https://solidity.readthedocs.io/en/${version}/security-considerations.html#sending-and-receiving-ether`
break
}
return { warning: text, more: morehref, location: item.node.src }
})

@ -1,10 +1,10 @@
import { default as test} from "tape"
import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommon'
const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, abiNamespaceCallNodes,
inlineAssembly, unaryOperation, nowAst, blockTimestamp, stateVariableContractNode,
functionDefinition, requireCall, selfdestruct, storageVariableNodes, dynamicDeleteUnaryOp,
// eslint-disable-next-line @typescript-eslint/no-var-requires
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition, funcDefForComplexParams } = require('./astBlocks')
inlineAssembly, unaryOperation, nowAst, blockTimestamp, stateVariableContractNode,
functionDefinition, requireCall, selfdestruct, storageVariableNodes, dynamicDeleteUnaryOp,
// eslint-disable-next-line @typescript-eslint/no-var-requires
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition, funcDefForComplexParams } = require('./astBlocks')
// eslint-disable-next-line @typescript-eslint/no-var-requires
@ -40,11 +40,11 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
'function (bytes memory) payable returns (bool,bytes memory)',
'check fixed call type')
t.equal(common.lowLevelCallTypes['CALL-0.4'].type,
t.equal(common.lowLevelCallTypes['CALL-0.4'].type,
'function () payable returns (bool)',
'check fixed call type for versions before 0.5.0')
t.equal(common.lowLevelCallTypes.CALLCODE.type,
t.equal(common.lowLevelCallTypes.CALLCODE.type,
'function () payable returns (bool)',
'check fixed callcode type')
@ -56,7 +56,7 @@ t.equal(common.lowLevelCallTypes.CALLCODE.type,
'function (bytes memory) returns (bool,bytes memory)',
'check fixed delegatecall type')
t.equal(common.lowLevelCallTypes['DELEGATECALL-0.4'].type,
t.equal(common.lowLevelCallTypes['DELEGATECALL-0.4'].type,
'function () returns (bool)',
'check fixed delegatecall type for version before 0.5.0')
})
@ -141,18 +141,18 @@ test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) {
test('staticAnalysisCommon.getType', function (t) {
t.plan(3)
const node = { "argumentTypes": null,
"id": 3,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 22,
"src": "52:1:0",
"typeDescriptions":
"id": 3,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 22,
"src": "52:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
}
t.ok(common.getType(blockHashAccess) === 'bytes32', 'gettype should work for different nodes')
t.ok(common.getType(node) === 'uint256', 'gettype should work for different nodes')
t.ok(common.getType(assignment) === 'uint256', 'gettype should work for different nodes')

@ -816,11 +816,11 @@ test('Integration test forLoopIteratesOverDynamicArray module', function (t: tes
function runModuleOnFiles (Module: any, t: test.Test, cb: ((fname: string, report: AnalysisReportObj[]) => void)): void {
const statRunner: StatRunner = new StatRunner()
testFiles.forEach((fileName: string) => {
const reports = statRunner.runWithModuleList(compilationResults[fileName], [{ name: new Module().name, mod: new Module() }])
const report: AnalysisReportObj[] = reports[0].report
if (report.some((x: AnalysisReportObj) => x['warning'].includes('INTERNAL ERROR'))) {
t.comment('Error while executing Module: ' + JSON.stringify(report))
}
cb(fileName, report)
const reports = statRunner.runWithModuleList(compilationResults[fileName], [{ name: new Module().name, mod: new Module() }])
const report: AnalysisReportObj[] = reports[0].report
if (report.some((x: AnalysisReportObj) => x['warning'].includes('INTERNAL ERROR'))) {
t.comment('Error while executing Module: ' + JSON.stringify(report))
}
cb(fileName, report)
})
}

@ -95,7 +95,7 @@ export class CompilerArtefacts extends Plugin {
* filter compilation output for contracts compiled during a session of Remix IDE
* @returns compilatin output
*/
filterAllContractDatas (filter) {
filterAllContractDatas (filter) {
const contractsData = {}
Object.keys(this.compilersArtefactsPerFile).map((targetFile) => {
const artefact = this.compilersArtefactsPerFile[targetFile]

@ -167,8 +167,8 @@ export class CompilerImports extends Plugin {
Doesn't make sense to try to resolve "localhost/node_modules/localhost/node_modules/<path>" and we'll end in an infinite loop.
*/
if (!exist && (url === 'remix_tests.sol' || url === 'remix_accounts.sol')) {
await this.call('solidityUnitTesting', 'createTestLibs')
exist = await provider.exists(url)
await this.call('solidityUnitTesting', 'createTestLibs')
exist = await provider.exists(url)
}
if (!exist && url.startsWith('browser/')) throw new Error(`not found ${url}`)
if (!exist && url.startsWith('localhost/')) throw new Error(`not found ${url}`)

@ -88,10 +88,10 @@ export class CompilerMetadata extends Plugin {
const buildData = {id, _format: format, solcVersion, solcLongVersion, input, output}
await this.call('fileManager', 'writeFile', buildFilename, JSON.stringify(buildData, null, '\t'))
} else if (this.buildInfoNames[filePath] && this.buildInfoNames[filePath] !== buildFilename) {
await this.call('fileManager', 'remove', this.buildInfoNames[filePath])
this.buildInfoNames[filePath] = buildFilename
const buildData = {id, _format: format, solcVersion, solcLongVersion, input, output}
await this.call('fileManager', 'writeFile', buildFilename, JSON.stringify(buildData, null, '\t'))
await this.call('fileManager', 'remove', this.buildInfoNames[filePath])
this.buildInfoNames[filePath] = buildFilename
const buildData = {id, _format: format, solcVersion, solcLongVersion, input, output}
await this.call('fileManager', 'writeFile', buildFilename, JSON.stringify(buildData, null, '\t'))
}
}

@ -10,88 +10,88 @@ export const UUPSRuns = 0
export const UUPSEvmVersion = null
export const UUPSABI = [
{
"inputs": [
{
"internalType": "address",
"name": "_logic",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"stateMutability": "payable",
"type": "constructor"
"inputs": [
{
"internalType": "address",
"name": "_logic",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"stateMutability": "payable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "previousAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "AdminChanged",
"type": "event"
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "previousAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "AdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "beacon",
"type": "address"
}
],
"name": "BeaconUpgraded",
"type": "event"
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "beacon",
"type": "address"
}
],
"name": "BeaconUpgraded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
}
],
"name": "Upgraded",
"type": "event"
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
}
],
"name": "Upgraded",
"type": "event"
},
{
"stateMutability": "payable",
"type": "fallback"
"stateMutability": "payable",
"type": "fallback"
},
{
"stateMutability": "payable",
"type": "receive"
"stateMutability": "payable",
"type": "receive"
}
]
export const UUPSfunAbi = {
name: "",
inputs: [
{
"internalType": "address",
"name": "_logic",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
{
"internalType": "address",
"name": "_logic",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
type: "constructor",
outputs: [],
@ -99,17 +99,17 @@ export const UUPSfunAbi = {
}
export const UUPSupgradeAbi = {
"inputs": [
{
"internalType": "address",
"name": "newImplementation",
"type": "address"
}
],
"name": "upgradeTo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
"inputs": [
{
"internalType": "address",
"name": "newImplementation",
"type": "address"
}
],
"name": "upgradeTo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
export const EnableProxyURLParam = 'deployProxy'
export const EnableUpgradeURLParam = 'upgradeProxy'

@ -191,7 +191,7 @@ export interface ContractSources {
}
}
export interface NetworkDeploymentFile {
export interface NetworkDeploymentFile {
id: string,
network: string,
deployments: {
@ -204,7 +204,7 @@ export interface ContractSources {
}[]
}
export interface SolcBuildFile {
export interface SolcBuildFile {
solcInput: SolcInput,
solcOutput: SolcOutput
}

@ -67,7 +67,7 @@ cmdLine.startDebug(tx, shortFilename)
cmdLine.events.on('source', () => {
cmdLine.getSource().forEach(console.dir)
})
// })
// })
// })
const repl = require('repl')

@ -31,15 +31,15 @@ export function decodeLocals (st, index, traceManager, callTree, verifier) {
callback(error)
}
}],
index,
function (error, result) {
if (error) {
return st.fail(error)
}
solidityLocals(index, callTree, result[0].value, result[1].value, {}, result[2].value, { start: 5000 }, null).then((locals) => {
verifier(locals)
})
index,
function (error, result) {
if (error) {
return st.fail(error)
}
solidityLocals(index, callTree, result[0].value, result[1].value, {}, result[2].value, { start: 5000 }, null).then((locals) => {
verifier(locals)
})
})
} catch (e) {
st.fail(e.message)
}

@ -46,63 +46,63 @@ module.exports = async function testMappingStorage (st, cb) {
function testMapping (st, privateKey, contractAddress, output, compilationResults, web3, cb) {
(vmCall as any).sendTx(web3, {nonce: 1, privateKey: privateKey}, contractAddress, 0, '2fd0a83a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001074686973206973206120737472696e6700000000000000000000000000000000',
function (error, hash) {
function (error, hash) {
if (error) {
console.log(error)
st.end(error)
} else {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
console.log(compilationResults)
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResults
})
const debuggerEvent = new EventManager()
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
const storageViewer = new StorageViewer({
stepIndex: 268,
tx: tx,
address: contractAddress
}, new StorageResolver({web3}), traceManager)
const stateVars = stateDecoder.extractStateVariables('SimpleMappingState', output.sources)
stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
st.equal(result['_num'].value, '1')
st.equal(result['_num'].type, 'uint256')
st.equal(result['_iBreakSolidityState'].type, 'mapping(string => uint256)')
st.equal(result['_iBreakSolidityState'].value['74686973206973206120737472696e67'].value, '1')
st.equal(result['_iBreakSolidityState'].value['74686973206973206120737472696e67'].type, 'uint256')
st.equal(result['_iBreakSolidityStateInt'].type, 'mapping(uint256 => uint256)')
st.equal(result['_iBreakSolidityStateInt'].value['0000000000000000000000000000000000000000000000000000000000000001'].value, '1')
st.equal(result['_iBreakSolidityStateInt'].value['0000000000000000000000000000000000000000000000000000000000000001'].type, 'uint256')
cb()
}, (reason) => {
console.log('fail')
st.end(reason)
})
})
} else {
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
console.log(compilationResults)
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResults
})
const debuggerEvent = new EventManager()
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
const storageViewer = new StorageViewer({
stepIndex: 268,
tx: tx,
address: contractAddress
}, new StorageResolver({web3}), traceManager)
const stateVars = stateDecoder.extractStateVariables('SimpleMappingState', output.sources)
stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
st.equal(result['_num'].value, '1')
st.equal(result['_num'].type, 'uint256')
st.equal(result['_iBreakSolidityState'].type, 'mapping(string => uint256)')
st.equal(result['_iBreakSolidityState'].value['74686973206973206120737472696e67'].value, '1')
st.equal(result['_iBreakSolidityState'].value['74686973206973206120737472696e67'].type, 'uint256')
st.equal(result['_iBreakSolidityStateInt'].type, 'mapping(uint256 => uint256)')
st.equal(result['_iBreakSolidityStateInt'].value['0000000000000000000000000000000000000000000000000000000000000001'].value, '1')
st.equal(result['_iBreakSolidityStateInt'].value['0000000000000000000000000000000000000000000000000000000000000001'].type, 'uint256')
cb()
}, (reason) => {
console.log('fail')
st.end(reason)
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
}
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
}
})
}
})
}

@ -3,64 +3,64 @@ const node = {}
node['ast'] = {"legacyAST":{"children":[{"attributes":{"fullyImplemented":true,"isLibrary":false,"linearizedBaseContracts":[5640396],"name":"test"},"children":[{"attributes":{"name":"x","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5657860,"name":"ElementaryTypeName","src":"21:3:11"}],"id":5658100,"name":"VariableDeclaration","src":"21:5:11"},{"attributes":{"name":"y","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658180,"name":"ElementaryTypeName","src":"38:3:11"}],"id":5658268,"name":"VariableDeclaration","src":"38:5:11"},{"attributes":{"constant":false,"name":"set","public":true},"children":[{"children":[{"attributes":{"name":"_x","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658404,"name":"ElementaryTypeName","src":"68:3:11"}],"id":5658492,"name":"VariableDeclaration","src":"68:6:11"}],"id":5658572,"name":"ParameterList","src":"67:8:11"},{"children":[{"attributes":{"name":"_r","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658628,"name":"ElementaryTypeName","src":"85:3:11"}],"id":5658716,"name":"VariableDeclaration","src":"85:6:11"}],"id":5658796,"name":"ParameterList","src":"84:8:11"},{"children":[{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"x"},"id":5658900,"name":"Identifier","src":"108:1:11"},{"attributes":{"type":"int256","value":"_x"},"id":5658980,"name":"Identifier","src":"112:2:11"}],"id":5657492,"name":"Assignment","src":"108:6:11"}],"id":5659028,"name":"ExpressionStatement","src":"108:6:11"},{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"y"},"id":5659116,"name":"Identifier","src":"125:1:11"},{"attributes":{"string":null,"type":"int_const 10","value":"10"},"id":5659196,"name":"Literal","src":"129:2:11"}],"id":5659252,"name":"Assignment","src":"125:6:11"}],"id":5659316,"name":"ExpressionStatement","src":"125:6:11"},{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"_r"},"id":5659428,"name":"Identifier","src":"141:2:11"},{"attributes":{"type":"int256","value":"x"},"id":5639308,"name":"Identifier","src":"146:1:11"}],"id":5639356,"name":"Assignment","src":"141:6:11"}],"id":5639420,"name":"ExpressionStatement","src":"141:6:11"}],"id":5639516,"name":"Block","src":"97:57:11"}],"id":5639612,"name":"FunctionDefinition","src":"55:99:11"},{"attributes":{"constant":false,"name":"get","public":true},"children":[{"children":[],"id":5639764,"name":"ParameterList","src":"179:2:11"},{"children":[{"attributes":{"name":"x","type":"uint256"},"children":[{"attributes":{"name":"uint"},"id":5639820,"name":"ElementaryTypeName","src":"191:4:11"}],"id":5639908,"name":"VariableDeclaration","src":"191:6:11"},{"attributes":{"name":"y","type":"uint256"},"children":[{"attributes":{"name":"uint"},"id":5639988,"name":"ElementaryTypeName","src":"199:4:11"}],"id":5640076,"name":"VariableDeclaration","src":"199:6:11"}],"id":5640156,"name":"ParameterList","src":"190:16:11"},{"children":[],"id":5640212,"name":"Block","src":"212:17:11"}],"id":5640276,"name":"FunctionDefinition","src":"167:62:11"}],"id":5640396,"name":"ContractDefinition","src":"0:231:11"}],"name":"SourceUnit"}}
node['ast'].ast = {
absolutePath: 'sample.sol',
exportedSymbols: { test: [ 33 ] },
id: 34,
nodeType: 'SourceUnit',
nodes:
absolutePath: 'sample.sol',
exportedSymbols: { test: [ 33 ] },
id: 34,
nodeType: 'SourceUnit',
nodes:
[ {
abstract: false,
baseContracts: [],
contractDependencies: [],
contractKind: 'contract',
documentation: null,
fullyImplemented: true,
id: 33,
linearizedBaseContracts: [ 33 ],
name: 'test',
nodeType: 'ContractDefinition',
nodes:
abstract: false,
baseContracts: [],
contractDependencies: [],
contractKind: 'contract',
documentation: null,
fullyImplemented: true,
id: 33,
linearizedBaseContracts: [ 33 ],
name: 'test',
nodeType: 'ContractDefinition',
nodes:
[ { constant: false,
id: 2,
name: 'x',
nodeType: 'VariableDeclaration',
overrides: null,
scope: 33,
src: '20:5:0',
stateVariable: true,
storageLocation: 'default',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' },
typeName: {
id: 1,
name: 'int',
nodeType: 'ElementaryTypeName',
src: '20:3:0',
typeDescriptions: [Object]
},
value: null,
visibility: 'internal' },
id: 2,
name: 'x',
nodeType: 'VariableDeclaration',
overrides: null,
scope: 33,
src: '20:5:0',
stateVariable: true,
storageLocation: 'default',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' },
typeName: {
id: 1,
name: 'int',
nodeType: 'ElementaryTypeName',
src: '20:3:0',
typeDescriptions: [Object]
},
value: null,
visibility: 'internal' },
{ constant: false,
id: 4,
name: 'y',
nodeType: 'VariableDeclaration',
overrides: null,
scope: 33,
src: '31:5:0',
stateVariable: true,
storageLocation: 'default',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' },
typeName:
id: 4,
name: 'y',
nodeType: 'VariableDeclaration',
overrides: null,
scope: 33,
src: '31:5:0',
stateVariable: true,
storageLocation: 'default',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' },
typeName:
{ id: 3,
name: 'int',
nodeType: 'ElementaryTypeName',
src: '31:3:0',
typeDescriptions: [Object] },
value: null,
visibility: 'internal' },
name: 'int',
nodeType: 'ElementaryTypeName',
src: '31:3:0',
typeDescriptions: [Object] },
value: null,
visibility: 'internal' },
{ body: { id: 23,
nodeType: 'Block',
src: '96:55:0',
statements:
nodeType: 'Block',
src: '96:55:0',
statements:
[ { expression:
{ argumentTypes: null,
id: 13,
@ -70,31 +70,31 @@ node['ast'].ast = {
lValueRequested: false,
leftHandSide:
{ argumentTypes: null,
id: 11,
name: 'x',
nodeType: 'Identifier',
overloadedDeclarations: [],
referencedDeclaration: 2,
src: '106:1:0',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' } },
id: 11,
name: 'x',
nodeType: 'Identifier',
overloadedDeclarations: [],
referencedDeclaration: 2,
src: '106:1:0',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' } },
nodeType: 'Assignment',
operator: '=',
rightHandSide:
{ argumentTypes: null,
id: 12,
name: '_x',
nodeType: 'Identifier',
overloadedDeclarations: [],
referencedDeclaration: 6,
src: '110:2:0',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' } },
id: 12,
name: '_x',
nodeType: 'Identifier',
overloadedDeclarations: [],
referencedDeclaration: 6,
src: '110:2:0',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' } },
src: '106:6:0',
typeDescriptions: { typeIdentifier: 't_int256', typeString: 'int256' }
},
id: 14,
nodeType: 'ExpressionStatement',
src: '106:6:0' },
{ expression:
id: 14,
nodeType: 'ExpressionStatement',
src: '106:6:0' },
{ expression:
{ argumentTypes: null,
id: 17,
isConstant: false,
@ -107,10 +107,10 @@ node['ast'].ast = {
rightHandSide: [Object],
src: '122:6:0',
typeDescriptions: [Object] },
id: 18,
nodeType: 'ExpressionStatement',
src: '122:6:0' },
{ expression:
id: 18,
nodeType: 'ExpressionStatement',
src: '122:6:0' },
{ expression:
{ argumentTypes: null,
id: 21,
isConstant: false,
@ -123,61 +123,61 @@ node['ast'].ast = {
rightHandSide: [Object],
src: '138:6:0',
typeDescriptions: [Object] },
id: 22,
nodeType: 'ExpressionStatement',
src: '138:6:0' } ]
},
documentation: null,
functionSelector: 'e5c19b2d',
id: 24,
implemented: true,
kind: 'function',
modifiers: [],
name: 'set',
nodeType: 'FunctionDefinition',
overrides: null,
parameters: { id: 7,
nodeType: 'ParameterList',
parameters: [Array],
src: '59:8:0' },
returnParameters: { id: 10,
nodeType: 'ParameterList',
parameters: [Array],
src: '83:8:0' },
scope: 33,
src: '47:104:0',
stateMutability: 'nonpayable',
virtual: false,
visibility: 'public' },
id: 22,
nodeType: 'ExpressionStatement',
src: '138:6:0' } ]
},
documentation: null,
functionSelector: 'e5c19b2d',
id: 24,
implemented: true,
kind: 'function',
modifiers: [],
name: 'set',
nodeType: 'FunctionDefinition',
overrides: null,
parameters: { id: 7,
nodeType: 'ParameterList',
parameters: [Array],
src: '59:8:0' },
returnParameters: { id: 10,
nodeType: 'ParameterList',
parameters: [Array],
src: '83:8:0' },
scope: 33,
src: '47:104:0',
stateMutability: 'nonpayable',
virtual: false,
visibility: 'public' },
{ body: { id: 31, nodeType: 'Block', src: '214:17:0', statements: [] },
documentation: null,
functionSelector: '6d4ce63c',
id: 32,
implemented: true,
kind: 'function',
modifiers: [],
name: 'get',
nodeType: 'FunctionDefinition',
overrides: null,
parameters:
documentation: null,
functionSelector: '6d4ce63c',
id: 32,
implemented: true,
kind: 'function',
modifiers: [],
name: 'get',
nodeType: 'FunctionDefinition',
overrides: null,
parameters:
{ id: 25,
nodeType: 'ParameterList',
parameters: [],
src: '175:2:0' },
returnParameters:
nodeType: 'ParameterList',
parameters: [],
src: '175:2:0' },
returnParameters:
{ id: 30,
nodeType: 'ParameterList',
parameters: [Array],
src: '193:16:0' },
scope: 33,
src: '163:68:0',
stateMutability: 'nonpayable',
virtual: false,
visibility: 'public' } ],
scope: 34,
src: '0:233:0'
nodeType: 'ParameterList',
parameters: [Array],
src: '193:16:0' },
scope: 33,
src: '163:68:0',
stateMutability: 'nonpayable',
virtual: false,
visibility: 'public' } ],
scope: 34,
src: '0:233:0'
} ],
src: '0:233:0'
src: '0:233:0'
}

@ -134,21 +134,21 @@ export function encodeConstructorCallAndLinkLibraries (contract, params, funAbi,
*/
export function linkLibraries (contract, linkLibraries, linkReferences, callback) {
let bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
if (linkLibraries && linkReferences) {
for (const libFile in linkLibraries) {
for (const lib in linkLibraries[libFile]) {
const address = linkLibraries[libFile][lib]
if (!isValidAddress(address)) return callback(address + ' is not a valid address. Please check the provided address is valid.')
bytecodeToDeploy = linkLibraryStandardFromlinkReferences(lib, address.replace('0x', ''), bytecodeToDeploy, linkReferences)
}
if (bytecodeToDeploy.indexOf('_') >= 0) {
if (linkLibraries && linkReferences) {
for (const libFile in linkLibraries) {
for (const lib in linkLibraries[libFile]) {
const address = linkLibraries[libFile][lib]
if (!isValidAddress(address)) return callback(address + ' is not a valid address. Please check the provided address is valid.')
bytecodeToDeploy = linkLibraryStandardFromlinkReferences(lib, address.replace('0x', ''), bytecodeToDeploy, linkReferences)
}
}
}
if (bytecodeToDeploy.indexOf('_') >= 0) {
return callback('Failed to link some libraries')
}
return callback(null, bytecodeToDeploy)
}
if (bytecodeToDeploy.indexOf('_') >= 0) {
return callback('Failed to link some libraries')
}
return callback(null, bytecodeToDeploy)
}
/**
@ -459,7 +459,7 @@ export function parseFunctionParams (params) {
args.push(parseFunctionParams(params.substring(i + 1, j)))
i = j - 1
} else if (params.charAt(i) === ',' || i === params.length - 1) { // , or end of string
// if startIndex >= 0, it means a parameter was being parsed, it can be first or other parameter
// if startIndex >= 0, it means a parameter was being parsed, it can be first or other parameter
if (startIndex >= 0) {
let param = params.substring(startIndex, i === params.length - 1 ? undefined : i)
param = normalizeParam(param)

@ -10,22 +10,22 @@ import { toBuffer, setLengthLeft, isHexString } from '@ethereumjs/util'
*/
export const keccak = function(a: Buffer, bits: number = 256): Buffer {
assertIsBuffer(a)
switch (bits) {
case 224: {
return toBuffer(keccak224(a))
}
case 256: {
return toBuffer(k256(a))
}
case 384: {
return toBuffer(keccak384(a))
}
case 512: {
return toBuffer(keccak512(a))
}
default: {
throw new Error(`Invald algorithm: keccak${bits}`)
}
switch (bits) {
case 224: {
return toBuffer(keccak224(a))
}
case 256: {
return toBuffer(k256(a))
}
case 384: {
return toBuffer(keccak384(a))
}
case 512: {
return toBuffer(keccak512(a))
}
default: {
throw new Error(`Invald algorithm: keccak${bits}`)
}
}
}

@ -222,7 +222,7 @@ export function getinputParameters (value) {
if (regex && regex[1]) {
return regex[1]
} else
return ''
return ''
}
/**

@ -183,7 +183,7 @@ tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t)
function testLinkLibrary (st, fakeDeployedContracts, callbackDeployLibraries) {
const deployMsg = ['creation of library test.sol:lib1 pending...',
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
txFormat.buildData('testContractLinkLibrary', context.contract, context.output.contracts, true, context.contract.abi[0], '', (error, data) => {
if (error) { return st.fail(error) }
console.log(data)
@ -212,7 +212,7 @@ function testLinkLibrary2 (st, callbackDeployLibraries) {
const data = '608060405234801561001057600080fd5b506101e2806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80636d4ce63c14610030575b600080fd5b61003861003a565b005b73f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561007e57600080fd5b505af4158015610092573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b1580156100da57600080fd5b505af41580156100ee573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561013657600080fd5b505af415801561014a573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561019257600080fd5b505af41580156101a6573d6000803e3d6000fd5b5050505056fea264697066735822122007784c53df7f324243100f6642d889a08a88831c3811dd13eebe3163b7eb2e5464736f6c63430006000033'
const deployMsg = ['creation of library test.sol:lib1 pending...',
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
txFormat.encodeConstructorCallAndLinkLibraries(context.contract, '', context.contract.abi[0], librariesReference, context.contract.evm.bytecode.linkReferences, (error, result) => {
console.log(error, result)
st.equal(data, result.dataHex)

@ -43,25 +43,25 @@ export class Blocks {
}
const transactions = block.transactions.map((t) => {
const hash = '0x' + t.hash().toString('hex')
const tx = this.vmContext.txByHash[hash]
const receipt = this.vmContext.currentVm.web3vm.txsReceipt[hash]
if (receipt) {
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: bigIntToHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
const hash = '0x' + t.hash().toString('hex')
const tx = this.vmContext.txByHash[hash]
const receipt = this.vmContext.currentVm.web3vm.txsReceipt[hash]
if (receipt) {
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: bigIntToHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
}
}
}
})
const b = {
baseFeePerGas: '0x01',
@ -101,22 +101,22 @@ export class Blocks {
const tx = this.vmContext.txByHash[hash]
const receipt = this.vmContext.currentVm.web3vm.txsReceipt[hash]
if (receipt) {
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: toHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
}
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: toHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
}
}
})
})
const b = {
baseFeePerGas: '0x01',
number: bigIntToHex(block.header.number),

@ -3,53 +3,53 @@ import helper from './helper'
import { CompilationResult, CompilerInput, CompilationSourceCode } from './types'
export class CompilerAbstract {
languageversion: string
data: CompilationResult
source: CompilationSourceCode
input: CompilerInput
constructor (languageversion: string, data: CompilationResult, source: CompilationSourceCode, input?: CompilerInput) {
this.languageversion = languageversion
this.data = data
this.source = source // source code
this.input = input
}
getContracts () {
return this.data.contracts || {}
}
getContract (name) {
return helper.getContract(name, this.data.contracts)
}
visitContracts (calllback) {
return helper.visitContracts(this.data.contracts, calllback)
}
getData () {
return this.data
}
getInput () {
return this.input
}
getAsts () {
return this.data.sources // ast
}
getSourceName (fileIndex) {
if (this.data && this.data.sources) {
return Object.keys(this.data.sources)[fileIndex]
} else if (Object.keys(this.source.sources).length === 1) {
languageversion: string
data: CompilationResult
source: CompilationSourceCode
input: CompilerInput
constructor (languageversion: string, data: CompilationResult, source: CompilationSourceCode, input?: CompilerInput) {
this.languageversion = languageversion
this.data = data
this.source = source // source code
this.input = input
}
getContracts () {
return this.data.contracts || {}
}
getContract (name) {
return helper.getContract(name, this.data.contracts)
}
visitContracts (calllback) {
return helper.visitContracts(this.data.contracts, calllback)
}
getData () {
return this.data
}
getInput () {
return this.input
}
getAsts () {
return this.data.sources // ast
}
getSourceName (fileIndex) {
if (this.data && this.data.sources) {
return Object.keys(this.data.sources)[fileIndex]
} else if (Object.keys(this.source.sources).length === 1) {
// if we don't have ast, we return the only one filename present.
const sourcesArray = Object.keys(this.source.sources)
return sourcesArray[0]
}
return null
const sourcesArray = Object.keys(this.source.sources)
return sourcesArray[0]
}
return null
}
getSourceCode () {
return this.source
}
getSourceCode () {
return this.source
}
}

@ -295,27 +295,27 @@ export class Compiler {
return
}
switch (data.cmd) {
case 'versionLoaded':
if (data.data) this.onCompilerLoaded(data.data, data.license)
break
case 'compiled':
{
let result: CompilationResult
if (data.data && data.job !== undefined && data.job >= 0) {
try {
result = JSON.parse(data.data)
} catch (exception) {
result = { error: { formattedMessage: 'Invalid JSON output from the compiler: ' + exception } }
}
let sources: SourceWithTarget = {}
if (data.job in jobs !== undefined) {
sources = jobs[data.job].sources
delete jobs[data.job]
}
this.onCompilationFinished(result, data.missingInputs, sources, data.input, this.state.currentVersion)
}
break
case 'versionLoaded':
if (data.data) this.onCompilerLoaded(data.data, data.license)
break
case 'compiled':
{
let result: CompilationResult
if (data.data && data.job !== undefined && data.job >= 0) {
try {
result = JSON.parse(data.data)
} catch (exception) {
result = { error: { formattedMessage: 'Invalid JSON output from the compiler: ' + exception } }
}
let sources: SourceWithTarget = {}
if (data.job in jobs !== undefined) {
sources = jobs[data.job].sources
delete jobs[data.job]
}
this.onCompilationFinished(result, data.missingInputs, sources, data.input, this.state.currentVersion)
}
break
}
}
})

@ -502,6 +502,6 @@ export interface BytecodeObject {
}
}
export interface EsWebWorkerHandlerInterface {
export interface EsWebWorkerHandlerInterface {
getWorker(): Worker
}

@ -6,42 +6,42 @@ const missingInputs: string[] = []
self.onmessage = (e: MessageEvent) => {
const data: MessageToWorker = e.data
switch (data.cmd) {
case 'loadVersion':
{
(self as any).importScripts(data.data)
const compiler = setupMethods(self)
compileJSON = (input) => {
try {
const missingInputsCallback = (path) => {
missingInputs.push(path)
return { error: 'Deferred import' }
}
return compiler.compile(input, { import: missingInputsCallback })
} catch (exception) {
return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception })
}
case 'loadVersion':
{
(self as any).importScripts(data.data)
const compiler = setupMethods(self)
compileJSON = (input) => {
try {
const missingInputsCallback = (path) => {
missingInputs.push(path)
return { error: 'Deferred import' }
}
self.postMessage({
cmd: 'versionLoaded',
data: compiler.version(),
license: compiler.license()
})
break
return compiler.compile(input, { import: missingInputsCallback })
} catch (exception) {
return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception })
}
}
self.postMessage({
cmd: 'versionLoaded',
data: compiler.version(),
license: compiler.license()
})
break
}
case 'compile':
missingInputs.length = 0
if (data.input && compileJSON) {
self.postMessage({
cmd: 'compiled',
job: data.job,
timestamp: data.timestamp,
data: compileJSON(data.input),
input: data.input,
missingInputs: missingInputs
})
}
break
case 'compile':
missingInputs.length = 0
if (data.input && compileJSON) {
self.postMessage({
cmd: 'compiled',
job: data.job,
timestamp: data.timestamp,
data: compileJSON(data.input),
input: data.input,
missingInputs: missingInputs
})
}
break
}
}

@ -1,12 +1,12 @@
class ESWebWorkerHandler {
constructor() {
constructor() {
}
}
getWorker () {
// @ts-ignore
return new Worker(new URL('./compiler-worker', import.meta.url))
}
getWorker () {
// @ts-ignore
return new Worker(new URL('./compiler-worker', import.meta.url))
}
}
export default ESWebWorkerHandler

@ -31,28 +31,28 @@ const logFmt = winston.format.printf((info) => {
})
class Log {
logger: Logger;
constructor () {
this.logger = winston.createLogger({
level: 'info',
transports: [new winston.transports.Console()],
format: winston.format.combine(
winston.format.colorize({ all: true }),
logFmt
)
})
}
setVerbosity (v: LoggerOptions['level']): void {
this.logger.configure({
level: v,
transports: [new winston.transports.Console()],
format: winston.format.combine(
winston.format.colorize({ all: true }),
logFmt
)
})
}
logger: Logger;
constructor () {
this.logger = winston.createLogger({
level: 'info',
transports: [new winston.transports.Console()],
format: winston.format.combine(
winston.format.colorize({ all: true }),
logFmt
)
})
}
setVerbosity (v: LoggerOptions['level']): void {
this.logger.configure({
level: v,
transports: [new winston.transports.Console()],
format: winston.format.combine(
winston.format.colorize({ all: true }),
logFmt
)
})
}
}
export default Log

@ -3,35 +3,35 @@ import { resolve } from 'path'
import { expect } from 'chai';
describe('testRunner: remix-tests CLI', function(){
this.timeout(120000)
// remix-tests binary, after build, is used as executable
this.timeout(120000)
// remix-tests binary, after build, is used as executable
const executablePath = resolve(__dirname + '/../../../dist/libs/remix-tests/bin/remix-tests')
const executablePath = resolve(__dirname + '/../../../dist/libs/remix-tests/bin/remix-tests')
const result = spawnSync('ls', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
if(result) {
const dirContent = result.stdout.toString()
// Install dependencies if 'node_modules' is not already present
if(!dirContent.includes('node_modules')) {
execSync('yarn add @remix-project/remix-lib ../../libs/remix-lib', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-url-resolver ../../libs/remix-url-resolver', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-solidity ../../libs/remix-solidity', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-simulator ../../libs/remix-simulator', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn install', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
}
const result = spawnSync('ls', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
if(result) {
const dirContent = result.stdout.toString()
// Install dependencies if 'node_modules' is not already present
if(!dirContent.includes('node_modules')) {
execSync('yarn add @remix-project/remix-lib ../../libs/remix-lib', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-url-resolver ../../libs/remix-url-resolver', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-solidity ../../libs/remix-solidity', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn add @remix-project/remix-simulator ../../libs/remix-simulator', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
execSync('yarn install', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
}
}
describe('test various CLI options', function() {
it('remix-tests version', () => {
const res = spawnSync(executablePath, ['-V'])
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(res.stdout.toString().trim()).to.equal(require('../package.json').version)
})
describe('test various CLI options', function() {
it('remix-tests version', () => {
const res = spawnSync(executablePath, ['-V'])
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(res.stdout.toString().trim()).to.equal(require('../package.json').version)
})
it('remix-tests help', () => {
const res = spawnSync(executablePath, ['-h'])
const expectedHelp = `Usage: remix-tests [options] [command] <file_path>
it('remix-tests help', () => {
const res = spawnSync(executablePath, ['-h'])
const expectedHelp = `Usage: remix-tests [options] [command] <file_path>
Arguments:
file_path path to test file or directory
@ -55,8 +55,8 @@ Options:
Commands:
version output the version number
help output usage information`
expect(res.stdout.toString().trim()).to.equal(expectedHelp)
})
expect(res.stdout.toString().trim()).to.equal(expectedHelp)
})
it('remix-tests running a test file', function() {
const res = spawnSync(executablePath, [resolve(__dirname + '/examples_0/assert_ok_test.sol')])

@ -14,476 +14,476 @@ import { ResultsInterface, TestCbInterface, ResultCbInterface } from '../src/ind
// In this specific test, we'll use this helper to exclude `time` keys.
// Assertions for the existance of these will be made at the correct places.
function deepEqualExcluding(a: any, b: any, excludedKeys: string[]) {
function removeKeysFromObject(obj: any, excludedKeys: string[]) {
if (obj !== Object(obj)) {
return obj
}
if (Object.prototype.toString.call(obj) !== '[object Array]') {
obj = Object.assign({}, obj)
for (const key of excludedKeys) {
delete obj[key]
}
function removeKeysFromObject(obj: any, excludedKeys: string[]) {
if (obj !== Object(obj)) {
return obj
}
return obj
}
if (Object.prototype.toString.call(obj) !== '[object Array]') {
obj = Object.assign({}, obj)
for (const key of excludedKeys) {
delete obj[key]
}
const newObj = []
for (const idx in obj) {
newObj[idx] = removeKeysFromObject(obj[idx], excludedKeys);
}
return obj
}
return newObj
const newObj = []
for (const idx in obj) {
newObj[idx] = removeKeysFromObject(obj[idx], excludedKeys);
}
const aStripped: any = removeKeysFromObject(a, excludedKeys);
const bStripped: any = removeKeysFromObject(b, excludedKeys);
assert.deepEqual(aStripped, bStripped)
return newObj
}
const aStripped: any = removeKeysFromObject(a, excludedKeys);
const bStripped: any = removeKeysFromObject(b, excludedKeys);
assert.deepEqual(aStripped, bStripped)
}
let accounts: string[]
const provider: any = new Provider()
async function compileAndDeploy(filename: string, callback: any) {
const web3: Web3 = new Web3()
const sourceASTs: any = {}
await provider.init()
web3.setProvider(provider)
extend(web3)
let compilationData: any
async.waterfall([
function getAccountList(next: any): void {
web3.eth.getAccounts((_err: Error | null | undefined, _accounts: string[]) => {
accounts = _accounts
web3.eth.defaultAccount = accounts[0]
next(_err)
})
},
function compile(next: any): void {
compileFileOrFiles(filename, false, { accounts }, null, next)
},
function deployAllContracts(compilationResult: compilationInterface, asts, next: any): void {
for (const filename in asts) {
if (filename.endsWith('_test.sol'))
sourceASTs[filename] = asts[filename].ast
}
// eslint-disable-next-line no-useless-catch
try {
compilationData = compilationResult
deployAll(compilationResult, web3, accounts, false, null, next)
} catch (e) {
throw e
}
}
], function (_err: Error | null | undefined, contracts: any): void {
callback(null, compilationData, contracts, sourceASTs, accounts, web3)
})
const web3: Web3 = new Web3()
const sourceASTs: any = {}
await provider.init()
web3.setProvider(provider)
extend(web3)
let compilationData: any
async.waterfall([
function getAccountList(next: any): void {
web3.eth.getAccounts((_err: Error | null | undefined, _accounts: string[]) => {
accounts = _accounts
web3.eth.defaultAccount = accounts[0]
next(_err)
})
},
function compile(next: any): void {
compileFileOrFiles(filename, false, { accounts }, null, next)
},
function deployAllContracts(compilationResult: compilationInterface, asts, next: any): void {
for (const filename in asts) {
if (filename.endsWith('_test.sol'))
sourceASTs[filename] = asts[filename].ast
}
// eslint-disable-next-line no-useless-catch
try {
compilationData = compilationResult
deployAll(compilationResult, web3, accounts, false, null, next)
} catch (e) {
throw e
}
}
], function (_err: Error | null | undefined, contracts: any): void {
callback(null, compilationData, contracts, sourceASTs, accounts, web3)
})
}
describe('testRunner', function () {
let tests: any[] = [], results: ResultsInterface;
let tests: any[] = [], results: ResultsInterface;
const testCallback: TestCbInterface = (err, test) => {
if (err) { throw err }
const testCallback: TestCbInterface = (err, test) => {
if (err) { throw err }
if (test.type === 'testPass' || test.type === 'testFailure') {
assert.ok(test.time, 'test time not reported')
assert.ok(!Number.isInteger(test.time || 0), 'test time should not be an integer')
}
tests.push(test)
if (test.type === 'testPass' || test.type === 'testFailure') {
assert.ok(test.time, 'test time not reported')
assert.ok(!Number.isInteger(test.time || 0), 'test time should not be an integer')
}
const resultsCallback = (done) => {
return (err, _results) => {
if (err) { throw err }
results = _results
done()
}
tests.push(test)
}
const resultsCallback = (done) => {
return (err, _results) => {
if (err) { throw err }
results = _results
done()
}
}
describe('#runTest', function () {
this.timeout(10000)
describe('assert library OK method tests', () => {
const filename: string = __dirname + '/examples_0/assert_ok_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 1 passing test', () => {
assert.equal(results.passingNum, 1)
})
it('should have 1 failing test', () => {
assert.equal(results.failureNum, 1)
})
const hhLogs1 = [["AssertOkTest", "okPassTest"]]
const hhLogs2 = [["AssertOkTest", "okFailTest"]]
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertOkTest', filename: __dirname + '/examples_0/assert_ok_test.sol' },
{ type: 'testPass', debugTxHash: '0x5b665752a4faf83229259b9b2811d3295be0af633b0051d4b90042283ef55707', value: 'Ok pass test', filename: __dirname + '/examples_0/assert_ok_test.sol', context: 'AssertOkTest', hhLogs: hhLogs1 },
{ type: 'testFailure', debugTxHash: '0xa0a30ad042a7fc3495f72be7ba788d705888ffbbec7173f60bb27e07721510f2', value: 'Ok fail test', filename: __dirname + '/examples_0/assert_ok_test.sol', errMsg: 'okFailTest fails', context: 'AssertOkTest', hhLogs: hhLogs2, assertMethod: 'ok', location: '366:36:0', expected: 'true', returned: 'false' },
], ['time', 'web3'])
})
})
describe('#runTest', function () {
this.timeout(10000)
describe('assert library OK method tests', () => {
const filename: string = __dirname + '/examples_0/assert_ok_test.sol'
describe('assert library EQUAL method tests', function () {
const filename: string = __dirname + '/examples_0/assert_equal_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 6 passing test', () => {
assert.equal(results.passingNum, 6)
})
it('should have 6 failing test', () => {
assert.equal(results.failureNum, 6)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertEqualTest', filename: __dirname + '/examples_0/assert_equal_test.sol' },
{ type: 'testPass', debugTxHash: '0x233b8d91f0fa068b1a4deae1141178bc3eb79c3d2a6786160595a358363a157c', value: 'Equal uint pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xa5e39c78663c2e5071c08467047ba5b2650d16081b50369700d46d7f90c4d94b', value: 'Equal uint fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalUintFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '273:57:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x57af51c2c19db390a4ccf72fa3d32347fb3d998e70820909c7876bd8ccebf8a3', value: 'Equal int pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x710f3a54a561c009fcf0277273b8fe337b2c493e9e83e0ae02786d487339ca7b', value: 'Equal int fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalIntFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '493:45:0', expected: '2', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x10c1ed8651110ad5de6adcad8e1284aa5c1fd3a998a1e863bbecc0ec855fcd7b', value: 'Equal bool pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x004871a82968f43e02278eab9dd3d7eb0bbe88b64d459efa50065e5996fe5fad', value: 'Equal bool fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBoolFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '708:52:0', expected: false, returned: true },
{ type: 'testPass', debugTxHash: '0x64a4d4853ab7907712912cf2120ac2bfd2e08b4767b375250f0e907757546454', value: 'Equal address pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xcf62fb76e3b2eb95d92aa2671a9e81e30fefb944f55e2fb8b97096c45fc74a38', value: 'Equal address fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalAddressFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1015:130:0', expected: '0x1c6637567229159d1eFD45f95A6675e77727E013', returned: '0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9' },
{ type: 'testPass', debugTxHash: '0x18ef613acc128a21282e09cf920b32ef3be648bb35c0299471ddbbbeeb0faf8c', value: 'Equal bytes32 pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x86fbf2f14e13d228f80a87a947841270d8c55073adddf78e8d4e2ba05d724ec6', value: 'Equal bytes32 fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBytes32FailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1670:48:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6979000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x80b3465f2504b74359790baa009237ba066685b24afa65a31814f1ad1bc4f99f', value: 'Equal string pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x88b035a85c5f87f54a805334817f3e4599b4190d98f25947fe14d7804facd8b7', value: 'Equal string fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalStringFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1916:81:0', expected: 'remix-tests', returned: 'remix' }
], ['time', 'web3'])
})
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 1 passing test', () => {
assert.equal(results.passingNum, 1)
})
it('should have 1 failing test', () => {
assert.equal(results.failureNum, 1)
})
const hhLogs1 = [["AssertOkTest", "okPassTest"]]
const hhLogs2 = [["AssertOkTest", "okFailTest"]]
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertOkTest', filename: __dirname + '/examples_0/assert_ok_test.sol' },
{ type: 'testPass', debugTxHash: '0x5b665752a4faf83229259b9b2811d3295be0af633b0051d4b90042283ef55707', value: 'Ok pass test', filename: __dirname + '/examples_0/assert_ok_test.sol', context: 'AssertOkTest', hhLogs: hhLogs1 },
{ type: 'testFailure', debugTxHash: '0xa0a30ad042a7fc3495f72be7ba788d705888ffbbec7173f60bb27e07721510f2', value: 'Ok fail test', filename: __dirname + '/examples_0/assert_ok_test.sol', errMsg: 'okFailTest fails', context: 'AssertOkTest', hhLogs: hhLogs2, assertMethod: 'ok', location: '366:36:0', expected: 'true', returned: 'false' },
describe('assert library NOTEQUAL method tests', function () {
const filename: string = __dirname + '/examples_0/assert_notEqual_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 6 passing test', () => {
assert.equal(results.passingNum, 6)
})
it('should have 6 failing test', () => {
assert.equal(results.failureNum, 6)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertNotEqualTest', filename: __dirname + '/examples_0/assert_notEqual_test.sol' },
{ type: 'testPass', debugTxHash: '0xdef34ec7fbc6a3e6c6ef619b424bf8ebf16db16ed3f74500d56d8170d3aeca66', value: 'Not equal uint pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0xfcbd35bc5f460e22e885951d560171d687cf90ccdffc41fb5de1beb7075fe4e9', value: 'Not equal uint fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualUintFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '288:63:0', expected: '1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x7f269855c3fc5c677eca416eb85665b8f10df00d3b7ec5dcc00cbf8e6364cba4', value: 'Not equal int pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x76555e218571d4ad69496d7d10ae46d30149c4bfd8c6e15ff2a58668ab6fba62', value: 'Not equal int fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualIntFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '525:52:0', expected: '-2', returned: '-2' },
{ type: 'testPass', debugTxHash: '0x5fe790b3f32b9580c1d5f9a2dbb0e10ddcb62846037d3f5800d47a51bb67cc91', value: 'Not equal bool pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x660d0a73395e6855aea8f6d3450e63640437dc15071842b417c39f40e1d7ae61', value: 'Not equal bool fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBoolFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '760:57:0', expected: true, returned: true },
{ type: 'testPass', debugTxHash: '0x6fddce5573bd6723acf5a3e4137d698ff78f695873a228939276c4323ddfb132', value: 'Not equal address pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
{ type: 'testFailure', debugTxHash: '0x51479e46db802fb598c61ca0dd630345b9d70cc58667b5a80aa79e8119fa7787', value: 'Not equal address fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualAddressFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1084:136:0', expected: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9, returned: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9 },
{ type: 'testPass', debugTxHash: '0xbcaf6d8977b655fdedb280e0e9221d728706d41e85e0973d00c8da1d128022c7', value: 'Not equal bytes32 pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x34008ef0ea908fedbf80471424d801f5069e6e46221f8ee4a2ee16776a6eeef6', value: 'Not equal bytes32 fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBytes32FailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1756:54:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6978000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x8e0bc9dedea6e088ca7bd82b1e9fab516be5a52f7716a26ccca8197236aae105', value: 'Not equal string pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x13c6d270c3609ef858dd6d0c79433ca0b43e47b485b2e40ffe363f18f2868ea8', value: 'Not equal string fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualStringFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '2026:81:0', expected: 'remix', returned: 'remix' },
], ['time', 'web3'])
})
], ['time', 'web3'])
})
})
describe('assert library EQUAL method tests', function () {
const filename: string = __dirname + '/examples_0/assert_equal_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 6 passing test', () => {
assert.equal(results.passingNum, 6)
})
it('should have 6 failing test', () => {
assert.equal(results.failureNum, 6)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertEqualTest', filename: __dirname + '/examples_0/assert_equal_test.sol' },
{ type: 'testPass', debugTxHash: '0x233b8d91f0fa068b1a4deae1141178bc3eb79c3d2a6786160595a358363a157c', value: 'Equal uint pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xa5e39c78663c2e5071c08467047ba5b2650d16081b50369700d46d7f90c4d94b', value: 'Equal uint fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalUintFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '273:57:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x57af51c2c19db390a4ccf72fa3d32347fb3d998e70820909c7876bd8ccebf8a3', value: 'Equal int pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x710f3a54a561c009fcf0277273b8fe337b2c493e9e83e0ae02786d487339ca7b', value: 'Equal int fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalIntFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '493:45:0', expected: '2', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x10c1ed8651110ad5de6adcad8e1284aa5c1fd3a998a1e863bbecc0ec855fcd7b', value: 'Equal bool pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x004871a82968f43e02278eab9dd3d7eb0bbe88b64d459efa50065e5996fe5fad', value: 'Equal bool fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBoolFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '708:52:0', expected: false, returned: true },
{ type: 'testPass', debugTxHash: '0x64a4d4853ab7907712912cf2120ac2bfd2e08b4767b375250f0e907757546454', value: 'Equal address pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xcf62fb76e3b2eb95d92aa2671a9e81e30fefb944f55e2fb8b97096c45fc74a38', value: 'Equal address fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalAddressFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1015:130:0', expected: '0x1c6637567229159d1eFD45f95A6675e77727E013', returned: '0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9' },
{ type: 'testPass', debugTxHash: '0x18ef613acc128a21282e09cf920b32ef3be648bb35c0299471ddbbbeeb0faf8c', value: 'Equal bytes32 pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x86fbf2f14e13d228f80a87a947841270d8c55073adddf78e8d4e2ba05d724ec6', value: 'Equal bytes32 fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBytes32FailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1670:48:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6979000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x80b3465f2504b74359790baa009237ba066685b24afa65a31814f1ad1bc4f99f', value: 'Equal string pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x88b035a85c5f87f54a805334817f3e4599b4190d98f25947fe14d7804facd8b7', value: 'Equal string fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalStringFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1916:81:0', expected: 'remix-tests', returned: 'remix' }
], ['time', 'web3'])
})
})
describe('assert library GREATERTHAN method tests', function () {
const filename: string = __dirname + '/examples_0/assert_greaterThan_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 4 passing test', () => {
assert.equal(results.passingNum, 4)
})
it('should have 4 failing test', () => {
assert.equal(results.failureNum, 4)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertGreaterThanTest', filename: __dirname + '/examples_0/assert_greaterThan_test.sol' },
{ type: 'testPass', debugTxHash: '0xdc325916fd93227b76231131e52e67f8913d395098c5ac767032db9bd757a91c', value: 'Greater than uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xf98eea22bb86f13e0bb4072df22b540289a46b332bdb203a1e488d7e14a1dcd4', value: 'Greater than uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '303:69:0', expected: '4', returned: '1' },
{ type: 'testPass', debugTxHash: '0xef5ef38329ba6aac2f868d53d803053c52b1895a2c25b704260435c141a63bfc', value: 'Greater than int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x6b9430f3f12c12fb11e5a8d32fef849ab34614e644be20c6b41a25e510453440', value: 'Greater than int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '569:67:0', expected: '1', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x4c6e10815a5e82bf2c60950606dc886317f680028a9229ba2dda17b5ea36325a', value: 'Greater than uint int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x989c405c32c8e270a5dea69e6250a514c05dacd6fcf018365a241abc28c2497b', value: 'Greater than uint int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '845:71:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x9fed670ae2061929f71780835b7ea3eb7da6d4fb553cd2d5f62950c353165861', value: 'Greater than int uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xcf394fd279293cdcf58efc42f3a443595fdb171769a45df01b0c84cd76b3a9a2', value: 'Greater than int uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '1125:76:0', expected: '115792089237316195423570985008687907853269984665640564039457584007913129639836', returned: '100' }
], ['time', 'web3'])
})
describe('assert library NOTEQUAL method tests', function () {
const filename: string = __dirname + '/examples_0/assert_notEqual_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 6 passing test', () => {
assert.equal(results.passingNum, 6)
})
it('should have 6 failing test', () => {
assert.equal(results.failureNum, 6)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertNotEqualTest', filename: __dirname + '/examples_0/assert_notEqual_test.sol' },
{ type: 'testPass', debugTxHash: '0xdef34ec7fbc6a3e6c6ef619b424bf8ebf16db16ed3f74500d56d8170d3aeca66', value: 'Not equal uint pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0xfcbd35bc5f460e22e885951d560171d687cf90ccdffc41fb5de1beb7075fe4e9', value: 'Not equal uint fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualUintFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '288:63:0', expected: '1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x7f269855c3fc5c677eca416eb85665b8f10df00d3b7ec5dcc00cbf8e6364cba4', value: 'Not equal int pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x76555e218571d4ad69496d7d10ae46d30149c4bfd8c6e15ff2a58668ab6fba62', value: 'Not equal int fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualIntFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '525:52:0', expected: '-2', returned: '-2' },
{ type: 'testPass', debugTxHash: '0x5fe790b3f32b9580c1d5f9a2dbb0e10ddcb62846037d3f5800d47a51bb67cc91', value: 'Not equal bool pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x660d0a73395e6855aea8f6d3450e63640437dc15071842b417c39f40e1d7ae61', value: 'Not equal bool fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBoolFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '760:57:0', expected: true, returned: true },
{ type: 'testPass', debugTxHash: '0x6fddce5573bd6723acf5a3e4137d698ff78f695873a228939276c4323ddfb132', value: 'Not equal address pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
{ type: 'testFailure', debugTxHash: '0x51479e46db802fb598c61ca0dd630345b9d70cc58667b5a80aa79e8119fa7787', value: 'Not equal address fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualAddressFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1084:136:0', expected: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9, returned: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9 },
{ type: 'testPass', debugTxHash: '0xbcaf6d8977b655fdedb280e0e9221d728706d41e85e0973d00c8da1d128022c7', value: 'Not equal bytes32 pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x34008ef0ea908fedbf80471424d801f5069e6e46221f8ee4a2ee16776a6eeef6', value: 'Not equal bytes32 fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBytes32FailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1756:54:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6978000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x8e0bc9dedea6e088ca7bd82b1e9fab516be5a52f7716a26ccca8197236aae105', value: 'Not equal string pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x13c6d270c3609ef858dd6d0c79433ca0b43e47b485b2e40ffe363f18f2868ea8', value: 'Not equal string fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualStringFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '2026:81:0', expected: 'remix', returned: 'remix' },
], ['time', 'web3'])
})
})
describe('assert library LESSERTHAN method tests', function () {
const filename: string = __dirname + '/examples_0/assert_lesserThan_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 4 passing test', () => {
assert.equal(results.passingNum, 4)
})
it('should have 4 failing test', () => {
assert.equal(results.failureNum, 4)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertLesserThanTest', filename: __dirname + '/examples_0/assert_lesserThan_test.sol' },
{ type: 'testPass', debugTxHash: '0x524fb46aa0e8a78bc11a99432908d422450c2933d837f858aeacba9b84706d5c', value: 'Lesser than uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x0551a67b10b9e13182e8bdb4e530ed92466d5054ae959f999f2c558da2c39d22', value: 'Lesser than uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '298:67:0', expected: '2', returned: '4' },
{ type: 'testPass', debugTxHash: '0x6d63958d8c3230e837d0ca8335e57262c6e0c6b2c07a5b481842b9ad7329ac28', value: 'Lesser than int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x38e96ef44f4e785db4d40a95862a9797e8cef6de0ce1d059da72ff42e2f3ca62', value: 'Lesser than int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '557:65:0', expected: '-1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x699f9fc2bf7a14134e89b94cd9dc1c537b5d4581a1c26a34a0c3343ddede9608', value: 'Lesser than uint int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0xce1391dcfbfdc6c611e357e6c1c9f6cd9f257153ee400cb80bd36af6d239c342', value: 'Lesser than uint int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '826:71:0', expected: '-1', returned: '115792089237316195423570985008687907853269984665640564039457584007913129639935' },
{ type: 'testPass', debugTxHash: '0x7040e6664c13e6b35ef1daaef93a8cae36a62150d818183892096a98b921800c', value: 'Lesser than int uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x8c58bb433ea41760dcf11114232407d703e8ebf7d5e9637e2923282eae5caee6', value: 'Lesser than int uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '1105:69:0', expected: '1', returned: '1' },
], ['time', 'web3'])
})
describe('assert library GREATERTHAN method tests', function () {
const filename: string = __dirname + '/examples_0/assert_greaterThan_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 4 passing test', () => {
assert.equal(results.passingNum, 4)
})
it('should have 4 failing test', () => {
assert.equal(results.failureNum, 4)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertGreaterThanTest', filename: __dirname + '/examples_0/assert_greaterThan_test.sol' },
{ type: 'testPass', debugTxHash: '0xdc325916fd93227b76231131e52e67f8913d395098c5ac767032db9bd757a91c', value: 'Greater than uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xf98eea22bb86f13e0bb4072df22b540289a46b332bdb203a1e488d7e14a1dcd4', value: 'Greater than uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '303:69:0', expected: '4', returned: '1' },
{ type: 'testPass', debugTxHash: '0xef5ef38329ba6aac2f868d53d803053c52b1895a2c25b704260435c141a63bfc', value: 'Greater than int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x6b9430f3f12c12fb11e5a8d32fef849ab34614e644be20c6b41a25e510453440', value: 'Greater than int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '569:67:0', expected: '1', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x4c6e10815a5e82bf2c60950606dc886317f680028a9229ba2dda17b5ea36325a', value: 'Greater than uint int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x989c405c32c8e270a5dea69e6250a514c05dacd6fcf018365a241abc28c2497b', value: 'Greater than uint int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '845:71:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x9fed670ae2061929f71780835b7ea3eb7da6d4fb553cd2d5f62950c353165861', value: 'Greater than int uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xcf394fd279293cdcf58efc42f3a443595fdb171769a45df01b0c84cd76b3a9a2', value: 'Greater than int uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '1125:76:0', expected: '115792089237316195423570985008687907853269984665640564039457584007913129639836', returned: '100' }
], ['time', 'web3'])
})
})
describe('test with before', function () {
const filename: string = __dirname + '/examples_1/simple_storage_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 3 passing test', () => {
assert.equal(results.passingNum, 3)
})
it('should have 1 failing test', () => {
assert.equal(results.failureNum, 1)
})
it('should return 6 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_1/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x79cae5c4f44edfd7ae3490e01c75df5741b107672cef5e69800e4d30d380a721', value: 'Initial value should not be200', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testFailure', debugTxHash: '0x24a20f7643e88f891e469ef495911ab0b75f99e2b09b9b091e688674910d1506', value: 'Should trigger one fail', filename: __dirname + '/examples_1/simple_storage_test.sol', errMsg: 'uint test 1 fails', context: 'MyTest', assertMethod: 'equal', location: '532:51:1', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x08b1f60c908b7e6cf2dd24fc166c755f0fe5336aebfb325cae4ce00ea9bbf932', value: 'Should trigger one pass', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
describe('assert library LESSERTHAN method tests', function () {
const filename: string = __dirname + '/examples_0/assert_lesserThan_test.sol'
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 4 passing test', () => {
assert.equal(results.passingNum, 4)
})
it('should have 4 failing test', () => {
assert.equal(results.failureNum, 4)
})
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertLesserThanTest', filename: __dirname + '/examples_0/assert_lesserThan_test.sol' },
{ type: 'testPass', debugTxHash: '0x524fb46aa0e8a78bc11a99432908d422450c2933d837f858aeacba9b84706d5c', value: 'Lesser than uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x0551a67b10b9e13182e8bdb4e530ed92466d5054ae959f999f2c558da2c39d22', value: 'Lesser than uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '298:67:0', expected: '2', returned: '4' },
{ type: 'testPass', debugTxHash: '0x6d63958d8c3230e837d0ca8335e57262c6e0c6b2c07a5b481842b9ad7329ac28', value: 'Lesser than int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x38e96ef44f4e785db4d40a95862a9797e8cef6de0ce1d059da72ff42e2f3ca62', value: 'Lesser than int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '557:65:0', expected: '-1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x699f9fc2bf7a14134e89b94cd9dc1c537b5d4581a1c26a34a0c3343ddede9608', value: 'Lesser than uint int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0xce1391dcfbfdc6c611e357e6c1c9f6cd9f257153ee400cb80bd36af6d239c342', value: 'Lesser than uint int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '826:71:0', expected: '-1', returned: '115792089237316195423570985008687907853269984665640564039457584007913129639935' },
{ type: 'testPass', debugTxHash: '0x7040e6664c13e6b35ef1daaef93a8cae36a62150d818183892096a98b921800c', value: 'Lesser than int uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x8c58bb433ea41760dcf11114232407d703e8ebf7d5e9637e2923282eae5caee6', value: 'Lesser than int uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '1105:69:0', expected: '1', returned: '1' },
], ['time', 'web3'])
})
})
describe('test with before', function () {
const filename: string = __dirname + '/examples_1/simple_storage_test.sol'
describe('test with beforeEach', function () {
const filename: string = __dirname + '/examples_2/simple_storage_test.sol'
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 2 passing tests', () => {
assert.equal(results.passingNum, 2)
})
it('should 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_2/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x8ed5b4858405b43ad4052f5690b4b711c0f6cdeb67a64f54084417d43bc54308', value: 'Value is set200', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
before((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 3 passing test', () => {
assert.equal(results.passingNum, 3)
})
it('should have 1 failing test', () => {
assert.equal(results.failureNum, 1)
})
it('should return 6 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_1/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x79cae5c4f44edfd7ae3490e01c75df5741b107672cef5e69800e4d30d380a721', value: 'Initial value should not be200', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testFailure', debugTxHash: '0x24a20f7643e88f891e469ef495911ab0b75f99e2b09b9b091e688674910d1506', value: 'Should trigger one fail', filename: __dirname + '/examples_1/simple_storage_test.sol', errMsg: 'uint test 1 fails', context: 'MyTest', assertMethod: 'equal', location: '532:51:1', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x08b1f60c908b7e6cf2dd24fc166c755f0fe5336aebfb325cae4ce00ea9bbf932', value: 'Should trigger one pass', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
})
describe('test with beforeEach', function () {
const filename: string = __dirname + '/examples_2/simple_storage_test.sol'
// Test string equality
describe('test string equality', function () {
const filename: string = __dirname + '/examples_3/simple_string_test.sol'
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should 2 passing tests', () => {
assert.equal(results.passingNum, 2)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StringTest', filename: __dirname + '/examples_3/simple_string_test.sol' },
{ type: 'testPass', debugTxHash: '0x3567da76ffbec37e3b43a41987a7ff3e61b41b4c544f35c010d2d4b39568d6d4', value: 'Initial value should be hello world', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' },
{ type: 'testPass', debugTxHash: '0x8619b743ccc99be7d5347a064732474b2d1b69844be65b0e7754c6ac1340d275', value: 'Value should not be hello wordl', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' }
], ['time', 'web3'])
})
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should have 2 passing tests', () => {
assert.equal(results.passingNum, 2)
})
it('should 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_2/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x8ed5b4858405b43ad4052f5690b4b711c0f6cdeb67a64f54084417d43bc54308', value: 'Value is set200', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
})
// Test multiple directory import in test contract
describe('test multiple directory import in test contract', function () {
const filename: string = __dirname + '/examples_5/test/simple_storage_test.sol'
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should 3 passing tests', () => {
assert.equal(results.passingNum, 3)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StorageResolveTest', filename: __dirname + '/examples_5/test/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x6893fe4f5a83cc51f03c9237ab93b93ffd826236167d58e20666be4c1b3128a4', value: 'Check if even', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x64e600b32be681b68926660042ddd96f22d07949b424959811b8acb56e72f719', value: 'Check if odd', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }
], ['time', 'web3'])
})
// Test string equality
describe('test string equality', function () {
const filename: string = __dirname + '/examples_3/simple_string_test.sol'
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should 2 passing tests', () => {
assert.equal(results.passingNum, 2)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StringTest', filename: __dirname + '/examples_3/simple_string_test.sol' },
{ type: 'testPass', debugTxHash: '0x3567da76ffbec37e3b43a41987a7ff3e61b41b4c544f35c010d2d4b39568d6d4', value: 'Initial value should be hello world', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' },
{ type: 'testPass', debugTxHash: '0x8619b743ccc99be7d5347a064732474b2d1b69844be65b0e7754c6ac1340d275', value: 'Value should not be hello wordl', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' }
], ['time', 'web3'])
})
})
//Test SafeMath library methods
describe('test SafeMath library', function () {
const filename: string = __dirname + '/examples_4/SafeMath_test.sol'
// Test multiple directory import in test contract
describe('test multiple directory import in test contract', function () {
const filename: string = __dirname + '/examples_5/test/simple_storage_test.sol'
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should 3 passing tests', () => {
assert.equal(results.passingNum, 3)
})
it('should return 4 messages', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StorageResolveTest', filename: __dirname + '/examples_5/test/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x6893fe4f5a83cc51f03c9237ab93b93ffd826236167d58e20666be4c1b3128a4', value: 'Check if even', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x64e600b32be681b68926660042ddd96f22d07949b424959811b8acb56e72f719', value: 'Check if odd', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }
], ['time', 'web3'])
})
})
after(() => { tests = [] })
//Test SafeMath library methods
describe('test SafeMath library', function () {
const filename: string = __dirname + '/examples_4/SafeMath_test.sol'
it('should have 10 passing tests', () => {
assert.equal(results.passingNum, 10)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
//Test signed/unsigned integer weight
describe('test number weight', function () {
const filename: string = __dirname + '/number/number_test.sol'
after(() => { tests = [] })
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
it('should have 10 passing tests', () => {
assert.equal(results.passingNum, 10)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
})
after(() => { tests = [] })
//Test signed/unsigned integer weight
describe('test number weight', function () {
const filename: string = __dirname + '/number/number_test.sol'
it('should have 6 passing tests', () => {
assert.equal(results.passingNum, 6)
})
it('should have 2 failing tests', () => {
assert.equal(results.failureNum, 2)
})
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
// Test Transaction with custom sender & value
describe('various sender', function () {
const filename: string = __dirname + '/various_sender/sender_and_value_test.sol'
after(() => { tests = [] })
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
it('should have 6 passing tests', () => {
assert.equal(results.passingNum, 6)
})
it('should have 2 failing tests', () => {
assert.equal(results.failureNum, 2)
})
})
after(() => { tests = [] })
// Test Transaction with custom sender & value
describe('various sender', function () {
const filename: string = __dirname + '/various_sender/sender_and_value_test.sol'
it('should have 17 passing tests', () => {
assert.equal(results.passingNum, 17)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
// Test `runTest` method without sending contract object (should throw error)
describe('runTest method without contract json interface', function () {
const filename: string = __dirname + '/various_sender/sender_and_value_test.sol'
const errorCallback: any = (done) => {
return (err, _results) => {
if (err && err.message.includes('Contract interface not available')) {
results = _results
done()
}
else throw err
}
}
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, errorCallback(done))
})
})
it('should have 0 passing tests', () => {
assert.equal(results.passingNum, 0)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
})
after(() => { tests = [] })
it('should have 17 passing tests', () => {
assert.equal(results.passingNum, 17)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
})
// Test `runTest` method without sending contract object (should throw error)
describe('runTest method without contract json interface', function () {
const filename: string = __dirname + '/various_sender/sender_and_value_test.sol'
const errorCallback: any = (done) => {
return (err, _results) => {
if (err && err.message.includes('Contract interface not available')) {
results = _results
done()
}
else throw err
}
}
before(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, errorCallback(done))
})
})
it('should have 0 passing tests', () => {
assert.equal(results.passingNum, 0)
})
it('should have 0 failing tests', () => {
assert.equal(results.failureNum, 0)
})
})
})
})

@ -74,10 +74,10 @@ const ModalWrapper = (props: ModalWrapperProps) => {
const createForm = (validation: ValidationResult) => {
return (
<>
<form onChange={onFormChanged} ref={formRef}>
<form onChange={onFormChanged} ref={formRef}>
{props.message}
</form>
{validation && !validation.valid && <span className='text-warning'>{validation.message}</span>}
</form>
{validation && !validation.valid && <span className='text-warning'>{validation.message}</span>}
</>
)
}
@ -86,30 +86,30 @@ const ModalWrapper = (props: ModalWrapperProps) => {
data.current = props.data
if (props.modalType) {
switch (props.modalType) {
case ModalTypes.prompt:
case ModalTypes.password:
setState({
...props,
okFn: onFinishPrompt,
cancelFn: onCancelFn,
message: createModalMessage(props.defaultValue, { valid: true })
})
break
case ModalTypes.form:
setState({
...props,
okFn: onFinishPrompt,
cancelFn: onCancelFn,
message: createForm({ valid: true })
})
break
default:
setState({
...props,
okFn: onOkFn,
cancelFn: onCancelFn
})
break
case ModalTypes.prompt:
case ModalTypes.password:
setState({
...props,
okFn: onFinishPrompt,
cancelFn: onCancelFn,
message: createModalMessage(props.defaultValue, { valid: true })
})
break
case ModalTypes.form:
setState({
...props,
okFn: onFinishPrompt,
cancelFn: onCancelFn,
message: createForm({ valid: true })
})
break
default:
setState({
...props,
okFn: onOkFn,
cancelFn: onCancelFn
})
break
}
} else {
setState({

@ -4,80 +4,80 @@ import { AppModal, ModalState } from '../interface'
export const modalReducer = (state: ModalState = ModalInitialState, action: ModalAction) => {
switch (action.type) {
case modalActionTypes.setModal: {
const timestamp = Date.now()
const focusModal: AppModal = {
timestamp,
id: action.payload.id || timestamp.toString(),
hide: false,
title: action.payload.title,
validationFn: action.payload.validationFn,
message: action.payload.message,
okLabel: action.payload.okLabel,
okFn: action.payload.okFn,
cancelLabel: action.payload.cancelLabel,
cancelFn: action.payload.cancelFn,
modalType: action.payload.modalType,
defaultValue: action.payload.defaultValue,
hideFn: action.payload.hideFn,
resolve: action.payload.resolve,
next: action.payload.next,
data: action.payload.data
}
case modalActionTypes.setModal: {
const timestamp = Date.now()
const focusModal: AppModal = {
timestamp,
id: action.payload.id || timestamp.toString(),
hide: false,
title: action.payload.title,
validationFn: action.payload.validationFn,
message: action.payload.message,
okLabel: action.payload.okLabel,
okFn: action.payload.okFn,
cancelLabel: action.payload.cancelLabel,
cancelFn: action.payload.cancelFn,
modalType: action.payload.modalType,
defaultValue: action.payload.defaultValue,
hideFn: action.payload.hideFn,
resolve: action.payload.resolve,
next: action.payload.next,
data: action.payload.data
}
const modalList: AppModal[] = state.modals.slice()
modalList.push(focusModal)
const modalList: AppModal[] = state.modals.slice()
modalList.push(focusModal)
if (modalList.length === 1) {
return { ...state, modals: modalList, focusModal }
} else {
return { ...state, modals: modalList }
}
}
case modalActionTypes.handleHideModal: {
setTimeout(() => {
if (state.focusModal.hideFn) {
state.focusModal.hideFn()
}
if (state.focusModal.resolve) {
state.focusModal.resolve(undefined)
}
if (state.focusModal.next) {
state.focusModal.next()
}
}, 250)
const modalList: AppModal[] = state.modals.slice()
modalList.shift() // remove the current modal from the list
state.focusModal = { ...state.focusModal, hide: true, message: null }
if (modalList.length === 1) {
return { ...state, modals: modalList, focusModal }
} else {
return { ...state, modals: modalList }
}
case modalActionTypes.processQueue: {
const modalList: AppModal[] = state.modals.slice()
if (modalList.length) {
const focusModal = modalList[0] // extract the next modal from the list
return { ...state, modals: modalList, focusModal }
} else {
return { ...state, modals: modalList }
}
case modalActionTypes.handleHideModal: {
setTimeout(() => {
if (state.focusModal.hideFn) {
state.focusModal.hideFn()
}
}
case modalActionTypes.setToast: {
const toasterList = state.toasters.slice()
toasterList.push(action.payload)
if (toasterList.length === 1) {
return { ...state, toasters: toasterList, focusToaster: action.payload }
} else {
return { ...state, toasters: toasterList }
if (state.focusModal.resolve) {
state.focusModal.resolve(undefined)
}
}
case modalActionTypes.handleToaster: {
const toasterList = state.toasters.slice()
toasterList.shift()
if (toasterList.length) {
const toaster = toasterList[0]
return { ...state, toasters: toasterList, focusToaster: toaster }
} else {
return { ...state, toasters: [] }
if (state.focusModal.next) {
state.focusModal.next()
}
}, 250)
const modalList: AppModal[] = state.modals.slice()
modalList.shift() // remove the current modal from the list
state.focusModal = { ...state.focusModal, hide: true, message: null }
return { ...state, modals: modalList }
}
case modalActionTypes.processQueue: {
const modalList: AppModal[] = state.modals.slice()
if (modalList.length) {
const focusModal = modalList[0] // extract the next modal from the list
return { ...state, modals: modalList, focusModal }
} else {
return { ...state, modals: modalList }
}
}
case modalActionTypes.setToast: {
const toasterList = state.toasters.slice()
toasterList.push(action.payload)
if (toasterList.length === 1) {
return { ...state, toasters: toasterList, focusToaster: action.payload }
} else {
return { ...state, toasters: toasterList }
}
}
case modalActionTypes.handleToaster: {
const toasterList = state.toasters.slice()
toasterList.shift()
if (toasterList.length) {
const toaster = toasterList[0]
return { ...state, toasters: toasterList, focusToaster: toaster }
} else {
return { ...state, toasters: [] }
}
}
}
}

@ -43,10 +43,10 @@ export const RemixUiCheckbox = ({
const childJSXWithTooltip = (
<CustomTooltip
tooltipText={title}
tooltipId={`${name}Tooltip`}
placement={tooltipPlacement}
>
tooltipText={title}
tooltipId={`${name}Tooltip`}
placement={tooltipPlacement}
>
<div className={`listenOnNetwork_2A0YE0 custom-control custom-checkbox ${optionalClassName}`} style={{ display: display, alignItems: 'center', visibility: visibility } as CSSProperties } onClick={onClick}>
<input
id={id}
@ -67,20 +67,20 @@ export const RemixUiCheckbox = ({
)
const childJSX = (
<div className="listenOnNetwork_2A0YE0 custom-control custom-checkbox" style={{ display: display, alignItems: 'center', visibility: visibility } as CSSProperties } onClick={onClick}>
<input
id={id}
type={inputType}
onChange={onChange}
style={{ verticalAlign: 'bottom' }}
name={name}
className="custom-control-input"
checked={checked}
/>
<label className="form-check-label custom-control-label" id={`heading${categoryId}`} style={{ paddingTop: '0.15rem' }}>
{name ? <div className="font-weight-bold">{itemName}</div> : ''}
{label}
</label>
</div>
<input
id={id}
type={inputType}
onChange={onChange}
style={{ verticalAlign: 'bottom' }}
name={name}
className="custom-control-input"
checked={checked}
/>
<label className="form-check-label custom-control-label" id={`heading${categoryId}`} style={{ paddingTop: '0.15rem' }}>
{name ? <div className="font-weight-bold">{itemName}</div> : ''}
{label}
</label>
</div>
)
return (
title ? (childJSXWithTooltip) : (childJSX)

@ -52,8 +52,8 @@ export const CopyToClipboard = (props: ICopyToClipboard) => {
const childJSX = (
children || (<i className={`far ${icon} ml-1 p-2`} aria-hidden="true"
{...otherProps}
></i>)
{...otherProps}
></i>)
)
return (

@ -49,16 +49,16 @@ export const DebuggerApiMixin = (Base) => class extends Base {
await this.call('editor', 'highlight', lineColumnPos, path, '', { focus: true })
const label = `${stepDetail.op} costs ${stepDetail.gasCost} gas - this line costs ${lineGasCost} gas - ${stepDetail.gas} gas left`
const linetext: lineText = {
content: label,
position: lineColumnPos,
hide: false,
className: 'text-muted small',
afterContentClassName: 'text-muted small fas fa-gas-pump pl-4',
from: 'debugger',
hoverMessage: [{
value: label,
},
],
content: label,
position: lineColumnPos,
hide: false,
className: 'text-muted small',
afterContentClassName: 'text-muted small fas fa-gas-pump pl-4',
from: 'debugger',
hoverMessage: [{
value: label,
},
],
}
await this.call('editor', 'addLineText' as any, linetext, path)
}

@ -64,81 +64,81 @@ export const ButtonNavigation = ({ stepOverBack, stepIntoBack, stepIntoForward,
placement: 'top-start',
tagId: 'overbackTooltip',
tooltipMsg: 'Step over back'
},
},
stepBackJSX : {
markup: (
<div className={state.intoBackDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepIntoBack && stepIntoBack() }} data-id="buttonNavigatorIntoBack" id="buttonNavigatorIntoBackContainer">
<button id='intoback' data-id="buttonNavigatorIntoBack" className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepIntoBack && stepIntoBack() }} disabled={state.intoBackDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<div className={state.intoBackDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepIntoBack && stepIntoBack() }} data-id="buttonNavigatorIntoBack" id="buttonNavigatorIntoBackContainer">
<button id='intoback' data-id="buttonNavigatorIntoBack" className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepIntoBack && stepIntoBack() }} disabled={state.intoBackDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<span className="fas fa-level-up-alt"></span>
</button>
</div>
),
placement: 'top-start',
tagId: 'intobackTooltip',
tooltipMsg: 'Step back'
},
</button>
</div>
),
placement: 'top-start',
tagId: 'intobackTooltip',
tooltipMsg: 'Step back'
},
stepIntoJSX : {
markup: (
<div className={state.intoForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepIntoForward && stepIntoForward() }} data-id="buttonNavigatorIntoForward" id="buttonNavigatorIntoFowardContainer">
<button id='intoforward' data-id="buttonNavigatorIntoForward" className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepIntoForward && stepIntoForward() }} disabled={state.intoForwardDisabled}
style={{ pointerEvents: 'none', color: 'white' }}
>
<div className={state.intoForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepIntoForward && stepIntoForward() }} data-id="buttonNavigatorIntoForward" id="buttonNavigatorIntoFowardContainer">
<button id='intoforward' data-id="buttonNavigatorIntoForward" className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepIntoForward && stepIntoForward() }} disabled={state.intoForwardDisabled}
style={{ pointerEvents: 'none', color: 'white' }}
>
<span className="fas fa-level-down-alt"></span>
</button>
</div>
),
placement: 'top-start',
tagId: 'intoforwardTooltip',
tooltipMsg: 'Step into'
},
</button>
</div>
),
placement: 'top-start',
tagId: 'intoforwardTooltip',
tooltipMsg: 'Step into'
},
stepOverForwardJSX : {
markup: (
<div className={state.overForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepOverForward && stepOverForward() }} data-id="buttonNavigatorOverForward" id="buttonNavigatorOverForwardContainer">
<button id='overforward' className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepOverForward && stepOverForward() }} disabled={state.overForwardDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<div className={state.overForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { stepOverForward && stepOverForward() }} data-id="buttonNavigatorOverForward" id="buttonNavigatorOverForwardContainer">
<button id='overforward' className='btn btn-link btn-sm stepButton m-0 p-0' onClick={() => { stepOverForward && stepOverForward() }} disabled={state.overForwardDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<span className="fas fa-share"></span>
</button>
</div>
),
placement: 'top-end',
tagId: 'overbackTooltip',
tooltipMsg: 'Step over forward',
</button>
</div>
),
placement: 'top-end',
tagId: 'overbackTooltip',
tooltipMsg: 'Step over forward',
}
}
}
const jumpMarkupStructure = {
jumpPreviousBreakpointJSX : {
markup: (
<div className={state.jumpPreviousBreakpointDisabled ? `${stepBtnStyle} ${disableJumpBtnStyle}`: `${stepBtnStyle}`} id="buttonNavigatorJumpPreviousBreakpointContainer" onClick={() => { jumpPreviousBreakpoint && jumpPreviousBreakpoint() }} data-id="buttonNavigatorJumpPreviousBreakpoint">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumppreviousbreakpoint' data-id="buttonNavigatorJumpPreviousBreakpoint" onClick={() => { jumpPreviousBreakpoint && jumpPreviousBreakpoint() }} disabled={state.jumpPreviousBreakpointDisabled} style={{ pointerEvents: 'none', backgroundColor: 'inherit', color: 'white' }}>
<span className="fas fa-step-backward"></span>
</button>
</div>
),
placement: 'bottom-start',
tagId: 'jumppreviousbreakpointTooltip',
tooltipMsg: 'Jump to the previous breakpoint'
},
<div className={state.jumpPreviousBreakpointDisabled ? `${stepBtnStyle} ${disableJumpBtnStyle}`: `${stepBtnStyle}`} id="buttonNavigatorJumpPreviousBreakpointContainer" onClick={() => { jumpPreviousBreakpoint && jumpPreviousBreakpoint() }} data-id="buttonNavigatorJumpPreviousBreakpoint">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumppreviousbreakpoint' data-id="buttonNavigatorJumpPreviousBreakpoint" onClick={() => { jumpPreviousBreakpoint && jumpPreviousBreakpoint() }} disabled={state.jumpPreviousBreakpointDisabled} style={{ pointerEvents: 'none', backgroundColor: 'inherit', color: 'white' }}>
<span className="fas fa-step-backward"></span>
</button>
</div>
),
placement: 'bottom-start',
tagId: 'jumppreviousbreakpointTooltip',
tooltipMsg: 'Jump to the previous breakpoint'
},
jumpOutJSX : {
markup: (
<div className={state.jumpOutDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { jumpOut && jumpOut() }} data-id="buttonNavigatorJumpOut" id="buttonNavigatorJumpOutContainer">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumpout' onClick={() => { jumpOut && jumpOut() }} disabled={state.jumpOutDisabled} style={{ pointerEvents: 'none', backgroundColor: 'inherit', color: 'white' }} data-id="buttonNavigatorJumpOut">
<span className="fas fa-eject"></span>
</button>
</div>
),
placement: 'bottom-end',
tagId: 'jumpoutTooltip',
tooltipMsg: 'Jump out'
<div className={state.jumpOutDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { jumpOut && jumpOut() }} data-id="buttonNavigatorJumpOut" id="buttonNavigatorJumpOutContainer">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumpout' onClick={() => { jumpOut && jumpOut() }} disabled={state.jumpOutDisabled} style={{ pointerEvents: 'none', backgroundColor: 'inherit', color: 'white' }} data-id="buttonNavigatorJumpOut">
<span className="fas fa-eject"></span>
</button>
</div>
),
placement: 'bottom-end',
tagId: 'jumpoutTooltip',
tooltipMsg: 'Jump out'
},
jumpNextBreakpointJSX : {
markup: (
<div className={state.jumpNextBreakpointDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { jumpNextBreakpoint && jumpNextBreakpoint() }} data-id="buttonNavigatorJumpNextBreakpoint" id="buttonNavigatorJumpNextBreakpointContainer">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumpnextbreakpoint' data-id="buttonNavigatorJumpNextBreakpoint" onClick={() => { jumpNextBreakpoint && jumpNextBreakpoint() }} disabled={state.jumpNextBreakpointDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<span className="fas fa-step-forward"></span>
</button>
</div>
),
placement: 'bottom-end',
<div className={state.jumpNextBreakpointDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}`: `${stepBtnStyle}`} onClick={() => { jumpNextBreakpoint && jumpNextBreakpoint() }} data-id="buttonNavigatorJumpNextBreakpoint" id="buttonNavigatorJumpNextBreakpointContainer">
<button className='btn btn-link btn-sm jumpButton m-0 p-0' id='jumpnextbreakpoint' data-id="buttonNavigatorJumpNextBreakpoint" onClick={() => { jumpNextBreakpoint && jumpNextBreakpoint() }} disabled={state.jumpNextBreakpointDisabled} style={{ pointerEvents: 'none', color: 'white' }}>
<span className="fas fa-step-forward"></span>
</button>
</div>
),
placement: 'bottom-end',
tagId: 'jumpnextbreakpointTooltip',
tooltipMsg: 'Jump to the next breakpoint'
}
@ -162,18 +162,18 @@ export const ButtonNavigation = ({ stepOverBack, stepIntoBack, stepIntoForward,
</div>
<div className="jumpButtons btn-group py-1">
{
Object.keys(jumpMarkupStructure).map(x => (
<CustomTooltip
placement={jumpMarkupStructure[x].placement}
tooltipText={jumpMarkupStructure[x].tooltipMsg}
tooltipId={jumpMarkupStructure[x].tooltipId}
key={`${jumpMarkupStructure[x].placement}-${jumpMarkupStructure[x].tooltipMsg}-${jumpMarkupStructure[x].tagId}`}
>
{jumpMarkupStructure[x].markup}
{
Object.keys(jumpMarkupStructure).map(x => (
<CustomTooltip
placement={jumpMarkupStructure[x].placement}
tooltipText={jumpMarkupStructure[x].tooltipMsg}
tooltipId={jumpMarkupStructure[x].tooltipId}
key={`${jumpMarkupStructure[x].placement}-${jumpMarkupStructure[x].tooltipMsg}-${jumpMarkupStructure[x].tagId}`}
>
{jumpMarkupStructure[x].markup}
</CustomTooltip>
))
}
))
}
</div>
<div id='reverted' style={{ display: revertedReason === '' ? 'none' : 'block' }}>
<span className='text-warning'>This call has reverted, state changes made during the call will be reverted.</span>

@ -379,7 +379,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
data-id="debugGeneratedSourcesLabel"
className="form-check-label custom-control-label"
htmlFor="debugGeneratedSourcesInput">
<FormattedMessage id='debugger.useGeneratedSources' />(Solidity {'>='} v0.7.2)
<FormattedMessage id='debugger.useGeneratedSources' />(Solidity {'>='} v0.7.2)
</label>
</span>
)

@ -52,17 +52,17 @@ export const TxBrowser = ({ requestDebug, updateTxNumberFlag, unloadRequested, t
}
const customJSX = (
<div id="debuggerTransactionStartButtonContainer" data-id="debuggerTransactionStartButton" onClick={handleSubmit} className="btn btn-primary btn-sm btn-block text-decoration-none">
<button
className='btn btn-link btn-sm btn-block h-75 p-0 m-0 text-decoration-none'
id='load'
onClick={handleSubmit}
data-id='debuggerTransactionStartButton'
disabled={!state.txNumber }
style={{ pointerEvents: 'none', color: 'white' }}
>
<span><FormattedMessage id={`debugger.${debugging ? 'stopDebugging' : 'startDebugging'}`} /></span>
</button>
</div>
<button
className='btn btn-link btn-sm btn-block h-75 p-0 m-0 text-decoration-none'
id='load'
onClick={handleSubmit}
data-id='debuggerTransactionStartButton'
disabled={!state.txNumber }
style={{ pointerEvents: 'none', color: 'white' }}
>
<span><FormattedMessage id={`debugger.${debugging ? 'stopDebugging' : 'startDebugging'}`} /></span>
</button>
</div>
)
return (
<div className='pb-2 container px-0'>

@ -44,54 +44,54 @@ const reducedOpcode = (opCodes, payload) => {
export const reducer = (state = initialState, action: Action) => {
switch (action.type) {
case 'FETCH_OPCODES_REQUEST': {
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'FETCH_OPCODES_REQUEST': {
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'FETCH_OPCODES_SUCCESS': {
const opCodes = action.payload.address === state.opCodes.address ? {
...state.opCodes, index: action.payload.index, nextIndexes: action.payload.nextIndexes, absoluteCurrentLineIndexes: state.absoluteCurrentLineIndexes
} : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload
}
case 'FETCH_OPCODES_SUCCESS': {
const opCodes = action.payload.address === state.opCodes.address ? {
...state.opCodes, index: action.payload.index, nextIndexes: action.payload.nextIndexes, absoluteCurrentLineIndexes: state.absoluteCurrentLineIndexes
} : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload
const reduced = reducedOpcode(opCodes, action.payload)
return {
...state,
opCodes,
display: reduced.display,
initialIndex: action.payload.index,
index: reduced.index,
nextIndexes: reduced.nextIndexes,
isRequesting: false,
isSuccessful: true,
hasError: null,
returnInstructionIndexes: reduced.returnInstructionIndexes,
outOfGasInstructionIndexes: reduced.outOfGasInstructionIndexes,
currentLineIndexes: reduced.currentLineIndexes
}
const reduced = reducedOpcode(opCodes, action.payload)
return {
...state,
opCodes,
display: reduced.display,
initialIndex: action.payload.index,
index: reduced.index,
nextIndexes: reduced.nextIndexes,
isRequesting: false,
isSuccessful: true,
hasError: null,
returnInstructionIndexes: reduced.returnInstructionIndexes,
outOfGasInstructionIndexes: reduced.outOfGasInstructionIndexes,
currentLineIndexes: reduced.currentLineIndexes
}
case 'FETCH_OPCODES_ERROR': {
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
}
case 'FETCH_OPCODES_ERROR': {
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
case 'FETCH_INDEXES_FOR_NEW_LINE': {
let bottom = state.initialIndex - 10
bottom = bottom < 0 ? 0 : bottom
return {
...state,
absoluteCurrentLineIndexes: action.payload.currentLineIndexes,
currentLineIndexes: action.payload.currentLineIndexes.map(index => index - bottom),
line: action.payload.line
}
}
case 'FETCH_INDEXES_FOR_NEW_LINE': {
let bottom = state.initialIndex - 10
bottom = bottom < 0 ? 0 : bottom
return {
...state,
absoluteCurrentLineIndexes: action.payload.currentLineIndexes,
currentLineIndexes: action.payload.currentLineIndexes.map(index => index - bottom),
line: action.payload.line
}
default:
throw new Error()
}
default:
throw new Error()
}
}

@ -12,50 +12,50 @@ export const initialState = {
export const reducer = (state = initialState, action: Action) => {
switch (action.type) {
case 'FETCH_CALLDATA_REQUEST':
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'FETCH_CALLDATA_SUCCESS':
return {
calldata: action.payload,
isRequesting: false,
isSuccessful: true,
hasError: null
}
case 'FETCH_CALLDATA_ERROR':
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
case 'UPDATE_CALLDATA_REQUEST':
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'UPDATE_CALLDATA_SUCCESS':
return {
calldata: mergeLocals(action.payload, state.calldata),
isRequesting: false,
isSuccessful: true,
hasError: null
}
case 'UPDATE_CALLDATA_ERROR':
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
default:
throw new Error()
case 'FETCH_CALLDATA_REQUEST':
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'FETCH_CALLDATA_SUCCESS':
return {
calldata: action.payload,
isRequesting: false,
isSuccessful: true,
hasError: null
}
case 'FETCH_CALLDATA_ERROR':
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
case 'UPDATE_CALLDATA_REQUEST':
return {
...state,
isRequesting: true,
isSuccessful: false,
hasError: null
}
case 'UPDATE_CALLDATA_SUCCESS':
return {
calldata: mergeLocals(action.payload, state.calldata),
isRequesting: false,
isSuccessful: true,
hasError: null
}
case 'UPDATE_CALLDATA_ERROR':
return {
...state,
isRequesting: false,
isSuccessful: false,
hasError: action.payload
}
default:
throw new Error()
}
}

@ -68,25 +68,25 @@ export const Draggable = (props: DraggableType) => {
<>
{
props.isDraggable ? props.children :
<span
ref={dragRef}
draggable
onDrop={(event) => {
handleDrop(event)
}}
onDragStart={() => {
if (destination) {
handleDrag()
}
}}
onDragOver={(event) => {
if (destination) {
handleDragover(event)
}
}}
>
{props.children}
</span>
<span
ref={dragRef}
draggable
onDrop={(event) => {
handleDrop(event)
}}
onDragStart={() => {
if (destination) {
handleDrag()
}
}}
onDragOver={(event) => {
if (destination) {
handleDragover(event)
}
}}
>
{props.children}
</span>
}
</>
)

@ -13,87 +13,87 @@ export const reducerActions = (models = initialState, action: Action) => {
const monaco = action.monaco
const editor = action.editor
switch (action.type) {
case 'ADD_MODEL': {
if (!editor) return models
const uri = action.payload.uri
const value = action.payload.value
const language = action.payload.language
const readOnly = action.payload.readOnly
if (models[uri]) return models // already existing
models[uri] = { language, uri, readOnly }
let model
try {
model = monaco.editor.createModel(value, language, monaco.Uri.parse(uri))
} catch (e) {
case 'ADD_MODEL': {
if (!editor) return models
const uri = action.payload.uri
const value = action.payload.value
const language = action.payload.language
const readOnly = action.payload.readOnly
if (models[uri]) return models // already existing
models[uri] = { language, uri, readOnly }
let model
try {
model = monaco.editor.createModel(value, language, monaco.Uri.parse(uri))
} catch (e) {
}
models[uri].model = model
model.onDidChangeContent(() => action.payload.events.onDidChangeContent(uri))
return models
}
case 'DISPOSE_MODEL': {
const uri = action.payload.uri
const model = models[uri]?.model
if (model) model.dispose()
delete models[uri]
return models
}
case 'SET_VALUE': {
if (!editor) return models
const uri = action.payload.uri
const value = action.payload.value
const model = models[uri]?.model
if (model) {
model.setValue(value)
}
return models
}
case 'REVEAL_LINE': {
if (!editor) return models
const line = action.payload.line
const column = action.payload.column
editor.revealLine(line)
editor.setPosition({ column, lineNumber: line })
return models
}
case 'REVEAL_RANGE': {
if (!editor) return models
const range: monacoTypes.IRange = {
startLineNumber: action.payload.startLineNumber + 1,
startColumn: action.payload.startColumn,
endLineNumber: action.payload.endLineNumber + 1,
endColumn: action.payload.endColumn
}
// reset to start of line
if (action.payload.startColumn < 100) {
editor.revealRange({
startLineNumber: range.startLineNumber,
startColumn: 1,
endLineNumber: range.endLineNumber,
endColumn: 1
})
} else {
editor.revealRangeInCenter(range)
}
return models
}
case 'FOCUS': {
if (!editor) return models
editor.focus()
return models
models[uri].model = model
model.onDidChangeContent(() => action.payload.events.onDidChangeContent(uri))
return models
}
case 'DISPOSE_MODEL': {
const uri = action.payload.uri
const model = models[uri]?.model
if (model) model.dispose()
delete models[uri]
return models
}
case 'SET_VALUE': {
if (!editor) return models
const uri = action.payload.uri
const value = action.payload.value
const model = models[uri]?.model
if (model) {
model.setValue(value)
}
case 'SET_FONTSIZE': {
if (!editor) return models
const size = action.payload.size
editor.updateOptions({ fontSize: size })
return models
return models
}
case 'REVEAL_LINE': {
if (!editor) return models
const line = action.payload.line
const column = action.payload.column
editor.revealLine(line)
editor.setPosition({ column, lineNumber: line })
return models
}
case 'REVEAL_RANGE': {
if (!editor) return models
const range: monacoTypes.IRange = {
startLineNumber: action.payload.startLineNumber + 1,
startColumn: action.payload.startColumn,
endLineNumber: action.payload.endLineNumber + 1,
endColumn: action.payload.endColumn
}
case 'SET_WORDWRAP': {
if (!editor) return models
const wrap = action.payload.wrap
editor.updateOptions({ wordWrap: wrap ? 'on' : 'off' })
return models
// reset to start of line
if (action.payload.startColumn < 100) {
editor.revealRange({
startLineNumber: range.startLineNumber,
startColumn: 1,
endLineNumber: range.endLineNumber,
endColumn: 1
})
} else {
editor.revealRangeInCenter(range)
}
return models
}
case 'FOCUS': {
if (!editor) return models
editor.focus()
return models
}
case 'SET_FONTSIZE': {
if (!editor) return models
const size = action.payload.size
editor.updateOptions({ fontSize: size })
return models
}
case 'SET_WORDWRAP': {
if (!editor) return models
const wrap = action.payload.wrap
editor.updateOptions({ wordWrap: wrap ? 'on' : 'off' })
return models
}
}
}

@ -1,15 +1,15 @@
import { EditorAPIType, PluginType } from "../remix-ui-editor"
export const retrieveNodesAtPosition = async (editorAPI: EditorAPIType, plugin: PluginType) => {
const cursorPosition = editorAPI.getCursorPosition()
let nodesAtPosition = await plugin.call('codeParser', 'nodesAtPosition', cursorPosition)
// if no nodes exits at position, try to get the block of which the position is in
const block = await plugin.call('codeParser', 'getANTLRBlockAtPosition', cursorPosition, null)
const cursorPosition = editorAPI.getCursorPosition()
let nodesAtPosition = await plugin.call('codeParser', 'nodesAtPosition', cursorPosition)
// if no nodes exits at position, try to get the block of which the position is in
const block = await plugin.call('codeParser', 'getANTLRBlockAtPosition', cursorPosition, null)
if (!nodesAtPosition.length) {
if (block) {
nodesAtPosition = await plugin.call('codeParser', 'nodesAtPosition', block.start)
}
if (!nodesAtPosition.length) {
if (block) {
nodesAtPosition = await plugin.call('codeParser', 'nodesAtPosition', block.start)
}
return { nodesAtPosition, block }
}
return { nodesAtPosition, block }
}

@ -4,45 +4,45 @@ import { EditorUIProps } from "../remix-ui-editor"
import { default as fixes } from "./quickfixes"
export class RemixCodeActionProvider implements monaco.languages.CodeActionProvider {
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
async provideCodeActions (
model /**ITextModel*/,
range /**Range*/,
context /**CodeActionContext*/,
token /**CancellationToken*/
) {
async provideCodeActions (
model /**ITextModel*/,
range /**Range*/,
context /**CodeActionContext*/,
token /**CancellationToken*/
) {
const actions = context.markers.map(error => {
const errStrings = Object.keys(fixes)
const errStr = errStrings.find(es => error.message.includes(es))
const fix = fixes[errStr]
return {
title: fix.title,
diagnostics: [error],
kind: "quickfix",
edit: {
edits: [
{
resource: model.uri,
edit: {
range: fix.range || error,
text: fix.message
}
}
]
},
isPreferred: true
const actions = context.markers.map(error => {
const errStrings = Object.keys(fixes)
const errStr = errStrings.find(es => error.message.includes(es))
const fix = fixes[errStr]
return {
title: fix.title,
diagnostics: [error],
kind: "quickfix",
edit: {
edits: [
{
resource: model.uri,
edit: {
range: fix.range || error,
text: fix.message
}
}
})
return {
actions: actions,
dispose: () => {}
}
]
},
isPreferred: true
}
})
return {
actions: actions,
dispose: () => {}
}
}
}

@ -6,431 +6,431 @@ import { monacoTypes } from '@remix-ui/editor';
import { retrieveNodesAtPosition } from "../helpers/retrieveNodesAtPosition";
export class RemixCompletionProvider implements monacoTypes.languages.CompletionItemProvider {
props: EditorUIProps
monaco: any
maximumItemsForContractCompletion = 100
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
triggerCharacters = ['.', '', '"', '@', '/']
async provideCompletionItems(model: monacoTypes.editor.ITextModel, position: monacoTypes.Position, context: monacoTypes.languages.CompletionContext): Promise<monacoTypes.languages.CompletionList | undefined> {
const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion')
if (!completionSettings) return
const word = model.getWordUntilPosition(position);
const range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn,
endColumn: word.endColumn
};
const line = model.getLineContent(position.lineNumber)
let nodes: AstNode[] = []
let suggestions: monacoTypes.languages.CompletionItem[] = []
if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') {
const lastpart = line.substring(0, position.column - 1).split(';').pop()
if (lastpart.startsWith('import')) {
const imports = await this.props.plugin.call('codeParser', 'getImports')
if (context.triggerCharacter === '"' || context.triggerCharacter === '@') {
suggestions = [...suggestions,
...GetImports(range, this.monaco, imports, context.triggerCharacter),
]
} else if (context.triggerCharacter === '/') {
const word = line.split('"')[1]
suggestions = [...suggestions,
...GetImports(range, this.monaco, imports, word),
]
} else {
return
}
}
} else if (context.triggerCharacter === '.') {
const lineTextBeforeCursor: string = line.substring(0, position.column - 1)
const lastNodeInExpression = await this.getLastNodeInExpression(lineTextBeforeCursor)
const expressionElements = lineTextBeforeCursor.split('.')
props: EditorUIProps
monaco: any
maximumItemsForContractCompletion = 100
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
triggerCharacters = ['.', '', '"', '@', '/']
async provideCompletionItems(model: monacoTypes.editor.ITextModel, position: monacoTypes.Position, context: monacoTypes.languages.CompletionContext): Promise<monacoTypes.languages.CompletionList | undefined> {
const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion')
if (!completionSettings) return
const word = model.getWordUntilPosition(position);
const range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn,
endColumn: word.endColumn
};
const line = model.getLineContent(position.lineNumber)
let nodes: AstNode[] = []
let suggestions: monacoTypes.languages.CompletionItem[] = []
if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') {
const lastpart = line.substring(0, position.column - 1).split(';').pop()
if (lastpart.startsWith('import')) {
const imports = await this.props.plugin.call('codeParser', 'getImports')
if (context.triggerCharacter === '"' || context.triggerCharacter === '@') {
suggestions = [...suggestions,
...GetImports(range, this.monaco, imports, context.triggerCharacter),
]
} else if (context.triggerCharacter === '/') {
const word = line.split('"')[1]
suggestions = [...suggestions,
...GetImports(range, this.monaco, imports, word),
]
} else {
return
}
}
} else if (context.triggerCharacter === '.') {
const lineTextBeforeCursor: string = line.substring(0, position.column - 1)
const lastNodeInExpression = await this.getLastNodeInExpression(lineTextBeforeCursor)
const expressionElements = lineTextBeforeCursor.split('.')
let dotCompleted = false
// handles completion from for builtin types
if (lastNodeInExpression.memberName === 'sender') { // exception for this member
lastNodeInExpression.name = 'sender'
}
const globalCompletion = getContextualAutoCompleteByGlobalVariable(lastNodeInExpression.name, range, this.monaco)
if (globalCompletion) {
dotCompleted = true
suggestions = [...suggestions, ...globalCompletion]
}
// handle completion for global THIS.
if (lastNodeInExpression.name === 'this') {
dotCompleted = true
nodes = [...nodes, ...await this.getThisCompletions()]
}
// handle completion for other dot completions
if (expressionElements.length > 1 && !dotCompleted) {
const nameOfLastTypedExpression = lastNodeInExpression.name || lastNodeInExpression.memberName
const dotCompletions = await this.getDotCompletions(nameOfLastTypedExpression, range)
nodes = [...nodes, ...dotCompletions.nodes]
suggestions = [...suggestions, ...dotCompletions.suggestions]
}
} else {
// handles contract completions and other suggestions
suggestions = [...suggestions,
...GetGlobalVariable(range, this.monaco),
...getCompletionSnippets(range, this.monaco),
...GetCompletionTypes(range, this.monaco),
...GetCompletionKeywords(range, this.monaco),
...GetGlobalFunctions(range, this.monaco),
...GeCompletionUnits(range, this.monaco),
]
let contractCompletions = await this.getContractCompletions()
// we can't have external nodes without using this.
contractCompletions = contractCompletions.filter(node => {
if (node.visibility && node.visibility === 'external') {
return false
}
return true
})
let dotCompleted = false
nodes = [...nodes, ...contractCompletions]
// handles completion from for builtin types
if (lastNodeInExpression.memberName === 'sender') { // exception for this member
lastNodeInExpression.name = 'sender'
}
const globalCompletion = getContextualAutoCompleteByGlobalVariable(lastNodeInExpression.name, range, this.monaco)
if (globalCompletion) {
dotCompleted = true
suggestions = [...suggestions, ...globalCompletion]
}
// handle completion for global THIS.
if (lastNodeInExpression.name === 'this') {
dotCompleted = true
nodes = [...nodes, ...await this.getThisCompletions()]
}
// handle completion for other dot completions
if (expressionElements.length > 1 && !dotCompleted) {
}
const nameOfLastTypedExpression = lastNodeInExpression.name || lastNodeInExpression.memberName
const dotCompletions = await this.getDotCompletions(nameOfLastTypedExpression, range)
nodes = [...nodes, ...dotCompletions.nodes]
suggestions = [...suggestions, ...dotCompletions.suggestions]
}
} else {
// remove duplicates
const nodeIds = {};
let filteredNodes = nodes.filter((node) => {
if (node.id) {
if (nodeIds[node.id]) {
return false;
}
nodeIds[node.id] = true;
}
return true;
});
// truncate for performance
if (filteredNodes.length > this.maximumItemsForContractCompletion) {
// await this.props.plugin.call('notification', 'toast', `Too many completion items. Only ${this.maximumItemsForContractCompletion} items will be shown.`)
filteredNodes = filteredNodes.slice(0, this.maximumItemsForContractCompletion)
}
// handles contract completions and other suggestions
suggestions = [...suggestions,
...GetGlobalVariable(range, this.monaco),
...getCompletionSnippets(range, this.monaco),
...GetCompletionTypes(range, this.monaco),
...GetCompletionKeywords(range, this.monaco),
...GetGlobalFunctions(range, this.monaco),
...GeCompletionUnits(range, this.monaco),
]
const getNodeLink = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getNodeLink', node)
}
let contractCompletions = await this.getContractCompletions()
const getDocs = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getNodeDocumentation', node)
}
// we can't have external nodes without using this.
contractCompletions = contractCompletions.filter(node => {
if (node.visibility && node.visibility === 'external') {
return false
}
return true
})
const getParamaters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionParamaters', node)
}
nodes = [...nodes, ...contractCompletions]
const completeParameters = async (parameters: any) => {
const localParam = (parameters && parameters.parameters) || (parameters)
if (localParam) {
const params = []
for (const key in localParam) {
params.push('${' + (key + 1) + ':' + localParam[key].name + '}')
}
return `(${params.join(', ')})`
}
}
const getVariableDeclaration = async (node: any) => {
let variableDeclaration = await this.props.plugin.call('codeParser', 'getVariableDeclaration', node)
if (node.scope) {
const scopeNode = await this.props.plugin.call('codeParser', 'getNodeById', node.scope)
if (scopeNode) {
variableDeclaration = `${scopeNode.name}.${variableDeclaration}`
}
}
return variableDeclaration
}
// remove duplicates
const nodeIds = {};
let filteredNodes = nodes.filter((node) => {
if (node.id) {
if (nodeIds[node.id]) {
return false;
}
nodeIds[node.id] = true;
}
return true;
});
// truncate for performance
if (filteredNodes.length > this.maximumItemsForContractCompletion) {
// await this.props.plugin.call('notification', 'toast', `Too many completion items. Only ${this.maximumItemsForContractCompletion} items will be shown.`)
filteredNodes = filteredNodes.slice(0, this.maximumItemsForContractCompletion)
for (const node of Object.values(filteredNodes) as any[]) {
if (!node.name) continue
if (node.nodeType === 'VariableDeclaration') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${await getVariableDeclaration(node)}` },
kind: this.monaco.languages.CompletionItemKind.Variable,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
const getNodeLink = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getNodeLink', node)
suggestions.push(completion)
} else if (node.nodeType === 'FunctionDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` -> ${node.name} ${await getParamaters(node)}` },
kind: this.monaco.languages.CompletionItemKind.Function,
insertText: `${node.name}${await completeParameters(node.parameters)};`,
insertTextRules: this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range: range,
documentation: await getDocs(node)
}
const getDocs = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getNodeDocumentation', node)
suggestions.push(completion)
} else if
(node.nodeType === 'ContractDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Interface,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
const getParamaters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionParamaters', node)
suggestions.push(completion)
} else if
(node.nodeType === 'StructDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Struct,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
const completeParameters = async (parameters: any) => {
const localParam = (parameters && parameters.parameters) || (parameters)
if (localParam) {
const params = []
for (const key in localParam) {
params.push('${' + (key + 1) + ':' + localParam[key].name + '}')
}
return `(${params.join(', ')})`
}
suggestions.push(completion)
} else if
(node.nodeType === 'EnumDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Enum,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
const getVariableDeclaration = async (node: any) => {
let variableDeclaration = await this.props.plugin.call('codeParser', 'getVariableDeclaration', node)
if (node.scope) {
const scopeNode = await this.props.plugin.call('codeParser', 'getNodeById', node.scope)
if (scopeNode) {
variableDeclaration = `${scopeNode.name}.${variableDeclaration}`
}
}
return variableDeclaration
suggestions.push(completion)
} else if
(node.nodeType === 'EventDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` -> ${node.name} ${await getParamaters(node)}` },
kind: this.monaco.languages.CompletionItemKind.Event,
insertText: `${node.name}${await completeParameters(node.parameters)};`,
insertTextRules: this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range: range,
documentation: await getDocs(node)
}
for (const node of Object.values(filteredNodes) as any[]) {
if (!node.name) continue
if (node.nodeType === 'VariableDeclaration') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${await getVariableDeclaration(node)}` },
kind: this.monaco.languages.CompletionItemKind.Variable,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if (node.nodeType === 'FunctionDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` -> ${node.name} ${await getParamaters(node)}` },
kind: this.monaco.languages.CompletionItemKind.Function,
insertText: `${node.name}${await completeParameters(node.parameters)};`,
insertTextRules: this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'ContractDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Interface,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'StructDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Struct,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'EnumDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Enum,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'EventDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` -> ${node.name} ${await getParamaters(node)}` },
kind: this.monaco.languages.CompletionItemKind.Event,
insertText: `${node.name}${await completeParameters(node.parameters)};`,
insertTextRules: this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'ModifierDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Method,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
suggestions.push(completion)
} else if
(node.nodeType === 'EnumValue' || node.type === 'EnumValue') {
const completion = {
label: { label: `"${node.name}"` },
kind: this.monaco.languages.CompletionItemKind.EnumMember,
insertText: node.name,
range: range,
documentation: null
}
suggestions.push(completion)
}
suggestions.push(completion)
} else if
(node.nodeType === 'ModifierDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getNodeLink(node), detail: ` ${node.name}` },
kind: this.monaco.languages.CompletionItemKind.Method,
insertText: node.name,
range: range,
documentation: await getDocs(node)
}
return {
suggestions
suggestions.push(completion)
} else if
(node.nodeType === 'EnumValue' || node.type === 'EnumValue') {
const completion = {
label: { label: `"${node.name}"` },
kind: this.monaco.languages.CompletionItemKind.EnumMember,
insertText: node.name,
range: range,
documentation: null
}
suggestions.push(completion)
}
}
private getContractCompletions = async () => {
let nodes: any[] = []
const { nodesAtPosition, block } = await retrieveNodesAtPosition(this.props.editorAPI, this.props.plugin)
const fileNodes = await this.props.plugin.call('codeParser', 'getCurrentFileNodes')
// find the contract and get the nodes of the contract and the base contracts and imports
if (isArray(nodesAtPosition) && nodesAtPosition.length) {
let contractNode: any = {}
for (const node of nodesAtPosition) {
if (node.nodeType === 'ContractDefinition') {
contractNode = node
const contractNodes = fileNodes.contracts[node.name]
nodes = [...Object.values(contractNodes.contractScopeNodes), ...nodes]
nodes = [...Object.values(contractNodes.baseNodesWithBaseContractScope), ...nodes]
nodes = [...Object.values(fileNodes.imports), ...nodes]
// add the nodes at the block itself
if (block && block.name) {
const contractNodes = fileNodes.contracts[node.name].contractNodes
for (const contractNode of Object.values(contractNodes)) {
if (contractNode['name'] === block.name
return {
suggestions
}
}
private getContractCompletions = async () => {
let nodes: any[] = []
const { nodesAtPosition, block } = await retrieveNodesAtPosition(this.props.editorAPI, this.props.plugin)
const fileNodes = await this.props.plugin.call('codeParser', 'getCurrentFileNodes')
// find the contract and get the nodes of the contract and the base contracts and imports
if (isArray(nodesAtPosition) && nodesAtPosition.length) {
let contractNode: any = {}
for (const node of nodesAtPosition) {
if (node.nodeType === 'ContractDefinition') {
contractNode = node
const contractNodes = fileNodes.contracts[node.name]
nodes = [...Object.values(contractNodes.contractScopeNodes), ...nodes]
nodes = [...Object.values(contractNodes.baseNodesWithBaseContractScope), ...nodes]
nodes = [...Object.values(fileNodes.imports), ...nodes]
// add the nodes at the block itself
if (block && block.name) {
const contractNodes = fileNodes.contracts[node.name].contractNodes
for (const contractNode of Object.values(contractNodes)) {
if (contractNode['name'] === block.name
|| (contractNode['kind'] === 'constructor' && block.name === 'constructor')
) {
let nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode as any).id)
nodes = [...nodes, ...nodeOfScope]
if (contractNode['body']) {
nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode['body'] as any).id)
nodes = [...nodes, ...nodeOfScope]
}
}
}
} else { // we use the block info from the nodesAtPosition
const contractNodes = fileNodes.contracts[node.name].contractNodes
for (const contractNode of Object.values(contractNodes)) {
if((contractNode as any).nodeType === 'Block'){
const nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode as any).id)
nodes = [...nodes, ...nodeOfScope]
}
}
}
// filter private nodes, only allow them when contract ID is the same as the current contract
nodes = nodes.filter(node => {
if (node.visibility) {
if (node.visibility === 'private') {
return (node.contractId ? node.contractId === contractNode.id : false) || false
}
}
return true
})
break;
) {
let nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode as any).id)
nodes = [...nodes, ...nodeOfScope]
if (contractNode['body']) {
nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode['body'] as any).id)
nodes = [...nodes, ...nodeOfScope]
}
}
}
} else {
// get all the nodes from a simple code parser which only parses the current file
const allNodesFromAntlr = await this.props.plugin.call('codeParser', 'listAstNodes')
if (allNodesFromAntlr) {
nodes = [...nodes, ...allNodesFromAntlr]
} else { // we use the block info from the nodesAtPosition
const contractNodes = fileNodes.contracts[node.name].contractNodes
for (const contractNode of Object.values(contractNodes)) {
if((contractNode as any).nodeType === 'Block'){
const nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode as any).id)
nodes = [...nodes, ...nodeOfScope]
}
}
}
return nodes
}
private getThisCompletions = async () => {
let nodes: any[] = []
let thisCompletionNodes = await this.getContractCompletions()
const allowedTypesForThisCompletion = ['VariableDeclaration', 'FunctionDefinition']
// with this. you can't have internal nodes and no contractDefinitions
thisCompletionNodes = thisCompletionNodes.filter(node => {
if (node.visibility && (node.visibility === 'internal' || node.visibility === 'private')) {
return false
}
if (node.nodeType && !allowedTypesForThisCompletion.includes(node.nodeType)) {
return false
}
// filter private nodes, only allow them when contract ID is the same as the current contract
nodes = nodes.filter(node => {
if (node.visibility) {
if (node.visibility === 'private') {
return (node.contractId ? node.contractId === contractNode.id : false) || false
}
}
return true
})
nodes = [...nodes, ...thisCompletionNodes]
return nodes
}
})
break;
}
private getDotCompletions = async (nameOfLastTypedExpression: string, range) => {
const contractCompletions = await this.getContractCompletions()
let nodes: any[] = []
let suggestions: monacoTypes.languages.CompletionItem[] = []
const filterNodes = (nodes: any[], parentNode: any, declarationOf: any = null) => {
return nodes && nodes.filter(node => {
if (node.visibility) {
if (declarationOf && declarationOf.nodeType && declarationOf.nodeType === 'StructDefinition') {
return true
}
if ((node.visibility === 'internal' && !parentNode.isBaseNode) || node.visibility === 'private') {
return false
}
}
return true
})
}
} else {
// get all the nodes from a simple code parser which only parses the current file
const allNodesFromAntlr = await this.props.plugin.call('codeParser', 'listAstNodes')
if (allNodesFromAntlr) {
nodes = [...nodes, ...allNodesFromAntlr]
}
}
return nodes
}
private getThisCompletions = async () => {
let nodes: any[] = []
let thisCompletionNodes = await this.getContractCompletions()
const allowedTypesForThisCompletion = ['VariableDeclaration', 'FunctionDefinition']
// with this. you can't have internal nodes and no contractDefinitions
thisCompletionNodes = thisCompletionNodes.filter(node => {
if (node.visibility && (node.visibility === 'internal' || node.visibility === 'private')) {
return false
}
if (node.nodeType && !allowedTypesForThisCompletion.includes(node.nodeType)) {
return false
}
return true
})
nodes = [...nodes, ...thisCompletionNodes]
return nodes
}
private getDotCompletions = async (nameOfLastTypedExpression: string, range) => {
const contractCompletions = await this.getContractCompletions()
let nodes: any[] = []
let suggestions: monacoTypes.languages.CompletionItem[] = []
const filterNodes = (nodes: any[], parentNode: any, declarationOf: any = null) => {
return nodes && nodes.filter(node => {
if (node.visibility) {
if (declarationOf && declarationOf.nodeType && declarationOf.nodeType === 'StructDefinition') {
return true
}
if ((node.visibility === 'internal' && !parentNode.isBaseNode) || node.visibility === 'private') {
return false
}
}
return true
})
}
for (const nodeOfScope of contractCompletions) {
if (nodeOfScope.name === nameOfLastTypedExpression) {
if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'UserDefinedTypeName') {
const declarationOf: AstNode = await this.props.plugin.call('codeParser', 'declarationOf', nodeOfScope.typeName)
nodes = [...nodes,
...filterNodes(declarationOf.nodes, nodeOfScope, declarationOf)
for (const nodeOfScope of contractCompletions) {
if (nodeOfScope.name === nameOfLastTypedExpression) {
if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'UserDefinedTypeName') {
const declarationOf: AstNode = await this.props.plugin.call('codeParser', 'declarationOf', nodeOfScope.typeName)
nodes = [...nodes,
...filterNodes(declarationOf.nodes, nodeOfScope, declarationOf)
|| filterNodes(declarationOf.members, nodeOfScope, declarationOf)]
const baseContracts = await this.getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...filterNodes(baseContract.nodes, nodeOfScope)]
}
} else if (nodeOfScope.members) {
nodes = [...nodes, ...filterNodes(nodeOfScope.members, nodeOfScope)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ArrayTypeName') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('ArrayTypeName', range, this.monaco)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'bytes') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('bytes', range, this.monaco)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'address') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('address', range, this.monaco)]
}
}
const baseContracts = await this.getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...filterNodes(baseContract.nodes, nodeOfScope)]
}
} else if (nodeOfScope.members) {
nodes = [...nodes, ...filterNodes(nodeOfScope.members, nodeOfScope)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ArrayTypeName') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('ArrayTypeName', range, this.monaco)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'bytes') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('bytes', range, this.monaco)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'address') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('address', range, this.monaco)]
}
}
}
return { nodes, suggestions }
}
private getlinearizedBaseContracts = async (node: any) => {
let params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
if (id !== node.id) {
const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id)
params = [...params, ...[baseContract]]
}
}
return { nodes, suggestions }
}
private getlinearizedBaseContracts = async (node: any) => {
let params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
if (id !== node.id) {
const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id)
params = [...params, ...[baseContract]]
}
return params
}
}
return params
}
/**
/**
*
* @param lineTextBeforeCursor
* @returns
*/
private async getLastNodeInExpression(lineTextBeforeCursor: string) {
private async getLastNodeInExpression(lineTextBeforeCursor: string) {
const wrapLineInFunction = async (text: string) => {
return `function() {
const wrapLineInFunction = async (text: string) => {
return `function() {
${text}
}`
}
}
let lastNodeInExpression
let lastNodeInExpression
const linesToCheck =
const linesToCheck =
[
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;",
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;}",
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode);",
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;}"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;)"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode)"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode);"),
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;",
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;}",
lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode);",
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;}"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode;)"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode)"),
await wrapLineInFunction(lineTextBeforeCursor.substring(0, lineTextBeforeCursor.lastIndexOf('.')) + ".lastnode);"),
]
for (const line of linesToCheck) {
try {
const lineAst = await this.props.plugin.call('codeParser', 'parseSolidity', line)
const lastNode = await this.props.plugin.call('codeParser', 'getLastNodeInLine', lineAst)
if (lastNode) {
lastNodeInExpression = lastNode
break
}
for (const line of linesToCheck) {
try {
const lineAst = await this.props.plugin.call('codeParser', 'parseSolidity', line)
const lastNode = await this.props.plugin.call('codeParser', 'getLastNodeInLine', lineAst)
if (lastNode) {
lastNodeInExpression = lastNode
break
}
} catch (e) {
} catch (e) {
}
}
return lastNodeInExpression
}
}
return lastNodeInExpression
}
}

@ -3,86 +3,86 @@ import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
export class RemixDefinitionProvider implements monaco.languages.DefinitionProvider {
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideDefinition(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken): Promise<monaco.languages.Definition | monaco.languages.LocationLink[]> {
const cursorPosition = this.props.editorAPI.getCursorPosition()
let jumpLocation = await this.jumpToDefinition(cursorPosition)
if (!jumpLocation || !jumpLocation.fileName) {
const line = model.getLineContent(position.lineNumber)
const lastpart = line.substring(0, position.column - 1).split(';').pop()
if (lastpart.startsWith('import')) {
const importPath = line.substring(lastpart.indexOf('"') + 1)
const importPath2 = importPath.substring(0, importPath.indexOf('"'))
jumpLocation = {
startLineNumber: 1,
startColumn: 1,
endColumn: 1,
endLineNumber: 1,
fileName: importPath2
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideDefinition(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken): Promise<monaco.languages.Definition | monaco.languages.LocationLink[]> {
const cursorPosition = this.props.editorAPI.getCursorPosition()
let jumpLocation = await this.jumpToDefinition(cursorPosition)
if (!jumpLocation || !jumpLocation.fileName) {
const line = model.getLineContent(position.lineNumber)
const lastpart = line.substring(0, position.column - 1).split(';').pop()
if (lastpart.startsWith('import')) {
const importPath = line.substring(lastpart.indexOf('"') + 1)
const importPath2 = importPath.substring(0, importPath.indexOf('"'))
jumpLocation = {
startLineNumber: 1,
startColumn: 1,
endColumn: 1,
endLineNumber: 1,
fileName: importPath2
}
if (jumpLocation && jumpLocation.fileName) {
return [{
uri: this.monaco.Uri.parse(jumpLocation.fileName),
range: {
startLineNumber: jumpLocation.startLineNumber,
startColumn: jumpLocation.startColumn,
endLineNumber: jumpLocation.endLineNumber,
endColumn: jumpLocation.endColumn
}
}]
}
}
if (jumpLocation && jumpLocation.fileName) {
return [{
uri: this.monaco.Uri.parse(jumpLocation.fileName),
range: {
startLineNumber: jumpLocation.startLineNumber,
startColumn: jumpLocation.startColumn,
endLineNumber: jumpLocation.endLineNumber,
endColumn: jumpLocation.endColumn
}
return []
}]
}
return []
}
async jumpToDefinition(position: any) {
const node = await this.props.plugin.call('codeParser', 'definitionAtPosition', position)
const sourcePosition = await this.props.plugin.call('codeParser', 'positionOfDefinition', node)
if (sourcePosition) {
return await this.jumpToPosition(sourcePosition)
}
async jumpToDefinition(position: any) {
const node = await this.props.plugin.call('codeParser', 'definitionAtPosition', position)
const sourcePosition = await this.props.plugin.call('codeParser', 'positionOfDefinition', node)
if (sourcePosition) {
return await this.jumpToPosition(sourcePosition)
}
}
/*
/*
* onClick jump to position of ast node in the editor
*/
async jumpToPosition(position: any) {
const jumpToLine = async (fileName: string, lineColumn: any) => {
const fileTarget = await this.props.plugin.call('fileManager', 'getPathFromUrl', fileName)
if (fileName !== await this.props.plugin.call('fileManager', 'file')) {
await this.props.plugin.call('contentImport', 'resolveAndSave', fileName, null)
const fileContent = await this.props.plugin.call('fileManager', 'readFile', fileName)
try {
await this.props.plugin.call('editor', 'addModel', fileTarget.file, fileContent)
} catch (e) {
async jumpToPosition(position: any) {
const jumpToLine = async (fileName: string, lineColumn: any) => {
const fileTarget = await this.props.plugin.call('fileManager', 'getPathFromUrl', fileName)
if (fileName !== await this.props.plugin.call('fileManager', 'file')) {
await this.props.plugin.call('contentImport', 'resolveAndSave', fileName, null)
const fileContent = await this.props.plugin.call('fileManager', 'readFile', fileName)
try {
await this.props.plugin.call('editor', 'addModel', fileTarget.file, fileContent)
} catch (e) {
}
}
if (lineColumn.start && lineColumn.start.line >= 0 && lineColumn.start.column >= 0) {
const pos = {
startLineNumber: lineColumn.start.line + 1,
startColumn: lineColumn.start.column + 1,
endColumn: lineColumn.end.column + 1,
endLineNumber: lineColumn.end.line + 1,
fileName: (fileTarget && fileTarget.file) || fileName
}
return pos
}
}
const lastCompilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult') // await this.props.plugin.call('compilerArtefacts', 'getLastCompilationResult')
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
const filename = lastCompilationResult.getSourceName(position.file)
return await jumpToLine(filename, lineColumn)
}
if (lineColumn.start && lineColumn.start.line >= 0 && lineColumn.start.column >= 0) {
const pos = {
startLineNumber: lineColumn.start.line + 1,
startColumn: lineColumn.start.column + 1,
endColumn: lineColumn.end.column + 1,
endLineNumber: lineColumn.end.line + 1,
fileName: (fileTarget && fileTarget.file) || fileName
}
return pos
}
}
const lastCompilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult') // await this.props.plugin.call('compilerArtefacts', 'getLastCompilationResult')
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
const filename = lastCompilationResult.getSourceName(position.file)
return await jumpToLine(filename, lineColumn)
}
}
}

@ -4,35 +4,35 @@ import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
export class RemixHighLightProvider implements monaco.languages.DocumentHighlightProvider {
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideDocumentHighlights(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken): Promise<monaco.languages.DocumentHighlight[]> {
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodes = await this.props.plugin.call('codeParser', 'referrencesAtPosition', cursorPosition)
const highlights: monaco.languages.DocumentHighlight[] = []
if (nodes && nodes.length) {
const compilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult')
const file = await this.props.plugin.call('fileManager', 'file')
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
for (const node of nodes) {
const position = sourceMappingDecoder.decode(node.src)
const fileInNode = compilationResult.getSourceName(position.file)
if (fileInNode === file) {
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
const range = new this.monaco.Range(lineColumn.start.line + 1, lineColumn.start.column + 1, lineColumn.end.line + 1, lineColumn.end.column + 1)
highlights.push({
range,
})
}
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideDocumentHighlights(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken): Promise<monaco.languages.DocumentHighlight[]> {
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodes = await this.props.plugin.call('codeParser', 'referrencesAtPosition', cursorPosition)
const highlights: monaco.languages.DocumentHighlight[] = []
if (nodes && nodes.length) {
const compilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult')
const file = await this.props.plugin.call('fileManager', 'file')
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
for (const node of nodes) {
const position = sourceMappingDecoder.decode(node.src)
const fileInNode = compilationResult.getSourceName(position.file)
if (fileInNode === file) {
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
const range = new this.monaco.Range(lineColumn.start.line + 1, lineColumn.start.column + 1, lineColumn.end.line + 1, lineColumn.end.column + 1)
highlights.push({
range,
})
}
}
return highlights
}
}
return highlights
}
}

@ -4,203 +4,203 @@ import { EditorUIProps } from '../remix-ui-editor'
import { monacoTypes } from '@remix-ui/editor';
export class RemixHoverProvider implements monacoTypes.languages.HoverProvider {
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
provideHover = async function (model: monacoTypes.editor.ITextModel, position: monacoTypes.Position): Promise<monacoTypes.languages.Hover> {
const cursorPosition = this.props.editorAPI.getHoverPosition(position)
const nodeAtPosition = await this.props.plugin.call('codeParser', 'definitionAtPosition', cursorPosition)
const contents = []
const getDocs = async (node: any) => {
contents.push({
value: await this.props.plugin.call('codeParser', 'getNodeDocumentation', node)
})
}
provideHover = async function (model: monacoTypes.editor.ITextModel, position: monacoTypes.Position): Promise<monacoTypes.languages.Hover> {
const cursorPosition = this.props.editorAPI.getHoverPosition(position)
const nodeAtPosition = await this.props.plugin.call('codeParser', 'definitionAtPosition', cursorPosition)
const contents = []
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getScope = async (node: any) => {
if (node.id) {
contents.push({
value: `id: ${node.id}`
})
}
if (node.scope) {
contents.push({
value: `scope: ${node.scope}`
})
}
}
const getDocs = async (node: any) => {
contents.push({
value: await this.props.plugin.call('codeParser', 'getNodeDocumentation', node)
})
}
const getLinks = async (node: any) => {
contents.push({
value: await this.props.plugin.call('codeParser', 'getNodeLink', node)
})
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getScope = async (node: any) => {
if (node.id) {
contents.push({
value: `id: ${node.id}`
})
}
if (node.scope) {
contents.push({
value: `scope: ${node.scope}`
})
}
}
const getVariableDeclaration = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getVariableDeclaration', node)
}
const getLinks = async (node: any) => {
contents.push({
value: await this.props.plugin.call('codeParser', 'getNodeLink', node)
})
}
const getVariableDeclaration = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getVariableDeclaration', node)
}
const getParamaters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionParamaters', node)
}
const getReturnParameters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionReturnParameters', node)
}
const getParamaters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionParamaters', node)
const getOverrides = async (node: any) => {
if (node.overrides) {
const overrides = []
for (const override of node.overrides.overrides) {
overrides.push(override.name)
}
if (overrides.length)
return ` overrides (${overrides.join(', ')})`
}
return ''
}
const getReturnParameters = async (node: any) => {
return await this.props.plugin.call('codeParser', 'getFunctionReturnParameters', node)
const getlinearizedBaseContracts = async (node: any) => {
const params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id)
params.push(
baseContract.name
)
}
if (params.length)
return `is ${params.join(', ')}`
}
return ''
}
const getOverrides = async (node: any) => {
if (node.overrides) {
const overrides = []
for (const override of node.overrides.overrides) {
overrides.push(override.name)
}
if (overrides.length)
return ` overrides (${overrides.join(', ')})`
}
return ''
if (nodeAtPosition) {
if (nodeAtPosition.absolutePath) {
const target = await this.props.plugin.call('fileManager', 'getPathFromUrl', nodeAtPosition.absolutePath)
if (target.file !== nodeAtPosition.absolutePath) {
contents.push({
value: `${target.file}`
})
}
const getlinearizedBaseContracts = async (node: any) => {
const params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id)
params.push(
baseContract.name
)
}
if (params.length)
return `is ${params.join(', ')}`
}
return ''
contents.push({
value: `${nodeAtPosition.absolutePath}`
})
}
if (nodeAtPosition.nodeType === 'VariableDeclaration') {
contents.push({
value: await getVariableDeclaration(nodeAtPosition)
})
}
else if (nodeAtPosition.nodeType === 'ElementaryTypeName') {
contents.push({
value: `${nodeAtPosition.typeDescriptions.typeString}`
})
} else if (nodeAtPosition.nodeType === 'FunctionDefinition') {
if (!nodeAtPosition.name) return
const returns = await getReturnParameters(nodeAtPosition)
contents.push({
value: `function ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)} ${nodeAtPosition.visibility} ${nodeAtPosition.stateMutability}${await getOverrides(nodeAtPosition)} ${returns ? `returns ${returns}` : ''}`
})
} else if (nodeAtPosition.nodeType === 'ModifierDefinition') {
contents.push({
value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'EventDefinition') {
contents.push({
value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'ContractDefinition') {
contents.push({
value: `${nodeAtPosition.contractKind || nodeAtPosition.kind} ${nodeAtPosition.name} ${await getlinearizedBaseContracts(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'InvalidNode') {
contents.push({
value: `There are errors in the code.`
})
} else if (nodeAtPosition.nodeType === 'Block') {
} else {
contents.push({
value: `${nodeAtPosition.nodeType}`
})
}
for (const key in contents) {
contents[key].value = '```remix-solidity\n' + contents[key].value + '\n```'
}
getLinks(nodeAtPosition)
getDocs(nodeAtPosition)
// getScope(nodeAtPosition)
try {
if (nodeAtPosition?.name === 'msg') {
const global = await this.props.plugin.call('debugger', 'globalContext')
if (global !== null && global[nodeAtPosition?.name]) {
contents.push({
value: `GLOBAL VARIABLE ${nodeAtPosition.name}: ${JSON.stringify(global[nodeAtPosition?.name], null, '\t')}`
})
}
}
} catch (e) {}
if (nodeAtPosition) {
if (nodeAtPosition.absolutePath) {
const target = await this.props.plugin.call('fileManager', 'getPathFromUrl', nodeAtPosition.absolutePath)
if (target.file !== nodeAtPosition.absolutePath) {
contents.push({
value: `${target.file}`
})
}
contents.push({
value: `${nodeAtPosition.absolutePath}`
})
}
if (nodeAtPosition.nodeType === 'VariableDeclaration') {
contents.push({
value: await getVariableDeclaration(nodeAtPosition)
})
}
else if (nodeAtPosition.nodeType === 'ElementaryTypeName') {
contents.push({
value: `${nodeAtPosition.typeDescriptions.typeString}`
})
} else if (nodeAtPosition.nodeType === 'FunctionDefinition') {
if (!nodeAtPosition.name) return
const returns = await getReturnParameters(nodeAtPosition)
contents.push({
value: `function ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)} ${nodeAtPosition.visibility} ${nodeAtPosition.stateMutability}${await getOverrides(nodeAtPosition)} ${returns ? `returns ${returns}` : ''}`
})
} else if (nodeAtPosition.nodeType === 'ModifierDefinition') {
contents.push({
value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'EventDefinition') {
contents.push({
value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'ContractDefinition') {
contents.push({
value: `${nodeAtPosition.contractKind || nodeAtPosition.kind} ${nodeAtPosition.name} ${await getlinearizedBaseContracts(nodeAtPosition)}`
})
} else if (nodeAtPosition.nodeType === 'InvalidNode') {
contents.push({
value: `There are errors in the code.`
})
} else if (nodeAtPosition.nodeType === 'Block') {
} else {
contents.push({
value: `${nodeAtPosition.nodeType}`
})
}
for (const key in contents) {
contents[key].value = '```remix-solidity\n' + contents[key].value + '\n```'
}
getLinks(nodeAtPosition)
getDocs(nodeAtPosition)
// getScope(nodeAtPosition)
try {
if (nodeAtPosition?.name === 'msg') {
const global = await this.props.plugin.call('debugger', 'globalContext')
if (global !== null && global[nodeAtPosition?.name]) {
contents.push({
value: `GLOBAL VARIABLE ${nodeAtPosition.name}: ${JSON.stringify(global[nodeAtPosition?.name], null, '\t')}`
})
}
}
} catch (e) {}
try {
if (nodeAtPosition?.expression?.name === 'msg' && nodeAtPosition?.memberName) {
const global = await this.props.plugin.call('debugger', 'globalContext')
if (global !== null && global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName] && global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName]) {
contents.push({
value: `GLOBAL VARIABLE msg.${nodeAtPosition.memberName}: ${global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName]}`
})
}
}
} catch (e) {}
try {
const decodedVar = await this.props.plugin.call('debugger', 'decodeLocalVariable', nodeAtPosition.id)
if (decodedVar !== null && decodedVar.type) {
contents.push({
value: `LOCAL VARIABLE ${nodeAtPosition.name}: ${typeof(decodedVar.value) === 'string' ? decodedVar.value : JSON.stringify(decodedVar.value, null, '\t')}`
})
}
} catch (e) {}
try {
const decodedVar = await this.props.plugin.call('debugger', 'decodeStateVariable', nodeAtPosition.id)
if (decodedVar !== null && decodedVar.type) {
contents.push({
value: `STATE VARIABLE ${nodeAtPosition.name}: ${typeof(decodedVar.value) === 'string' ? decodedVar.value : JSON.stringify(decodedVar.value, null, '\t')}`
})
}
} catch (e) {}
try {
if (nodeAtPosition?.expression?.name === 'msg' && nodeAtPosition?.memberName) {
const global = await this.props.plugin.call('debugger', 'globalContext')
if (global !== null && global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName] && global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName]) {
contents.push({
value: `GLOBAL VARIABLE msg.${nodeAtPosition.memberName}: ${global[nodeAtPosition?.expression?.name][nodeAtPosition.memberName]}`
})
}
}
setTimeout(() => {
// eslint-disable-next-line no-debugger
// debugger
},1000)
return {
range: new this.monaco.Range(
position.lineNumber,
position.column,
position.lineNumber,
model.getLineMaxColumn(position.lineNumber)
),
contents: contents
};
} catch (e) {}
try {
const decodedVar = await this.props.plugin.call('debugger', 'decodeLocalVariable', nodeAtPosition.id)
if (decodedVar !== null && decodedVar.type) {
contents.push({
value: `LOCAL VARIABLE ${nodeAtPosition.name}: ${typeof(decodedVar.value) === 'string' ? decodedVar.value : JSON.stringify(decodedVar.value, null, '\t')}`
})
}
} catch (e) {}
try {
const decodedVar = await this.props.plugin.call('debugger', 'decodeStateVariable', nodeAtPosition.id)
if (decodedVar !== null && decodedVar.type) {
contents.push({
value: `STATE VARIABLE ${nodeAtPosition.name}: ${typeof(decodedVar.value) === 'string' ? decodedVar.value : JSON.stringify(decodedVar.value, null, '\t')}`
})
}
} catch (e) {}
}
setTimeout(() => {
// eslint-disable-next-line no-debugger
// debugger
},1000)
return {
range: new this.monaco.Range(
position.lineNumber,
position.column,
position.lineNumber,
model.getLineMaxColumn(position.lineNumber)
),
contents: contents
};
}
}

@ -1,16 +1,16 @@
export default {
"Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.": {
"title": "Add open-source license",
"message": "// SPDX-License-Identifier: GPL-3.0"
},
"Warning: Source file does not specify required compiler version! Consider adding" : {
"title": "Add pragma line",
"message": "pragma solidity ^0.*.*;",
"range": {
startLineNumber: 2,
endLineNumber: 2,
startColumn: 1,
endColumn: 1
}
"Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.": {
"title": "Add open-source license",
"message": "// SPDX-License-Identifier: GPL-3.0"
},
"Warning: Source file does not specify required compiler version! Consider adding" : {
"title": "Add pragma line",
"message": "pragma solidity ^0.*.*;",
"range": {
startLineNumber: 2,
endLineNumber: 2,
startColumn: 1,
endColumn: 1
}
}
}

@ -4,44 +4,44 @@ import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
export class RemixReferenceProvider implements monaco.languages.ReferenceProvider {
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
props: EditorUIProps
monaco: Monaco
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideReferences(model: monaco.editor.ITextModel, position: monaco.Position, context: monaco.languages.ReferenceContext, token: monaco.CancellationToken) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideReferences(model: monaco.editor.ITextModel, position: monaco.Position, context: monaco.languages.ReferenceContext, token: monaco.CancellationToken) {
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodes = await this.props.plugin.call('codeParser', 'referrencesAtPosition', cursorPosition)
const references = []
if (nodes && nodes.length) {
const compilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult')
const file = await this.props.plugin.call('fileManager', 'file')
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
for (const node of nodes) {
const position = sourceMappingDecoder.decode(node.src)
const fileInNode = compilationResult.getSourceName(position.file)
let fileTarget = await this.props.plugin.call('fileManager', 'getPathFromUrl', fileInNode)
fileTarget = fileTarget.file
const fileContent = await this.props.plugin.call('fileManager', 'readFile', fileInNode)
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodes = await this.props.plugin.call('codeParser', 'referrencesAtPosition', cursorPosition)
const references = []
if (nodes && nodes.length) {
const compilationResult = await this.props.plugin.call('codeParser', 'getLastCompilationResult')
const file = await this.props.plugin.call('fileManager', 'file')
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
for (const node of nodes) {
const position = sourceMappingDecoder.decode(node.src)
const fileInNode = compilationResult.getSourceName(position.file)
let fileTarget = await this.props.plugin.call('fileManager', 'getPathFromUrl', fileInNode)
fileTarget = fileTarget.file
const fileContent = await this.props.plugin.call('fileManager', 'readFile', fileInNode)
const lineColumn = await this.props.plugin.call('codeParser', 'getLineColumnOfPosition', position)
try {
this.props.plugin.call('editor', 'addModel', fileTarget, fileContent)
} catch (e) {
try {
this.props.plugin.call('editor', 'addModel', fileTarget, fileContent)
} catch (e) {
}
const range = new this.monaco.Range(lineColumn.start.line + 1, lineColumn.start.column + 1, lineColumn.end.line + 1, lineColumn.end.column + 1)
references.push({
range,
uri: this.monaco.Uri.parse(fileTarget)
})
}
}
const range = new this.monaco.Range(lineColumn.start.line + 1, lineColumn.start.column + 1, lineColumn.end.line + 1, lineColumn.end.column + 1)
references.push({
range,
uri: this.monaco.Uri.parse(fileTarget)
})
}
return references
}
}
return references
}
}

@ -566,7 +566,7 @@ export const EditorUI = (props: EditorUIProps) => {
})
editor.onDidPaste((e) => {
if (!pasteCodeRef.current && e && e.range && e.range.startLineNumber >= 0 && e.range.endLineNumber >= 0 && e.range.endLineNumber - e.range.startLineNumber > 10) {
if (!pasteCodeRef.current && e && e.range && e.range.startLineNumber >= 0 && e.range.endLineNumber >= 0 && e.range.endLineNumber - e.range.startLineNumber > 10) {
const modalContent: AlertModal = {
id: 'newCodePasted',
title: 'Pasted Code Alert',
@ -769,7 +769,7 @@ export const EditorUI = (props: EditorUIProps) => {
{editorModelsState[props.currentFile]?.readOnly && <span className='pl-4 h6 mb-0 w-100 alert-info position-absolute bottom-0 end-0'>
<i className="fas fa-lock-alt p-2"></i>
The file is opened in <b>read-only</b> mode.
</span>
</span>
}
</div>
)

@ -2,240 +2,240 @@ import { remixTypes } from './remix-plugin-types'
import { hardhatEthersExtension } from './hardhat-ethers-extension'
export const loadTypes = async (monaco) => {
// ethers.js
// @ts-ignore
const ethersAbi = await import('raw-loader!@ethersproject/abi/lib/index.d.ts')
const ethersAbiDefault = ethersAbi.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAbiDefault, `file:///node_modules/@types/@ethersproject_abi/index.d.ts`)
// @ts-ignore
const ethersAbstract = await import('raw-loader!@ethersproject/abstract-provider/lib/index.d.ts')
const ethersAbstractDefault = ethersAbstract.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAbstractDefault, `file:///node_modules/@types/@ethersproject_abstract-provider/index.d.ts`)
// @ts-ignore
const ethersSigner = await import('raw-loader!@ethersproject/abstract-signer/lib/index.d.ts')
const ethersSignerDefault = ethersSigner.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSignerDefault, `file:///node_modules/@types/@ethersproject_abstract-signer/index.d.ts`)
// @ts-ignore
const ethersAddress = await import('raw-loader!@ethersproject/address/lib/index.d.ts')
const ethersAddressDefault = ethersAddress.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAddressDefault, `file:///node_modules/@types/@ethersproject_address/index.d.ts`)
// @ts-ignore
const ethersBase64 = await import('raw-loader!@ethersproject/base64/lib/index.d.ts')
const ethersBase64Default = ethersBase64.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBase64Default, `file:///node_modules/@types/@ethersproject_base64/index.d.ts`)
// ethers.js
// @ts-ignore
const ethersAbi = await import('raw-loader!@ethersproject/abi/lib/index.d.ts')
const ethersAbiDefault = ethersAbi.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAbiDefault, `file:///node_modules/@types/@ethersproject_abi/index.d.ts`)
// @ts-ignore
const ethersAbstract = await import('raw-loader!@ethersproject/abstract-provider/lib/index.d.ts')
const ethersAbstractDefault = ethersAbstract.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAbstractDefault, `file:///node_modules/@types/@ethersproject_abstract-provider/index.d.ts`)
// @ts-ignore
const ethersSigner = await import('raw-loader!@ethersproject/abstract-signer/lib/index.d.ts')
const ethersSignerDefault = ethersSigner.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSignerDefault, `file:///node_modules/@types/@ethersproject_abstract-signer/index.d.ts`)
// @ts-ignore
const ethersAddress = await import('raw-loader!@ethersproject/address/lib/index.d.ts')
const ethersAddressDefault = ethersAddress.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersAddressDefault, `file:///node_modules/@types/@ethersproject_address/index.d.ts`)
// @ts-ignore
const ethersBase64 = await import('raw-loader!@ethersproject/base64/lib/index.d.ts')
const ethersBase64Default = ethersBase64.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBase64Default, `file:///node_modules/@types/@ethersproject_base64/index.d.ts`)
// @ts-ignore
const ethersBasex = await import('raw-loader!@ethersproject/basex/lib/index.d.ts')
const ethersBasexDefault = ethersBasex.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBasexDefault, `file:///node_modules/@types/@ethersproject_basex/index.d.ts`)
// @ts-ignore
const ethersBignumber = await import('raw-loader!@ethersproject/bignumber/lib/index.d.ts')
const ethersBignumberDefault = ethersBignumber.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBignumberDefault, `file:///node_modules/@types/@ethersproject_bignumber/index.d.ts`)
// @ts-ignore
const ethersBytes = await import('raw-loader!@ethersproject/bytes/lib/index.d.ts')
const ethersBytesDefault = ethersBytes.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBytesDefault, `file:///node_modules/@types/@ethersproject_bytes/index.d.ts`)
// @ts-ignore
const ethersConstants = await import('raw-loader!@ethersproject/constants/lib/index.d.ts')
const ethersConstantsDefault = ethersConstants.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersConstantsDefault, `file:///node_modules/@types/@ethersproject_constants/index.d.ts`)
// @ts-ignore
const ethersContracts = await import('raw-loader!@ethersproject/contracts/lib/index.d.ts')
const ethersContractsDefault = ethersContracts.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersContractsDefault, `file:///node_modules/@types/@ethersproject_contracts/index.d.ts`)
// @ts-ignore
const ethersHash = await import('raw-loader!@ethersproject/hash/lib/index.d.ts')
const ethersHashDefault = ethersHash.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersHashDefault, `file:///node_modules/@types/@ethersproject_hash/index.d.ts`)
// @ts-ignore
const ethersHdnode = await import('raw-loader!@ethersproject/hdnode/lib/index.d.ts')
const ethersHdnodeDefault = ethersHdnode.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersHdnodeDefault, `file:///node_modules/@types/@ethersproject_hdnode/index.d.ts`)
// @ts-ignore
const ethersJsonWallets = await import('raw-loader!@ethersproject/json-wallets/lib/index.d.ts')
const ethersJsonWalletsDefault = ethersJsonWallets.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersJsonWalletsDefault, `file:///node_modules/@types/@ethersproject_json-wallets/index.d.ts`)
// @ts-ignore
const ethersKeccak256 = await import('raw-loader!@ethersproject/keccak256/lib/index.d.ts')
const ethersKeccak256Default = ethersKeccak256.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersKeccak256Default, `file:///node_modules/@types/@ethersproject_keccak256/index.d.ts`)
// @ts-ignore
const ethersLogger = await import('raw-loader!@ethersproject/logger/lib/index.d.ts')
const ethersLoggerDefault = ethersLogger.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersLoggerDefault, `file:///node_modules/@types/@ethersproject_logger/index.d.ts`)
// @ts-ignore
const ethersNetworks = await import('raw-loader!@ethersproject/networks/lib/index.d.ts')
const ethersNetworksDefault = ethersNetworks.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersNetworksDefault, `file:///node_modules/@types/@ethersproject_networks/index.d.ts`)
// @ts-ignore
const ethersPbkdf2 = await import('raw-loader!@ethersproject/pbkdf2/lib/index.d.ts')
const ethersPbkdf2Default = ethersPbkdf2.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersPbkdf2Default, `file:///node_modules/@types/@ethersproject_pbkdf2/index.d.ts`)
// @ts-ignore
const ethersProperties = await import('raw-loader!@ethersproject/properties/lib/index.d.ts')
const ethersPropertiesDefault = ethersProperties.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersPropertiesDefault, `file:///node_modules/@types/@ethersproject_properties/index.d.ts`)
// @ts-ignore
const ethersProviders = await import('raw-loader!@ethersproject/providers/lib/index.d.ts')
const ethersProvidersDefault = ethersProviders.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersProvidersDefault, `file:///node_modules/@types/@ethersproject_providers/index.d.ts`)
// @ts-ignore
const ethersRandom = await import('raw-loader!@ethersproject/random/lib/index.d.ts')
const ethersRandomDefault = ethersRandom.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersRandomDefault, `file:///node_modules/@types/@ethersproject_random/index.d.ts`)
// @ts-ignore
const ethersRlp = await import('raw-loader!@ethersproject/rlp/lib/index.d.ts')
const ethersRlpDefault = ethersRlp.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersRlpDefault, `file:///node_modules/@types/@ethersproject_rlp/index.d.ts`)
// @ts-ignore
const ethersSha2 = await import('raw-loader!@ethersproject/sha2/lib/index.d.ts')
const ethersSha2Default = ethersSha2.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSha2Default, `file:///node_modules/@types/@ethersproject_sha2/index.d.ts`)
// @ts-ignore
const ethersSingningkey = await import('raw-loader!@ethersproject/signing-key/lib/index.d.ts')
const ethersSingningkeyDefault = ethersSingningkey.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSingningkeyDefault, `file:///node_modules/@types/@ethersproject_signing-key/index.d.ts`)
// @ts-ignore
const ethersSolidity = await import('raw-loader!@ethersproject/solidity/lib/index.d.ts')
const ethersSolidityDefault = ethersSolidity.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSolidityDefault, `file:///node_modules/@types/@ethersproject_solidity/index.d.ts`)
// @ts-ignore
const ethersStrings = await import('raw-loader!@ethersproject/strings/lib/index.d.ts')
const ethersStringsDefault = ethersStrings.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersStringsDefault, `file:///node_modules/@types/@ethersproject_strings/index.d.ts`)
// @ts-ignore
const ethersTransactions = await import('raw-loader!@ethersproject/transactions/lib/index.d.ts')
const ethersTransactionsDefault = ethersTransactions.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersTransactionsDefault, `file:///node_modules/@types/@ethersproject_transactions/index.d.ts`)
// @ts-ignore
const ethersUnits = await import('raw-loader!@ethersproject/units/lib/index.d.ts')
const ethersUnitsDefault = ethersUnits.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersUnitsDefault, `file:///node_modules/@types/@ethersproject_units/index.d.ts`)
// @ts-ignore
const ethersWallet = await import('raw-loader!@ethersproject/wallet/lib/index.d.ts')
const ethersWalletDefault = ethersWallet.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWalletDefault, `file:///node_modules/@types/@ethersproject_wallet/index.d.ts`)
// @ts-ignore
const ethersWeb = await import('raw-loader!@ethersproject/web/lib/index.d.ts')
const ethersWebDefault = ethersWeb.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWebDefault, `file:///node_modules/@types/@ethersproject_web/index.d.ts`)
// @ts-ignore
const ethersWordlists = await import('raw-loader!@ethersproject/wordlists/lib/index.d.ts')
const ethersWordlistsDefault = ethersWordlists.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWordlistsDefault, `file:///node_modules/@types/@ethersproject_wordlists/index.d.ts`)
// @ts-ignore
const versionEthers = await import('raw-loader!ethers/lib/_version.d.ts')
const versionEthersDefault = versionEthers.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(versionEthersDefault, `file:///node_modules/@types/_version-ethers-lib/index.d.ts`)
// @ts-ignore
const utilEthers = await import('raw-loader!ethers/lib/utils.d.ts')
const utilEthersDefault = utilEthers.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(utilEthersDefault, `file:///node_modules/@types/utils-ethers-lib/index.d.ts`)
// @ts-ignore
const ethers = await import('raw-loader!ethers/lib/ethers.d.ts')
let ethersDefault = ethers.default
ethersDefault = ethersDefault.replace(/.\/utils/g, 'utils-ethers-lib')
ethersDefault = ethersDefault.replace(/.\/_version/g, '_version-ethers-lib')
ethersDefault = ethersDefault.replace(/.\/ethers/g, 'ethers-lib')
ethersDefault = ethersDefault.replace(/@ethersproject\//g, '@ethersproject_')
ethersDefault = ethersDefault + '\n' + hardhatEthersExtension
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersDefault, `file:///node_modules/@types/ethers-lib/index.d.ts`)
// @ts-ignore
const indexEthers = await import('raw-loader!ethers/lib/index.d.ts')
let indexEthersDefault = indexEthers.default
indexEthersDefault = indexEthersDefault.replace(/.\/ethers/g, 'ethers-lib')
indexEthersDefault = indexEthersDefault.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexEthersDefault, `file:///node_modules/@types/ethers/index.d.ts`)
// Web3
// @ts-ignore
const indexWeb3 = await import('raw-loader!web3/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3.default, `file:///node_modules/@types/web3/index.d.ts`)
// @ts-ignore
const indexWeb3Bzz = await import('raw-loader!web3-bzz/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Bzz.default, `file:///node_modules/@types/web3-bzz/index.d.ts`)
// @ts-ignore
const indexWeb3Core = await import('raw-loader!web3-core/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Core.default, `file:///node_modules/@types/web3-core/index.d.ts`)
// @ts-ignore
const indexWeb3Eth = await import('raw-loader!web3-eth/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Eth.default, `file:///node_modules/@types/web3-eth/index.d.ts`)
// @ts-ignore
const indexWeb3Personal = await import('raw-loader!web3-eth-personal/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Personal.default, `file:///node_modules/@types/web3-eth-personal/index.d.ts`)
// @ts-ignore
const indexWeb3Contract = await import('raw-loader!web3-eth-contract/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Contract.default, `file:///node_modules/@types/web3-eth-contract/index.d.ts`)
// @ts-ignore
const indexWeb3Net = await import('raw-loader!web3-net/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Net.default, `file:///node_modules/@types/web3-net/index.d.ts`)
// @ts-ignore
const indexWeb3Shh = await import('raw-loader!web3-shh/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Shh.default, `file:///node_modules/@types/web3-shh/index.d.ts`)
// @ts-ignore
const indexWeb3Util = await import('raw-loader!web3-utils/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Util.default, `file:///node_modules/@types/web3-utils/index.d.ts`)
// remix
const indexRemixApi = remixTypes + `\n
// @ts-ignore
const ethersBasex = await import('raw-loader!@ethersproject/basex/lib/index.d.ts')
const ethersBasexDefault = ethersBasex.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBasexDefault, `file:///node_modules/@types/@ethersproject_basex/index.d.ts`)
// @ts-ignore
const ethersBignumber = await import('raw-loader!@ethersproject/bignumber/lib/index.d.ts')
const ethersBignumberDefault = ethersBignumber.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBignumberDefault, `file:///node_modules/@types/@ethersproject_bignumber/index.d.ts`)
// @ts-ignore
const ethersBytes = await import('raw-loader!@ethersproject/bytes/lib/index.d.ts')
const ethersBytesDefault = ethersBytes.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersBytesDefault, `file:///node_modules/@types/@ethersproject_bytes/index.d.ts`)
// @ts-ignore
const ethersConstants = await import('raw-loader!@ethersproject/constants/lib/index.d.ts')
const ethersConstantsDefault = ethersConstants.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersConstantsDefault, `file:///node_modules/@types/@ethersproject_constants/index.d.ts`)
// @ts-ignore
const ethersContracts = await import('raw-loader!@ethersproject/contracts/lib/index.d.ts')
const ethersContractsDefault = ethersContracts.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersContractsDefault, `file:///node_modules/@types/@ethersproject_contracts/index.d.ts`)
// @ts-ignore
const ethersHash = await import('raw-loader!@ethersproject/hash/lib/index.d.ts')
const ethersHashDefault = ethersHash.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersHashDefault, `file:///node_modules/@types/@ethersproject_hash/index.d.ts`)
// @ts-ignore
const ethersHdnode = await import('raw-loader!@ethersproject/hdnode/lib/index.d.ts')
const ethersHdnodeDefault = ethersHdnode.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersHdnodeDefault, `file:///node_modules/@types/@ethersproject_hdnode/index.d.ts`)
// @ts-ignore
const ethersJsonWallets = await import('raw-loader!@ethersproject/json-wallets/lib/index.d.ts')
const ethersJsonWalletsDefault = ethersJsonWallets.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersJsonWalletsDefault, `file:///node_modules/@types/@ethersproject_json-wallets/index.d.ts`)
// @ts-ignore
const ethersKeccak256 = await import('raw-loader!@ethersproject/keccak256/lib/index.d.ts')
const ethersKeccak256Default = ethersKeccak256.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersKeccak256Default, `file:///node_modules/@types/@ethersproject_keccak256/index.d.ts`)
// @ts-ignore
const ethersLogger = await import('raw-loader!@ethersproject/logger/lib/index.d.ts')
const ethersLoggerDefault = ethersLogger.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersLoggerDefault, `file:///node_modules/@types/@ethersproject_logger/index.d.ts`)
// @ts-ignore
const ethersNetworks = await import('raw-loader!@ethersproject/networks/lib/index.d.ts')
const ethersNetworksDefault = ethersNetworks.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersNetworksDefault, `file:///node_modules/@types/@ethersproject_networks/index.d.ts`)
// @ts-ignore
const ethersPbkdf2 = await import('raw-loader!@ethersproject/pbkdf2/lib/index.d.ts')
const ethersPbkdf2Default = ethersPbkdf2.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersPbkdf2Default, `file:///node_modules/@types/@ethersproject_pbkdf2/index.d.ts`)
// @ts-ignore
const ethersProperties = await import('raw-loader!@ethersproject/properties/lib/index.d.ts')
const ethersPropertiesDefault = ethersProperties.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersPropertiesDefault, `file:///node_modules/@types/@ethersproject_properties/index.d.ts`)
// @ts-ignore
const ethersProviders = await import('raw-loader!@ethersproject/providers/lib/index.d.ts')
const ethersProvidersDefault = ethersProviders.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersProvidersDefault, `file:///node_modules/@types/@ethersproject_providers/index.d.ts`)
// @ts-ignore
const ethersRandom = await import('raw-loader!@ethersproject/random/lib/index.d.ts')
const ethersRandomDefault = ethersRandom.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersRandomDefault, `file:///node_modules/@types/@ethersproject_random/index.d.ts`)
// @ts-ignore
const ethersRlp = await import('raw-loader!@ethersproject/rlp/lib/index.d.ts')
const ethersRlpDefault = ethersRlp.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersRlpDefault, `file:///node_modules/@types/@ethersproject_rlp/index.d.ts`)
// @ts-ignore
const ethersSha2 = await import('raw-loader!@ethersproject/sha2/lib/index.d.ts')
const ethersSha2Default = ethersSha2.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSha2Default, `file:///node_modules/@types/@ethersproject_sha2/index.d.ts`)
// @ts-ignore
const ethersSingningkey = await import('raw-loader!@ethersproject/signing-key/lib/index.d.ts')
const ethersSingningkeyDefault = ethersSingningkey.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSingningkeyDefault, `file:///node_modules/@types/@ethersproject_signing-key/index.d.ts`)
// @ts-ignore
const ethersSolidity = await import('raw-loader!@ethersproject/solidity/lib/index.d.ts')
const ethersSolidityDefault = ethersSolidity.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersSolidityDefault, `file:///node_modules/@types/@ethersproject_solidity/index.d.ts`)
// @ts-ignore
const ethersStrings = await import('raw-loader!@ethersproject/strings/lib/index.d.ts')
const ethersStringsDefault = ethersStrings.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersStringsDefault, `file:///node_modules/@types/@ethersproject_strings/index.d.ts`)
// @ts-ignore
const ethersTransactions = await import('raw-loader!@ethersproject/transactions/lib/index.d.ts')
const ethersTransactionsDefault = ethersTransactions.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersTransactionsDefault, `file:///node_modules/@types/@ethersproject_transactions/index.d.ts`)
// @ts-ignore
const ethersUnits = await import('raw-loader!@ethersproject/units/lib/index.d.ts')
const ethersUnitsDefault = ethersUnits.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersUnitsDefault, `file:///node_modules/@types/@ethersproject_units/index.d.ts`)
// @ts-ignore
const ethersWallet = await import('raw-loader!@ethersproject/wallet/lib/index.d.ts')
const ethersWalletDefault = ethersWallet.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWalletDefault, `file:///node_modules/@types/@ethersproject_wallet/index.d.ts`)
// @ts-ignore
const ethersWeb = await import('raw-loader!@ethersproject/web/lib/index.d.ts')
const ethersWebDefault = ethersWeb.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWebDefault, `file:///node_modules/@types/@ethersproject_web/index.d.ts`)
// @ts-ignore
const ethersWordlists = await import('raw-loader!@ethersproject/wordlists/lib/index.d.ts')
const ethersWordlistsDefault = ethersWordlists.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersWordlistsDefault, `file:///node_modules/@types/@ethersproject_wordlists/index.d.ts`)
// @ts-ignore
const versionEthers = await import('raw-loader!ethers/lib/_version.d.ts')
const versionEthersDefault = versionEthers.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(versionEthersDefault, `file:///node_modules/@types/_version-ethers-lib/index.d.ts`)
// @ts-ignore
const utilEthers = await import('raw-loader!ethers/lib/utils.d.ts')
const utilEthersDefault = utilEthers.default.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(utilEthersDefault, `file:///node_modules/@types/utils-ethers-lib/index.d.ts`)
// @ts-ignore
const ethers = await import('raw-loader!ethers/lib/ethers.d.ts')
let ethersDefault = ethers.default
ethersDefault = ethersDefault.replace(/.\/utils/g, 'utils-ethers-lib')
ethersDefault = ethersDefault.replace(/.\/_version/g, '_version-ethers-lib')
ethersDefault = ethersDefault.replace(/.\/ethers/g, 'ethers-lib')
ethersDefault = ethersDefault.replace(/@ethersproject\//g, '@ethersproject_')
ethersDefault = ethersDefault + '\n' + hardhatEthersExtension
monaco.languages.typescript.typescriptDefaults.addExtraLib(ethersDefault, `file:///node_modules/@types/ethers-lib/index.d.ts`)
// @ts-ignore
const indexEthers = await import('raw-loader!ethers/lib/index.d.ts')
let indexEthersDefault = indexEthers.default
indexEthersDefault = indexEthersDefault.replace(/.\/ethers/g, 'ethers-lib')
indexEthersDefault = indexEthersDefault.replace(/@ethersproject\//g, '@ethersproject_')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexEthersDefault, `file:///node_modules/@types/ethers/index.d.ts`)
// Web3
// @ts-ignore
const indexWeb3 = await import('raw-loader!web3/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3.default, `file:///node_modules/@types/web3/index.d.ts`)
// @ts-ignore
const indexWeb3Bzz = await import('raw-loader!web3-bzz/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Bzz.default, `file:///node_modules/@types/web3-bzz/index.d.ts`)
// @ts-ignore
const indexWeb3Core = await import('raw-loader!web3-core/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Core.default, `file:///node_modules/@types/web3-core/index.d.ts`)
// @ts-ignore
const indexWeb3Eth = await import('raw-loader!web3-eth/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Eth.default, `file:///node_modules/@types/web3-eth/index.d.ts`)
// @ts-ignore
const indexWeb3Personal = await import('raw-loader!web3-eth-personal/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Personal.default, `file:///node_modules/@types/web3-eth-personal/index.d.ts`)
// @ts-ignore
const indexWeb3Contract = await import('raw-loader!web3-eth-contract/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Contract.default, `file:///node_modules/@types/web3-eth-contract/index.d.ts`)
// @ts-ignore
const indexWeb3Net = await import('raw-loader!web3-net/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Net.default, `file:///node_modules/@types/web3-net/index.d.ts`)
// @ts-ignore
const indexWeb3Shh = await import('raw-loader!web3-shh/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Shh.default, `file:///node_modules/@types/web3-shh/index.d.ts`)
// @ts-ignore
const indexWeb3Util = await import('raw-loader!web3-utils/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Util.default, `file:///node_modules/@types/web3-utils/index.d.ts`)
// remix
const indexRemixApi = remixTypes + `\n
declare global {
const remix: PluginClient;
const web3Provider;
}
`
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexRemixApi)
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexRemixApi)
// @ts-ignore
const chaiType = await import('raw-loader!@types/chai/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(chaiType.default, `file:///node_modules/@types/chai/index.d.ts`)
// @ts-ignore
const chaiType = await import('raw-loader!@types/chai/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(chaiType.default, `file:///node_modules/@types/chai/index.d.ts`)
// @ts-ignore
const mochaType = await import('raw-loader!@types/mocha/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(mochaType.default, `file:///node_modules/@types/mocha/index.d.ts`)
// @ts-ignore
const mochaType = await import('raw-loader!@types/mocha/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(mochaType.default, `file:///node_modules/@types/mocha/index.d.ts`)
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'typesloaded')
document.body.appendChild(loadedElement)
const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'typesloaded')
document.body.appendChild(loadedElement)
}

@ -24,15 +24,15 @@ export const FileDecorationIcons = (props: fileDecorationProps) => {
for (const [index, state] of states.entries()) {
switch (state.fileStateType) {
case fileDecorationType.Error:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationErrorIcon fileDecoration={state} key={index}/>}/>)
break
case fileDecorationType.Warning:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationWarningIcon fileDecoration={state} key={index}/>}/>)
break
case fileDecorationType.Custom:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationCustomIcon fileDecoration={state} key={index}/>}/>)
break
case fileDecorationType.Error:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationErrorIcon fileDecoration={state} key={index}/>}/>)
break
case fileDecorationType.Warning:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationWarningIcon fileDecoration={state} key={index}/>}/>)
break
case fileDecorationType.Custom:
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationCustomIcon fileDecoration={state} key={index}/>}/>)
break
}
}
return elements

@ -5,9 +5,9 @@ import { fileDecoration } from '../../types'
const FileDecorationCustomIcon = (props: {
fileDecoration: fileDecoration
}) => {
return <><span data-id={`file-decoration-custom-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} pr-2`}>
<>{props.fileDecoration.fileStateIcon}</>
</span></>
return <><span data-id={`file-decoration-custom-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} pr-2`}>
<>{props.fileDecoration.fileStateIcon}</>
</span></>
}
export default FileDecorationCustomIcon

@ -6,9 +6,9 @@ import { fileDecoration } from '../../types'
const FileDecorationErrorIcon = (props: {
fileDecoration: fileDecoration
}) => {
return <>
<span data-id={`file-decoration-error-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-danger pr-2`}>{props.fileDecoration.text}</span>
</>
return <>
<span data-id={`file-decoration-error-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-danger pr-2`}>{props.fileDecoration.text}</span>
</>
}
export default FileDecorationErrorIcon

@ -25,7 +25,7 @@ const FileDecorationTooltip = (props: {
<Popover.Content id={`error-tooltip-${props.fileDecoration.path}`} style={{minWidth: "fit-content"}} className={"text-wrap bg-secondary w-100 p-1 m-0"}>
<pre>{getComments(props.fileDecoration)}</pre>
</Popover.Content>
</Popover>
</Popover>
}
>
<div>{props.icon}</div>

@ -5,7 +5,7 @@ import { fileDecoration } from '../../types'
const FileDecorationWarningIcon = (props: {
fileDecoration: fileDecoration
}) => {
return <><span data-id={`file-decoration-warning-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-warning pr-2`}>{props.fileDecoration.text}</span></>
return <><span data-id={`file-decoration-warning-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-warning pr-2`}>{props.fileDecoration.text}</span></>
}
export default FileDecorationWarningIcon

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save