pre ts parse

editorcontextDummy
bunsenstraat 3 years ago
parent 06e411e76b
commit 2d04d3cb2c
  1. 1
      libs/remix-astwalker/src/astWalker.ts
  2. 43
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  3. 14
      libs/remix-core-plugin/tsconfig.json
  4. 7
      libs/remix-core-plugin/tsconfig.lib.json
  5. 2
      libs/remix-solidity/package.json
  6. 6
      libs/remix-tests/src/compiler.ts
  7. 3
      libs/remix-tests/tsconfig.json
  8. 105
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  9. 21
      libs/remix-ui/editor/src/lib/providers/hoverProvider.ts
  10. 25
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  11. 2
      package.json
  12. 8
      yarn.lock

@ -1,6 +1,5 @@
import { EventEmitter } from 'events'
import { Node, AstNode } from './index'
import type { CompilationError } from '@remix-project/remix-solidity-ts'
export declare interface AstWalker {
new(): EventEmitter;

@ -7,11 +7,9 @@ import { Compiler } from '@remix-project/remix-solidity'
import { helper } from '@remix-project/remix-solidity'
import type { CompilationError } from '@remix-project/remix-solidity-ts'
const profile = {
name: 'contextualListener',
methods: ['getBlockName', 'getAST', 'nodesWithScope', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'nodesAtEditorPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'jumpToPosition'],
methods: ['getBlockName', 'resolveImports', 'getAST', 'nodesWithScope', 'nodesWithName', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'nodesAtEditorPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'jumpToPosition'],
events: [],
version: '0.0.1'
}
@ -43,9 +41,7 @@ export class EditorContextListener extends Plugin {
codeDepositCost: any
contract: any
activated: boolean
lastCompilationResult: any
lastAST: any
compiler: any
onAstFinished: (success: any, data: any, source: any, input: any, version: any) => Promise<void>
@ -70,16 +66,16 @@ export class EditorContextListener extends Plugin {
this._stopHighlighting()
})
this.on('solidity', 'loadingCompiler', async(url) => {
this.on('solidity', 'loadingCompiler', async (url) => {
console.log('loading compiler', url)
this.compiler.event.register('compilerLoaded', async() => await this.compile() )
this.compiler.event.register('compilerLoaded', async () => await this.compile())
this.compiler.loadVersion(true, url)
})
this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url, undefined, false).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.onAstFinished = async (success, data, source, input, version) => {
console.log('compile success', success)
@ -129,7 +125,7 @@ export class EditorContextListener extends Plugin {
//await this.compile()
}, 1000)
setInterval(async () => {
const compilationResult = this.lastCompilationResult // await this.call('compilerArtefacts', 'getLastCompilationResult')
@ -173,6 +169,21 @@ export class EditorContextListener extends Plugin {
}
}
async resolveImports(node, imported = {}) {
if (node.nodeType === 'ImportDirective' && !imported[node.sourceUnit]) {
console.log('IMPORTING', node)
const importNode = await this.getNodeById(node.sourceUnit)
imported[importNode.id] = importNode
if (importNode.nodes) {
for (const child of importNode.nodes) {
imported = await this.resolveImports(child, imported)
}
}
}
console.log(imported)
return imported
}
async getBlockName(position: any, text: string = null) {
await this.getAST(text)
const allowedTypes = ['SourceUnit', 'ContractDefinition', 'FunctionDefinition']
@ -191,7 +202,7 @@ export class EditorContextListener extends Plugin {
}
return null
}
if(!this.lastAST) return
if (!this.lastAST) return
return walkAst(this.lastAST)
}
@ -243,7 +254,7 @@ export class EditorContextListener extends Plugin {
return results
}
async nodesAtEditorPosition(position: any, type: string = '') {
async nodesAtEditorPosition(position: any, type = '') {
const lastCompilationResult = this.lastCompilationResult // await this.call('compilerArtefacts', 'getLastCompilationResult')
if (!lastCompilationResult) return false
const urlFromPath = await this.call('fileManager', 'getUrlFromPath', this.currentFile)
@ -280,6 +291,14 @@ export class EditorContextListener extends Plugin {
return nodes
}
async nodesWithName(name: string) {
const nodes = []
for (const node of Object.values(this._index.FlatReferences) as any[]) {
if (node.name === name) nodes.push(node)
}
return nodes
}
async definitionAtPosition(position: any) {
const nodes = await this.nodesAtEditorPosition(position)
console.log('nodes at position', nodes)

@ -1,10 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
"compilerOptions": {
"types": ["node"],
"esModuleInterop": true
},
"include": ["**/*.ts"]
}

@ -3,10 +3,15 @@
"compilerOptions": {
"module": "commonjs",
"outDir": "../../dist/out-tsc",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"declaration": true,
"rootDir": "./src",
"types": ["node"]
},
"exclude": ["**/*.spec.ts"],
"exclude": [
"**/*.spec.ts",
"tests/"
],
"include": ["**/*.ts"]
}

@ -1,5 +1,5 @@
{
"name": "@remix-project/remix-solidity",
"name": "@remix-project/remix-solidity-ts",
"version": "0.4.13",
"description": "Tool to load and run Solidity compiler",
"main": "src/index.js",

@ -3,7 +3,7 @@ import async from 'async'
import path from 'path'
import deepequal from 'deep-equal'
import Log from './logger'
import { Compiler as RemixCompiler } from '@remix-project/remix-solidity'
import { Compiler } from '@remix-project/remix-solidity'
import { SrcIfc, CompilerConfiguration, CompilationErrors } from './types'
const logger = new Log()
const log = logger.logger
@ -114,7 +114,7 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts
} finally {
async.waterfall([
function loadCompiler (next) {
compiler = new RemixCompiler((url, cb) => {
compiler = new Compiler((url, cb) => {
try {
cb(null, fs.readFileSync(url, 'utf-8'))
} catch (e) {
@ -186,7 +186,7 @@ export function compileContractSources (sources: SrcIfc, newCompConfig: any, imp
if (!compiler || !deepequal(UTRunner.compilerConfig, newCompConfig)) {
UTRunner.compilerConfig = newCompConfig
const { currentCompilerUrl, evmVersion, optimize, runs, usingWorker } = newCompConfig
compiler = new RemixCompiler(importFileCb)
compiler = new Compiler(importFileCb)
compiler.set('evmVersion', evmVersion)
compiler.set('optimize', optimize)
compiler.set('runs', runs)

@ -4,8 +4,7 @@
"types": ["node", "jest"],
"module": "commonjs",
"esModuleInterop": true,
"allowJs": true,
"rootDir": "./",
"rootDir": "./src",
},
"include": ["**/*.ts"]
}

@ -1,6 +1,10 @@
export class RemixCompletionProvider {
import { editor, languages, Position } from "monaco-editor"
import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
props: any
export class RemixCompletionProvider implements languages.CompletionItemProvider {
props: EditorUIProps
monaco: any
constructor(props: any, monaco: any) {
this.props = props
@ -8,31 +12,10 @@ export class RemixCompletionProvider {
}
triggerCharacters = ['.', '']
async provideCompletionItems(model: any, position: any, context: any) {
async provideCompletionItems(model: editor.ITextModel, position: Position, context: monaco.languages.CompletionContext) {
console.log('AUTOCOMPLETE', context)
console.log(position)
//await this.props.plugin.call('contextualListener', 'compile')
//const block = await this.props.plugin.call('contextualListener', 'getBlockName', position)
//console.log('BLOCK', block)
//return null
return await this.run(model, position, context)
const word = model.getWordUntilPosition(position);
const wordAt = model.getWordAtPosition(position);
console.log('WORD', word)
console.log('WORDAT', wordAt)
return new Promise((resolve, reject) => {
this.props.plugin.once('contextualListener', 'astFinished', async () => {
console.log('AST FINISHED')
resolve(await this.run(model, position, context))
})
this.props.plugin.call('contextualListener', 'compile')
})
}
async run(model: any, position: any, context: any) {
const textUntilPosition = model.getValueInRange({
startLineNumber: 1,
startColumn: 1,
@ -68,7 +51,7 @@ export class RemixCompletionProvider {
const line = model.getLineContent(position.lineNumber)
let nodes
let nodes = []
@ -119,14 +102,15 @@ export class RemixCompletionProvider {
let nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
console.log('NODES AT POSITION', nodesAtPosition)
if (!nodesAtPosition.length) {
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, textWithoutEdits)
console.log('BLOCK', block)
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.range[0])
console.log('NODES AT POSITION', nodesAtPosition)
}
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, textWithoutEdits)
console.log('BLOCK', block)
//if (!nodesAtPosition.length) {
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.body ? block.body.range[0] : block.range[0])
console.log('NODES AT POSITION WITH BLOCK', nodesAtPosition)
}
//}
// explore nodes at the BLOCK
if (nodesAtPosition) {
for (const node of nodesAtPosition) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithScope', node.id)
@ -137,7 +121,7 @@ export class RemixCompletionProvider {
if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'UserDefinedTypeName') {
const declarationOf = await this.props.plugin.call('contextualListener', 'declarationOf', nodeOfScope.typeName)
console.log('HAS DECLARATION OF', declarationOf)
nodes = declarationOf.nodes || declarationOf.members
nodes = [...nodes, ...declarationOf.nodes || declarationOf.members]
const baseContracts = await getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
@ -146,7 +130,46 @@ export class RemixCompletionProvider {
}
}
}
// anything within the block statements might provide a clue to what it is
if (!nodes.length) {
for (const node of nodesAtPosition) {
if (node.statements) {
for (const statement of node.statements) {
if (statement.expression && statement.expression.memberName === last) {
const declarationOf = await this.props.plugin.call('contextualListener', 'declarationOf', statement.expression)
if (declarationOf.typeName && declarationOf.typeName.nodeType === 'UserDefinedTypeName') {
const baseDeclaration = await this.props.plugin.call('contextualListener', 'declarationOf', declarationOf.typeName)
console.log('HAS BASE DECLARATION OF', baseDeclaration)
nodes = [...nodes, ...baseDeclaration.nodes || baseDeclaration.members]
}
}
}
}
}
}
}
// brute force search in all nodes with the name
//if (!nodes.length) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithName', last)
console.log('NODES WITHE NAME ', last, nodesOfScope)
for (const nodeOfScope of nodesOfScope) {
if (nodeOfScope.name === last) {
console.log('FOUND NODE', nodeOfScope)
if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'UserDefinedTypeName') {
const declarationOf = await this.props.plugin.call('contextualListener', 'declarationOf', nodeOfScope.typeName)
console.log('HAS DECLARATION OF', declarationOf)
nodes = [...nodes,...declarationOf.nodes || declarationOf.members]
const baseContracts = await getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
}
}
}
}
//}
}
} else {
const cursorPosition = this.props.editorAPI.getCursorPosition()
@ -162,16 +185,32 @@ export class RemixCompletionProvider {
}
}
// get all children of all nodes at position
for (const node of nodesAtPosition) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithScope', node.id)
for (const nodeOfScope of nodesOfScope) {
const imports = await this.props.plugin.call('contextualListener', 'resolveImports', nodeOfScope)
if (imports) {
for (const key in imports) {
if (imports[key].nodes)
nodes = [...nodes, ...imports[key].nodes]
}
}
}
nodes = [...nodes, ...nodesOfScope]
}
// get the linearized base contracts
for (const node of nodesAtPosition) {
const baseContracts = await getlinearizedBaseContracts(node)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
}
}
//nodes = await this.props.plugin.call('contextualListener', 'getNodes')
}

@ -1,27 +1,18 @@
import { editor, languages, Position } from 'monaco-editor'
import monaco from '../../types/monaco'
import { EditorUIProps } from '../remix-ui-editor'
export class RemixHoverProvider implements languages.HoverProvider {
export class RemixHoverProvider {
props: any
props: EditorUIProps
monaco: any
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
}
provideHover = async function (model: any, position: any) {
provideHover = async function (model: editor.ITextModel, position: Position) {
console.log('HOVERING')
return await this.run(model, position)
return new Promise((resolve, reject) => {
this.props.plugin.once('contextualListener', 'astFinished', async () => {
console.log('AST FINISHED')
resolve(await this.run(model, position))
})
this.props.plugin.call('contextualListener', 'compile')
})
}
async run(model: any, position: any) {
const cursorPosition = this.props.editorAPI.getHoverPosition(position)
const nodeAtPosition = await this.props.plugin.call('contextualListener', 'definitionAtPosition', cursorPosition)

@ -8,8 +8,8 @@ import { cairoLang, cairoConf } from './cairoSyntax'
import './remix-ui-editor.css'
import { loadTypes } from './web-types'
import monaco from '../types/monaco'
import { IPosition, languages } from 'monaco-editor'
import { sourceMappingDecoder } from '@remix-project/remix-debug'
import { IPosition } from 'monaco-editor'
import { RemixHoverProvider } from './providers/hoverProvider'
import { RemixReferenceProvider } from './providers/referenceProvider'
import { RemixCompletionProvider } from './providers/completionProvider'
@ -103,7 +103,7 @@ export const EditorUI = (props: EditorUIProps) => {
\t\t\t\t\t\t\t\tTwitter: https://twitter.com/ethereumremix\n
`
const editorRef = useRef(null)
const monacoRef = useRef(null)
const monacoRef = useRef<Monaco>(null)
const currentFileRef = useRef('')
// const currentDecorations = useRef({ sourceAnnotationsPerFile: {}, markerPerFile: {} }) // decorations that are currently in use by the editor
// const registeredDecorations = useRef({}) // registered decorations
@ -428,31 +428,34 @@ export const EditorUI = (props: EditorUIProps) => {
(window as any).addRemixBreakpoint(e.target.position)
}
})
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | monacoRef.current.KeyCode.US_EQUAL, () => {
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | (monacoRef.current.KeyCode as any).US_EQUAL, () => {
editor.updateOptions({ fontSize: editor.getOption(43).fontSize + 1 })
})
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | monacoRef.current.KeyCode.US_MINUS, () => {
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | (monacoRef.current.KeyCode as any).US_MINUS, () => {
editor.updateOptions({ fontSize: editor.getOption(43).fontSize - 1 })
})
}
function handleEditorWillMount(monaco) {
function handleEditorWillMount(monaco: Monaco) {
console.log('editor will mount', monaco, typeof monaco)
monacoRef.current = monaco
// Register a new language
monacoRef.current.languages.register({ id: 'remix-solidity' })
monacoRef.current.languages.register({ id: 'remix-cairo' })
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', language)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', conf)
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', language as any)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', conf as any)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang as any)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf as any)
// register Definition Provider
monacoRef.current.languages.registerDefinitionProvider('remix-solidity', {
provideDefinition(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken) {
provideDefinition(model:any, position: any, token: any) {
const cursorPosition = props.editorAPI.getCursorPosition()
props.plugin.call('contextualListener', 'jumpToDefinition', cursorPosition)
return null
}
})

@ -323,7 +323,7 @@
"ts-jest": "^27.0.5",
"ts-node": "^7.0.1",
"tslint": "~6.0.0",
"typescript": "^4.4.3",
"typescript": "^4.7.2",
"uglify-js": "^2.8.16",
"vm-browserify": "0.0.4",
"watchify": "^3.9.0",

@ -22536,10 +22536,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^4.4.3:
version "4.4.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
typescript@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
uglify-js@^2.8.16:
version "2.8.29"

Loading…
Cancel
Save