From c2c26da4bbe809ff5f2c9c8aeabe84ae3c458095 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 24 Nov 2021 11:21:12 +0100 Subject: [PATCH 01/14] context view in react --- .../tests/{editor.spec.ts => editor.test.ts} | 70 ++++++- .../src/tests/fileExplorer.test.ts | 4 +- apps/remix-ide/src/app.js | 5 +- apps/remix-ide/src/app/editor/contextView.js | 194 ------------------ apps/remix-ide/src/app/editor/editor.js | 5 +- apps/remix-ide/src/app/panels/main-view.js | 50 +++-- libs/remix-core-plugin/src/index.ts | 1 + .../src/lib/compiler-artefacts.ts | 6 +- .../src/lib/editor-context-listener.ts | 98 ++++----- libs/remix-ui/editor-context-view/.babelrc | 4 + libs/remix-ui/editor-context-view/.eslintrc | 19 ++ libs/remix-ui/editor-context-view/README.md | 7 + .../remix-ui/editor-context-view/src/index.ts | 1 + .../src/lib/remix-ui-editor-context-view.css | 20 +- .../src/lib/remix-ui-editor-context-view.tsx | 159 ++++++++++++++ .../editor-context-view/tsconfig.json | 16 ++ .../editor-context-view/tsconfig.lib.json | 13 ++ nx.json | 3 + tsconfig.base.json | 7 +- workspace.json | 96 +++------ 20 files changed, 421 insertions(+), 357 deletions(-) rename apps/remix-ide-e2e/src/tests/{editor.spec.ts => editor.test.ts} (71%) delete mode 100644 apps/remix-ide/src/app/editor/contextView.js rename apps/remix-ide/src/app/editor/contextualListener.js => libs/remix-core-plugin/src/lib/editor-context-listener.ts (64%) create mode 100644 libs/remix-ui/editor-context-view/.babelrc create mode 100644 libs/remix-ui/editor-context-view/.eslintrc create mode 100644 libs/remix-ui/editor-context-view/README.md create mode 100644 libs/remix-ui/editor-context-view/src/index.ts rename apps/remix-ide/src/app/editor/styles/contextView-styles.js => libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.css (70%) create mode 100644 libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx create mode 100644 libs/remix-ui/editor-context-view/tsconfig.json create mode 100644 libs/remix-ui/editor-context-view/tsconfig.lib.json diff --git a/apps/remix-ide-e2e/src/tests/editor.spec.ts b/apps/remix-ide-e2e/src/tests/editor.test.ts similarity index 71% rename from apps/remix-ide-e2e/src/tests/editor.spec.ts rename to apps/remix-ide-e2e/src/tests/editor.test.ts index f0e88fe5cc..7b714a432b 100644 --- a/apps/remix-ide-e2e/src/tests/editor.spec.ts +++ b/apps/remix-ide-e2e/src/tests/editor.test.ts @@ -6,10 +6,10 @@ import init from '../helpers/init' module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { - init(browser, done) + init(browser, done, 'http://127.0.0.1:8080', true) }, - 'Should zoom in editor ': function (browser: NightwatchBrowser) { + 'Should zoom in editor #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]') .clickLaunchIcon('filePanel') .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') @@ -22,7 +22,7 @@ module.exports = { .checkElementStyle('.view-lines', 'font-size', '16px') }, - 'Should zoom out editor ': function (browser: NightwatchBrowser) { + 'Should zoom out editor #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('#editorView') .checkElementStyle('.view-lines', 'font-size', '16px') .click('*[data-id="tabProxyZoomOut"]') @@ -30,7 +30,7 @@ module.exports = { .checkElementStyle('.view-lines', 'font-size', '14px') }, - 'Should display compile error in editor ': function (browser: NightwatchBrowser) { + 'Should display compile error in editor #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('#editorView') .setEditorValue(storageContractWithError + 'error') .pause(2000) @@ -42,7 +42,7 @@ module.exports = { .checkAnnotations('fa-exclamation-square', 29) // error }, - 'Should minimize and maximize codeblock in editor ': '' + function (browser: NightwatchBrowser) { + 'Should minimize and maximize codeblock in editor #group1': '' + function (browser: NightwatchBrowser) { browser.waitForElementVisible('#editorView') .waitForElementVisible('.ace_open') .click('.ace_start:nth-of-type(1)') @@ -51,7 +51,7 @@ module.exports = { .waitForElementVisible('.ace_open') }, - 'Should add breakpoint to editor ': function (browser: NightwatchBrowser) { + 'Should add breakpoint to editor #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('#editorView') .waitForElementNotPresent('.margin-view-overlays .fa-circle') .execute(() => { @@ -60,7 +60,7 @@ module.exports = { .waitForElementVisible('.margin-view-overlays .fa-circle') }, - 'Should load syntax highlighter for ace light theme': '' + function (browser: NightwatchBrowser) { + 'Should load syntax highlighter for ace light theme #group1': '' + function (browser: NightwatchBrowser) { browser.waitForElementVisible('#editorView') .checkElementStyle('.ace_keyword', 'color', aceThemes.light.keyword) .checkElementStyle('.ace_comment.ace_doc', 'color', aceThemes.light.comment) @@ -68,7 +68,7 @@ module.exports = { .checkElementStyle('.ace_variable', 'color', aceThemes.light.variable) }, - 'Should load syntax highlighter for ace dark theme': '' + function (browser: NightwatchBrowser) { + 'Should load syntax highlighter for ace dark theme #group1': '' + function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="verticalIconsKindsettings"]') .click('*[data-id="verticalIconsKindsettings"]') .waitForElementVisible('*[data-id="settingsTabThemeLabelDark"]') @@ -83,7 +83,7 @@ module.exports = { */ }, - 'Should highlight source code ': function (browser: NightwatchBrowser) { + 'Should highlight source code #group1': function (browser: NightwatchBrowser) { // include all files here because switching between plugins in side-panel removes highlight browser .addFile('sourcehighlight.js', sourcehighlightScript) @@ -101,7 +101,7 @@ module.exports = { .checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)') }, - 'Should remove 1 highlight from source code': '' + function (browser: NightwatchBrowser) { + 'Should remove 1 highlight from source code #group1': '' + function (browser: NightwatchBrowser) { browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]') .click('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]') .pause(2000) @@ -115,7 +115,7 @@ module.exports = { .checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)') }, - 'Should remove all highlights from source code ': function (browser: NightwatchBrowser) { + 'Should remove all highlights from source code #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]') .click('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]') .pause(2000) @@ -126,6 +126,54 @@ module.exports = { .waitForElementNotPresent('.highlightLine33', 60000) .waitForElementNotPresent('.highlightLine41', 60000) .waitForElementNotPresent('.highlightLine51', 60000) + }, + + 'Should display the context view #group2': function (browser: NightwatchBrowser) { + browser + .openFile('contracts') + .openFile('contracts/1_Storage.sol') + .waitForElementVisible('#editorView') + .setEditorValue(storageContractWithError) + .pause(2000) + .execute(() => { + (document.getElementById('editorView') as any).gotoLine(17, 16) + }, [], () => {}) + .waitForElementVisible('.contextview') + .waitForElementContainsText('.contextview .type', 'FunctionDefinition') + .waitForElementContainsText('.contextview .name', 'store') + .execute(() => { + (document.getElementById('editorView') as any).gotoLine(18, 12) + }, [], () => {}) + .waitForElementContainsText('.contextview .type', 'uint256') + .waitForElementContainsText('.contextview .name', 'number') + .click('.contextview [data-action="previous"]') // declaration + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '180') + }) + .click('.contextview [data-action="next"]') // back to the initial state + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '323') + }) + .click('.contextview [data-action="next"]') // next reference + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '489') + }) + .click('.contextview [data-action="gotoref"]') // back to the declaration + .execute(() => { + return (document.getElementById('editorView') as any).getCursorPosition() + }, [], (result) => { + console.log('result', result) + browser.assert.equal(result.value, '180') + }) .end() } } diff --git a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts index 267daa9e1c..663c1bb791 100644 --- a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts +++ b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts @@ -4,7 +4,7 @@ import init from '../helpers/init' import * as path from 'path' const testData = { - testFile1: path.resolve(__dirname + '/editor.spec.js'), // eslint-disable-line + testFile1: path.resolve(__dirname + '/editor.test.js'), // eslint-disable-line testFile2: path.resolve(__dirname + '/fileExplorer.test.js'), // eslint-disable-line testFile3: path.resolve(__dirname + '/generalSettings.test.js') // eslint-disable-line } @@ -105,7 +105,7 @@ module.exports = { .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3) - .waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.spec.js"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.test.js"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemfileExplorer.test.js"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemgeneralSettings.test.js"]') .end() diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index e569cc5e15..d2b8a690ae 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -15,7 +15,7 @@ import { FramingService } from './framingService' import { WalkthroughService } from './walkthroughService' -import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports } from '@remix-project/core-plugin' +import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, EditorContextListener } from '@remix-project/core-plugin' import migrateFileSystem from './migrateFileSystem' @@ -48,7 +48,6 @@ const TestTab = require('./app/tabs/test-tab') const FilePanel = require('./app/panels/file-panel') const Editor = require('./app/editor/editor') const Terminal = require('./app/panels/terminal') -const ContextualListener = require('./app/editor/contextualListener') class AppComponent { constructor (api = {}, events = {}, opts = {}) { @@ -156,7 +155,7 @@ class AppComponent { } } ) - const contextualListener = new ContextualListener({ editor }) + const contextualListener = new EditorContextListener() self.engine.register([ blockchain, diff --git a/apps/remix-ide/src/app/editor/contextView.js b/apps/remix-ide/src/app/editor/contextView.js deleted file mode 100644 index da01321762..0000000000 --- a/apps/remix-ide/src/app/editor/contextView.js +++ /dev/null @@ -1,194 +0,0 @@ -'use strict' -import { sourceMappingDecoder } from '@remix-project/remix-debug' -const yo = require('yo-yo') -const globalRegistry = require('../../global/registry') - -const css = require('./styles/contextView-styles') - -/* - Display information about the current focused code: - - if it's a reference, display information about the declaration - - jump to the declaration - - number of references - - rename declaration/references -*/ -class ContextView { - constructor (opts, localRegistry) { - this._components = {} - this._components.registry = localRegistry || globalRegistry - this.contextualListener = opts.contextualListener - this.editor = opts.editor - this._deps = { - compilersArtefacts: this._components.registry.get('compilersartefacts').api, - offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api, - config: this._components.registry.get('config').api, - fileManager: this._components.registry.get('filemanager').api - } - this._view = null - this._nodes = null - this._current = null - this.sourceMappingDecoder = sourceMappingDecoder - this.previousElement = null - this.contextualListener.event.register('contextChanged', nodes => { - this.show() - this._nodes = nodes - this.update() - }) - this.contextualListener.event.register('stopHighlighting', () => { - }) - } - - render () { - const view = yo` -
-
- ${this._renderTarget()} -
-
` - if (!this._view) { - this._view = view - } - return view - } - - hide () { - if (this._view) { - this._view.style.display = 'none' - } - } - - show () { - if (this._view) { - this._view.style.display = 'block' - } - } - - update () { - if (this._view) { - yo.update(this._view, this.render()) - } - } - - _renderTarget () { - let last - const previous = this._current - if (this._nodes && this._nodes.length) { - last = this._nodes[this._nodes.length - 1] - if (isDefinition(last)) { - this._current = last - } else { - const target = this.contextualListener.declarationOf(last) - if (target) { - this._current = target - } else { - this._current = null - } - } - } - if (!this._current || !previous || previous.id !== this._current.id || (this.previousElement && !this.previousElement.children.length)) { - this.previousElement = this._render(this._current, last) - } - return this.previousElement - } - - _jumpToInternal (position) { - const jumpToLine = (lineColumn) => { - if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { - this.editor.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) - } - } - const lastCompilationResult = this._deps.compilersArtefacts.__last - if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) { - const lineColumn = this._deps.offsetToLineColumnConverter.offsetToLineColumn( - position, - position.file, - lastCompilationResult.getSourceCode().sources, - lastCompilationResult.getAsts()) - const filename = lastCompilationResult.getSourceName(position.file) - // TODO: refactor with rendererAPI.errorClick - if (filename !== this._deps.config.get('currentFile')) { - const provider = this._deps.fileManager.fileProviderOf(filename) - if (provider) { - provider.exists(filename).then(exist => { - this._deps.fileManager.open(filename) - jumpToLine(lineColumn) - }).catch(error => { - if (error) return console.log(error) - }) - } - } else { - jumpToLine(lineColumn) - } - } - } - - _render (node, nodeAtCursorPosition) { - if (!node) return yo`
` - let references = this.contextualListener.referencesOf(node) - const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType - references = `${references ? references.length : '0'} reference(s)` - - let ref = 0 - const nodes = this.contextualListener.getActiveHighlights() - for (const k in nodes) { - if (nodeAtCursorPosition.id === nodes[k].nodeId) { - ref = k - break - } - } - - // JUMP BETWEEN REFERENCES - const jump = (e) => { - e.target.dataset.action === 'next' ? ref++ : ref-- - if (ref < 0) ref = nodes.length - 1 - if (ref >= nodes.length) ref = 0 - this._jumpToInternal(nodes[ref].position) - } - - const jumpTo = () => { - if (node && node.src) { - const position = this.sourceMappingDecoder.decode(node.src) - if (position) { - this._jumpToInternal(position) - } - } - } - - const showGasEstimation = () => { - if (node.nodeType === 'FunctionDefinition') { - const result = this.contextualListener.gasEstimation(node) - const executionCost = ' Execution cost: ' + result.executionCost + ' gas' - const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' - const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` - return yo` -
- - ${estimatedGas} -
- ` - } - } - - return yo` -
${showGasEstimation()} -
${type}
-
${node.name}
- - ${references} - - -
- ` - } -} - -function isDefinition (node) { - return node.nodeType === 'ContractDefinition' || - node.nodeType === 'FunctionDefinition' || - node.nodeType === 'ModifierDefinition' || - node.nodeType === 'VariableDeclaration' || - node.nodeType === 'StructDefinition' || - node.nodeType === 'EventDefinition' -} - -module.exports = ContextView diff --git a/apps/remix-ide/src/app/editor/editor.js b/apps/remix-ide/src/app/editor/editor.js index 295d83fd59..013b1b9853 100644 --- a/apps/remix-ide/src/app/editor/editor.js +++ b/apps/remix-ide/src/app/editor/editor.js @@ -12,7 +12,7 @@ const profile = { name: 'editor', description: 'service - editor', version: packageJson.version, - methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine'] + methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine', 'getCursorPosition'] } class Editor extends Plugin { @@ -75,7 +75,8 @@ class Editor extends Plugin { this._onChange(this.currentFile) } } - this.el.gotoLine = (line) => this.gotoLine(line, 0) + this.el.gotoLine = (line, column) => this.gotoLine(line, column || 0) + this.el.getCursorPosition = () => this.getCursorPosition() return this.el } diff --git a/apps/remix-ide/src/app/panels/main-view.js b/apps/remix-ide/src/app/panels/main-view.js index 537b296796..cad19a58f3 100644 --- a/apps/remix-ide/src/app/panels/main-view.js +++ b/apps/remix-ide/src/app/panels/main-view.js @@ -1,11 +1,14 @@ + +import React from 'react' // eslint-disable-line +import ReactDOM from 'react-dom' +import { RemixUiEditorContextView } from '@remix-ui/editor-context-view' + var yo = require('yo-yo') var EventManager = require('../../lib/events') var globalRegistry = require('../../global/registry') var { TabProxy } = require('./tab-proxy.js') -var ContextView = require('../editor/contextView') - var csjs = require('csjs-inject') var css = csjs` @@ -15,6 +18,10 @@ var css = csjs` height : 100%; width : 100%; } + .contextview { + opacity : 1; + position : relative; + } ` // @todo(#650) Extract this into two classes: MainPanel (TabsProxy + Iframe/Editor) & BottomPanel (Terminal) @@ -25,12 +32,13 @@ export class MainView { self._view = {} self._components = {} self._components.registry = globalRegistry + self.contextualListener = contextualListener + self.hideContextView = false self.editor = editor self.fileManager = fileManager self.mainPanel = mainPanel self.txListener = globalRegistry.get('txlistener').api self._components.terminal = terminal - self._components.contextualListener = contextualListener this.appManager = appManager this.init() } @@ -39,7 +47,8 @@ export class MainView { this.fileManager.unselectCurrentFile() this.mainPanel.showContent(name) this._view.editor.style.display = 'none' - this._components.contextView.hide() + this.hideContextView = true + this.renderContextView() this._view.mainPanel.style.display = 'block' } @@ -63,19 +72,22 @@ export class MainView { // we check upstream for "fileChanged" self._view.editor.style.display = 'block' self._view.mainPanel.style.display = 'none' - self._components.contextView.show() + this.hideContextView = false + this.renderContextView() }) self.tabProxy.event.on('openFile', (file) => { self._view.editor.style.display = 'block' self._view.mainPanel.style.display = 'none' - self._components.contextView.show() + this.hideContextView = false + this.renderContextView() }) self.tabProxy.event.on('closeFile', (file) => { }) self.tabProxy.event.on('switchApp', self.showApp.bind(self)) self.tabProxy.event.on('closeApp', (name) => { self._view.editor.style.display = 'block' - self._components.contextView.show() + this.hideContextView = false + this.renderContextView() self._view.mainPanel.style.display = 'none' }) self.tabProxy.event.on('tabCountChanged', (count) => { @@ -90,10 +102,6 @@ export class MainView { } } - const contextView = new ContextView({ contextualListener: self._components.contextualListener, editor: self.editor }) - - self._components.contextView = contextView - self._components.terminal.event.register('resize', delta => self._adjustLayout('top', delta)) if (self.txListener) { self._components.terminal.event.register('listenOnNetWork', (listenOnNetWork) => { @@ -181,15 +189,17 @@ export class MainView { self._view.editor.style.display = 'none' self._view.mainPanel = self.mainPanel.render() self._view.terminal = self._components.terminal.render() + self._view.mainview = yo`
${self.tabProxy.renderTabsbar()} ${self._view.editor} ${self._view.mainPanel} - ${self._components.contextView.render()} +
${self._view.terminal}
` + // INIT self._adjustLayout('top', self.data._layout.top.offset) @@ -200,6 +210,22 @@ export class MainView { return self._view.mainview } + renderContextView () { + if (!this.contextualListener.activated) return + + ReactDOM.render( + this.contextualListener.call('editor', 'gotoLine', line, column)} + openFile={(file) => this.contextualListener.call('editor', 'openFile', file)} + getLastCompilationResult={_ => { return this.contextualListener.call('compilerArtefacts', 'getLastCompilationResult') } } + offsetToLineColumn={(position, file, sources, asts) => { return this.contextualListener.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } } + getCurrentFileName={() => { return this.contextualListener.call('fileManager', 'file') } } + /> + , this._view.mainview.querySelector('.contextview')) + } + registerCommand (name, command, opts) { var self = this return self._components.terminal.registerCommand(name, command, opts) diff --git a/libs/remix-core-plugin/src/index.ts b/libs/remix-core-plugin/src/index.ts index 73c98a6181..fe8a5c661e 100644 --- a/libs/remix-core-plugin/src/index.ts +++ b/libs/remix-core-plugin/src/index.ts @@ -3,3 +3,4 @@ export { CompilerMetadata } from './lib/compiler-metadata' export { FetchAndCompile } from './lib/compiler-fetch-and-compile' export { CompilerImports } from './lib/compiler-content-imports' export { CompilerArtefacts } from './lib/compiler-artefacts' +export { EditorContextListener } from './lib/editor-context-listener' diff --git a/libs/remix-core-plugin/src/lib/compiler-artefacts.ts b/libs/remix-core-plugin/src/lib/compiler-artefacts.ts index 148aa292c7..715bd2e9c4 100644 --- a/libs/remix-core-plugin/src/lib/compiler-artefacts.ts +++ b/libs/remix-core-plugin/src/lib/compiler-artefacts.ts @@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' const profile = { name: 'compilerArtefacts', - methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas'], + methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas', 'getLastCompilationResult'], events: [], version: '0.0.1' } @@ -59,6 +59,10 @@ export class CompilerArtefacts extends Plugin { }) } + getLastCompilationResult () { + return this.compilersArtefacts.__last + } + getAllContractDatas () { const contractsData = {} Object.keys(this.compilersArtefactsPerFile).map((targetFile) => { diff --git a/apps/remix-ide/src/app/editor/contextualListener.js b/libs/remix-core-plugin/src/lib/editor-context-listener.ts similarity index 64% rename from apps/remix-ide/src/app/editor/contextualListener.js rename to libs/remix-core-plugin/src/lib/editor-context-listener.ts index 9eea6aeaed..72ccee7457 100644 --- a/apps/remix-ide/src/app/editor/contextualListener.js +++ b/libs/remix-core-plugin/src/lib/editor-context-listener.ts @@ -1,47 +1,48 @@ 'use strict' import { Plugin } from '@remixproject/engine' -import * as packageJson from '../../../../../package.json' import { sourceMappingDecoder } from '@remix-project/remix-debug' const { AstWalker } = require('@remix-project/remix-astwalker') -const EventManager = require('../../lib/events') -const globalRegistry = require('../../global/registry') const profile = { name: 'contextualListener', methods: [], events: [], - version: packageJson.version + version: '0.0.1' } /* trigger contextChanged(nodes) */ -class ContextualListener extends Plugin { - constructor (opts) { +export class EditorContextListener extends Plugin { + _index: any + _activeHighlights: Array + astWalker: any + currentPosition: any + currentFile: String + nodes: Array + results: any + estimationObj: any + creationCost: any + codeDepositCost: any + contract: any + activated: boolean + + constructor () { super(profile) - this.event = new EventManager() - this._components = {} - this._components.registry = globalRegistry - this.editor = opts.editor - this.pluginManager = opts.pluginManager - this._deps = { - compilersArtefacts: this._components.registry.get('compilersartefacts').api, - config: this._components.registry.get('config').api, - offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api - } + this.activated = false this._index = { Declarations: {}, FlatReferences: {} } this._activeHighlights = [] - this.editor.event.register('contentChanged', () => { this._stopHighlighting() }) - this.sourceMappingDecoder = sourceMappingDecoder this.astWalker = new AstWalker() } onActivation () { + this.on('editor', 'contentChanged', () => { this._stopHighlighting() }) + this.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => { if (languageVersion.indexOf('soljson') !== 0) return this._stopHighlighting() @@ -52,11 +53,18 @@ class ContextualListener extends Plugin { this._buildIndex(data, source) }) - setInterval(() => { - if (this._deps.compilersArtefacts.__last && this._deps.compilersArtefacts.__last.languageversion.indexOf('soljson') === 0) { - this._highlightItems(this.editor.getCursorPosition(), this._deps.compilersArtefacts.__last, this._deps.config.get('currentFile')) + setInterval(async () => { + const compilationResult = await this.call('compilerArtefacts', 'getLastCompilationResult') + if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) { + this._highlightItems( + await this.call('editor', 'getCursorPosition'), + compilationResult, + await this.call('fileManager', 'file') + ) } }, 1000) + + this.activated = true } getActiveHighlights () { @@ -74,7 +82,7 @@ class ContextualListener extends Plugin { return this._index.Declarations[node.id] } - _highlightItems (cursorPosition, compilationResult, file) { + async _highlightItems (cursorPosition, compilationResult, file) { if (this.currentPosition === cursorPosition) return if (this.currentFile !== file) { this.currentFile = file @@ -85,12 +93,12 @@ class ContextualListener extends Plugin { this.currentPosition = cursorPosition this.currentFile = file if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) { - const nodes = this.sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) + const nodes = sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) this.nodes = nodes if (nodes && nodes.length && nodes[nodes.length - 1]) { - this._highlightExpressions(nodes[nodes.length - 1], compilationResult) + await this._highlightExpressions(nodes[nodes.length - 1], compilationResult) } - this.event.trigger('contextChanged', [nodes]) + this.emit('contextChanged', nodes) } } @@ -111,21 +119,19 @@ class ContextualListener extends Plugin { } } - _highlight (node, compilationResult) { + async _highlight (node, compilationResult) { if (!node) return - const position = this.sourceMappingDecoder.decode(node.src) - const eventId = this._highlightInternal(position, node) - const lastCompilationResult = this._deps.compilersArtefacts.__last - if (eventId && lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0) { - this._activeHighlights.push({ eventId, position, fileTarget: lastCompilationResult.getSourceName(position.file), nodeId: node.id }) + const position = sourceMappingDecoder.decode(node.src) + 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 }) } } - _highlightInternal (position, node) { + async _highlightInternal (position, node, compilationResult) { if (node.nodeType === 'Block') return - const lastCompilationResult = this._deps.compilersArtefacts.__last - if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0) { - let lineColumn = this._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, lastCompilationResult.getSourceCode().sources, lastCompilationResult.getAsts()) + if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) { + let lineColumn = await this.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, position.file, compilationResult.getSourceCode().sources, compilationResult.getAsts()) if (node.nodes && node.nodes.length) { // If node has children, highlight the entire line. if not, just highlight the current source position of the node. lineColumn = { @@ -139,38 +145,38 @@ class ContextualListener extends Plugin { } } } - const fileName = lastCompilationResult.getSourceName(position.file) + const fileName = compilationResult.getSourceName(position.file) if (fileName) { - return this.call('editor', 'highlight', lineColumn, fileName, '', { focus: false }) + return await this.call('editor', 'highlight', lineColumn, fileName, '', { focus: false }) } } return null } - _highlightExpressions (node, compilationResult) { - const highlights = (id) => { + async _highlightExpressions (node, compilationResult) { + const highlights = async (id) => { if (this._index.Declarations && this._index.Declarations[id]) { const refs = this._index.Declarations[id] for (const ref in refs) { const node = refs[ref] - this._highlight(node, compilationResult) + await this._highlight(node, compilationResult) } } } if (node && node.referencedDeclaration) { - highlights(node.referencedDeclaration) + await highlights(node.referencedDeclaration) const current = this._index.FlatReferences[node.referencedDeclaration] - this._highlight(current, compilationResult) + await this._highlight(current, compilationResult) } else { - highlights(node.id) - this._highlight(node, compilationResult) + await highlights(node.id) + await this._highlight(node, compilationResult) } this.results = compilationResult } _stopHighlighting () { this.call('editor', 'discardHighlight') - this.event.trigger('stopHighlighting', []) + this.emit('stopHighlighting') this._activeHighlights = [] } @@ -229,5 +235,3 @@ class ContextualListener extends Plugin { return '(' + params.toString() + ')' } } - -module.exports = ContextualListener diff --git a/libs/remix-ui/editor-context-view/.babelrc b/libs/remix-ui/editor-context-view/.babelrc new file mode 100644 index 0000000000..09d67939cc --- /dev/null +++ b/libs/remix-ui/editor-context-view/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@nrwl/react/babel"], + "plugins": [] +} diff --git a/libs/remix-ui/editor-context-view/.eslintrc b/libs/remix-ui/editor-context-view/.eslintrc new file mode 100644 index 0000000000..9d709f91d0 --- /dev/null +++ b/libs/remix-ui/editor-context-view/.eslintrc @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "extends": "../../../.eslintrc", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 11, + "sourceType": "module" + }, + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "error" + } +} diff --git a/libs/remix-ui/editor-context-view/README.md b/libs/remix-ui/editor-context-view/README.md new file mode 100644 index 0000000000..0b9719fedb --- /dev/null +++ b/libs/remix-ui/editor-context-view/README.md @@ -0,0 +1,7 @@ +# remix-ui-editor-context-view + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test remix-ui-editor-context-view` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/remix-ui/editor-context-view/src/index.ts b/libs/remix-ui/editor-context-view/src/index.ts new file mode 100644 index 0000000000..b595accc41 --- /dev/null +++ b/libs/remix-ui/editor-context-view/src/index.ts @@ -0,0 +1 @@ +export * from './lib/remix-ui-editor-context-view'; diff --git a/apps/remix-ide/src/app/editor/styles/contextView-styles.js b/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.css similarity index 70% rename from apps/remix-ide/src/app/editor/styles/contextView-styles.js rename to libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.css index 5303a356fa..f57c88f78f 100644 --- a/apps/remix-ide/src/app/editor/styles/contextView-styles.js +++ b/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.css @@ -1,17 +1,9 @@ -var csjs = require('csjs-inject') -var css = csjs` - .contextview { - opacity : 1; - position : relative; - height : 25px; - } - .container { + .container-context-view { padding : 1px 15px; } .line { display : flex; - justify-content : flex-end; align-items : center; text-overflow : ellipsis; overflow : hidden; @@ -48,12 +40,4 @@ var css = csjs` z-index : 50; border-radius : 1px; border : 2px solid var(--secondary); - } - .contextviewcontainer{ - z-index : 50; - border-radius : 1px; - border : 2px solid var(--secondary); - } -` - -module.exports = css + } \ No newline at end of file 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 new file mode 100644 index 0000000000..51b6f6bf9d --- /dev/null +++ b/libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx @@ -0,0 +1,159 @@ +import React, { useEffect, useState, useRef } from 'react' // eslint-disable-line +import { sourceMappingDecoder } from '@remix-project/remix-debug' + +import './remix-ui-editor-context-view.css'; + +/* eslint-disable-next-line */ +export interface RemixUiEditorContextViewProps { + hide: boolean, + contextualListener: any, + gotoLine: (line: number, column: number) => void, + openFile: (fileName: string) => void, + getLastCompilationResult: () => any, + offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any, + getCurrentFileName: () => String +} + +function isDefinition (node: any) { + return node.nodeType === 'ContractDefinition' || + node.nodeType === 'FunctionDefinition' || + node.nodeType === 'ModifierDefinition' || + node.nodeType === 'VariableDeclaration' || + node.nodeType === 'StructDefinition' || + node.nodeType === 'EventDefinition' +} + +type astNode = { + name: string, + id: number, + children: Array, + typeDescriptions: any, + nodeType: String, + src: any, + nodeId: any, + position: any +} + +type nullableAstNode = astNode | null + +export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) { + const nodesRef = useRef>([]) + /* + 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 [nodesState, setNode] = useState>([]) + const contextualListener = props.contextualListener + + useEffect(() => { + contextualListener.on('contextualListener', 'contextChanged', (nodes: Array) => { + if (gotoLineDisableRef.current) { + gotoLineDisableRef.current = false + return + } + nodesRef.current = nodes + setNode(nodes) + }) + }, []) + + const _render = (node: nullableAstNode) => { + if (!node) return (
) + let references = contextualListener.referencesOf(node) + const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType + references = `${references ? references.length : '0'} reference(s)` + + let ref = 0 + const nodes: Array = contextualListener.getActiveHighlights() + + /* + * show gas estimation + */ + const gasEstimation = () => { + if (node.nodeType === 'FunctionDefinition') { + const result = contextualListener.gasEstimation(node) + const executionCost = ' Execution cost: ' + result.executionCost + ' gas' + const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' + const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` + return ( +
+ + {estimatedGas} +
+ ) + } else { + return (
) + } + } + + /* + * onClick jump to ast node in the editor + */ + const _jumpToInternal = async (position: any) => { + const jumpToLine = async (fileName: string, lineColumn: any) => { + if (fileName !== await props.getCurrentFileName()) { + await props.openFile(fileName) + } + if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { + gotoLineDisableRef.current = true + props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) + } + } + const lastCompilationResult = await props.getLastCompilationResult() + if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) { + const lineColumn = await props.offsetToLineColumn( + position, + position.file, + lastCompilationResult.getSourceCode().sources, + lastCompilationResult.getAsts()) + const filename = lastCompilationResult.getSourceName(position.file) + // TODO: refactor with rendererAPI.errorClick + jumpToLine(filename, lineColumn) + } + } + + const jumpTo = () => { + if (node && node.src) { + const position = sourceMappingDecoder.decode(node.src) + if (position) { + _jumpToInternal(position) + } + } + } + + // 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) + } + + return ( +
{gasEstimation()} +
{type}
+
{node.name}
+ + {references} + + +
+ ) + } + + let last: nullableAstNode = null + if (!props.hide && nodesRef.current && nodesRef.current.length) { + last = nodesRef.current[nodesRef.current.length - 1] + if (!isDefinition(last)) { + last = contextualListener.declarationOf(last) + } + } + + return ( + !props.hide &&
+ {_render(last)} +
+ ); +} + +export default RemixUiEditorContextView diff --git a/libs/remix-ui/editor-context-view/tsconfig.json b/libs/remix-ui/editor-context-view/tsconfig.json new file mode 100644 index 0000000000..d52e31ad74 --- /dev/null +++ b/libs/remix-ui/editor-context-view/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/libs/remix-ui/editor-context-view/tsconfig.lib.json b/libs/remix-ui/editor-context-view/tsconfig.lib.json new file mode 100644 index 0000000000..b560bc4dec --- /dev/null +++ b/libs/remix-ui/editor-context-view/tsconfig.lib.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["node"] + }, + "files": [ + "../../../node_modules/@nrwl/react/typings/cssmodule.d.ts", + "../../../node_modules/@nrwl/react/typings/image.d.ts" + ], + "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/nx.json b/nx.json index 8bc14e4e9d..a1a7131ff6 100644 --- a/nx.json +++ b/nx.json @@ -147,6 +147,9 @@ }, "remix-ui-theme-module": { "tags": [] + }, + "remix-ui-editor-context-view": { + "tags": [] } }, "targetDependencies": { diff --git a/tsconfig.base.json b/tsconfig.base.json index 3633434dce..68e1ae5175 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -69,10 +69,9 @@ "@remix-ui/tabs": ["libs/remix-ui/tabs/src/index.ts"], "@remix-ui/helper": ["libs/remix-ui/helper/src/index.ts"], "@remix-ui/app": ["libs/remix-ui/app/src/index.ts"], - "@remix-ui/vertical-icons-panel": [ - "libs/remix-ui/vertical-icons-panel/src/index.ts" - ], - "@remix-ui/theme-module": ["libs/remix-ui/theme-module/src/index.ts"] + "@remix-ui/vertical-icons-panel": ["libs/remix-ui/vertical-icons-panel/src/index.ts"], + "@remix-ui/theme-module": ["libs/remix-ui/theme-module/src/index.ts"], + "@remix-ui/editor-context-view": ["libs/remix-ui/editor-context-view/src/index.ts"] } }, "exclude": ["node_modules", "tmp"] diff --git a/workspace.json b/workspace.json index 8ce5f9f9ce..8850066499 100644 --- a/workspace.json +++ b/workspace.json @@ -1116,80 +1116,48 @@ } } } + }, + "remix-ui-editor-context-view": { + "root": "libs/remix-ui/editor-context-view", + "sourceRoot": "libs/remix-ui/editor-context-view/src", + "projectType": "library", + "architect": { + "lint": { + "builder": "@nrwl/linter:lint", + "options": { + "linter": "eslint", + "tsConfig": ["libs/remix-ui/vertical-icons-panel/tsconfig.lib.json"], + "exclude": ["**/node_modules/**", "!libs/remix-ui/vertical-icons-panel/**/*"] + } + } + } } }, - "remix-ui-editor": { - "root": "libs/remix-ui/editor", - "sourceRoot": "libs/remix-ui/editor/src", - "projectType": "library", - "schematics": {}, - "architect": { - "lint": { - "builder": "@nrwl/linter:lint", - "options": { - "linter": "eslint", - "babel": true - }, - "component": { - "style": "css" - }, - "library": { - "style": "css", - "linter": "eslint" - } - }, + "cli": { + "defaultCollection": "@nrwl/react" + }, + "schematics": { + "@nrwl/workspace": { "library": { "linter": "eslint" } }, - "@nrwl/nx-plugin": { - "plugin": { + "@nrwl/cypress": { + "cypress-project": { "linter": "eslint" } }, - "@nrwl/web": { - "application": { - "linter": "eslint" - } - }, - "@nrwl/node": { - "application": { - "linter": "eslint" - }, - "library": { - "linter": "eslint" - } - } - }, - "cli": { - "defaultCollection": "@nrwl/react" - }, - "schematics": { - "@nrwl/workspace": { - "library": { - "linter": "eslint" - } - }, - "@nrwl/cypress": { - "cypress-project": { - "linter": "eslint" - } + "@nrwl/react": { + "application": { + "style": "css", + "linter": "eslint", + "babel": true }, - "@nrwl/react": { - "application": { - "style": "css", - "linter": "eslint", - "babel": true - }, - "component": { - "style": "css" - }, - "library": { - "style": "css", - "linter": "eslint" - } + "component": { + "style": "css" }, "library": { + "style": "css", "linter": "eslint" } }, @@ -1199,4 +1167,6 @@ } }, "defaultProject": "remix-ide" -} \ No newline at end of file + } +} + From 15e49763452803c9d22b73568c8528f7756f0522 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 15:35:17 +0100 Subject: [PATCH 02/14] fix css --- .../src/lib/remix-ui-editor-context-view.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 51b6f6bf9d..336c290ffc 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 @@ -150,7 +150,7 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) { } return ( - !props.hide &&
+ !props.hide &&
{_render(last)}
); From 10365638d5a7806d54dd6f1af66de8e629b6a95f Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 17:17:09 +0100 Subject: [PATCH 03/14] refactor contextview to be added in the editor --- apps/remix-ide/src/app/panels/main-view.js | 34 +---------- .../src/lib/editor-context-listener.ts | 2 +- .../src/lib/remix-ui-editor-context-view.tsx | 59 ++++++++++++------- .../editor/src/lib/remix-ui-editor.css | 7 ++- .../editor/src/lib/remix-ui-editor.tsx | 20 +++++++ 5 files changed, 67 insertions(+), 55 deletions(-) diff --git a/apps/remix-ide/src/app/panels/main-view.js b/apps/remix-ide/src/app/panels/main-view.js index cad19a58f3..cf8009b469 100644 --- a/apps/remix-ide/src/app/panels/main-view.js +++ b/apps/remix-ide/src/app/panels/main-view.js @@ -1,7 +1,6 @@ import React from 'react' // eslint-disable-line import ReactDOM from 'react-dom' -import { RemixUiEditorContextView } from '@remix-ui/editor-context-view' var yo = require('yo-yo') var EventManager = require('../../lib/events') @@ -17,11 +16,7 @@ var css = csjs` flex-direction : column; height : 100%; width : 100%; - } - .contextview { - opacity : 1; - position : relative; - } + } ` // @todo(#650) Extract this into two classes: MainPanel (TabsProxy + Iframe/Editor) & BottomPanel (Terminal) @@ -33,7 +28,6 @@ export class MainView { self._components = {} self._components.registry = globalRegistry self.contextualListener = contextualListener - self.hideContextView = false self.editor = editor self.fileManager = fileManager self.mainPanel = mainPanel @@ -47,8 +41,6 @@ export class MainView { this.fileManager.unselectCurrentFile() this.mainPanel.showContent(name) this._view.editor.style.display = 'none' - this.hideContextView = true - this.renderContextView() this._view.mainPanel.style.display = 'block' } @@ -72,22 +64,16 @@ export class MainView { // we check upstream for "fileChanged" self._view.editor.style.display = 'block' self._view.mainPanel.style.display = 'none' - this.hideContextView = false - this.renderContextView() }) self.tabProxy.event.on('openFile', (file) => { self._view.editor.style.display = 'block' - self._view.mainPanel.style.display = 'none' - this.hideContextView = false - this.renderContextView() + self._view.mainPanel.style.display = 'none' }) self.tabProxy.event.on('closeFile', (file) => { }) self.tabProxy.event.on('switchApp', self.showApp.bind(self)) self.tabProxy.event.on('closeApp', (name) => { self._view.editor.style.display = 'block' - this.hideContextView = false - this.renderContextView() self._view.mainPanel.style.display = 'none' }) self.tabProxy.event.on('tabCountChanged', (count) => { @@ -210,22 +196,6 @@ export class MainView { return self._view.mainview } - renderContextView () { - if (!this.contextualListener.activated) return - - ReactDOM.render( - this.contextualListener.call('editor', 'gotoLine', line, column)} - openFile={(file) => this.contextualListener.call('editor', 'openFile', file)} - getLastCompilationResult={_ => { return this.contextualListener.call('compilerArtefacts', 'getLastCompilationResult') } } - offsetToLineColumn={(position, file, sources, asts) => { return this.contextualListener.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } } - getCurrentFileName={() => { return this.contextualListener.call('fileManager', 'file') } } - /> - , this._view.mainview.querySelector('.contextview')) - } - registerCommand (name, command, opts) { var self = this return self._components.terminal.registerCommand(name, command, opts) 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 72ccee7457..7bde42de11 100644 --- a/libs/remix-core-plugin/src/lib/editor-context-listener.ts +++ b/libs/remix-core-plugin/src/lib/editor-context-listener.ts @@ -6,7 +6,7 @@ const { AstWalker } = require('@remix-project/remix-astwalker') const profile = { name: 'contextualListener', - methods: [], + methods: ['referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf'], events: [], version: '0.0.1' } 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 336c290ffc..22672ad539 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 @@ -3,15 +3,21 @@ import { sourceMappingDecoder } from '@remix-project/remix-debug' import './remix-ui-editor-context-view.css'; +export type onContextListenerChangedListener = (nodes: Array) => void + /* eslint-disable-next-line */ export interface RemixUiEditorContextViewProps { hide: boolean, - contextualListener: any, gotoLine: (line: number, column: number) => void, openFile: (fileName: string) => void, getLastCompilationResult: () => any, offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any, getCurrentFileName: () => String + onContextListenerChanged: (listener: onContextListenerChangedListener) => void + referencesOf: (nodes: astNode) => Array + getActiveHighlights: () => Array + gasEstimation: (node: astNode) => gasEstimation + declarationOf: (node: astNode) => astNode } function isDefinition (node: any) { @@ -23,7 +29,12 @@ function isDefinition (node: any) { node.nodeType === 'EventDefinition' } -type astNode = { +export type gasEstimationType = { + executionCost: string, + codeDepositCost: string +} + +export type astNode = { name: string, id: number, children: Array, @@ -42,36 +53,50 @@ 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 referencesRef = useRef([]) + const activeHighlightsRef = useRef([]) + const currentNodeRef = useRef(null as nullableAstNode) + const gasEstimationRef = useRef({} as gasEstimationType) + const gotoLineDisableRef = useRef(false) const [nodesState, setNode] = useState>([]) - const contextualListener = props.contextualListener - + useEffect(() => { - contextualListener.on('contextualListener', 'contextChanged', (nodes: Array) => { + props.onContextListenerChanged(async (nodes: Array) => { if (gotoLineDisableRef.current) { gotoLineDisableRef.current = false return } nodesRef.current = nodes + if (!props.hide && nodesRef.current && nodesRef.current.length) { + currentNodeRef.current = nodesRef.current[nodesRef.current.length - 1] + if (!isDefinition(currentNodeRef.current)) { + currentNodeRef.current = await props.declarationOf(currentNodeRef.current) + } + } + if (currentNodeRef.current) { + referencesRef.current = await props.referencesOf(currentNodeRef.current) + gasEstimationRef.current = await props.gasEstimation(currentNodeRef.current) + } + activeHighlightsRef.current = await props.getActiveHighlights() setNode(nodes) }) }, []) const _render = (node: nullableAstNode) => { if (!node) return (
) - let references = contextualListener.referencesOf(node) + let references = referencesRef.current const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType - references = `${references ? references.length : '0'} reference(s)` + let referencesCount = `${references ? references.length : '0'} reference(s)` let ref = 0 - const nodes: Array = contextualListener.getActiveHighlights() + const nodes: Array = activeHighlightsRef.current /* * show gas estimation */ const gasEstimation = () => { if (node.nodeType === 'FunctionDefinition') { - const result = contextualListener.gasEstimation(node) + const result: gasEstimationType = gasEstimationRef.current const executionCost = ' Execution cost: ' + result.executionCost + ' gas' const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` @@ -134,24 +159,16 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) {
{type}
{node.name}
- {references} + {referencesCount}
) - } - - let last: nullableAstNode = null - if (!props.hide && nodesRef.current && nodesRef.current.length) { - last = nodesRef.current[nodesRef.current.length - 1] - if (!isDefinition(last)) { - last = contextualListener.declarationOf(last) - } - } + } return ( !props.hide &&
- {_render(last)} + {_render(currentNodeRef.current)}
); } diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.css b/libs/remix-ui/editor/src/lib/remix-ui-editor.css index a487d143f8..a078bfd498 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.css +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.css @@ -8,4 +8,9 @@ border-radius : 10px; height: auto; width: auto; -} \ No newline at end of file +} + +.contextview { + opacity : 1; + position : relative; + } \ No newline at end of file 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 480b548be9..d731084a59 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line +import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view' import Editor, { loader } from '@monaco-editor/react' import { reducerActions, reducerListener, initialState } from './actions/editor' import { language, conf } from './syntax' @@ -49,6 +50,7 @@ loader.config({ paths: { vs: 'assets/js/monaco-editor/dev/vs' } }) /* eslint-disable-next-line */ export interface EditorUIProps { + contextualListener: any activated: boolean themeType: string currentFile: string @@ -62,6 +64,7 @@ export interface EditorUIProps { } plugin: { on: (plugin: string, event: string, listener: any) => void + call: (plugin: string, method: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any) => any } editorAPI: { findMatches: (uri: string, value: string) => any @@ -377,6 +380,7 @@ export const EditorUI = (props: EditorUIProps) => { } return ( +
{ beforeMount={handleEditorWillMount} options={{ glyphMargin: true }} /> +
+ props.plugin.call('editor', 'gotoLine', line, column)} + openFile={(file) => props.plugin.call('editor', 'openFile', 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) }} + 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) }} + declarationOf={(node: astNode) => { return props.plugin.call('contextualListener', 'declarationOf', node) }} + /> +
+
) } From 8422596553122d27f09b916182a56027c1d50656 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 17:43:15 +0100 Subject: [PATCH 04/14] fix css --- libs/remix-ui/editor/src/lib/remix-ui-editor.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 d731084a59..4f3dadd3cf 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -380,17 +380,16 @@ export const EditorUI = (props: EditorUIProps) => { } return ( -
+
-
+
props.plugin.call('editor', 'gotoLine', line, column)} From 4e6667d1937517558b1a6550d72fa363bd91514e Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 21:10:23 +0100 Subject: [PATCH 05/14] fix_build --- .../src/lib/remix-ui-editor-context-view.tsx | 2 +- workspace.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) 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 22672ad539..ea99c34b99 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 @@ -16,7 +16,7 @@ export interface RemixUiEditorContextViewProps { onContextListenerChanged: (listener: onContextListenerChangedListener) => void referencesOf: (nodes: astNode) => Array getActiveHighlights: () => Array - gasEstimation: (node: astNode) => gasEstimation + gasEstimation: (node: astNode) => gasEstimationType declarationOf: (node: astNode) => astNode } diff --git a/workspace.json b/workspace.json index 8850066499..f728458dbd 100644 --- a/workspace.json +++ b/workspace.json @@ -1165,8 +1165,8 @@ "plugin": { "linter": "eslint" } - }, - "defaultProject": "remix-ide" - } + } + }, + "defaultProject": "remix-ide" } From d92ff59b1bc6e64335a9270119ec37fc46c934b5 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 21:34:04 +0100 Subject: [PATCH 06/14] linting --- apps/remix-ide/src/app/panels/main-view.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/remix-ide/src/app/panels/main-view.js b/apps/remix-ide/src/app/panels/main-view.js index cf8009b469..1cb3b1ffa5 100644 --- a/apps/remix-ide/src/app/panels/main-view.js +++ b/apps/remix-ide/src/app/panels/main-view.js @@ -1,7 +1,3 @@ - -import React from 'react' // eslint-disable-line -import ReactDOM from 'react-dom' - var yo = require('yo-yo') var EventManager = require('../../lib/events') @@ -67,7 +63,7 @@ export class MainView { }) self.tabProxy.event.on('openFile', (file) => { self._view.editor.style.display = 'block' - self._view.mainPanel.style.display = 'none' + self._view.mainPanel.style.display = 'none' }) self.tabProxy.event.on('closeFile', (file) => { }) From 628aac0778c840506a36d732c6932552f6694dc6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 21 Dec 2021 23:37:42 +0100 Subject: [PATCH 07/14] linting --- libs/remix-ui/editor/src/lib/remix-ui-editor.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 4f3dadd3cf..16a5e062f1 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -381,14 +381,14 @@ export const EditorUI = (props: EditorUIProps) => { return (
- +
Date: Wed, 22 Dec 2021 11:31:25 +0100 Subject: [PATCH 08/14] linter --- .../src/lib/remix-ui-editor-context-view.tsx | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) 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 ea99c34b99..ca6ca5930c 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 @@ -1,11 +1,27 @@ import React, { useEffect, useState, useRef } from 'react' // eslint-disable-line import { sourceMappingDecoder } from '@remix-project/remix-debug' -import './remix-ui-editor-context-view.css'; +import './remix-ui-editor-context-view.css' + +/* eslint-disable-next-line */ + +export type astNode = { + name: string, + id: number, + children: Array, + typeDescriptions: any, + nodeType: String, + src: any, + nodeId: any, + position: any +} export type onContextListenerChangedListener = (nodes: Array) => void -/* eslint-disable-next-line */ +export type gasEstimationType = { + executionCost: string, + codeDepositCost: string +} export interface RemixUiEditorContextViewProps { hide: boolean, gotoLine: (line: number, column: number) => void, @@ -29,39 +45,25 @@ function isDefinition (node: any) { node.nodeType === 'EventDefinition' } -export type gasEstimationType = { - executionCost: string, - codeDepositCost: string -} -export type astNode = { - name: string, - id: number, - children: Array, - typeDescriptions: any, - nodeType: String, - src: any, - nodeId: any, - position: any -} type nullableAstNode = astNode | null -export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) { +export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) { const nodesRef = useRef>([]) /* - gotoLineDisableRef is used to temporarily disable the update of the view. + 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 referencesRef = useRef([]) const activeHighlightsRef = useRef([]) const currentNodeRef = useRef(null as nullableAstNode) const gasEstimationRef = useRef({} as gasEstimationType) - const gotoLineDisableRef = useRef(false) - const [nodesState, setNode] = useState>([]) - + const gotoLineDisableRef = useRef(false) + const [, setNode] = useState>([]) + useEffect(() => { - props.onContextListenerChanged(async (nodes: Array) => { + props.onContextListenerChanged(async (nodes: Array) => { if (gotoLineDisableRef.current) { gotoLineDisableRef.current = false return @@ -75,23 +77,23 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) { } if (currentNodeRef.current) { referencesRef.current = await props.referencesOf(currentNodeRef.current) - gasEstimationRef.current = await props.gasEstimation(currentNodeRef.current) + gasEstimationRef.current = await props.gasEstimation(currentNodeRef.current) } - activeHighlightsRef.current = await props.getActiveHighlights() + activeHighlightsRef.current = await props.getActiveHighlights() setNode(nodes) }) }, []) const _render = (node: nullableAstNode) => { if (!node) return (
) - let references = referencesRef.current + const references = referencesRef.current const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType - let referencesCount = `${references ? references.length : '0'} reference(s)` + const referencesCount = `${references ? references.length : '0'} reference(s)` let ref = 0 const nodes: Array = activeHighlightsRef.current - - /* + + /* * show gas estimation */ const gasEstimation = () => { @@ -120,7 +122,7 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) { await props.openFile(fileName) } if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { - gotoLineDisableRef.current = true + gotoLineDisableRef.current = true props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) } } @@ -164,13 +166,13 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) {
) - } + } return ( !props.hide &&
{_render(currentNodeRef.current)}
- ); + ) } export default RemixUiEditorContextView From e52145f9eee735e7c5a0a1910413ed55fa3c61ac Mon Sep 17 00:00:00 2001 From: lianahus Date: Wed, 22 Dec 2021 13:42:31 +0100 Subject: [PATCH 09/14] fixes the resize of editor div --- libs/remix-ui/editor/src/lib/remix-ui-editor.css | 6 +++--- libs/remix-ui/editor/src/lib/remix-ui-editor.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.css b/libs/remix-ui/editor/src/lib/remix-ui-editor.css index a078bfd498..af7cd06bfd 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.css +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.css @@ -11,6 +11,6 @@ } .contextview { - opacity : 1; - position : relative; - } \ No newline at end of file + opacity: 1; + position: absolute; +} \ No newline at end of file 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 16a5e062f1..db1017f0e5 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -259,7 +259,7 @@ export const EditorUI = (props: EditorUIProps) => { range: new monacoRef.current.Range(marker.position.start.line + 1, marker.position.start.column + 1, marker.position.end.line + 1, marker.position.end.column + 1), options: { isWholeLine, - inlineClassName: `bg-info highlightLine${marker.position.start.line + 1}` + inlineClassName: `alert-info highlightLine${marker.position.start.line + 1}` } }) } @@ -380,7 +380,7 @@ export const EditorUI = (props: EditorUIProps) => { } return ( -
+
Date: Wed, 22 Dec 2021 16:37:17 +0100 Subject: [PATCH 10/14] fixed the colors of editor's content menu --- libs/remix-ui/editor/src/lib/remix-ui-editor.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 db1017f0e5..67df7cd443 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -210,7 +210,12 @@ export const EditorUI = (props: EditorUIProps) => { 'editor.lineHighlightBorder': secondaryColor, 'editor.lineHighlightBackground': textbackground === darkColor ? lightColor : secondaryColor, 'editorGutter.background': lightColor, - 'minimap.background': lightColor + 'minimap.background': lightColor, + 'menu.foreground': textColor, + 'menu.background': textbackground, + 'menu.selectionBackground': secondaryColor, + 'menu.selectionForeground': textColor, + 'menu.selectionBorder': secondaryColor } }) monacoRef.current.editor.setTheme(themeName) From 224f6324b9f3bbd3226d2a0df9fbbfddfec87f1f Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 23 Dec 2021 11:03:04 +0100 Subject: [PATCH 11/14] use "useState" instead of "useRef" --- .../src/lib/remix-ui-editor-context-view.tsx | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) 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 ca6ca5930c..13ceb93426 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 @@ -50,55 +50,68 @@ function isDefinition (node: any) { type nullableAstNode = astNode | null export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) { - const nodesRef = useRef>([]) /* 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 referencesRef = useRef([]) - const activeHighlightsRef = useRef([]) - const currentNodeRef = useRef(null as nullableAstNode) - const gasEstimationRef = useRef({} as gasEstimationType) const gotoLineDisableRef = useRef(false) - const [, setNode] = useState>([]) - + const [state, setState] = useState<{ + nodes: Array, + references: Array, + activeHighlights: Array + currentNode: nullableAstNode, + gasEstimation: gasEstimationType + }>({ + nodes: [], + references: [], + activeHighlights: [], + currentNode: null, + gasEstimation: { executionCost: '', codeDepositCost: '' } + }) + useEffect(() => { props.onContextListenerChanged(async (nodes: Array) => { if (gotoLineDisableRef.current) { gotoLineDisableRef.current = false return } - nodesRef.current = nodes - if (!props.hide && nodesRef.current && nodesRef.current.length) { - currentNodeRef.current = nodesRef.current[nodesRef.current.length - 1] - if (!isDefinition(currentNodeRef.current)) { - currentNodeRef.current = await props.declarationOf(currentNodeRef.current) + let currentNode + if (!props.hide && nodes && nodes.length) { + currentNode = nodes[nodes.length - 1] + if (!isDefinition(currentNode)) { + currentNode = await props.declarationOf(currentNode) } } - if (currentNodeRef.current) { - referencesRef.current = await props.referencesOf(currentNodeRef.current) - gasEstimationRef.current = await props.gasEstimation(currentNodeRef.current) + let references + let gasEstimation + if (currentNode) { + references = await props.referencesOf(currentNode) + if (currentNode.nodeType === 'FunctionDefinition') { + gasEstimation = await props.gasEstimation(currentNode) + } } - activeHighlightsRef.current = await props.getActiveHighlights() - setNode(nodes) + let activeHighlights = await props.getActiveHighlights() + setState(prevState => { + return { ...prevState, nodes, references, activeHighlights, currentNode, gasEstimation } + }) }) }, []) const _render = (node: nullableAstNode) => { if (!node) return (
) - const references = referencesRef.current + const references = state.references 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 = activeHighlightsRef.current + const nodes: Array = state.activeHighlights /* * show gas estimation */ const gasEstimation = () => { if (node.nodeType === 'FunctionDefinition') { - const result: gasEstimationType = gasEstimationRef.current + const result: gasEstimationType = state.gasEstimation const executionCost = ' Execution cost: ' + result.executionCost + ' gas' const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` @@ -170,7 +183,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) return ( !props.hide &&
- {_render(currentNodeRef.current)} + {_render(state.currentNode)}
) } From 1d70aef400c98b9ed85a34f8cb81329931a4f19b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 27 Dec 2021 10:57:03 +0100 Subject: [PATCH 12/14] put functions at top level --- .../src/lib/remix-ui-editor-context-view.tsx | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) 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 13ceb93426..e0c0898868 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 @@ -97,6 +97,52 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) }) }, []) + /* + * show gas estimation + */ + const gasEstimation = (node) => { + if (node.nodeType === 'FunctionDefinition') { + const result: gasEstimationType = state.gasEstimation + const executionCost = ' Execution cost: ' + result.executionCost + ' gas' + const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' + const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` + return ( +
+ + {estimatedGas} +
+ ) + } else { + return (
) + } + } + + /* + * onClick jump to ast node in the editor + */ + const _jumpToInternal = async (position: any) => { + const jumpToLine = async (fileName: string, lineColumn: any) => { + if (fileName !== await props.getCurrentFileName()) { + await props.openFile(fileName) + } + if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { + gotoLineDisableRef.current = true + props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) + } + } + const lastCompilationResult = await props.getLastCompilationResult() + if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) { + const lineColumn = await props.offsetToLineColumn( + position, + position.file, + lastCompilationResult.getSourceCode().sources, + lastCompilationResult.getAsts()) + const filename = lastCompilationResult.getSourceName(position.file) + // TODO: refactor with rendererAPI.errorClick + jumpToLine(filename, lineColumn) + } + } + const _render = (node: nullableAstNode) => { if (!node) return (
) const references = state.references @@ -106,52 +152,6 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) let ref = 0 const nodes: Array = state.activeHighlights - /* - * show gas estimation - */ - const gasEstimation = () => { - if (node.nodeType === 'FunctionDefinition') { - const result: gasEstimationType = state.gasEstimation - const executionCost = ' Execution cost: ' + result.executionCost + ' gas' - const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas' - const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}` - return ( -
- - {estimatedGas} -
- ) - } else { - return (
) - } - } - - /* - * onClick jump to ast node in the editor - */ - const _jumpToInternal = async (position: any) => { - const jumpToLine = async (fileName: string, lineColumn: any) => { - if (fileName !== await props.getCurrentFileName()) { - await props.openFile(fileName) - } - if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { - gotoLineDisableRef.current = true - props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) - } - } - const lastCompilationResult = await props.getLastCompilationResult() - if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) { - const lineColumn = await props.offsetToLineColumn( - position, - position.file, - lastCompilationResult.getSourceCode().sources, - lastCompilationResult.getAsts()) - const filename = lastCompilationResult.getSourceName(position.file) - // TODO: refactor with rendererAPI.errorClick - jumpToLine(filename, lineColumn) - } - } - const jumpTo = () => { if (node && node.src) { const position = sourceMappingDecoder.decode(node.src) @@ -170,7 +170,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) } return ( -
{gasEstimation()} +
{gasEstimation(node)}
{type}
{node.name}
From 2d8ff4baf7182e363bfce57d0b80212ae2d1d4b3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 27 Dec 2021 11:02:47 +0100 Subject: [PATCH 13/14] linting --- .../src/lib/custom-hooks/useDragTerminal.tsx | 116 +++++++++--------- .../terminal/src/lib/remix-ui-terminal.tsx | 5 +- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx b/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx index cdd4f6dc6a..1416ff2ddb 100644 --- a/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx +++ b/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx @@ -1,77 +1,77 @@ import { useEffect, useState } from 'react' export const useDragTerminal = (minHeight: number, defaultPosition: number) => { - const [isOpen, setIsOpen] = useState(defaultPosition > minHeight) - const [lastYPosition, setLastYPosition] = useState(0) - const [terminalPosition, setTerminalPosition] = useState(defaultPosition) - // Used to save position of the terminal when it is closed - const [lastTerminalPosition, setLastTerminalPosition] = useState(defaultPosition) - const [isDragging, setIsDragging] = useState(false) + const [isOpen, setIsOpen] = useState(defaultPosition > minHeight) + const [lastYPosition, setLastYPosition] = useState(0) + const [terminalPosition, setTerminalPosition] = useState(defaultPosition) + // Used to save position of the terminal when it is closed + const [lastTerminalPosition, setLastTerminalPosition] = useState(defaultPosition) + const [isDragging, setIsDragging] = useState(false) - const handleDraggingStart = (event: React.MouseEvent) => { - setLastYPosition(event.clientY) - setIsDragging(true) - } + const handleDraggingStart = (event: React.MouseEvent) => { + setLastYPosition(event.clientY) + setIsDragging(true) + } - const handleDragging = (event: MouseEvent) => { - event.preventDefault() + const handleDragging = (event: MouseEvent) => { + event.preventDefault() - if (isDragging) { - const mouseYPosition = event.clientY - const difference = lastYPosition - mouseYPosition - const newTerminalPosition = terminalPosition + difference - setTerminalPosition(newTerminalPosition) - setLastYPosition(mouseYPosition) - } + if (isDragging) { + const mouseYPosition = event.clientY + const difference = lastYPosition - mouseYPosition + const newTerminalPosition = terminalPosition + difference + setTerminalPosition(newTerminalPosition) + setLastYPosition(mouseYPosition) } + } - const handleDraggingEnd = () => { - if(!isDragging) return - - setIsDragging(false) + const handleDraggingEnd = () => { + if (!isDragging) return - // Check terminal position to determine if it should be open or closed - setIsOpen(terminalPosition > minHeight) - } + setIsDragging(false) - const handleToggleTerminal = (event: React.MouseEvent) => { - event.preventDefault() - event.stopPropagation() + // Check terminal position to determine if it should be open or closed + setIsOpen(terminalPosition > minHeight) + } - if(isOpen) { - setLastTerminalPosition(terminalPosition) - setLastYPosition(0) - setTerminalPosition(minHeight) - } else { - setTerminalPosition(lastTerminalPosition <= minHeight ? 323 : lastTerminalPosition) - } + const handleToggleTerminal = (event: React.MouseEvent) => { + event.preventDefault() + event.stopPropagation() - setIsOpen(!isOpen) + if (isOpen) { + setLastTerminalPosition(terminalPosition) + setLastYPosition(0) + setTerminalPosition(minHeight) + } else { + setTerminalPosition(lastTerminalPosition <= minHeight ? 323 : lastTerminalPosition) } - // Add event listeners for dragging - useEffect(() => { - document.addEventListener('mousemove', handleDragging) - document.addEventListener('mouseup', handleDraggingEnd) + setIsOpen(!isOpen) + } - return () => { - document.removeEventListener('mousemove', handleDragging) - document.removeEventListener('mouseup', handleDraggingEnd) - } - }, [handleDragging, handleDraggingEnd]) + // Add event listeners for dragging + useEffect(() => { + document.addEventListener('mousemove', handleDragging) + document.addEventListener('mouseup', handleDraggingEnd) - // Reset terminal position - useEffect(() => { - if(!terminalPosition){ - setTerminalPosition(defaultPosition) - } - }, [terminalPosition, setTerminalPosition]) + return () => { + document.removeEventListener('mousemove', handleDragging) + document.removeEventListener('mouseup', handleDraggingEnd) + } + }, [handleDragging, handleDraggingEnd]) - return { - isOpen, - terminalPosition, - isDragging, - handleDraggingStart, - handleToggleTerminal, + // Reset terminal position + useEffect(() => { + if (!terminalPosition) { + setTerminalPosition(defaultPosition) } + }, [terminalPosition, setTerminalPosition]) + + return { + isOpen, + terminalPosition, + isDragging, + handleDraggingStart, + handleToggleTerminal, + } } \ No newline at end of file diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx index de6de4eb23..8cc0829796 100644 --- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx +++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx @@ -95,7 +95,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => { useEffect(() => { event.trigger('resize', [terminalPosition]) - } , [terminalPosition]) + }, [terminalPosition]) const scrollToBottom = () => { messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }) @@ -211,9 +211,6 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => { } } - - - const focusinput = () => { inputEl.current.focus() } From 34e49bf909edf44d78b7b5947f89e6ec57562132 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 27 Dec 2021 11:11:34 +0100 Subject: [PATCH 14/14] lintig --- .../terminal/src/lib/custom-hooks/useDragTerminal.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx b/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx index 1416ff2ddb..aba4bbf6a5 100644 --- a/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx +++ b/libs/remix-ui/terminal/src/lib/custom-hooks/useDragTerminal.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' export const useDragTerminal = (minHeight: number, defaultPosition: number) => { const [isOpen, setIsOpen] = useState(defaultPosition > minHeight) @@ -72,6 +72,6 @@ export const useDragTerminal = (minHeight: number, defaultPosition: number) => { terminalPosition, isDragging, handleDraggingStart, - handleToggleTerminal, + handleToggleTerminal } -} \ No newline at end of file +}