Merge branch 'master' into cconfig

pull/2921/head
bunsenstraat 2 years ago committed by GitHub
commit 2b20e687ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      apps/remix-ide-e2e/src/commands/addFile.ts
  2. 26
      apps/remix-ide/src/app/plugins/parser/code-parser.tsx
  3. 92
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  4. 82
      apps/remix-ide/src/app/plugins/parser/services/code-parser-imports.ts
  5. 99
      libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts
  6. 198
      libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt
  7. 38
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  8. 18
      libs/remix-ui/editor/src/lib/providers/definitionProvider.ts
  9. 2
      libs/remix-ui/search/src/index.ts
  10. 5
      package.json
  11. 10
      yarn.lock

@ -2,7 +2,7 @@ import { NightwatchBrowser, NightwatchContractContent } from 'nightwatch'
import EventEmitter from 'events'
class AddFile extends EventEmitter {
command (this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser {
command(this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser {
this.api.perform((done) => {
addFile(this.api, name, content, () => {
done()

@ -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<antlr.ParseResult>
getLastNodeInLine: (ast: string) => Promise<any>
listAstNodes: () => Promise<any>
getANTLRBlockAtPosition: (position: any, text?: string) => Promise<any>
getCurrentFileAST: (text?: string) => Promise<ParseResult>
getImports: () => Promise<CodeParserImportsData[]>
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,9 +124,18 @@ export class CodeParser extends Plugin {
this.on('filePanel', 'setWorkspace', async () => {
await this.call('fileDecorator', 'clearFileDecorators')
await this.importService.setFileTree()
})
this.on('fileManager', 'fileAdded', async () => {
await this.importService.setFileTree()
})
this.on('fileManager', 'fileRemoved', async () => {
await this.importService.setFileTree()
})
this.on('fileManager', 'currentFileChanged', async () => {
await this.call('editor', 'discardLineTexts')
await this.handleChangeEvents()
@ -135,8 +149,6 @@ export class CodeParser extends Plugin {
}
/**
*
* @returns
@ -145,10 +157,6 @@ export class CodeParser extends Plugin {
return this.compilerAbstract
}
getSubNodes<T extends genericASTNode>(node: T): number[] {
return node.nodeType == "ContractDefinition" && node.contractDependencies;
}

@ -8,6 +8,7 @@ import { fileDecoration, fileDecorationType } from '@remix-ui/file-decorators'
import { sourceMappingDecoder } from '@remix-project/remix-debug'
import { CompilerRetriggerMode } from '@remix-project/remix-solidity-ts';
import { MarkerSeverity } from 'monaco-editor';
import { findLinesInStringWithMatch, SearchResultLine } from '@remix-ui/search'
type errorMarker = {
message: string
@ -23,7 +24,7 @@ type errorMarker = {
}
},
file: string
}
}
export default class CodeParserCompiler {
plugin: CodeParser
compiler: any // used to compile the current file seperately from the main compiler
@ -43,36 +44,47 @@ export default class CodeParserCompiler {
this.errorState = true
const result = new CompilerAbstract('soljson', data, source, input)
let allErrors: errorMarker[] = []
if (data.errors) {
const sources = result.getSourceCode().sources
if (data.errors || data.error) {
const file = await this.plugin.call('fileManager', 'getCurrentFile')
const currentFileContent = await this.plugin.call('fileManager', 'readFile', file)
const sources = result.getSourceCode().sources || []
if (data.error) {
if (data.error.formattedMessage) {
// mark this file as error
const errorMarker = await this.createErrorMarker(data.error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
}
} else {
for (const error of data.errors) {
if (!error.sourceLocation) {
// mark this file as error
const errorMarker = await this.createErrorMarker(error, file, { start: { line: 0, column: 0 }, end: { line: 0, column: 100 } })
allErrors = [...allErrors, errorMarker]
} else {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content)
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({
start: error.sourceLocation.start,
length: error.sourceLocation.end - error.sourceLocation.start
}, lineBreaks)
const filePath = error.sourceLocation.file
const fileTarget = await this.plugin.call('fileManager', 'getUrlFromPath', filePath)
allErrors = [...allErrors, {
message: error.formattedMessage,
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning,
position: {
start: {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1,
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1
},
end: {
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1,
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
const importFilePositions = await this.getPositionForImportErrors(fileTarget.file, currentFileContent)
for (const importFilePosition of importFilePositions) {
for (const line of importFilePosition.lines) {
allErrors = [...allErrors, await this.createErrorMarker(error, file, line.position)]
}
}
, file: filePath
}]
allErrors = [...allErrors, await this.createErrorMarker(error, filePath, lineColumn)]
}
}
}
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if(displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors)
if (displayErrors) await this.plugin.call('editor', 'addErrorMarker', allErrors)
this.addDecorators(allErrors, sources)
} else {
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources)
@ -131,7 +143,7 @@ export default class CodeParserCompiler {
"*": ["evm.gasEstimates"]
}
},
"evmVersion": state.evmVersion && state.evmVersion.toString() || "byzantium",
"evmVersion": state.evmVersion && state.evmVersion.toString() || "berlin",
}
}
@ -149,8 +161,8 @@ export default class CodeParserCompiler {
async addDecorators(allErrors: errorMarker[], sources: any) {
const displayErrors = await this.plugin.call('config', 'getAppParameter', 'display-errors')
if(!displayErrors) return
const errorsPerFiles: {[fileName: string]: errorMarker[]} = {}
if (!displayErrors) return
const errorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const error of allErrors) {
if (!errorsPerFiles[error.file]) {
errorsPerFiles[error.file] = []
@ -164,7 +176,7 @@ export default class CodeParserCompiler {
}
// sort errorPerFiles by error priority
const sortedErrorsPerFiles: {[fileName: string]: errorMarker[]} = {}
const sortedErrorsPerFiles: { [fileName: string]: errorMarker[] } = {}
for (const fileName in errorsPerFiles) {
const errors = errorsPerFiles[fileName]
errors.sort((a, b) => {
@ -178,10 +190,11 @@ export default class CodeParserCompiler {
const decorators: fileDecoration[] = []
for (const fileName in sortedErrorsPerFiles) {
const errors = sortedErrorsPerFiles[fileName]
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileName,
path: fileTarget.file,
isDirectory: false,
fileStateType: errors[0].severity == MarkerSeverity.Error? fileDecorationType.Error : fileDecorationType.Warning,
fileStateType: errors[0].severity == MarkerSeverity.Error ? fileDecorationType.Error : fileDecorationType.Warning,
fileStateLabelClass: errors[0].severity == MarkerSeverity.Error ? 'text-danger' : 'text-warning',
fileStateIconClass: '',
fileStateIcon: '',
@ -193,8 +206,9 @@ export default class CodeParserCompiler {
decorators.push(decorator)
}
for (const fileName of filesWithOutErrors) {
const fileTarget = await this.plugin.call('fileManager', 'getPathFromUrl', fileName)
const decorator: fileDecoration = {
path: fileName,
path: fileTarget.file,
isDirectory: false,
fileStateType: fileDecorationType.None,
fileStateLabelClass: '',
@ -211,8 +225,27 @@ export default class CodeParserCompiler {
}
async createErrorMarker(error: any, filePath: string, lineColumn): Promise<errorMarker> {
return {
message: error.formattedMessage,
severity: error.severity === 'error' ? MarkerSeverity.Error : MarkerSeverity.Warning,
position: {
start: {
line: ((lineColumn.start && lineColumn.start.line) || 0) + 1,
column: ((lineColumn.start && lineColumn.start.column) || 0) + 1
},
end: {
line: ((lineColumn.end && lineColumn.end.line) || 0) + 1,
column: ((lineColumn.end && lineColumn.end.column) || 0) + 1
}
}
, file: filePath
}
}
async clearDecorators(sources: any) {
const decorators: fileDecoration[] = []
if (!sources) return
for (const fileName of Object.keys(sources)) {
const decorator: fileDecoration = {
path: fileName,
@ -232,4 +265,13 @@ export default class CodeParserCompiler {
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators)
}
async getPositionForImportErrors(importedFileName: string, text: string) {
const re = new RegExp(importedFileName, 'gi')
const result: SearchResultLine[] = findLinesInStringWithMatch(
text,
re
)
return result
}
}

@ -0,0 +1,82 @@
'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')
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]))]
}
setFileTree = async () => {
this.data.files = await this.getDirectory('/')
this.data.files = this.data.files.filter(x => x.endsWith('.sol') && !x.startsWith('.deps') && !x.startsWith('.git'))
}
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]
}
}

@ -1,5 +1,12 @@
import { IRange } from "monaco-editor";
import monaco from "../../../types/monaco";
import path from "path";
type CodeParserImportsData = {
files?: string[],
modules?: string[],
packages?: string[],
}
export function getStringCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
@ -176,13 +183,6 @@ export function getCompletionSnippets(range: IRange, monaco): monaco.languages.C
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,
@ -330,7 +330,7 @@ function CreateCompletionItem(label: string, kind: monaco.languages.CompletionIt
export function GetCompletionKeywords(range: IRange, monaco): monaco.languages.CompletionItem[] {
const completionItems = [];
const keywords = ['modifier', 'mapping', 'break', 'continue', 'delete', 'else', 'for',
'after', 'promise', 'alias', 'apply','auto', 'copyof', 'default', 'define', 'final', 'implements',
'after', 'promise', 'alias', 'apply', 'auto', 'copyof', 'default', 'define', 'final', 'implements',
'inline', 'let', 'macro', 'match', 'mutable', 'null', 'of', 'partial', 'reference', 'relocatable',
'sealed', 'sizeof', 'static', 'supports', 'switch', 'typedef',
'if', 'new', 'return', 'returns', 'while', 'using', 'emit', 'anonymous', 'indexed',
@ -390,6 +390,89 @@ export function GeCompletionUnits(range: IRange, monaco): monaco.languages.Compl
return completionItems;
}
export function GetImports(range: IRange
, monaco, data: CodeParserImportsData
, word: string
): monaco.languages.CompletionItem[] {
let 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;
};
export function GetGlobalVariable(range: IRange, monaco): monaco.languages.CompletionItem[] {
return [
{

@ -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

@ -4,7 +4,7 @@ import { isArray } 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 } from "./completion/completionGlobals"
import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteBTypeName, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, GetImports } from "./completion/completionGlobals"
export class RemixCompletionProvider implements languages.CompletionItemProvider {
@ -16,11 +16,11 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
this.monaco = monaco
}
triggerCharacters = ['.', '']
triggerCharacters = ['.', '', '"', '@', '/']
async provideCompletionItems(model: editor.ITextModel, position: Position, context: monaco.languages.CompletionContext): Promise<monaco.languages.CompletionList | undefined> {
const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion')
if(!completionSettings) return
if (!completionSettings) return
const word = model.getWordUntilPosition(position);
const range = {
startLineNumber: position.lineNumber,
@ -33,6 +33,28 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
let nodes: AstNode[] = []
let suggestions: monaco.languages.CompletionItem[] = []
if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') {
const lastpart = line.substring(0, position.column - 1).split(';').pop()
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]
suggestions = [...suggestions,
...GetImports(range, this.monaco, imports, word),
]
} else {
return
}
}
} else
if (context.triggerCharacter === '.') {
const lineTextBeforeCursor: string = line.substring(0, position.column - 1)
const lastNodeInExpression = await this.getLastNodeInExpression(lineTextBeforeCursor)
@ -41,7 +63,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
let dotCompleted = false
// handles completion from for builtin types
if(lastNodeInExpression.memberName === 'sender') { // exception for this member
if (lastNodeInExpression.memberName === 'sender') { // exception for this member
lastNodeInExpression.name = 'sender'
}
const globalCompletion = getContextualAutoCompleteByGlobalVariable(lastNodeInExpression.name, range, this.monaco)
@ -244,7 +266,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
const contractNodes = fileNodes.contracts[node.name].contractNodes
for (const contractNode of Object.values(contractNodes)) {
if (contractNode['name'] === ANTLRBlock.name
|| (contractNode['kind'] === 'constructor' && ANTLRBlock.name === null )
|| (contractNode['kind'] === 'constructor' && ANTLRBlock.name === null)
) {
let nodeOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', (contractNode as any).id)
nodes = [...nodes, ...nodeOfScope]
@ -279,7 +301,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
return true
}
}
if(node.outSideBlock){ return true }
if (node.outSideBlock) { return true }
return false
})
@ -387,9 +409,9 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
nodes = [...nodes, ...filterNodes(nodeOfScope.members, nodeOfScope)]
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ArrayTypeName') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('ArrayTypeName', range, this.monaco)]
} else if(nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'bytes') {
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'bytes') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('bytes', range, this.monaco)]
} else if(nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'address') {
} else if (nodeOfScope.typeName && nodeOfScope.typeName.nodeType === 'ElementaryTypeName' && nodeOfScope.typeName.name === 'address') {
suggestions = [...suggestions, ...getContextualAutoCompleteBTypeName('address', range, this.monaco)]
}
}

@ -13,8 +13,22 @@ export class RemixDefinitionProvider implements monaco.languages.DefinitionProvi
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async provideDefinition(model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken): Promise<monaco.languages.Definition | monaco.languages.LocationLink[]> {
const cursorPosition = this.props.editorAPI.getCursorPosition()
const jumpLocation = await this.jumpToDefinition(cursorPosition)
let jumpLocation = await this.jumpToDefinition(cursorPosition)
if (!jumpLocation || !jumpLocation.fileName) {
const line = model.getLineContent(position.lineNumber)
const lastpart = line.substring(0, position.column - 1).split(';').pop()
if (lastpart.startsWith('import')) {
const importPath = line.substring(lastpart.indexOf('"') + 1)
const importPath2 = importPath.substring(0, importPath.indexOf('"'))
jumpLocation = {
startLineNumber: 1,
startColumn: 1,
endColumn: 1,
endLineNumber: 1,
fileName: importPath2
}
}
}
return [{
uri: this.monaco.Uri.parse(jumpLocation.fileName),
range: {

@ -1 +1,3 @@
export { SearchTab } from './lib/components/Search';
export * from './lib/components/results/SearchHelper';
export * from './lib/types';

@ -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": [
@ -263,6 +264,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",

@ -4813,6 +4813,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"

Loading…
Cancel
Save