mv functions

pull/5370/head
filip mertens 2 years ago
parent 9a0261c0b9
commit 481ed9b795
  1. 4
      apps/remix-ide/src/app/files/fileSystem.ts
  2. 7
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  3. 3
      libs/remix-core-plugin/src/lib/offset-line-to-column-converter.ts
  4. 375
      libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts
  5. 0
      libs/remix-ui/editor/src/lib/providers/completion/dotCompletions.ts
  6. 178
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  7. 2
      libs/remix-ui/editor/src/lib/providers/hoverProvider.ts
  8. 0
      libs/remix-ui/editor/src/types/monaco.ts
  9. 2
      libs/remix-ui/editor/tsconfig.lib.json

@ -19,9 +19,10 @@ export class fileSystem {
checkWorkspaces = async () => {
try {
await this.fs.stat('.workspaces')
console.log('Workspaces found in', this.name)
this.hasWorkSpaces = true
} catch (e) {
console.log('No workspaces found in', this.name)
}
}
@ -49,6 +50,7 @@ export class fileSystems {
return true
} catch (e) {
console.log(fs.name + ' not available...')
console.log(e)
return false
}
}

@ -75,17 +75,10 @@ export class EditorContextListener extends Plugin {
this.on('solidity', 'loadingCompiler', async (url) => {
console.log('loading compiler', url)
this.compiler.loadVersion(true, url)
this.compiler.event.register('compilerLoaded', async () => {
console.log('compiler loaded')
//await this.compile()
//await this.getAST()
const a = 'function (){a=4; c.getBook().run.}'
const ast = (SolidityParser as any).parse(a, { loc: true, range: true, tolerant: true })
console.log('BAD AST', ast)
})
})
this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url, undefined, false).then((result) => cb(null, result)).catch((error) => cb(error.message)))

@ -30,12 +30,10 @@ export class OffsetToLineColumnConverter extends Plugin {
* @param {Object.<string, {ast, id}>} asts - Map of content sources
*/
offsetToLineColumn (rawLocation, file, sources, asts) {
console.log('offsetToLineColumn', rawLocation, file, sources, asts)
//if (!this.lineBreakPositionsByContent[file]) {
const sourcesArray = Object.keys(sources)
if (!asts || (file === 0 && sourcesArray.length === 1)) {
// if we don't have ast, we process the only one available content (applicable also for compiler older than 0.4.12)
console.log('convert ', sources[sourcesArray[0]].content)
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[sourcesArray[0]].content)
} else {
@ -48,7 +46,6 @@ export class OffsetToLineColumnConverter extends Plugin {
}
}
//}
console.log(this.lineBreakPositionsByContent[file])
return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file])
}

@ -1,12 +1,12 @@
import { IRange } from "monaco-editor";
import monaco from "../../../types/monaco";
export function getBlockCompletionItems(range: IRange): monaco.languages.CompletionItem[] {
export function getBlockCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: '(address): Current block miner’s address',
kind: monaco.languages.CompletionItemKind.Property,
insertText: 'miner',
insertText: 'coinbase',
label: 'coinbase',
range,
},
@ -14,6 +14,7 @@ export function getBlockCompletionItems(range: IRange): monaco.languages.Complet
detail: '(bytes32): DEPRICATED In 0.4.22 use blockhash(uint) instead. Hash of the given block - only works for 256 most recent blocks excluding current',
insertText: 'blockhash(${1:blockNumber});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'blockhash',
range
},
@ -48,7 +49,89 @@ export function getBlockCompletionItems(range: IRange): monaco.languages.Complet
];
}
export function getTxCompletionItems(range: IRange): monaco.languages.CompletionItem[] {
export function getCompletionSnippets(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
label: 'contract',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'contract ${1:Name} {\n\t$0\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'library',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'library ${1:Name} {\n\t$0\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'interface',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'interface ${1:Name} {\n\t$0\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'enum',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'enum ${1:Name} {${2:item1}, ${3:item2} }',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'function',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'function ${1:name}(${2:params}) {\n\t${3:code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'constructor',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'constructor(${1:params}) {\n\t${2:code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'ifstatement',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'if (${1:condition}) {\n\t${2:code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'ifstatementelse',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'if (${1:condition}) {\n\t${2:code}\n} else {\n\t${3:code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'pragma',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: '// SPDX-License-Identifier: MIT\npragma solidity ${1:version};',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'import',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'import "${1:library}";',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
},
{
label: 'SPDX-License-Identifier',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: '// SPDX-License-Identifier: MIT',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range
}
]
}
export function getTxCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: '(uint): gas price of the transaction',
@ -67,7 +150,7 @@ export function getTxCompletionItems(range: IRange): monaco.languages.Completion
];
}
export function getMsgCompletionItems(range: IRange): monaco.languages.CompletionItem[] {
export function getMsgCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: '(bytes): complete calldata',
@ -107,12 +190,13 @@ export function getMsgCompletionItems(range: IRange): monaco.languages.Completio
];
}
export function getAbiCompletionItems(range: IRange): monaco.languages.CompletionItem[] {
export function getAbiCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: 'encode(..) returs (bytes): ABI-encodes the given arguments',
insertText: 'encode(${1:arg});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'encode',
range
},
@ -120,6 +204,7 @@ export function getAbiCompletionItems(range: IRange): monaco.languages.Completio
detail: 'encodePacked(..) returns (bytes): Performes packed encoding of the given arguments',
insertText: 'encodePacked(${1:arg});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'encodePacked',
range
},
@ -127,6 +212,7 @@ export function getAbiCompletionItems(range: IRange): monaco.languages.Completio
detail: 'encodeWithSelector(bytes4,...) returns (bytes): ABI-encodes the given arguments starting from the second and prepends the given four-byte selector',
insertText: 'encodeWithSelector(${1:bytes4}, ${2:arg});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'encodeWithSelector',
range
},
@ -134,8 +220,285 @@ export function getAbiCompletionItems(range: IRange): monaco.languages.Completio
detail: 'encodeWithSignature(string,...) returns (bytes): Equivalent to abi.encodeWithSelector(bytes4(keccak256(signature), ...)`',
insertText: 'encodeWithSignature(${1:signatureString}, ${2:arg});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'encodeWithSignature',
range
range
},
];
}
export function GetCompletionTypes(range: IRange, monaco): monaco.languages.CompletionItem[] {
const completionItems = [];
const types = ['address', 'string', 'bytes', 'byte', 'int', 'uint', 'bool', 'hash'];
for (let index = 8; index <= 256; index += 8) {
types.push('int' + index);
types.push('uint' + index);
types.push('bytes' + index / 8);
}
types.forEach(type => {
const completionItem = CreateCompletionItem(type, monaco.languages.CompletionItemKind.Keyword, type + ' type', range);
completionItems.push(completionItem);
});
// add mapping
return completionItems;
}
function CreateCompletionItem(label: string, kind: monaco.languages.CompletionItemKind, detail: string, range: IRange) {
const completionItem: monaco.languages.CompletionItem = {
label,
kind,
detail,
insertText: label,
range
}
completionItem.kind = kind;
completionItem.detail = detail;
return completionItem;
}
export function GetCompletionKeywords(range: IRange, monaco): monaco.languages.CompletionItem[] {
const completionItems = [];
const keywords = ['modifier', 'mapping', 'break', 'continue', 'delete', 'else', 'for',
'if', 'new', 'return', 'returns', 'while', 'using',
'private', 'public', 'external', 'internal', 'payable', 'nonpayable', 'view', 'pure', 'case', 'do', 'else', 'finally',
'in', 'instanceof', 'return', 'throw', 'try', 'catch', 'typeof', 'yield', 'void', 'virtual', 'override'];
keywords.forEach(unit => {
const completionItem: monaco.languages.CompletionItem = {
label: unit,
kind: monaco.languages.CompletionItemKind.Keyword,
detail: unit + ' keyword',
insertText: `${unit} `,
range
}
completionItems.push(completionItem);
});
completionItems.push(CreateCompletionItem('contract', monaco.languages.CompletionItemKind.Class, null, range));
completionItems.push(CreateCompletionItem('library', monaco.languages.CompletionItemKind.Class, null, range));
completionItems.push(CreateCompletionItem('storage', monaco.languages.CompletionItemKind.Field, null, range));
completionItems.push(CreateCompletionItem('memory', monaco.languages.CompletionItemKind.Field, null, range));
completionItems.push(CreateCompletionItem('var', monaco.languages.CompletionItemKind.Field, null, range));
completionItems.push(CreateCompletionItem('constant', monaco.languages.CompletionItemKind.Constant, null, range));
completionItems.push(CreateCompletionItem('immutable', monaco.languages.CompletionItemKind.Keyword, null, range));
completionItems.push(CreateCompletionItem('constructor', monaco.languages.CompletionItemKind.Constructor, null, range));
completionItems.push(CreateCompletionItem('event', monaco.languages.CompletionItemKind.Event, null, range));
completionItems.push(CreateCompletionItem('import', monaco.languages.CompletionItemKind.Module, null, range));
completionItems.push(CreateCompletionItem('enum', monaco.languages.CompletionItemKind.Enum, null, range));
completionItems.push(CreateCompletionItem('struct', monaco.languages.CompletionItemKind.Struct, null, range));
completionItems.push(CreateCompletionItem('function', monaco.languages.CompletionItemKind.Function, null, range));
return completionItems;
}
export function GeCompletionUnits(range: IRange, monaco): monaco.languages.CompletionItem[] {
const completionItems = [];
const etherUnits = ['wei', 'gwei', 'finney', 'szabo', 'ether'];
etherUnits.forEach(unit => {
const completionItem = CreateCompletionItem(unit, monaco.languages.CompletionItemKind.Unit, unit + ': ether unit', range);
completionItems.push(completionItem);
});
const timeUnits = ['seconds', 'minutes', 'hours', 'days', 'weeks', 'years'];
timeUnits.forEach(unit => {
const completionItem = CreateCompletionItem(unit, monaco.languages.CompletionItemKind.Unit, unit + ': time unit', range);
completionItem.kind = monaco.languages.CompletionItemKind.Unit;
if (unit !== 'years') {
completionItem.detail = unit + ': time unit';
} else {
completionItem.detail = 'DEPRECATED: ' + unit + ': time unit';
}
completionItems.push(completionItem);
});
return completionItems;
}
export function GetGlobalVariable(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: 'Current block',
kind: monaco.languages.CompletionItemKind.Variable,
insertText: 'block',
label: 'block',
range
},
{
detail: 'Current Message',
kind: monaco.languages.CompletionItemKind.Variable,
insertText: 'msg',
label: 'msg',
range
},
{
detail: '(uint): current block timestamp (alias for block.timestamp)',
kind: monaco.languages.CompletionItemKind.Variable,
insertText: 'now',
label: 'now',
range
},
{
detail: 'Current transaction',
kind: monaco.languages.CompletionItemKind.Variable,
label: 'tx',
insertText: 'tx',
range
},
{
detail: 'ABI encoding / decoding',
kind: monaco.languages.CompletionItemKind.Variable,
label: 'abi',
insertText: 'abi',
range
},
{
detail: '',
kind: monaco.languages.CompletionItemKind.Variable,
label: 'this',
insertText: 'this',
range
},
];
}
export function GetGlobalFunctions(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{
detail: 'assert(bool condition): throws if the condition is not met - to be used for internal errors.',
insertText: 'assert(${1:condition});',
kind: monaco.languages.CompletionItemKind.Function,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'assert',
range
},
{
detail: 'gasleft(): returns the remaining gas',
insertText: 'gasleft();',
kind: monaco.languages.CompletionItemKind.Function,
label: 'gasleft',
range
},
{
detail: 'unicode: converts string into unicode',
insertText: 'unicode"${1:text}"',
kind: monaco.languages.CompletionItemKind.Function,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'unicode',
range
},
{
detail: 'blockhash(uint blockNumber): hash of the given block - only works for 256 most recent, excluding current, blocks',
insertText: 'blockhash(${1:blockNumber});',
kind: monaco.languages.CompletionItemKind.Function,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'blockhash',
range
},
{
detail: 'require(bool condition): reverts if the condition is not met - to be used for errors in inputs or external components.',
insertText: 'require(${1:condition});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'require',
range
},
{
// tslint:disable-next-line:max-line-length
detail: 'require(bool condition, string message): reverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message.',
insertText: 'require(${1:condition}, ${2:message});',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'require',
range
},
{
detail: 'revert(): abort execution and revert state changes',
insertText: 'revert();',
kind: monaco.languages.CompletionItemKind.Method,
label: 'revert',
range
},
{
detail: 'addmod(uint x, uint y, uint k) returns (uint):' +
'compute (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2**256',
insertText: 'addmod(${1:x}, ${2:y}, ${3:k})',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'addmod',
range
},
{
detail: 'mulmod(uint x, uint y, uint k) returns (uint):' +
'compute (x * y) % k where the multiplication is performed with arbitrary precision and does not wrap around at 2**256',
insertText: 'mulmod(${1:x}, ${2:y}, ${3:k})',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'mulmod',
range
},
{
detail: 'keccak256(...) returns (bytes32):' +
'compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments',
insertText: 'keccak256(${1:x})',
kind: monaco.languages.CompletionItemKind.Method,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
label: 'keccak256',
range
},
{
detail: 'sha256(...) returns (bytes32):' +
'compute the SHA-256 hash of the (tightly packed) arguments',
insertText: 'sha256(${1:x})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
kind: monaco.languages.CompletionItemKind.Method,
label: 'sha256',
range
},
{
detail: 'sha3(...) returns (bytes32):' +
'alias to keccak256',
insertText: 'sha3(${1:x})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
kind: monaco.languages.CompletionItemKind.Method,
label: 'sha3',
range
},
{
detail: 'ripemd160(...) returns (bytes20):' +
'compute RIPEMD-160 hash of the (tightly packed) arguments',
insertText: 'ripemd160(${1:x})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
kind: monaco.languages.CompletionItemKind.Method,
label: 'ripemd160',
range
},
{
detail: 'ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):' +
'recover the address associated with the public key from elliptic curve signature or return zero on error',
insertText: 'ecrecover(${1:hash}, ${2:v}, ${3:r}, ${4:s})',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
kind: monaco.languages.CompletionItemKind.Method,
label: 'ecrecover',
range
},
];
}
export function getContextualAutoCompleteByGlobalVariable(word: string, range: IRange, monaco): monaco.languages.CompletionItem[] {
if (word === 'block') {
return getBlockCompletionItems(range, monaco);
}
if (word === 'msg') {
return getMsgCompletionItems(range, monaco);
}
if (word === 'tx') {
return getTxCompletionItems(range, monaco);
}
if (word === 'address') {
return getAbiCompletionItems(range, monaco);
}
return null;
}

@ -1,12 +1,13 @@
import { editor, languages, Position } from "monaco-editor"
import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
import { getBlockCompletionItems } from "./completion/completionGlobals"
import { GeCompletionUnits, getBlockCompletionItems, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, getMsgCompletionItems, getTxCompletionItems } from "./completion/completionGlobals"
export class RemixCompletionProvider implements languages.CompletionItemProvider {
props: EditorUIProps
monaco: any
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
@ -17,16 +18,6 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
console.log('AUTOCOMPLETE', context)
console.log(position)
const textUntilPosition = model.getValueInRange({
startLineNumber: 1,
startColumn: 1,
endLineNumber: position.lineNumber,
endColumn: position.column
});
const word = model.getWordUntilPosition(position);
const wordAt = model.getWordAtPosition(position);
const range = {
@ -37,25 +28,10 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
};
console.log('WORD', word)
const getlinearizedBaseContracts = async (node: any) => {
let params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
if (id !== node.id) {
const baseContract = await this.props.plugin.call('contextualListener', 'getNodeById', id)
params = [...params, ...[baseContract]]
}
}
}
return params
}
const line = model.getLineContent(position.lineNumber)
let nodes = []
let suggestions = []
const cursorPosition = this.props.editorAPI.getCursorPosition()
console.log('cursor', cursorPosition)
@ -85,7 +61,6 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
}
const linesToCheck =
[
textBeforeCursor.substring(0, textBeforeCursor.lastIndexOf('.')) + ".lastnode;",
@ -105,23 +80,30 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
}
console.log('lastNode found', lastNode)
console.log(textBeforeCursor, textAfterCursor)
const splits = textBeforeCursor.split('.')
console.log('splits', splits)
if (splits.length > 1) {
let dotCompleted = false
if (splits.length === 2) {
let globalCompletion = getContextualAutoCompleteByGlobalVariable(lastNode.name, range, this.monaco)
if (globalCompletion) {
dotCompleted = true
suggestions = [...suggestions, ...globalCompletion]
}
if (lastNode.name === 'this') {
dotCompleted = true
nodes = [...nodes, ...await this.getContractCompletions(nodes, position)]
}
}
if (splits.length > 1 && !dotCompleted) {
let last = splits[splits.length - 2].trim()
const lastParentheses = last.lastIndexOf('(')
const lastClosingParentheses = last.lastIndexOf(')')
const lastBracket = last.lastIndexOf('{')
const lastSemiColon = last.lastIndexOf(';')
let textBefore = null
let lastWord = null
let lineWithoutEdits = null
// get word before last closing parentheses
if (lastParentheses > -1 && lastClosingParentheses > -1) {
@ -130,7 +112,6 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
// find largest
const lastIndex = Math.max(lastParentheses, lastBracket, lastSemiColon)
if (lastIndex > -1) {
lastWord = last.substring(lastIndex + 1)
textBefore = last.substring(0, lastIndex + 1)
console.log('textBefore', textBefore)
console.log('text without edits', textBefore, textAfterCursor)
@ -168,7 +149,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
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)
const baseContracts = await this.getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
}
@ -195,7 +176,6 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
}
// brute force search in all nodes with the name
if (!nodes.length) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithName', last)
@ -207,7 +187,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
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)
const baseContracts = await this.getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
//nodes = [...nodes, ...baseContract.nodes]
}
@ -217,54 +197,21 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
}
} else {
const cursorPosition = this.props.editorAPI.getCursorPosition()
let nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
nodes = []
console.log('NODES AT POSITION', nodesAtPosition)
if (!nodesAtPosition.length) {
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, null)
console.log('BLOCK', block)
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.range[0])
console.log('NODES AT POSITION', nodesAtPosition)
}
}
// 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]
}
}
}
suggestions = [...suggestions,
...GetGlobalVariable(range, this.monaco),
...getCompletionSnippets(range, this.monaco),
...GetCompletionTypes(range, this.monaco),
...GetCompletionKeywords(range, this.monaco),
...GetGlobalFunctions(range, this.monaco),
...GeCompletionUnits(range, this.monaco),
]
nodes = [...nodes, ...await this.getContractCompletions(nodes, position)]
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')
}
console.log('WORD', word, wordAt)
console.log('NODES', nodes)
console.log('NODES', Object.values(nodes))
const getLinks = async (node: any) => {
const position = await this.props.plugin.call('contextualListener', 'positionOfDefinition', node)
@ -301,8 +248,8 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
const completeParameters = async (parameters: any) => {
if (parameters && parameters.parameters) {
const params = []
for (const param of parameters.parameters) {
params.push(param.name)
for (const key in parameters.parameters) {
params.push('${' + (key + 1) + ':' + parameters.parameters[key].name + '}')
}
return `(${params.join(', ')})`
}
@ -320,7 +267,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
}
const suggestions = []
for (const node of Object.values(nodes) as any[]) {
if (!node.name) continue
if (node.nodeType === 'VariableDeclaration') {
@ -333,10 +280,12 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
}
suggestions.push(completion)
} else if (node.nodeType === 'FunctionDefinition') {
const completion = {
label: { label: `"${node.name}"`, description: await getLinks(node), detail: ` -> ${node.name} ${await getParamaters(node.parameters)}` },
kind: this.monaco.languages.CompletionItemKind.Function,
insertText: `${node.name}${await completeParameters(node.parameters)};`,
insertTextRules: this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range: range,
documentation: await getDocs(node)
}
@ -391,14 +340,75 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
documentation: await getDocs(node)
}
suggestions.push(completion)
} else {
console.log('UNKNOWN NODE', node)
}
}
suggestions.push(getBlockCompletionItems(range))
suggestions = [...suggestions,
/* ...GetGlobalVariable(range, this.monaco),
...getCompletionSnippets(range, this.monaco),
...getBlockCompletionItems(range, this.monaco),
...GetCompletionTypes(range,this.monaco),
...GetCompletionKeywords(range,this.monaco),
...GetGlobalFunctions(range,this.monaco),
...GeCompletionUnits(range,this.monaco),
...getMsgCompletionItems(range,this.monaco),
...getTxCompletionItems(range,this.monaco), */
]
console.log(suggestions)
return {
suggestions
}
}
private getlinearizedBaseContracts = async (node: any) => {
let params = []
if (node.linearizedBaseContracts) {
for (const id of node.linearizedBaseContracts) {
if (id !== node.id) {
const baseContract = await this.props.plugin.call('contextualListener', 'getNodeById', id)
params = [...params, ...[baseContract]]
}
}
}
return params
}
private getContractCompletions = async (nodes: any[], position: Position) => {
const cursorPosition = this.props.editorAPI.getCursorPosition()
let nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
// if no nodes exits at position, try to get the block of which the position is in
if (!nodesAtPosition.length) {
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, null)
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.range[0])
}
}
// 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 this.getlinearizedBaseContracts(node)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
}
}
return nodes
}
}

@ -13,7 +13,7 @@ export class RemixHoverProvider implements languages.HoverProvider {
provideHover = async function (model: editor.ITextModel, position: Position) {
console.log('HOVERING')
return null
const cursorPosition = this.props.editorAPI.getHoverPosition(position)
const nodeAtPosition = await this.props.plugin.call('contextualListener', 'definitionAtPosition', cursorPosition)

@ -9,5 +9,5 @@
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "**/*.d.ts"]
}

Loading…
Cancel
Save