From e9d44346f761e979717ed6f392fd6891152500f8 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Thu, 15 Sep 2022 00:48:46 +0200 Subject: [PATCH] refactor --- .../src/app/plugins/parser/code-parser.tsx | 18 +- .../parser/services/code-parser-compiler.ts | 4 +- .../parser/services/code-parser-imports.ts | 86 ++++++++ .../providers/completion/completionGlobals.ts | 107 ++++++++-- .../completion/contracts/contracts.txt | 198 ++++++++++++++++++ .../src/lib/providers/completionProvider.ts | 40 ++-- package.json | 6 +- yarn.lock | 15 ++ 8 files changed, 426 insertions(+), 48 deletions(-) create mode 100644 apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts create mode 100644 libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt diff --git a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx index b763f81a3c..9b51e42a4e 100644 --- a/apps/remix-ide/src/app/plugins/parser/code-parser.tsx +++ b/apps/remix-ide/src/app/plugins/parser/code-parser.tsx @@ -6,6 +6,7 @@ import { CompilationResult } from '@remix-project/remix-solidity' import CodeParserGasService from './services/code-parser-gas-service' import CodeParserCompiler from './services/code-parser-compiler' import CodeParserAntlrService from './services/code-parser-antlr-service' +import CodeParserImports, { CodeParserImportsData } from './services/code-parser-imports' import React from 'react' import { Profile } from '@remixproject/plugin-utils' import { ContractDefinitionAstNode, EventDefinitionAstNode, FunctionCallAstNode, FunctionDefinitionAstNode, IdentifierAstNode, ImportDirectiveAstNode, ModifierDefinitionAstNode, SourceUnitAstNode, StructDefinitionAstNode, VariableDeclarationAstNode } from 'dist/libs/remix-analyzer/src/types' @@ -15,7 +16,7 @@ import { ParseResult } from './types/antlr-types' const profile: Profile = { name: 'codeParser', - methods: ['nodesAtPosition', 'getContractNodes', 'getCurrentFileNodes', 'getLineColumnOfNode', 'getLineColumnOfPosition', 'getFunctionParamaters', 'getDeclaration', 'getFunctionReturnParameters', 'getVariableDeclaration', 'getNodeDocumentation', 'getNodeLink', 'listAstNodes', 'getANTLRBlockAtPosition', 'getLastNodeInLine', 'resolveImports', 'parseSolidity', 'getNodesWithScope', 'getNodesWithName', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'getGasEstimates'], + methods: ['nodesAtPosition', 'getContractNodes', 'getCurrentFileNodes', 'getLineColumnOfNode', 'getLineColumnOfPosition', 'getFunctionParamaters', 'getDeclaration', 'getFunctionReturnParameters', 'getVariableDeclaration', 'getNodeDocumentation', 'getNodeLink', 'listAstNodes', 'getANTLRBlockAtPosition', 'getLastNodeInLine', 'resolveImports', 'parseSolidity', 'getNodesWithScope', 'getNodesWithName', 'getNodes', 'compile', 'getNodeById', 'getLastCompilationResult', 'positionOfDefinition', 'definitionAtPosition', 'jumpToDefinition', 'referrencesAtPosition', 'referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf', 'getGasEstimates', 'getImports'], events: [], version: '0.0.1' } @@ -70,12 +71,15 @@ export class CodeParser extends Plugin { gasService: CodeParserGasService compilerService: CodeParserCompiler antlrService: CodeParserAntlrService + importService: CodeParserImports parseSolidity: (text: string) => Promise getLastNodeInLine: (ast: string) => Promise listAstNodes: () => Promise getANTLRBlockAtPosition: (position: any, text?: string) => Promise getCurrentFileAST: (text?: string) => Promise + getImports: () => Promise + constructor(astWalker: any) { super(profile) @@ -94,7 +98,7 @@ export class CodeParser extends Plugin { } const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas') const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors') - if(showGasSettings || showErrorSettings || completionSettings) { + if (showGasSettings || showErrorSettings || completionSettings) { await this.compilerService.compile() } } @@ -104,13 +108,14 @@ export class CodeParser extends Plugin { this.gasService = new CodeParserGasService(this) this.compilerService = new CodeParserCompiler(this) this.antlrService = new CodeParserAntlrService(this) + this.importService = new CodeParserImports(this) this.parseSolidity = this.antlrService.parseSolidity.bind(this.antlrService) this.getLastNodeInLine = this.antlrService.getLastNodeInLine.bind(this.antlrService) this.listAstNodes = this.antlrService.listAstNodes.bind(this.antlrService) this.getANTLRBlockAtPosition = this.antlrService.getANTLRBlockAtPosition.bind(this.antlrService) this.getCurrentFileAST = this.antlrService.getCurrentFileAST.bind(this.antlrService) - + this.getImports = this.importService.getImports.bind(this.importService) this.on('editor', 'didChangeFile', async (file) => { await this.call('editor', 'discardLineTexts') @@ -119,6 +124,7 @@ export class CodeParser extends Plugin { this.on('filePanel', 'setWorkspace', async () => { await this.call('fileDecorator', 'clearFileDecorators') + await this.importService.setFileTree() }) @@ -135,8 +141,6 @@ export class CodeParser extends Plugin { } - - /** * * @returns @@ -145,10 +149,6 @@ export class CodeParser extends Plugin { return this.compilerAbstract } - - - - getSubNodes(node: T): number[] { return node.nodeType == "ContractDefinition" && node.contractDependencies; } diff --git a/apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts b/apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts index 3f669a8814..9acd434728 100644 --- a/apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts +++ b/apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts @@ -39,6 +39,7 @@ export default class CodeParserCompiler { init() { this.onAstFinished = async (success, data: CompilationResult, source: CompilationSource, input: any, version) => { + //console.log('onAstFinished', success, data, source, input, version) this.plugin.call('editor', 'clearAnnotations') this.errorState = true const result = new CompilerAbstract('soljson', data, source, input) @@ -46,7 +47,7 @@ export default class CodeParserCompiler { if (data.errors) { const sources = result.getSourceCode().sources for (const error of data.errors) { - + //console.log(error) const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content) const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({ start: error.sourceLocation.start, @@ -213,6 +214,7 @@ export default class CodeParserCompiler { async clearDecorators(sources: any) { const decorators: fileDecoration[] = [] + if(!sources) return for (const fileName of Object.keys(sources)) { const decorator: fileDecoration = { path: fileName, diff --git a/apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts b/apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts new file mode 100644 index 0000000000..d2261c3154 --- /dev/null +++ b/apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts @@ -0,0 +1,86 @@ +'use strict' +import { CodeParser } from "../code-parser"; + +export type CodeParserImportsData= { + files?: string[], + modules?: string[], + packages?: string[], +} + +export default class CodeParserImports { + plugin: CodeParser + + data: CodeParserImportsData = {} + constructor(plugin: CodeParser) { + this.plugin = plugin + this.init() + } + + async getImports(){ + return this.data + } + + async init() { + // @ts-ignore + const txt = await import('raw-loader!libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt') + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + this.data.modules = txt.default.split('\n') + .filter(x => x !== '') + .map(x => x.replace('./node_modules/', '')) + .filter(x => { + if(x.includes('@openzeppelin')) { + return !x.includes('mock') + }else{ + return true + } + }) + + // get unique first words of the values in the array + this.data.packages = [...new Set(this.data.modules.map(x => x.split('/')[0]))] + console.log(this.data) + } + + setFileTree = async () => { + this.data.files = await this.getDirectory('/') + this.data.files = this.data.files.filter(x => x.endsWith('.sol') && !x.startsWith('.deps')) + console.log(this.data) + } + + getDirectory = async (dir: string) => { + let result = [] + const files = await this.plugin.call('fileManager', 'readdir', dir) + const fileArray = this.normalize(files) + for (const fi of fileArray) { + if (fi) { + const type = fi.data.isDirectory + if (type === true) { + result = [...result, ...(await this.getDirectory(`${fi.filename}`))] + } else { + result = [...result, fi.filename] + } + } + } + return result + } + + normalize = filesList => { + const folders = [] + const files = [] + Object.keys(filesList || {}).forEach(key => { + if (filesList[key].isDirectory) { + folders.push({ + filename: key, + data: filesList[key] + }) + } else { + files.push({ + filename: key, + data: filesList[key] + }) + } + }) + return [...folders, ...files] + } + +} \ No newline at end of file diff --git a/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts b/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts index 88c2369f5a..2209aa8c61 100644 --- a/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts +++ b/libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts @@ -1,16 +1,12 @@ import { IRange } from "monaco-editor"; import monaco from "../../../types/monaco"; import path from "path"; -let OZContracts; - -// @ts-ignore -import('raw-loader!libs/remix-ui/editor/src/lib/providers/completion/contracts/OpenZeppelinContracts.txt').then( - (txt) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - OZContracts = txt.default.split('\n').filter(x => !x.includes('mock')) - } -) +type CodeParserImportsData = { + files?: string[], + modules?: string[], + packages?: string[], +} export function getStringCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { return [ @@ -400,20 +396,87 @@ export function GeCompletionUnits(range: IRange, monaco): monaco.languages.Compl return completionItems; } -export function GetImports(range: IRange, monaco): monaco.languages.CompletionItem[] { + +export function GetImports(range: IRange + , monaco, data: CodeParserImportsData + , word: string +): monaco.languages.CompletionItem[] { let list = [] - list.filter - list = OZContracts - .map((item) => { - const filename = path.basename(item) - return { - kind: monaco.languages.CompletionItemKind.Module, - range: range, - label: `OZ ${filename}: ${item}`, - insertText: `@openzeppelin${item}`, - } - }) - console.log(list) + if (!word.startsWith('@')) { + word = word.replace('"', ''); + const nextPaths = [...new Set(data.files + .filter((item) => item.startsWith(word)) + .map((item) => item.replace(word, '').split('/')[0]))] + + list = [...list, ...nextPaths + .filter((item) => !item.endsWith('.sol')) + .map((item) => { + return { + kind: monaco.languages.CompletionItemKind.Folder, + range: range, + label: `${item}`, + insertText: `${item}`, + } + })] + + + list = [...list, + ...data.files + .filter((item) => item.startsWith(word)) + .map((item) => { + return { + kind: monaco.languages.CompletionItemKind.File, + range: range, + label: `${item}`, + insertText: `${item.replace(word, '')}`, + } + })] + } + if (word === '@' || word === '') { + list = [...list, ...data.packages.map((item) => { + return { + kind: monaco.languages.CompletionItemKind.Module, + range: range, + label: `${item}`, + insertText: word === '@' ? `${item.replace('@', '')}` : `${item}`, + } + })] + } + if (word.startsWith('@') && word.length > 1) { + const nextPaths = [...new Set(data.modules + .filter((item) => item.startsWith(word)) + .map((item) => item.replace(word, '').split('/')[0]))] + + list = [...list, ...nextPaths + .filter((item) => !item.endsWith('.sol')) + .map((item) => { + return { + kind: monaco.languages.CompletionItemKind.Folder, + range: range, + label: `${item}`, + insertText: `${item}`, + } + })] + + list = [...list + , ...data.modules + .filter((item) => item.startsWith(word)) + .map((item) => { + // remove the first part if it starts with @ + let label = item; + if (label.startsWith('@')) { + label = label.substring(label.indexOf('/') + 1); + } + const filename = path.basename(label) + return { + kind: monaco.languages.CompletionItemKind.Reference, + range: range, + label: `${filename}: ${label}`, + insertText: `${item.replace(word, '')}`, + } + }) + ] + } return list; }; diff --git a/libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt b/libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt new file mode 100644 index 0000000000..94615103e0 --- /dev/null +++ b/libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt @@ -0,0 +1,198 @@ +./node_modules/@openzeppelin/contracts/access/AccessControl.sol +./node_modules/@openzeppelin/contracts/access/AccessControlCrossChain.sol +./node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol +./node_modules/@openzeppelin/contracts/access/IAccessControl.sol +./node_modules/@openzeppelin/contracts/access/IAccessControlEnumerable.sol +./node_modules/@openzeppelin/contracts/access/Ownable.sol +./node_modules/@openzeppelin/contracts/crosschain/amb/CrossChainEnabledAMB.sol +./node_modules/@openzeppelin/contracts/crosschain/amb/LibAMB.sol +./node_modules/@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol +./node_modules/@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol +./node_modules/@openzeppelin/contracts/crosschain/arbitrum/LibArbitrumL1.sol +./node_modules/@openzeppelin/contracts/crosschain/arbitrum/LibArbitrumL2.sol +./node_modules/@openzeppelin/contracts/crosschain/CrossChainEnabled.sol +./node_modules/@openzeppelin/contracts/crosschain/errors.sol +./node_modules/@openzeppelin/contracts/crosschain/optimism/CrossChainEnabledOptimism.sol +./node_modules/@openzeppelin/contracts/crosschain/optimism/LibOptimism.sol +./node_modules/@openzeppelin/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol +./node_modules/@openzeppelin/contracts/finance/PaymentSplitter.sol +./node_modules/@openzeppelin/contracts/finance/VestingWallet.sol +./node_modules/@openzeppelin/contracts/governance/compatibility/GovernorCompatibilityBravo.sol +./node_modules/@openzeppelin/contracts/governance/compatibility/IGovernorCompatibilityBravo.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorPreventLateQuorum.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorProposalThreshold.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorSettings.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorTimelockCompound.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotes.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotesComp.sol +./node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol +./node_modules/@openzeppelin/contracts/governance/extensions/IGovernorTimelock.sol +./node_modules/@openzeppelin/contracts/governance/Governor.sol +./node_modules/@openzeppelin/contracts/governance/IGovernor.sol +./node_modules/@openzeppelin/contracts/governance/TimelockController.sol +./node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol +./node_modules/@openzeppelin/contracts/governance/utils/Votes.sol +./node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol +./node_modules/@openzeppelin/contracts/interfaces/draft-IERC2612.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1155.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1155MetadataURI.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1155Receiver.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1271.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1363Receiver.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1363Spender.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC165.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1820Implementer.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC1820Registry.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC20.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC20Metadata.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC2981.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC3156.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC4626.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC721.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC721Enumerable.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC721Metadata.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC721Receiver.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC777.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC777Recipient.sol +./node_modules/@openzeppelin/contracts/interfaces/IERC777Sender.sol +./node_modules/@openzeppelin/contracts/metatx/ERC2771Context.sol +./node_modules/@openzeppelin/contracts/metatx/MinimalForwarder.sol +./node_modules/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol +./node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol +./node_modules/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol +./node_modules/@openzeppelin/contracts/proxy/Clones.sol +./node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol +./node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol +./node_modules/@openzeppelin/contracts/proxy/Proxy.sol +./node_modules/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +./node_modules/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +./node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol +./node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol +./node_modules/@openzeppelin/contracts/security/Pausable.sol +./node_modules/@openzeppelin/contracts/security/PullPayment.sol +./node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol +./node_modules/@openzeppelin/contracts/token/common/ERC2981.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/ERC1155.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/IERC1155.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol +./node_modules/@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol +./node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20VotesComp.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol +./node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol +./node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol +./node_modules/@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol +./node_modules/@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol +./node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol +./node_modules/@openzeppelin/contracts/token/ERC20/utils/TokenTimelock.sol +./node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/draft-ERC721Votes.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol +./node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol +./node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol +./node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol +./node_modules/@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol +./node_modules/@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol +./node_modules/@openzeppelin/contracts/token/ERC777/ERC777.sol +./node_modules/@openzeppelin/contracts/token/ERC777/IERC777.sol +./node_modules/@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol +./node_modules/@openzeppelin/contracts/token/ERC777/IERC777Sender.sol +./node_modules/@openzeppelin/contracts/token/ERC777/presets/ERC777PresetFixedSupply.sol +./node_modules/@openzeppelin/contracts/utils/Address.sol +./node_modules/@openzeppelin/contracts/utils/Arrays.sol +./node_modules/@openzeppelin/contracts/utils/Base64.sol +./node_modules/@openzeppelin/contracts/utils/Checkpoints.sol +./node_modules/@openzeppelin/contracts/utils/Context.sol +./node_modules/@openzeppelin/contracts/utils/Counters.sol +./node_modules/@openzeppelin/contracts/utils/Create2.sol +./node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol +./node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol +./node_modules/@openzeppelin/contracts/utils/cryptography/MerkleProof.sol +./node_modules/@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol +./node_modules/@openzeppelin/contracts/utils/escrow/ConditionalEscrow.sol +./node_modules/@openzeppelin/contracts/utils/escrow/Escrow.sol +./node_modules/@openzeppelin/contracts/utils/escrow/RefundEscrow.sol +./node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol +./node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol +./node_modules/@openzeppelin/contracts/utils/introspection/ERC165Storage.sol +./node_modules/@openzeppelin/contracts/utils/introspection/ERC1820Implementer.sol +./node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol +./node_modules/@openzeppelin/contracts/utils/introspection/IERC1820Implementer.sol +./node_modules/@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol +./node_modules/@openzeppelin/contracts/utils/math/Math.sol +./node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol +./node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol +./node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol +./node_modules/@openzeppelin/contracts/utils/math/SignedSafeMath.sol +./node_modules/@openzeppelin/contracts/utils/Multicall.sol +./node_modules/@openzeppelin/contracts/utils/StorageSlot.sol +./node_modules/@openzeppelin/contracts/utils/Strings.sol +./node_modules/@openzeppelin/contracts/utils/structs/BitMaps.sol +./node_modules/@openzeppelin/contracts/utils/structs/DoubleEndedQueue.sol +./node_modules/@openzeppelin/contracts/utils/structs/EnumerableMap.sol +./node_modules/@openzeppelin/contracts/utils/structs/EnumerableSet.sol +./node_modules/@openzeppelin/contracts/utils/Timers.sol +./node_modules/@openzeppelin/contracts/vendor/amb/IAMB.sol +./node_modules/@openzeppelin/contracts/vendor/arbitrum/IArbSys.sol +./node_modules/@openzeppelin/contracts/vendor/arbitrum/IBridge.sol +./node_modules/@openzeppelin/contracts/vendor/arbitrum/IInbox.sol +./node_modules/@openzeppelin/contracts/vendor/arbitrum/IMessageProvider.sol +./node_modules/@openzeppelin/contracts/vendor/arbitrum/IOutbox.sol +./node_modules/@openzeppelin/contracts/vendor/compound/ICompoundTimelock.sol +./node_modules/@openzeppelin/contracts/vendor/optimism/ICrossDomainMessenger.sol +./node_modules/@openzeppelin/contracts/vendor/polygon/IFxMessageProcessor.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/IUniswapV3PoolDeployer.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol +./node_modules/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol +./node_modules/@uniswap/v3-core/contracts/libraries/BitMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/FixedPoint128.sol +./node_modules/@uniswap/v3-core/contracts/libraries/FixedPoint96.sol +./node_modules/@uniswap/v3-core/contracts/libraries/FullMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/LiquidityMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/Oracle.sol +./node_modules/@uniswap/v3-core/contracts/libraries/Position.sol +./node_modules/@uniswap/v3-core/contracts/libraries/SafeCast.sol +./node_modules/@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/SwapMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/Tick.sol +./node_modules/@uniswap/v3-core/contracts/libraries/TickBitmap.sol +./node_modules/@uniswap/v3-core/contracts/libraries/TickMath.sol +./node_modules/@uniswap/v3-core/contracts/libraries/TransferHelper.sol +./node_modules/@uniswap/v3-core/contracts/libraries/UnsafeMath.sol diff --git a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts index c9b88c9805..6e09dc1914 100644 --- a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts +++ b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts @@ -1,10 +1,10 @@ import { sourceMappingDecoder } from "@remix-project/remix-debug" import { AstNode } from "@remix-project/remix-solidity-ts" -import { isArray } from "lodash" +import { isArray, last } from "lodash" import { editor, languages, Position } from "monaco-editor" import monaco from "../../types/monaco" import { EditorUIProps } from "../remix-ui-editor" -import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteBTypeName, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, GetImports } from "./completion/completionGlobals" +import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteBTypeName, getContextualAutoCompleteByGlobalVariable, GetContractRepositories, GetGlobalFunctions, GetGlobalVariable, GetImports } from "./completion/completionGlobals" export class RemixCompletionProvider implements languages.CompletionItemProvider { @@ -16,7 +16,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider this.monaco = monaco } - triggerCharacters = ['.', '', '"'] + triggerCharacters = ['.', '', '"', '@', '/'] async provideCompletionItems(model: editor.ITextModel, position: Position, context: monaco.languages.CompletionContext): Promise { const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion') @@ -28,21 +28,31 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider startColumn: word.startColumn, endColumn: word.endColumn }; - + console.log(word) const line = model.getLineContent(position.lineNumber) let nodes: AstNode[] = [] let suggestions: monaco.languages.CompletionItem[] = [] - - if (context.triggerCharacter === '"') { - - const ast = await this.props.plugin.call('codeParser', 'parseSolidity', line) - if (ast && ast.children && ast.children[0] && ast.children[0].type === "ImportDirective") { - suggestions = [...suggestions, - ...GetImports(range, this.monaco), - ] - - }else{ - return + console.log('context', context.triggerCharacter) + + if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') { + + const lastpart = line.substring(0, position.column - 1).split(';').pop() + console.log('lastpart', lastpart) + if (lastpart.startsWith('import')) { + const imports = await this.props.plugin.call('codeParser', 'getImports') + if (context.triggerCharacter === '"' || context.triggerCharacter === '@') { + suggestions = [...suggestions, + ...GetImports(range, this.monaco, imports, context.triggerCharacter), + ] + } else if (context.triggerCharacter === '/') { + const word = line.split('"')[1] + console.log(word) + suggestions = [...suggestions, + ...GetImports(range, this.monaco, imports, word), + ] + } else { + return + } } } else diff --git a/package.json b/package.json index 8399c040bc..e73b61e6ee 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,8 @@ "test-browser": "npm-run-all -lpr selenium make-mock-compiler serve browsertest", "watch": "watchify apps/remix-ide/src/index.js -dv -p browserify-reload -o apps/remix-ide/build/app.js --exclude solc", "reinstall": "rm ./node-modules/ -rf && rm yarn.lock && rm ./build/ -rf && yarn install & yarn run build", - "ganache-cli": "npx ganache-cli" + "ganache-cli": "npx ganache-cli", + "build-contracts": "find ./node_modules/@openzeppelin/contracts | grep -i '.sol' > libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt && find ./node_modules/@uniswap/v3-core/contracts | grep -i '.sol' >> libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt" }, "browserify": { "transform": [ @@ -234,6 +235,7 @@ "@babel/preset-typescript": "7.9.0", "@babel/register": "^7.4.4", "@fortawesome/fontawesome-free": "^5.8.1", + "@hq20/contracts": "^0.0.6", "@nrwl/cli": "12.3.6", "@nrwl/eslint-plugin-nx": "12.3.6", "@nrwl/jest": "12.3.6", @@ -261,6 +263,8 @@ "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^4.32.0", "@typescript-eslint/parser": "^4.32.0", + "@uniswap/v2-core": "^1.0.1", + "@uniswap/v3-core": "^1.0.1", "ace-mode-lexon": "^1.*.*", "ace-mode-move": "0.0.1", "ace-mode-solidity": "^0.1.0", diff --git a/yarn.lock b/yarn.lock index 3809c46cb6..d5e5cff8a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2475,6 +2475,11 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== +"@hq20/contracts@^0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@hq20/contracts/-/contracts-0.0.6.tgz#fc0a05884294da8757c4187f8567638982b74b6a" + integrity sha512-l94ARK0LfcRY7Y5EiInA+0vdXh8lnkTRAw9unli7UC75DY7aBMJl4OqTT5SMdm/n4N1dVVhCnyCM1W84UAx2Vw== + "@isomorphic-git/idb-keyval@3.3.2": version "3.3.2" resolved "https://registry.yarnpkg.com/@isomorphic-git/idb-keyval/-/idb-keyval-3.3.2.tgz#c0509a6c5987d8a62efb3e47f2815bcc5eda2489" @@ -4806,6 +4811,16 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== +"@uniswap/v2-core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" + integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== + +"@uniswap/v3-core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" + integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"