From 062cae25f30ac111c8b7dac6d55bd3e1b11f052a Mon Sep 17 00:00:00 2001 From: Rory Date: Sun, 22 Aug 2021 09:49:52 +1000 Subject: [PATCH 01/19] Allow compiler language selection via query parameter, fixes #1489 --- apps/remix-ide-e2e/src/tests/url.spec.ts | 3 ++- .../solidity-compiler/src/lib/compiler-container.tsx | 9 ++++++--- .../solidity-compiler/src/lib/logic/compileTabLogic.ts | 10 ++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/url.spec.ts b/apps/remix-ide-e2e/src/tests/url.spec.ts index 9d7e8e323e..13227238f7 100644 --- a/apps/remix-ide-e2e/src/tests/url.spec.ts +++ b/apps/remix-ide-e2e/src/tests/url.spec.ts @@ -77,12 +77,13 @@ module.exports = { 'Should load using URL compiler params': function (browser: NightwatchBrowser) { browser .pause(5000) - .url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js') + .url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul') .refresh() .pause(5000) .clickLaunchIcon('solidity') .assert.containsText('#versionSelector option[data-id="selected"]', '0.7.4+commit.3f05b770') .assert.containsText('#evmVersionSelector option[data-id="selected"]', 'istanbul') + .assert.containsText('#compilierLanguageSelector option[data-id="selected"]', 'Yul') .verify.elementPresent('#optimize:checked') .verify.elementPresent('#autoCompile:checked') .verify.attributeEquals('#runs', 'value', '300') diff --git a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx index eabccbd8a8..f1b88e90a1 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx +++ b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx @@ -7,6 +7,7 @@ import { canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL, promi import { compilerReducer, compilerInitialState } from './reducers/compiler' import { resetEditorMode, listenToEvents } from './actions/compiler' import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line +import { helpers } from '@remix-project/remix-lib' import './css/style.css' @@ -74,6 +75,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { const optimize = params.optimize const runs = params.runs as string const evmVersion = params.evmVersion + const language = helpers.compiler.getValidLanguage(params.language) return { ...prevState, @@ -82,7 +84,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => { includeNightlies: includeNightlies, optimize: optimize, runs: runs, - evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default' + evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default', + language: (language !== null) ? language : 'Solidity' } }) } @@ -537,8 +540,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts index c938cdb633..db24685e3a 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts @@ -15,6 +15,7 @@ export class CompileTabLogic { public optimize public runs public evmVersion: string + public language: string public compilerImport public event @@ -39,6 +40,13 @@ export class CompileTabLogic { } this.api.setCompilerParameters({ evmVersion: this.evmVersion }) this.compiler.set('evmVersion', this.evmVersion) + + this.language = this.api.getParameters().language + if(this.language === 'undefined' || this.language === 'null' || !this.language) { + this.language = null + } + this.api.setParameters({ 'language': this.language }) + this.compiler.set('language', this.language) } setOptimize (newOptimizeValue) { @@ -68,6 +76,8 @@ export class CompileTabLogic { * @params lang {'Solidity' | 'Yul'} ... */ setLanguage (lang) { + this.language = lang; + this.api.setParameters({ language: lang }) this.compiler.set('language', lang) } From 8d6c014fda2480f2932d7e836406bf39b1fb8b27 Mon Sep 17 00:00:00 2001 From: Rory Date: Fri, 27 Aug 2021 16:38:36 +1000 Subject: [PATCH 02/19] Adding helper method for checking compiler language before setting --- libs/remix-lib/src/helpers/compilerHelper.ts | 12 ++++++++ libs/remix-lib/test/compilerHelper.ts | 29 +++++++++++++++++++ libs/remix-lib/test/tests.ts | 1 + .../src/lib/logic/compileTabLogic.ts | 13 ++++----- 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 libs/remix-lib/test/compilerHelper.ts diff --git a/libs/remix-lib/src/helpers/compilerHelper.ts b/libs/remix-lib/src/helpers/compilerHelper.ts index 1681520c95..124c71fcc5 100644 --- a/libs/remix-lib/src/helpers/compilerHelper.ts +++ b/libs/remix-lib/src/helpers/compilerHelper.ts @@ -1,3 +1,5 @@ +import {Language} from "@remix-project/remix-solidity-ts"; + export function compilerInput (contracts) { return JSON.stringify({ language: 'Solidity', @@ -20,3 +22,13 @@ export function compilerInput (contracts) { } }) } + +export const Languages = ['Solidity', 'Yul'] + +export function getValidLanguage (val: string): Language { + if (val !== undefined && val !== null && val) { + const lang = val.slice(0, 1).toUpperCase() + val.slice(1).toLowerCase() + return Languages.indexOf(lang) > -1 ? lang as Language : null + } + return null +} diff --git a/libs/remix-lib/test/compilerHelper.ts b/libs/remix-lib/test/compilerHelper.ts new file mode 100644 index 0000000000..27a05842db --- /dev/null +++ b/libs/remix-lib/test/compilerHelper.ts @@ -0,0 +1,29 @@ +'use strict' +import tape from 'tape' +import { getValidLanguage } from "../src/helpers/compilerHelper"; +import { Language } from "@remix-project/remix-solidity-ts"; + +tape('compilerHelper', function (t) { + t.test('lowerbound', function (st) { + st.plan(9) + + const correctYul: Language = 'Yul'; + const correctSolidity: Language = 'Solidity'; + + const yulUpperCase = 'Yul' + const yulLowerCase = 'yul' + + const solidityUpperCase = 'Solidity' + const solidityLowerCase = 'solidity' + + st.equal(getValidLanguage(yulLowerCase), correctYul) + st.equal(getValidLanguage(yulUpperCase), correctYul) + st.equal(getValidLanguage(solidityUpperCase), correctSolidity) + st.equal(getValidLanguage(solidityLowerCase), correctSolidity) + st.equal(getValidLanguage(null), null) + st.equal(getValidLanguage(undefined), null) + st.equal(getValidLanguage(''), null) + st.equal(getValidLanguage('A'), null) + st.equal(getValidLanguage('Something'), null) + }) +}) diff --git a/libs/remix-lib/test/tests.ts b/libs/remix-lib/test/tests.ts index 2921875905..3c8178a587 100644 --- a/libs/remix-lib/test/tests.ts +++ b/libs/remix-lib/test/tests.ts @@ -3,3 +3,4 @@ require('./util.ts') require('./txFormat.ts') require('./txHelper.ts') require('./txResultHelper.ts') +require('./compilerHelper.ts') diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts index db24685e3a..7441194206 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts @@ -1,4 +1,5 @@ import { ICompilerApi } from '@remix-project/remix-lib-ts' +import { helpers } from '@remix-project/remix-lib' const Compiler = require('@remix-project/remix-solidity').Compiler const EventEmitter = require('events') @@ -41,12 +42,10 @@ export class CompileTabLogic { this.api.setCompilerParameters({ evmVersion: this.evmVersion }) this.compiler.set('evmVersion', this.evmVersion) - this.language = this.api.getParameters().language - if(this.language === 'undefined' || this.language === 'null' || !this.language) { - this.language = null + this.language = helpers.compiler.getValidLanguage(this.api.getCompilerParameters().language) + if (this.language != null) { + this.compiler.set('language', this.language) } - this.api.setParameters({ 'language': this.language }) - this.compiler.set('language', this.language) } setOptimize (newOptimizeValue) { @@ -76,8 +75,8 @@ export class CompileTabLogic { * @params lang {'Solidity' | 'Yul'} ... */ setLanguage (lang) { - this.language = lang; - this.api.setParameters({ language: lang }) + this.language = lang + this.api.setCompilerParameters({ language: lang }) this.compiler.set('language', lang) } From 7be12dd1b2942c7f63e2b9a03587d2f7e2fb0991 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 11 Jan 2022 15:23:14 +0100 Subject: [PATCH 03/19] fix references --- libs/remix-lib/src/helpers/compilerHelper.ts | 12 ------------ libs/remix-solidity/src/compiler/compiler-input.ts | 13 ++++++++++++- libs/remix-solidity/src/index.ts | 2 +- .../test/compiler-input.ts} | 8 ++++---- libs/remix-solidity/tsconfig.json | 3 ++- .../src/lib/compiler-container.tsx | 4 ++-- .../src/lib/logic/compileTabLogic.ts | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) rename libs/{remix-lib/test/compilerHelper.ts => remix-solidity/test/compiler-input.ts} (79%) diff --git a/libs/remix-lib/src/helpers/compilerHelper.ts b/libs/remix-lib/src/helpers/compilerHelper.ts index 124c71fcc5..1681520c95 100644 --- a/libs/remix-lib/src/helpers/compilerHelper.ts +++ b/libs/remix-lib/src/helpers/compilerHelper.ts @@ -1,5 +1,3 @@ -import {Language} from "@remix-project/remix-solidity-ts"; - export function compilerInput (contracts) { return JSON.stringify({ language: 'Solidity', @@ -22,13 +20,3 @@ export function compilerInput (contracts) { } }) } - -export const Languages = ['Solidity', 'Yul'] - -export function getValidLanguage (val: string): Language { - if (val !== undefined && val !== null && val) { - const lang = val.slice(0, 1).toUpperCase() + val.slice(1).toLowerCase() - return Languages.indexOf(lang) > -1 ? lang as Language : null - } - return null -} diff --git a/libs/remix-solidity/src/compiler/compiler-input.ts b/libs/remix-solidity/src/compiler/compiler-input.ts index 2baabecc79..85a17a3c53 100644 --- a/libs/remix-solidity/src/compiler/compiler-input.ts +++ b/libs/remix-solidity/src/compiler/compiler-input.ts @@ -1,6 +1,6 @@ 'use strict' -import { CompilerInput, Source, CompilerInputOptions } from './types' +import { CompilerInput, Source, CompilerInputOptions, Language } from './types' export default (sources: Source, opts: CompilerInputOptions): string => { const o: CompilerInput = { @@ -32,3 +32,14 @@ export default (sources: Source, opts: CompilerInputOptions): string => { } return JSON.stringify(o) } + +export const Languages = ['Solidity', 'Yul'] + +export function getValidLanguage (val: string): Language { + if (val !== undefined && val !== null && val) { + const lang = val.slice(0, 1).toUpperCase() + val.slice(1).toLowerCase() + return Languages.indexOf(lang) > -1 ? lang as Language : null + } + return null +} + diff --git a/libs/remix-solidity/src/index.ts b/libs/remix-solidity/src/index.ts index 7de163dc97..d5878a0f85 100644 --- a/libs/remix-solidity/src/index.ts +++ b/libs/remix-solidity/src/index.ts @@ -1,6 +1,6 @@ export { Compiler } from './compiler/compiler' export { compile } from './compiler/compiler-helpers' -export { default as CompilerInput } from './compiler/compiler-input' +export { default as CompilerInput, getValidLanguage } from './compiler/compiler-input' export { CompilerAbstract } from './compiler/compiler-abstract' export * from './compiler/types' export { promisedMiniXhr, pathToURL, baseURLBin, baseURLWasm, canUseWorker, urlFromVersion } from './compiler/compiler-utils' diff --git a/libs/remix-lib/test/compilerHelper.ts b/libs/remix-solidity/test/compiler-input.ts similarity index 79% rename from libs/remix-lib/test/compilerHelper.ts rename to libs/remix-solidity/test/compiler-input.ts index 27a05842db..8532b0838f 100644 --- a/libs/remix-lib/test/compilerHelper.ts +++ b/libs/remix-solidity/test/compiler-input.ts @@ -1,10 +1,10 @@ 'use strict' import tape from 'tape' -import { getValidLanguage } from "../src/helpers/compilerHelper"; -import { Language } from "@remix-project/remix-solidity-ts"; +import { getValidLanguage } from "../src/compiler/compiler-input"; +import { Language } from "../src/compiler/types"; -tape('compilerHelper', function (t) { - t.test('lowerbound', function (st) { +tape('compiler-input', function (t) { + t.test('getValidLanguage', function (st) { st.plan(9) const correctYul: Language = 'Yul'; diff --git a/libs/remix-solidity/tsconfig.json b/libs/remix-solidity/tsconfig.json index 5ed408bd51..7f163468b2 100644 --- a/libs/remix-solidity/tsconfig.json +++ b/libs/remix-solidity/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "types": ["node"] + "types": ["node"], + "esModuleInterop": true }, "include": ["**/*.ts"] } \ No newline at end of file diff --git a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx index f1b88e90a1..398250a3dd 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx +++ b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx @@ -7,7 +7,7 @@ import { canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL, promi import { compilerReducer, compilerInitialState } from './reducers/compiler' import { resetEditorMode, listenToEvents } from './actions/compiler' import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line -import { helpers } from '@remix-project/remix-lib' +import { getValidLanguage } from '@remix-project/remix-solidity' import './css/style.css' @@ -75,7 +75,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { const optimize = params.optimize const runs = params.runs as string const evmVersion = params.evmVersion - const language = helpers.compiler.getValidLanguage(params.language) + const language = getValidLanguage(params.language) return { ...prevState, diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts index 7441194206..bb301dc402 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts @@ -1,5 +1,5 @@ import { ICompilerApi } from '@remix-project/remix-lib-ts' -import { helpers } from '@remix-project/remix-lib' +import { getValidLanguage } from '@remix-project/remix-solidity' const Compiler = require('@remix-project/remix-solidity').Compiler const EventEmitter = require('events') @@ -42,7 +42,7 @@ export class CompileTabLogic { this.api.setCompilerParameters({ evmVersion: this.evmVersion }) this.compiler.set('evmVersion', this.evmVersion) - this.language = helpers.compiler.getValidLanguage(this.api.getCompilerParameters().language) + this.language = getValidLanguage(this.api.getCompilerParameters().language) if (this.language != null) { this.compiler.set('language', this.language) } From 93361a3f3cf0e0baf29a5d26079e39f22b546f78 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 11 Jan 2022 16:12:30 +0100 Subject: [PATCH 04/19] fix test --- libs/remix-lib/test/tests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/remix-lib/test/tests.ts b/libs/remix-lib/test/tests.ts index 3c8178a587..2921875905 100644 --- a/libs/remix-lib/test/tests.ts +++ b/libs/remix-lib/test/tests.ts @@ -3,4 +3,3 @@ require('./util.ts') require('./txFormat.ts') require('./txHelper.ts') require('./txResultHelper.ts') -require('./compilerHelper.ts') From 6201a956ca15fb78c6815e6e20387057d0d7d910 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 11 Jan 2022 16:20:06 +0100 Subject: [PATCH 05/19] linting --- libs/remix-solidity/src/compiler/compiler-input.ts | 1 - libs/remix-solidity/test/compiler-input.ts | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/remix-solidity/src/compiler/compiler-input.ts b/libs/remix-solidity/src/compiler/compiler-input.ts index 85a17a3c53..8b00c647ee 100644 --- a/libs/remix-solidity/src/compiler/compiler-input.ts +++ b/libs/remix-solidity/src/compiler/compiler-input.ts @@ -42,4 +42,3 @@ export function getValidLanguage (val: string): Language { } return null } - diff --git a/libs/remix-solidity/test/compiler-input.ts b/libs/remix-solidity/test/compiler-input.ts index 8532b0838f..ba735ff023 100644 --- a/libs/remix-solidity/test/compiler-input.ts +++ b/libs/remix-solidity/test/compiler-input.ts @@ -1,14 +1,14 @@ 'use strict' import tape from 'tape' -import { getValidLanguage } from "../src/compiler/compiler-input"; -import { Language } from "../src/compiler/types"; +import { getValidLanguage } from '../src/compiler/compiler-input' +import { Language } from '../src/compiler/types' tape('compiler-input', function (t) { t.test('getValidLanguage', function (st) { st.plan(9) - const correctYul: Language = 'Yul'; - const correctSolidity: Language = 'Solidity'; + const correctYul: Language = 'Yul' + const correctSolidity: Language = 'Solidity' const yulUpperCase = 'Yul' const yulLowerCase = 'yul' From 6a26145d6f9c1fb6e1a86297c6470d916d68e743 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Jan 2022 09:32:13 +0100 Subject: [PATCH 06/19] fix tests --- libs/remix-solidity/jest.config.js | 24 +++++++++++++++ libs/remix-solidity/package.json | 1 - libs/remix-solidity/test/compiler-input.ts | 29 ------------------- .../tests/compiler-input.spec.ts | 25 ++++++++++++++++ libs/remix-solidity/tsconfig.json | 3 +- workspace.json | 6 ++-- 6 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 libs/remix-solidity/jest.config.js delete mode 100644 libs/remix-solidity/test/compiler-input.ts create mode 100644 libs/remix-solidity/tests/compiler-input.spec.ts diff --git a/libs/remix-solidity/jest.config.js b/libs/remix-solidity/jest.config.js new file mode 100644 index 0000000000..abfff6a986 --- /dev/null +++ b/libs/remix-solidity/jest.config.js @@ -0,0 +1,24 @@ +module.exports = { + name: 'remix-solidity', + preset: '../../jest.config.js', + verbose: true, + silent: false, // Silent console messages, specially the 'remix-simulator' ones + transform: { + '^.+\\.[tj]sx?$': 'ts-jest', + }, + transformIgnorePatterns: ["/node_modules/", "/dist/", "\\.pnp\\.[^\\\/]+$"], + rootDir: "./", + testTimeout: 40000, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'], + // Coverage + collectCoverage: true, + coverageReporters: ['text', 'text-summary'], + collectCoverageFrom: [ + "**/*.ts", + "!**/sol/**", + "!src/types.ts", + "!src/logger.ts" + ], + coverageDirectory: '../../coverage/libs/remix-solidity' + }; + \ No newline at end of file diff --git a/libs/remix-solidity/package.json b/libs/remix-solidity/package.json index 7f90f6ee3c..fdfaca6c02 100644 --- a/libs/remix-solidity/package.json +++ b/libs/remix-solidity/package.json @@ -41,7 +41,6 @@ "@types/node": "^13.1.1", "babel-eslint": "^10.0.0", "babelify": "^10.0.0", - "tape": "^4.6.0", "typescript": "^3.7.4" }, "scripts": { diff --git a/libs/remix-solidity/test/compiler-input.ts b/libs/remix-solidity/test/compiler-input.ts deleted file mode 100644 index ba735ff023..0000000000 --- a/libs/remix-solidity/test/compiler-input.ts +++ /dev/null @@ -1,29 +0,0 @@ -'use strict' -import tape from 'tape' -import { getValidLanguage } from '../src/compiler/compiler-input' -import { Language } from '../src/compiler/types' - -tape('compiler-input', function (t) { - t.test('getValidLanguage', function (st) { - st.plan(9) - - const correctYul: Language = 'Yul' - const correctSolidity: Language = 'Solidity' - - const yulUpperCase = 'Yul' - const yulLowerCase = 'yul' - - const solidityUpperCase = 'Solidity' - const solidityLowerCase = 'solidity' - - st.equal(getValidLanguage(yulLowerCase), correctYul) - st.equal(getValidLanguage(yulUpperCase), correctYul) - st.equal(getValidLanguage(solidityUpperCase), correctSolidity) - st.equal(getValidLanguage(solidityLowerCase), correctSolidity) - st.equal(getValidLanguage(null), null) - st.equal(getValidLanguage(undefined), null) - st.equal(getValidLanguage(''), null) - st.equal(getValidLanguage('A'), null) - st.equal(getValidLanguage('Something'), null) - }) -}) diff --git a/libs/remix-solidity/tests/compiler-input.spec.ts b/libs/remix-solidity/tests/compiler-input.spec.ts new file mode 100644 index 0000000000..3dc247624b --- /dev/null +++ b/libs/remix-solidity/tests/compiler-input.spec.ts @@ -0,0 +1,25 @@ +import { getValidLanguage } from '../src/compiler/compiler-input' +import { Language } from '../src/compiler/types' + +describe('compiler-input', () => { + test('getValidLanguage', () => { + const correctYul: Language = 'Yul' + const correctSolidity: Language = 'Solidity' + + const yulUpperCase = 'Yul' + const yulLowerCase = 'yul' + + const solidityUpperCase = 'Solidity' + const solidityLowerCase = 'solidity' + + expect(getValidLanguage(yulLowerCase)).toBe(correctYul) + expect(getValidLanguage(yulUpperCase)).toBe(correctYul) + expect(getValidLanguage(solidityUpperCase)).toBe(correctSolidity) + expect(getValidLanguage(solidityLowerCase)).toBe(correctSolidity) + expect(getValidLanguage(null)).toBe(null) + expect(getValidLanguage(undefined)).toBe(null) + expect(getValidLanguage('')).toBe(null) + expect(getValidLanguage('A')).toBe(null) + expect(getValidLanguage('Something')).toBe(null) + }) +}) diff --git a/libs/remix-solidity/tsconfig.json b/libs/remix-solidity/tsconfig.json index 7f163468b2..ec3a5d0c25 100644 --- a/libs/remix-solidity/tsconfig.json +++ b/libs/remix-solidity/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "types": ["node"], - "esModuleInterop": true + "types": ["jest", "node"] }, "include": ["**/*.ts"] } \ No newline at end of file diff --git a/workspace.json b/workspace.json index 5ff3f1ca9f..8e78b40751 100644 --- a/workspace.json +++ b/workspace.json @@ -309,10 +309,10 @@ } }, "test": { - "builder": "@nrwl/workspace:run-commands", + "builder": "@nrwl/jest:jest", "options": { - "commands": ["./../../node_modules/.bin/npm-run-all test"], - "cwd": "libs/remix-solidity" + "jestConfig": "libs/remix-solidity/jest.config.js", + "tsConfig": "libs/remix-solidity/tsconfig.spec.json" } }, "build": { From 849eaf2815770d83cf14ba7294c5959f0a8e64e8 Mon Sep 17 00:00:00 2001 From: lianahus Date: Thu, 20 Jan 2022 10:32:00 +0100 Subject: [PATCH 07/19] fixed icons paddings on verticalicons plugin manager selection fix --- libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx | 1 - .../remix-ui/vertical-icons-panel/src/lib/components/Home.tsx | 2 +- .../remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx | 2 +- .../src/lib/remix-ui-vertical-icons-panel.css | 1 + .../src/lib/remix-ui-vertical-icons-panel.tsx | 4 ++-- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index 73bd4f0357..1d0f594f74 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -173,7 +173,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => { _paq.push(['trackEvent', 'pluginManager', 'userActivate', 'sourcify']) } const startPluginManager = async () => { - await plugin.appManager.activatePlugin('pluginManager') plugin.verticalIcons.select('pluginManager') } diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx index efeceed420..94a56bed15 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx @@ -7,7 +7,7 @@ interface HomeProps { function Home ({ verticalIconPlugin }: HomeProps) { return (
await verticalIconPlugin.activateHome()} {...{ plugin: 'home'}} title="Home" diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx index cb5cc56931..c9a08db34d 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx @@ -85,7 +85,7 @@ const Icon = ({ return ( <>
{ (verticalIconPlugin as any).toggle(name) }} diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css index c14e3bb47c..16bca4aa03 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css @@ -19,6 +19,7 @@ flex-flow: column nowrap; justify-content: space-between; align-items: center; + text-align: center; } .remixui_icon:hover { box-shadow: 0px 0px 14px -7px; diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx index 6d606d3149..a033b9e4e6 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx @@ -90,7 +90,7 @@ const RemixUiVerticalIconsPanel = ({ ) : null } @@ -113,7 +113,7 @@ const RemixUiVerticalIconsPanel = ({ { scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight ? () : null } Date: Thu, 20 Jan 2022 12:37:54 +0100 Subject: [PATCH 08/19] icon alignment fixed --- .../src/lib/components/Icon.tsx | 2 +- .../src/lib/components/IconList.tsx | 2 +- .../src/lib/remix-ui-vertical-icons-panel.css | 12 +++------ .../src/lib/remix-ui-vertical-icons-panel.tsx | 26 +++++++++---------- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx index c9a08db34d..a0aa750e73 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx @@ -85,7 +85,7 @@ const Icon = ({ return ( <>
{ (verticalIconPlugin as any).toggle(name) }} diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx index b41a417ddd..1e22d528d2 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx @@ -12,7 +12,7 @@ interface OtherIconsProps { function IconList ({ verticalIconsPlugin, itemContextAction, icons, theme }: OtherIconsProps) { return ( -
+
{ icons .map(p => ( diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css index 16bca4aa03..42d8ddbbce 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css @@ -19,7 +19,6 @@ flex-flow: column nowrap; justify-content: space-between; align-items: center; - text-align: center; } .remixui_icon:hover { box-shadow: 0px 0px 14px -7px; @@ -30,6 +29,7 @@ width: 36px; height: 36px; border-radius: 8px; + align-items: center; } .remixui_icon img { width: 28px; @@ -40,15 +40,12 @@ .remixui_icon .selected-dark { filter: invert(1) grayscale(1); - } .remixui_icon .selected-light { filter: invert(0) grayscale(1); } - .remixui_image { - } .remixui_icon svg { width: 28px; height: 28px; @@ -120,9 +117,12 @@ } .remixui_default-icons-container { border-bottom: 2px solid #3f4455; + text-align: center; } .remixui_icon-chevron { z-index: 1000; + cursor: pointer; + align-items: center; } .remixui_settings { @@ -133,7 +133,3 @@ list-style: none; margin: 0px; } - - .remixui_icon-chevron { - cursor: pointer; - } \ No newline at end of file diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx index a033b9e4e6..3d4413eb4d 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx @@ -109,19 +109,19 @@ const RemixUiVerticalIconsPanel = ({ itemContextAction={itemContextAction} />
-
- { scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight ? () : null } - p.profile.name === 'settings' || p.profile.name === 'pluginManager')} - verticalIconsPlugin={verticalIconsPlugin} - itemContextAction={itemContextAction} - /> -
+
+ { scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight ? () : null } + p.profile.name === 'settings' || p.profile.name === 'pluginManager')} + verticalIconsPlugin={verticalIconsPlugin} + itemContextAction={itemContextAction} + /> +
) From 2aa45e37cfdd3b668937fe9b14e90ae3c76a787e Mon Sep 17 00:00:00 2001 From: lianahus Date: Thu, 20 Jan 2022 14:20:29 +0100 Subject: [PATCH 09/19] cleanup --- .../vertical-icons-panel/src/lib/components/IconList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx index 1e22d528d2..b41a417ddd 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx @@ -12,7 +12,7 @@ interface OtherIconsProps { function IconList ({ verticalIconsPlugin, itemContextAction, icons, theme }: OtherIconsProps) { return ( -
+
{ icons .map(p => ( From 8080cde4ec21d10d895ae688d5d97ca33adc06e2 Mon Sep 17 00:00:00 2001 From: lianahus Date: Thu, 20 Jan 2022 17:06:14 +0100 Subject: [PATCH 10/19] fixed remixd modal text typo --- apps/remix-ide/src/app/plugins/remixd-handle.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/app/plugins/remixd-handle.tsx b/apps/remix-ide/src/app/plugins/remixd-handle.tsx index 68367d1df3..fd33c03a0c 100644 --- a/apps/remix-ide/src/app/plugins/remixd-handle.tsx +++ b/apps/remix-ide/src/app/plugins/remixd-handle.tsx @@ -155,7 +155,7 @@ function remixdDialog () {
- Before using, make sure remixd version is latest i.e. ${remixdVersion} + Before using, make sure remixd version is latest i.e. v{remixdVersion}

Read here how to update it
From 9e1b5b98fe96dad7bc10c3c844e49ab9287aeb0d Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 20 Jan 2022 12:36:42 +0100 Subject: [PATCH 11/19] fix toaster when using plugin api to update provider --- apps/remix-ide-e2e/src/tests/plugin_api.ts | 12 ++++++++++++ libs/remix-ui/run-tab/src/lib/run-tab.tsx | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index d3df343415..fc09a9c8f1 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -149,6 +149,18 @@ module.exports = { await clickAndCheckLog(browser, 'udapp:getAccounts', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', null, null) }, + 'Should select another provider #group1': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'udapp:setEnvironmentMode', null, null, { context: 'vm', fork: 'berlin' }) + await browser + .frameParent() + .useCss() + .clickLaunchIcon('udapp') + .waitForElementContainsText('#selectExEnvOptions option:checked', 'JavaScript VM (Berlin)') + .clickLaunchIcon('localPlugin') + .useXpath() + // @ts-ignore + .frame(0) + }, // context menu item 'Should create context menu item #group1': async function (browser: NightwatchBrowser) { diff --git a/libs/remix-ui/run-tab/src/lib/run-tab.tsx b/libs/remix-ui/run-tab/src/lib/run-tab.tsx index 3dc10d1e52..8cf8615b09 100644 --- a/libs/remix-ui/run-tab/src/lib/run-tab.tsx +++ b/libs/remix-ui/run-tab/src/lib/run-tab.tsx @@ -205,7 +205,7 @@ export function RunTabUI (props: RunTabProps) { {from} is changing your environment to - {env} + {env && env.context}
) From 9cf96b2adad0824b6fbf6faa96cc6ada8b0df60c Mon Sep 17 00:00:00 2001 From: lianahus Date: Thu, 20 Jan 2022 17:39:39 +0100 Subject: [PATCH 12/19] fixed other places --- apps/remix-ide/src/app/plugins/remixd-handle.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/remixd-handle.tsx b/apps/remix-ide/src/app/plugins/remixd-handle.tsx index fd33c03a0c..9ff3d8339f 100644 --- a/apps/remix-ide/src/app/plugins/remixd-handle.tsx +++ b/apps/remix-ide/src/app/plugins/remixd-handle.tsx @@ -142,11 +142,11 @@ function remixdDialog () {
If you are just looking for the remixd command, here it is: -



${commandText} +



{commandText}
- When connected, a session will be started between ${window.location.origin} and your local file system at ws://127.0.0.1:65520. + When connected, a session will be started between {window.location.origin} and your local file system at ws://127.0.0.1:65520. The shared folder will be in the "File Explorers" workspace named "localhost".
Read more about other Remixd ports usage
From 13e1359364912433acc4d389008f768a28a57279 Mon Sep 17 00:00:00 2001 From: lianahus Date: Mon, 24 Jan 2022 09:14:24 +0100 Subject: [PATCH 13/19] icons padding on verticals --- .../src/lib/remix-ui-vertical-icons-panel.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css index 42d8ddbbce..5fd6e085ee 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css @@ -104,9 +104,13 @@ scrollbar-width: none; /* Firefox hide scrollbar */ -ms-overflow-style: none; } + .remixui_requiredSection { + text-align: center; + } .remixui_scrollable-container { flex-basis: 510px; flex-grow: 2; + text-align: center; /* border-bottom: 3px solid #3f4455; */ } .remixui_scrollbar::-webkit-scrollbar { /* Chrome, Safari and other Webkit browsers*/ From 6d1df98d1328937fdc1093a3b95a680e6ecefb7a Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 24 Jan 2022 11:09:06 +0100 Subject: [PATCH 14/19] add download backup in homepage --- .../home-tab/src/lib/remix-ui-home-tab.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index 1d0f594f74..5f1b8f6f87 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -1,6 +1,7 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import './remix-ui-home-tab.css' +import JSZip from 'jszip' import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import PluginButton from './components/pluginButton' // eslint-disable-line @@ -175,6 +176,43 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => { const startPluginManager = async () => { plugin.verticalIcons.select('pluginManager') } + const 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) { + var 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 + } + const downloadFiles = async () => { + try { + plugin.call('notification', 'toast', 'preparing files for download, please wait..') + const zip = new JSZip() + const browserProvider = fileManager.getProvider('browser') + await browserProvider.copyFolderToJson('/', ({ path, content }) => { + zip.file(path, content) + }) + zip.generateAsync({ type: 'blob' }).then(function (blob) { + var today = new Date() + var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate() + var time = today.getHours() + 'h' + today.getMinutes() + 'min' + saveAs(blob, `remix-backup-at-${time}-${date}.zip`) + }).catch((e) => { + plugin.call('notification', 'toast', e.message) + }) + } catch (e) { + plugin.call('notification', 'toast', e.message) + } + } const showFullMessage = (title: string, loadItem: string, examples: Array) => { setState(prevState => { @@ -279,6 +317,10 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {

+

+ + +

From a734fe8657db392d43a526162a7af1238d07e0b1 Mon Sep 17 00:00:00 2001 From: lianahus Date: Tue, 25 Jan 2022 10:44:24 +0100 Subject: [PATCH 15/19] added Scam lert to home --- .../home-tab/src/lib/remix-ui-home-tab.tsx | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index 5f1b8f6f87..d9c4850dc4 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -266,18 +266,28 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
-
-
- + +
+
+
+ +
+
+ playRemi() } alt=""> + +
-
- playRemi() } alt=""> - +
+ + + Scam Alert: Beware of Youtube videos promoting "liquidity front runner bots" saying to paste contract code into Remix IDE. + + More here
From 6187f35e0d4b614444cce431a3d81c7d1f67cffb Mon Sep 17 00:00:00 2001 From: lianahus Date: Tue, 25 Jan 2022 10:56:22 +0100 Subject: [PATCH 16/19] updates --- libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index d9c4850dc4..ace8ad155e 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -266,7 +266,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
-
@@ -283,11 +282,11 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
- + - Scam Alert: Beware of Youtube videos promoting "liquidity front runner bots" saying to paste contract code into Remix IDE. + Scam Alert: Beware of Youtube videos promoting "liquidity front runner bots" asking to paste contract code into Remix IDE. - More here + Learn more
From 8c49bfbc84504fe5a30af407ea074717d2082a6f Mon Sep 17 00:00:00 2001 From: David Disu Date: Tue, 25 Jan 2022 12:51:23 +0100 Subject: [PATCH 17/19] Fixed modal title for folder creation --- libs/remix-ui/workspace/src/lib/actions/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 390a1ff44d..e9bc5d1a62 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -179,7 +179,7 @@ export const createNewFolder = async (path: string, rootDir: string) => { const exists = await fileManager.exists(dirName) if (exists) { - return dispatch(displayNotification('Rename File Failed', `A file or folder ${extractNameFromKey(path)} already exists at this location. Please choose a different name.`, 'Close', null, () => {})) + return dispatch(displayNotification('Failed to create folder', `A folder ${extractNameFromKey(path)} already exists at this location. Please choose a different name.`, 'Close', null, () => {})) } await fileManager.mkdir(dirName) path = path.indexOf(rootDir + '/') === 0 ? path.replace(rootDir + '/', '') : path From a67d70b841053e1234e5e0af573d101b1bcdad1c Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 24 Jan 2022 12:22:08 +0100 Subject: [PATCH 18/19] fix loop over references --- .../src/commands/currentSelectedFileIs.ts | 15 ++ apps/remix-ide-e2e/src/tests/editor.test.ts | 211 ++++++++++++++++++ apps/remix-ide-e2e/src/types/index.d.ts | 1 + apps/remix-ide/src/app/editor/editor.js | 2 +- .../src/lib/editor-context-listener.ts | 22 +- .../src/lib/remix-ui-editor-context-view.tsx | 98 ++++---- .../editor/src/lib/remix-ui-editor.tsx | 3 +- libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx | 4 +- 8 files changed, 302 insertions(+), 54 deletions(-) create mode 100644 apps/remix-ide-e2e/src/commands/currentSelectedFileIs.ts diff --git a/apps/remix-ide-e2e/src/commands/currentSelectedFileIs.ts b/apps/remix-ide-e2e/src/commands/currentSelectedFileIs.ts new file mode 100644 index 0000000000..81164cb97a --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/currentSelectedFileIs.ts @@ -0,0 +1,15 @@ +import { NightwatchBrowser } from 'nightwatch' +import EventEmitter from 'events' + +class CurrentSelectedFileIs extends EventEmitter { + command (this: NightwatchBrowser, value: string): NightwatchBrowser { + this.api + .waitForElementContainsText('*[data-id="tabs-component"] *[data-id="tab-active"]', value) + .perform(() => { + this.emit('complete') + }) + return this + } +} + +module.exports = CurrentSelectedFileIs diff --git a/apps/remix-ide-e2e/src/tests/editor.test.ts b/apps/remix-ide-e2e/src/tests/editor.test.ts index 7b714a432b..59c3211e79 100644 --- a/apps/remix-ide-e2e/src/tests/editor.test.ts +++ b/apps/remix-ide-e2e/src/tests/editor.test.ts @@ -147,6 +147,7 @@ module.exports = { .waitForElementContainsText('.contextview .type', 'uint256') .waitForElementContainsText('.contextview .name', 'number') .click('.contextview [data-action="previous"]') // declaration + .pause(1000) .execute(() => { return (document.getElementById('editorView') as any).getCursorPosition() }, [], (result) => { @@ -154,6 +155,7 @@ module.exports = { browser.assert.equal(result.value, '180') }) .click('.contextview [data-action="next"]') // back to the initial state + .pause(1000) .execute(() => { return (document.getElementById('editorView') as any).getCursorPosition() }, [], (result) => { @@ -161,6 +163,7 @@ module.exports = { browser.assert.equal(result.value, '323') }) .click('.contextview [data-action="next"]') // next reference + .pause(1000) .execute(() => { return (document.getElementById('editorView') as any).getCursorPosition() }, [], (result) => { @@ -168,12 +171,74 @@ module.exports = { browser.assert.equal(result.value, '489') }) .click('.contextview [data-action="gotoref"]') // back to the declaration + .pause(1000) .execute(() => { return (document.getElementById('editorView') as any).getCursorPosition() }, [], (result) => { console.log('result', result) browser.assert.equal(result.value, '180') }) + }, + + 'Should display the context view, loop over "Owner" by switching file #group2': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('solidity') + .click('[for="autoCompile"]') // disable auto compile + .openFile('contracts') + .openFile('contracts/3_Ballot.sol') + .waitForElementVisible('#editorView') + .setEditorValue(BallotWithARefToOwner) + .clickLaunchIcon('solidity') + .click('*[data-id="compilerContainerCompileBtn"]') // compile + .pause(2000) + .execute(() => { + (document.getElementById('editorView') as any).gotoLine(14, 6) + }, [], () => {}) + .waitForElementVisible('.contextview') + .waitForElementContainsText('.contextview .type', 'ContractDefinition') + .waitForElementContainsText('.contextview .name', 'Owner') + .click('.contextview [data-action="next"]') + .pause(1000) + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '1061') + }) + .click('.contextview [data-action="next"]') + .pause(1000) + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '122') + }) + .currentSelectedFileIs('2_Owner.sol') // make sure the current file has been properly changed + .click('.contextview [data-action="next"]') + .pause(1000) + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '211') + }) + .click('.contextview [data-action="next"]') + .currentSelectedFileIs('3_Ballot.sol') + .pause(1000) + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '1061') + }) + .click('.contextview [data-action="gotoref"]') // go to the declaration + .pause(1000) + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '122') + }) .end() } } @@ -281,3 +346,149 @@ contract Storage { return number; } }` + +const BallotWithARefToOwner = ` + + +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +import "./2_Owner.sol"; + +/** + * @title Ballot + * @dev Implements voting process along with vote delegation + */ +contract Ballot { + Owner c; + struct Voter { + uint weight; // weight is accumulated by delegation + bool voted; // if true, that person already voted + address delegate; // person delegated to + uint vote; // index of the voted proposal + } + + struct Proposal { + // If you can limit the length to a certain number of bytes, + // always use one of bytes1 to bytes32 because they are much cheaper + bytes32 name; // short name (up to 32 bytes) + uint voteCount; // number of accumulated votes + } + + address public chairperson; + + mapping(address => Voter) public voters; + + Proposal[] public proposals; + + /** + * @dev Create a new ballot to choose one of 'proposalNames'. + * @param proposalNames names of proposals + */ + constructor(bytes32[] memory proposalNames) { + c = new Owner(); + chairperson = msg.sender; + voters[chairperson].weight = 1; + + for (uint i = 0; i < proposalNames.length; i++) { + // 'Proposal({...})' creates a temporary + // Proposal object and 'proposals.push(...)' + // appends it to the end of 'proposals'. + proposals.push(Proposal({ + name: proposalNames[i], + voteCount: 0 + })); + } + } + + /** + * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. + * @param voter address of voter + */ + function giveRightToVote(address voter) public { + require( + msg.sender == chairperson, + "Only chairperson can give right to vote." + ); + require( + !voters[voter].voted, + "The voter already voted." + ); + require(voters[voter].weight == 0); + voters[voter].weight = 1; + } + + /** + * @dev Delegate your vote to the voter 'to'. + * @param to address to which vote is delegated + */ + function delegate(address to) public { + Voter storage sender = voters[msg.sender]; + require(!sender.voted, "You already voted."); + require(to != msg.sender, "Self-delegation is disallowed."); + + while (voters[to].delegate != address(0)) { + to = voters[to].delegate; + + // We found a loop in the delegation, not allowed. + require(to != msg.sender, "Found loop in delegation."); + } + sender.voted = true; + sender.delegate = to; + Voter storage delegate_ = voters[to]; + if (delegate_.voted) { + // If the delegate already voted, + // directly add to the number of votes + proposals[delegate_.vote].voteCount += sender.weight; + } else { + // If the delegate did not vote yet, + // add to her weight. + delegate_.weight += sender.weight; + } + } + + /** + * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. + * @param proposal index of proposal in the proposals array + */ + function vote(uint proposal) public { + Voter storage sender = voters[msg.sender]; + require(sender.weight != 0, "Has no right to vote"); + require(!sender.voted, "Already voted."); + sender.voted = true; + sender.vote = proposal; + + // If 'proposal' is out of the range of the array, + // this will throw automatically and revert all + // changes. + proposals[proposal].voteCount += sender.weight; + } + + /** + * @dev Computes the winning proposal taking all previous votes into account. + * @return winningProposal_ index of winning proposal in the proposals array + */ + function winningProposal() public view + returns (uint winningProposal_) + { + uint winningVoteCount = 0; + for (uint p = 0; p < proposals.length; p++) { + if (proposals[p].voteCount > winningVoteCount) { + winningVoteCount = proposals[p].voteCount; + winningProposal_ = p; + } + } + } + + /** + * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then + * @return winnerName_ the name of the winner + */ + function winnerName() public view + returns (bytes32 winnerName_) + { + winnerName_ = proposals[winningProposal()].name; + } +} +` diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index f9a7c35d63..9abe5c2174 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -61,6 +61,7 @@ declare module 'nightwatch' { acceptAndRemember (this: NightwatchBrowser, remember: boolean, accept: boolean): NightwatchBrowser clearConsole (this: NightwatchBrowser): NightwatchBrowser clearTransactions (this: NightwatchBrowser): NightwatchBrowser + currentSelectedFileIs (name: string): NightwatchBrowser } export interface NightwatchBrowser { diff --git a/apps/remix-ide/src/app/editor/editor.js b/apps/remix-ide/src/app/editor/editor.js index 013b1b9853..1bc0a00b82 100644 --- a/apps/remix-ide/src/app/editor/editor.js +++ b/apps/remix-ide/src/app/editor/editor.js @@ -438,7 +438,7 @@ class Editor extends Plugin { if (!filePath) return filePath = await this.call('fileManager', 'getPathFromUrl', filePath) filePath = filePath.file - if (!this.sessions[filePath]) throw new Error('file not found' + filePath) + if (!this.sessions[filePath]) return const path = filePath || this.currentFile const { from } = this.currentRequest diff --git a/libs/remix-core-plugin/src/lib/editor-context-listener.ts b/libs/remix-core-plugin/src/lib/editor-context-listener.ts index 7bde42de11..9e73f6bc01 100644 --- a/libs/remix-core-plugin/src/lib/editor-context-listener.ts +++ b/libs/remix-core-plugin/src/lib/editor-context-listener.ts @@ -84,11 +84,6 @@ export class EditorContextListener extends Plugin { async _highlightItems (cursorPosition, compilationResult, file) { if (this.currentPosition === cursorPosition) return - if (this.currentFile !== file) { - this.currentFile = file - this.currentPosition = cursorPosition - return - } this._stopHighlighting() this.currentPosition = cursorPosition this.currentFile = file @@ -122,9 +117,13 @@ export class EditorContextListener extends Plugin { async _highlight (node, compilationResult) { if (!node) return const position = sourceMappingDecoder.decode(node.src) + const fileTarget = compilationResult.getSourceName(position.file) + const nodeFound = this._activeHighlights.find((el) => el.fileTarget === fileTarget && el.position.file === position.file && el.position.length === position.length && el.position.start === position.start) + if (nodeFound) return // if the content is already highlighted, do nothing. + await this._highlightInternal(position, node, compilationResult) if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) { - this._activeHighlights.push({ position, fileTarget: compilationResult.getSourceName(position.file), nodeId: node.id }) + this._activeHighlights.push({ position, fileTarget, nodeId: node.id }) } } @@ -204,13 +203,16 @@ export class EditorContextListener extends Plugin { } _loadContractInfos (node) { + const path = (this.nodes.length && this.nodes[0].absolutePath) || this.results.source.target for (const i in this.nodes) { if (this.nodes[i].id === node.scope) { const contract = this.nodes[i] - this.contract = this.results.data.contracts[this.results.source.target][contract.name] - this.estimationObj = this.contract.evm.gasEstimates - this.creationCost = this.estimationObj === null ? '-' : this.estimationObj.creation.totalCost - this.codeDepositCost = this.estimationObj === null ? '-' : this.estimationObj.creation.codeDepositCost + this.contract = this.results.data.contracts[path][contract.name] + if (contract) { + this.estimationObj = this.contract.evm.gasEstimates + this.creationCost = this.estimationObj === null ? '-' : this.estimationObj.creation.totalCost + this.codeDepositCost = this.estimationObj === null ? '-' : this.estimationObj.creation.codeDepositCost + } } } } diff --git a/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx b/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx index d2668d57d3..7e25e32592 100644 --- a/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx +++ b/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx @@ -8,15 +8,26 @@ import './remix-ui-editor-context-view.css' export type astNode = { name: string, id: number, - children: Array, + children?: Array, typeDescriptions: any, nodeType: String, - src: any, - nodeId: any, - position: any + src: string // e.g "142:1361:0" +} + +export type nodePositionLight = { + file: number, + length: number, + start: number +} + +export type astNodeLight = { + fileTarget: String, + nodeId: number, + position: nodePositionLight } export type onContextListenerChangedListener = (nodes: Array) => void +export type ononCurrentFileChangedListener = (name: string) => void export type gasEstimationType = { executionCost: string, @@ -30,8 +41,9 @@ export interface RemixUiEditorContextViewProps { offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any, getCurrentFileName: () => String onContextListenerChanged: (listener: onContextListenerChangedListener) => void + onCurrentFileChanged: (listener: ononCurrentFileChangedListener) => void referencesOf: (nodes: astNode) => Array - getActiveHighlights: () => Array + getActiveHighlights: () => Array gasEstimation: (node: astNode) => gasEstimationType declarationOf: (node: astNode) => astNode } @@ -48,49 +60,56 @@ function isDefinition (node: any) { type nullableAstNode = astNode | null export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) { - /* - gotoLineDisableRef is used to temporarily disable the update of the view. - e.g when the user ask the component to "gotoLine" we don't want to rerender the component (but just to put the mouse on the desired line) - */ - const gotoLineDisableRef = useRef(false) + const loopOverReferences = useRef(0) + const currentNodeDeclaration = useRef(null) const [state, setState] = useState<{ nodes: Array, - references: Array, activeHighlights: Array - currentNode: nullableAstNode, gasEstimation: gasEstimationType }>({ nodes: [], - references: [], activeHighlights: [], - currentNode: null, gasEstimation: { executionCost: '', codeDepositCost: '' } }) useEffect(() => { + props.onCurrentFileChanged(() => { + currentNodeDeclaration.current = null + setState(prevState => { + return { ...prevState, nodes: [], activeHighlights: [] } + }) + }) + props.onContextListenerChanged(async (nodes: Array) => { - if (gotoLineDisableRef.current) { - gotoLineDisableRef.current = false - return - } - let currentNode + let nextNodeDeclaration + let nextNode if (!props.hide && nodes && nodes.length) { - currentNode = nodes[nodes.length - 1] - if (!isDefinition(currentNode)) { - currentNode = await props.declarationOf(currentNode) + nextNode = nodes[nodes.length - 1] + if (!isDefinition(nextNode)) { + nextNodeDeclaration = await props.declarationOf(nextNode) + } else { + nextNodeDeclaration = nextNode } } - let references + if (nextNodeDeclaration && currentNodeDeclaration.current && nextNodeDeclaration.id === currentNodeDeclaration.current.id) return + + currentNodeDeclaration.current = nextNodeDeclaration + let gasEstimation - if (currentNode) { - references = await props.referencesOf(currentNode) - if (currentNode.nodeType === 'FunctionDefinition') { - gasEstimation = await props.gasEstimation(currentNode) + if (currentNodeDeclaration.current) { + if (currentNodeDeclaration.current.nodeType === 'FunctionDefinition') { + gasEstimation = await props.gasEstimation(currentNodeDeclaration.current) } } - const activeHighlights = await props.getActiveHighlights() + const activeHighlights: Array = await props.getActiveHighlights() + if (nextNode && activeHighlights && activeHighlights.length) { + loopOverReferences.current = activeHighlights.findIndex((el: astNodeLight) => `${el.position.start}:${el.position.length}:${el.position.file}` === nextNode.src) + loopOverReferences.current = loopOverReferences.current === -1 ? 0 : loopOverReferences.current + } else { + loopOverReferences.current = 0 + } setState(prevState => { - return { ...prevState, nodes, references, activeHighlights, currentNode, gasEstimation } + return { ...prevState, nodes, activeHighlights, gasEstimation } }) }) }, []) @@ -123,8 +142,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) if (fileName !== await props.getCurrentFileName()) { await props.openFile(fileName) } - if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { - gotoLineDisableRef.current = true + if (lineColumn.start && lineColumn.start.line >= 0 && lineColumn.start.column >= 0) { props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) } } @@ -141,14 +159,14 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) } } - const _render = (node: nullableAstNode) => { + const _render = () => { + const node = currentNodeDeclaration.current if (!node) return (
) - const references = state.references + const references = state.activeHighlights const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType const referencesCount = `${references ? references.length : '0'} reference(s)` - let ref = 0 - const nodes: Array = state.activeHighlights + const nodes: Array = state.activeHighlights const jumpTo = () => { if (node && node.src) { @@ -161,10 +179,10 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) // JUMP BETWEEN REFERENCES const jump = (e: any) => { - e.target.dataset.action === 'next' ? ref++ : ref-- - if (ref < 0) ref = nodes.length - 1 - if (ref >= nodes.length) ref = 0 - _jumpToInternal(nodes[ref].position) + e.target.dataset.action === 'next' ? loopOverReferences.current++ : loopOverReferences.current-- + if (loopOverReferences.current < 0) loopOverReferences.current = nodes.length - 1 + if (loopOverReferences.current >= nodes.length) loopOverReferences.current = 0 + _jumpToInternal(nodes[loopOverReferences.current].position) } return ( @@ -181,7 +199,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) return ( !props.hide &&
- {_render(state.currentNode)} + {_render()}
) } diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx index 67df7cd443..82a18ef075 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -398,11 +398,12 @@ export const EditorUI = (props: EditorUIProps) => { props.plugin.call('editor', 'gotoLine', line, column)} - openFile={(file) => props.plugin.call('editor', 'openFile', file)} + openFile={(file) => props.plugin.call('fileManager', 'switchFile', file)} getLastCompilationResult={() => { return props.plugin.call('compilerArtefacts', 'getLastCompilationResult') } } offsetToLineColumn={(position, file, sources, asts) => { return props.plugin.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } } getCurrentFileName={() => { return props.plugin.call('fileManager', 'file') } } onContextListenerChanged={(listener) => { props.plugin.on('contextualListener', 'contextChanged', listener) }} + onCurrentFileChanged={(listener) => { props.plugin.on('fileManager', 'currentFileChanged', listener) }} referencesOf={(node: astNode) => { return props.plugin.call('contextualListener', 'referencesOf', node) }} getActiveHighlights={() => { return props.plugin.call('contextualListener', 'getActiveHighlights') }} gasEstimation={(node: astNode) => { return props.plugin.call('contextualListener', 'gasEstimation', node) }} diff --git a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx index 3c791d1c1b..45632fc4de 100644 --- a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx +++ b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx @@ -36,7 +36,7 @@ export const TabsUI = (props: TabsUIProps) => { const classNameImg = 'my-1 mr-1 text-dark ' + tab.iconClass const classNameTab = 'nav-item nav-link d-flex justify-content-center align-items-center px-2 py-1 tab' + (index === currentIndexRef.current ? ' active' : '') return ( -
{ tabsRef.current[index] = el }} className={classNameTab} title={tab.tooltip}> +
{ tabsRef.current[index] = el }} className={classNameTab} data-id={index === currentIndexRef.current ? 'tab-active' : ''} title={tab.tooltip}> {tab.icon ? () : ()} {tab.title} { props.onClose(index); event.stopPropagation() }}> @@ -74,7 +74,7 @@ export const TabsUI = (props: TabsUIProps) => { }, []) return ( -
+
props.onZoomOut()}> From 1c1774dcaa653bf82fbcc7a4b49edcf06a7883e9 Mon Sep 17 00:00:00 2001 From: David Disu Date: Tue, 25 Jan 2022 15:14:13 +0100 Subject: [PATCH 19/19] Get current file from editor --- apps/remix-ide/src/app/files/fileManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index 1c4a3e61bf..a3828d68b3 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -470,7 +470,7 @@ class FileManager extends Plugin { } currentFile () { - return this._deps.config.get('currentFile') + return this.editor.current() } async closeAllFiles () {