jumpToDefinition

pull/5370/head
bunsenstraat 3 years ago
parent ad90f2e3ff
commit eb4e2b42bb
  1. 100
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  2. 40
      libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx
  3. 78
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  4. 64134
      package-lock.json

@ -2,14 +2,24 @@
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import { sourceMappingDecoder } from '@remix-project/remix-debug' import { sourceMappingDecoder } from '@remix-project/remix-debug'
import { AstNode } from '@remix-project/remix-solidity-ts'
const profile = { const profile = {
name: 'contextualListener', name: 'contextualListener',
methods: ['referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf'], methods: ['jumpToDefinition', 'nodesAtEditorPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'jumpTo'],
events: [], events: [],
version: '0.0.1' version: '0.0.1'
} }
export function isDefinition(node: any) {
return node.nodeType === 'ContractDefinition' ||
node.nodeType === 'FunctionDefinition' ||
node.nodeType === 'ModifierDefinition' ||
node.nodeType === 'VariableDeclaration' ||
node.nodeType === 'StructDefinition' ||
node.nodeType === 'EventDefinition'
}
/* /*
trigger contextChanged(nodes) trigger contextChanged(nodes)
*/ */
@ -27,7 +37,7 @@ export class EditorContextListener extends Plugin {
contract: any contract: any
activated: boolean activated: boolean
constructor (astWalker) { constructor(astWalker) {
super(profile) super(profile)
this.activated = false this.activated = false
this._index = { this._index = {
@ -39,7 +49,7 @@ export class EditorContextListener extends Plugin {
this.astWalker = astWalker this.astWalker = astWalker
} }
onActivation () { onActivation() {
this.on('editor', 'contentChanged', () => { this._stopHighlighting() }) this.on('editor', 'contentChanged', () => { this._stopHighlighting() })
this.on('solidity', 'compilationFinished', (file, source, languageVersion, data, input, version) => { this.on('solidity', 'compilationFinished', (file, source, languageVersion, data, input, version) => {
@ -50,6 +60,7 @@ export class EditorContextListener extends Plugin {
FlatReferences: {} FlatReferences: {}
} }
this._buildIndex(data, source) this._buildIndex(data, source)
console.log(this._index)
}) })
setInterval(async () => { setInterval(async () => {
@ -72,22 +83,78 @@ export class EditorContextListener extends Plugin {
this.activated = true this.activated = true
} }
getActiveHighlights () { getActiveHighlights() {
return [...this._activeHighlights] return [...this._activeHighlights]
} }
declarationOf (node) { declarationOf(node) {
if (node && node.referencedDeclaration) { if (node && node.referencedDeclaration) {
return this._index.FlatReferences[node.referencedDeclaration] return this._index.FlatReferences[node.referencedDeclaration]
} }
return null return null
} }
referencesOf (node) { referencesOf(node) {
return this._index.Declarations[node.id] return this._index.Declarations[node.id]
} }
async _highlightItems (cursorPosition, compilationResult, file) { async nodesAtEditorPosition(position: any){
const lastCompilationResult = await this.call('compilerArtefacts', 'getLastCompilationResult')
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const nodes = sourceMappingDecoder.nodesAtPosition(null, position, lastCompilationResult.data.sources[this.currentFile])
return nodes
}
return []
}
async jumpToDefinition(position: any) {
const nodes = await this.nodesAtEditorPosition(position)
console.log(nodes)
let nodeDeclaration: AstNode
let node: AstNode
if (nodes && nodes.length) {
node = nodes[nodes.length - 1]
if (!isDefinition(node)) {
nodeDeclaration = await this.declarationOf(node)
} else {
nodeDeclaration = node
}
}
console.log(node, nodeDeclaration)
if (nodeDeclaration && nodeDeclaration.src) {
console.log(nodeDeclaration)
const position = sourceMappingDecoder.decode(nodeDeclaration.src)
if (position) {
await this.jumpToPosition(position)
}
}
}
/*
* onClick jump to position of ast node in the editor
*/
async jumpToPosition(position: any) {
const jumpToLine = async (fileName: string, lineColumn: any) => {
if (fileName !== await this.call('fileManager', 'file')) {
await this.call('fileManager', 'open', fileName)
}
if (lineColumn.start && lineColumn.start.line >= 0 && lineColumn.start.column >= 0) {
this.call('editor', 'gotoLine', lineColumn.start.line, lineColumn.end.column + 1)
}
}
const lastCompilationResult = await this.call('compilerArtefacts', 'getLastCompilationResult')
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const lineColumn = await this.call('offsetToLineColumnConverter', 'offsetToLineColumn',
position,
position.file,
lastCompilationResult.getSourceCode().sources,
lastCompilationResult.getAsts())
const filename = lastCompilationResult.getSourceName(position.file)
// TODO: refactor with rendererAPI.errorClick
jumpToLine(filename, lineColumn)
}
}
async _highlightItems(cursorPosition, compilationResult, file) {
if (this.currentPosition === cursorPosition) return if (this.currentPosition === cursorPosition) return
this._stopHighlighting() this._stopHighlighting()
this.currentPosition = cursorPosition this.currentPosition = cursorPosition
@ -95,6 +162,7 @@ export class EditorContextListener extends Plugin {
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) { if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
const nodes = sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) const nodes = sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file])
this.nodes = nodes this.nodes = nodes
console.log(nodes)
if (nodes && nodes.length && nodes[nodes.length - 1]) { if (nodes && nodes.length && nodes[nodes.length - 1]) {
await this._highlightExpressions(nodes[nodes.length - 1], compilationResult) await this._highlightExpressions(nodes[nodes.length - 1], compilationResult)
} }
@ -102,7 +170,7 @@ export class EditorContextListener extends Plugin {
} }
} }
_buildIndex (compilationResult, source) { _buildIndex(compilationResult, source) {
if (compilationResult && compilationResult.sources) { if (compilationResult && compilationResult.sources) {
const callback = (node) => { const callback = (node) => {
if (node && node.referencedDeclaration) { if (node && node.referencedDeclaration) {
@ -119,7 +187,7 @@ export class EditorContextListener extends Plugin {
} }
} }
async _highlight (node, compilationResult) { async _highlight(node, compilationResult) {
if (!node) return if (!node) return
const position = sourceMappingDecoder.decode(node.src) const position = sourceMappingDecoder.decode(node.src)
const fileTarget = compilationResult.getSourceName(position.file) const fileTarget = compilationResult.getSourceName(position.file)
@ -132,7 +200,7 @@ export class EditorContextListener extends Plugin {
} }
} }
async _highlightInternal (position, node, compilationResult) { async _highlightInternal(position, node, compilationResult) {
if (node.nodeType === 'Block') return if (node.nodeType === 'Block') return
if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) { if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
let lineColumn = await this.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, position.file, compilationResult.getSourceCode().sources, compilationResult.getAsts()) let lineColumn = await this.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, position.file, compilationResult.getSourceCode().sources, compilationResult.getAsts())
@ -157,7 +225,7 @@ export class EditorContextListener extends Plugin {
return null return null
} }
async _highlightExpressions (node, compilationResult) { async _highlightExpressions(node, compilationResult) {
const highlights = async (id) => { const highlights = async (id) => {
if (this._index.Declarations && this._index.Declarations[id]) { if (this._index.Declarations && this._index.Declarations[id]) {
const refs = this._index.Declarations[id] const refs = this._index.Declarations[id]
@ -178,13 +246,13 @@ export class EditorContextListener extends Plugin {
this.results = compilationResult this.results = compilationResult
} }
_stopHighlighting () { _stopHighlighting() {
this.call('editor', 'discardHighlight') this.call('editor', 'discardHighlight')
this.emit('stopHighlighting') this.emit('stopHighlighting')
this._activeHighlights = [] this._activeHighlights = []
} }
gasEstimation (node) { gasEstimation(node) {
this._loadContractInfos(node) this._loadContractInfos(node)
let executionCost, codeDepositCost let executionCost, codeDepositCost
if (node.nodeType === 'FunctionDefinition') { if (node.nodeType === 'FunctionDefinition') {
@ -207,7 +275,7 @@ export class EditorContextListener extends Plugin {
return { executionCost, codeDepositCost } return { executionCost, codeDepositCost }
} }
_loadContractInfos (node) { _loadContractInfos(node) {
const path = (this.nodes.length && this.nodes[0].absolutePath) || this.results.source.target const path = (this.nodes.length && this.nodes[0].absolutePath) || this.results.source.target
for (const i in this.nodes) { for (const i in this.nodes) {
if (this.nodes[i].id === node.scope) { if (this.nodes[i].id === node.scope) {
@ -222,7 +290,9 @@ export class EditorContextListener extends Plugin {
} }
} }
_getInputParams (node) {
_getInputParams(node) {
const params = [] const params = []
const target = node.parameters const target = node.parameters
// for (const i in node.children) { // for (const i in node.children) {

@ -35,14 +35,9 @@ export type gasEstimationType = {
} }
export interface RemixUiEditorContextViewProps { export interface RemixUiEditorContextViewProps {
hide: boolean, hide: boolean,
gotoLine: (line: number, column: number) => void, jumpToPosition: (position: any) => void
openFile: (fileName: string) => void,
getLastCompilationResult: () => any,
offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any,
getCurrentFileName: () => string
onContextListenerChanged: (listener: onContextListenerChangedListener) => void onContextListenerChanged: (listener: onContextListenerChangedListener) => void
onCurrentFileChanged: (listener: ononCurrentFileChangedListener) => void onCurrentFileChanged: (listener: ononCurrentFileChangedListener) => void
referencesOf: (nodes: astNode) => Array<astNode>
getActiveHighlights: () => Array<astNodeLight> getActiveHighlights: () => Array<astNodeLight>
gasEstimation: (node: astNode) => gasEstimationType gasEstimation: (node: astNode) => gasEstimationType
declarationOf: (node: astNode) => astNode declarationOf: (node: astNode) => astNode
@ -91,6 +86,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps)
nextNodeDeclaration = nextNode nextNodeDeclaration = nextNode
} }
} }
console.log(nextNode, nextNodeDeclaration)
if (nextNodeDeclaration && currentNodeDeclaration.current && nextNodeDeclaration.id === currentNodeDeclaration.current.id) return if (nextNodeDeclaration && currentNodeDeclaration.current && nextNodeDeclaration.id === currentNodeDeclaration.current.id) return
currentNodeDeclaration.current = nextNodeDeclaration currentNodeDeclaration.current = nextNodeDeclaration
@ -134,35 +130,13 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps)
} }
} }
/*
* 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 >= 0 && lineColumn.start.column >= 0) {
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 = () => { const _render = () => {
const node = currentNodeDeclaration.current const node = currentNodeDeclaration.current
if (!node) return (<div></div>) if (!node) return (<div></div>)
const references = state.activeHighlights const references = state.activeHighlights
console.log(node)
const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType
const referencesCount = `${references ? references.length : '0'} reference(s)` const referencesCount = `${references ? references.length : '0'} reference(s)`
@ -170,9 +144,10 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps)
const jumpTo = () => { const jumpTo = () => {
if (node && node.src) { if (node && node.src) {
console.log(node)
const position = sourceMappingDecoder.decode(node.src) const position = sourceMappingDecoder.decode(node.src)
if (position) { if (position) {
_jumpToInternal(position) props.jumpToPosition(position)
} }
} }
} }
@ -182,7 +157,8 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps)
e.target.dataset.action === 'next' ? loopOverReferences.current++ : loopOverReferences.current-- e.target.dataset.action === 'next' ? loopOverReferences.current++ : loopOverReferences.current--
if (loopOverReferences.current < 0) loopOverReferences.current = nodes.length - 1 if (loopOverReferences.current < 0) loopOverReferences.current = nodes.length - 1
if (loopOverReferences.current >= nodes.length) loopOverReferences.current = 0 if (loopOverReferences.current >= nodes.length) loopOverReferences.current = 0
_jumpToInternal(nodes[loopOverReferences.current].position) console.log(loopOverReferences.current)
props.jumpToPosition(nodes[loopOverReferences.current].position)
} }
return ( return (

@ -1,12 +1,15 @@
import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line
import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view' import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view'
import Editor, { loader } from '@monaco-editor/react' import Editor, { loader, Monaco } from '@monaco-editor/react'
import { reducerActions, reducerListener, initialState } from './actions/editor' import { reducerActions, reducerListener, initialState } from './actions/editor'
import { language, conf } from './syntax' import { language, conf } from './syntax'
import { cairoLang, cairoConf } from './cairoSyntax' import { cairoLang, cairoConf } from './cairoSyntax'
import './remix-ui-editor.css' import './remix-ui-editor.css'
import { loadTypes } from './web-types' import { loadTypes } from './web-types'
import monaco from '../types/monaco'
import { IPosition, languages } from 'monaco-editor'
import { sourceMappingDecoder } from '@remix-project/remix-debug'
type cursorPosition = { type cursorPosition = {
startLineNumber: number, startLineNumber: number,
@ -67,6 +70,7 @@ export interface EditorUIProps {
getFontSize: () => number, getFontSize: () => number,
getValue: (uri: string) => string getValue: (uri: string) => string
getCursorPosition: () => cursorPosition getCursorPosition: () => cursorPosition
getHoverPosition: (position: IPosition) => number
addDecoration: (marker: sourceMarker, filePath: string, typeOfDecoration: string) => DecorationsReturn addDecoration: (marker: sourceMarker, filePath: string, typeOfDecoration: string) => DecorationsReturn
clearDecorationsByPlugin: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn clearDecorationsByPlugin: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
keepDecorationsFor: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn keepDecorationsFor: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
@ -80,7 +84,7 @@ export const EditorUI = (props: EditorUIProps) => {
const currentFileRef = useRef('') const currentFileRef = useRef('')
// const currentDecorations = useRef({ sourceAnnotationsPerFile: {}, markerPerFile: {} }) // decorations that are currently in use by the editor // const currentDecorations = useRef({ sourceAnnotationsPerFile: {}, markerPerFile: {} }) // decorations that are currently in use by the editor
// const registeredDecorations = useRef({}) // registered decorations // const registeredDecorations = useRef({}) // registered decorations
const [editorModelsState, dispatch] = useReducer(reducerActions, initialState) const [editorModelsState, dispatch] = useReducer(reducerActions, initialState)
const formatColor = (name) => { const formatColor = (name) => {
@ -237,7 +241,7 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-solidity') monacoRef.current.editor.setModelLanguage(file.model, 'remix-solidity')
} else if (file.language === 'cairo') { } else if (file.language === 'cairo') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-cairo') monacoRef.current.editor.setModelLanguage(file.model, 'remix-cairo')
} }
}, [props.currentFile]) }, [props.currentFile])
const convertToMonacoDecoration = (decoration: sourceAnnotation | sourceMarker, typeOfDecoration: string) => { const convertToMonacoDecoration = (decoration: sourceAnnotation | sourceMarker, typeOfDecoration: string) => {
@ -293,7 +297,7 @@ export const EditorUI = (props: EditorUIProps) => {
registeredDecorations: newRegisteredDecorations registeredDecorations: newRegisteredDecorations
} }
} }
props.editorAPI.keepDecorationsFor = (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => { props.editorAPI.keepDecorationsFor = (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => {
const model = editorModelsState[filePath]?.model const model = editorModelsState[filePath]?.model
if (!model) return { if (!model) return {
@ -322,7 +326,7 @@ export const EditorUI = (props: EditorUIProps) => {
registeredDecorations: [{ value: decoration, type: typeOfDecoration }] registeredDecorations: [{ value: decoration, type: typeOfDecoration }]
} }
} }
props.editorAPI.addDecoration = (marker: sourceMarker, filePath: string, typeOfDecoration: string) => { props.editorAPI.addDecoration = (marker: sourceMarker, filePath: string, typeOfDecoration: string) => {
return addDecoration(marker, filePath, typeOfDecoration) return addDecoration(marker, filePath, typeOfDecoration)
} }
@ -349,6 +353,16 @@ export const EditorUI = (props: EditorUIProps) => {
} }
} }
props.editorAPI.getHoverPosition = (position: monaco.Position) => {
if (!monacoRef.current) return
const model = editorModelsState[currentFileRef.current]?.model
if (model) {
return model.getOffsetAt(position)
}else{
return 0
}
}
props.editorAPI.getFontSize = () => { props.editorAPI.getFontSize = () => {
if (!editorRef.current) return if (!editorRef.current) return
return editorRef.current.getOption(43).fontSize return editorRef.current.getOption(43).fontSize
@ -381,7 +395,7 @@ export const EditorUI = (props: EditorUIProps) => {
} }
} }
function handleEditorDidMount (editor) { function handleEditorDidMount(editor) {
editorRef.current = editor editorRef.current = editor
defineAndSetTheme(monacoRef.current) defineAndSetTheme(monacoRef.current)
reducerListener(props.plugin, dispatch, monacoRef.current, editorRef.current, props.events) reducerListener(props.plugin, dispatch, monacoRef.current, editorRef.current, props.events)
@ -399,7 +413,7 @@ export const EditorUI = (props: EditorUIProps) => {
}) })
} }
function handleEditorWillMount (monaco) { function handleEditorWillMount(monaco) {
monacoRef.current = monaco monacoRef.current = monaco
// Register a new language // Register a new language
monacoRef.current.languages.register({ id: 'remix-solidity' }) monacoRef.current.languages.register({ id: 'remix-solidity' })
@ -410,6 +424,49 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang) monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf) monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf)
// register Definition Provider
monacoRef.current.languages.registerDefinitionProvider('remix-solidity', {
provideDefinition(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken){
const cursorPosition = props.editorAPI.getCursorPosition()
props.plugin.call('contextualListener', 'jumpToDefinition', cursorPosition)
return null
}
})
monacoRef.current.languages.registerHoverProvider('remix-solidity', {
provideHover: async function (model: any, position: monaco.Position) {
//console.log(position)
const cursorPosition = props.editorAPI.getHoverPosition(position)
//console.log(cursorPosition)
const compilationResult = await props.plugin.call('compilerArtefacts', 'getLastCompilationResult')
const file = await props.plugin.call('fileManager', 'file')
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
const nodes = sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file])
// console.log(cursorPosition, nodes)
// loop over nodes
if (nodes && nodes.length) {
nodes.forEach((node) => {
const position = sourceMappingDecoder.decode(node.src)
const fileTarget = compilationResult.getSourceName(position.file)
// console.log(position, fileTarget)
})
}
}
return {
range: new monaco.Range(
position.lineNumber,
position.column,
position.lineNumber,
model.getLineMaxColumn(position.lineNumber)
),
contents: [
{ value: '<div>test html</div>' }
]
};
}
})
loadTypes(monacoRef.current) loadTypes(monacoRef.current)
} }
@ -427,14 +484,9 @@ export const EditorUI = (props: EditorUIProps) => {
<div className="contextview"> <div className="contextview">
<RemixUiEditorContextView <RemixUiEditorContextView
hide={false} hide={false}
gotoLine={(line, column) => props.plugin.call('editor', 'gotoLine', line, column)} jumpToPosition={(position) => props.plugin.call('contextualListener', 'jumpToPosition', position)}
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) }} onContextListenerChanged={(listener) => { props.plugin.on('contextualListener', 'contextChanged', listener) }}
onCurrentFileChanged={(listener) => { props.plugin.on('fileManager', 'currentFileChanged', 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') }} getActiveHighlights={() => { return props.plugin.call('contextualListener', 'getActiveHighlights') }}
gasEstimation={(node: astNode) => { return props.plugin.call('contextualListener', 'gasEstimation', node) }} gasEstimation={(node: astNode) => { return props.plugin.call('contextualListener', 'gasEstimation', node) }}
declarationOf={(node: astNode) => { return props.plugin.call('contextualListener', 'declarationOf', node) }} declarationOf={(node: astNode) => { return props.plugin.call('contextualListener', 'declarationOf', node) }}

64134
package-lock.json generated

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save