Merge branch 'master' into filedecoratorplugin

pull/5370/head
bunsenstraat 2 years ago committed by GitHub
commit 804f9e75bd
  1. 3
      apps/solidity-compiler/src/app/compiler-api.ts
  2. 2
      libs/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.4.24.ts
  3. 133
      libs/remix-ui/editor/src/lib/cairoSyntax.ts
  4. 20
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  5. 132
      libs/remix-ui/editor/src/lib/syntaxes/cairo.ts
  6. 4
      libs/remix-ui/editor/src/lib/syntaxes/solidity.ts
  7. 144
      libs/remix-ui/editor/src/lib/syntaxes/zokrates.ts
  8. 18
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  9. 10
      libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx
  10. 70
      libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx
  11. 1
      package.json
  12. 5
      yarn.lock

@ -222,9 +222,10 @@ export const CompilerApiMixin = (Base) => class extends Base {
}
this.compiler.event.register('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)
this.data.eventHandlers.onCompilerLoaded = () => {
this.data.eventHandlers.onCompilerLoaded = (version) => {
this.data.loading = false
this.statusChanged({ key: 'none' })
this.emit('compilerLoaded', version)
}
this.compiler.event.register('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)

@ -38,7 +38,7 @@ const testFiles: string[] = [
'forLoopIteratesOverDynamicArray.sol'
]
let compilationResults: Record<string, CompilationResult> = {}
const compilationResults: Record<string, CompilationResult> = {}
test('setup', function (t: test.Test) {
solcOrg.loadRemoteVersion('v0.4.24+commit.e67f0147', (error, compiler) => {

@ -1,133 +0,0 @@
/* eslint-disable */
export const cairoConf = {
comments: {
lineComment: '#'
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
['%{', '%}']
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '%{', close: '%}' },
{ open: "'", close: "'", notIn: ['string', 'comment'] }
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '%{', close: '%}' },
{ open: "'", close: "'" }
]
}
export const cairoLang = {
defaultToken: '',
tokenPostfix: '.cairo',
brackets: [
{ token: 'delimiter.curly', open: '{', close: '}' },
{ token: 'delimiter.parenthesis', open: '(', close: ')' },
{ token: 'delimiter.square', open: '[', close: ']' },
{ token: 'delimiter.curly', open: '%{', close: '%}' }
],
keywords: [
// control
'if',
'else',
'end',
// meta
'alloc_locals',
'as',
'assert',
'cast',
'const',
'dw',
'felt',
'from',
'func',
'import',
'let',
'local',
'member',
'nondet',
'return',
'static_assert',
'struct',
'tempvar',
'with_attr',
'with',
// register
'ap',
'fp',
// opcode
'call',
'jmp',
'ret',
'abs',
'rel'
],
operators: ['=', ':', '==', '++', '+', '-', '*', '**', '/', '&', '%', '_'],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
numberDecimal: /[+-]?[0-9]+/,
numberHex: /[+-]?0x[0-9a-fA-F]+/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
'@keywords': { token: 'keyword.$0' },
'@default': 'identifier'
}
}
],
// whitespace
{ include: '@whitespace' },
// directives
[/^%[a-zA-Z]\w*/, 'tag'],
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@operators': 'delimiter',
'@default': ''
}
}
],
// numbers
[/(@numberHex)/, 'number.hex'],
[/(@numberDecimal)/, 'number'],
// strings
[/'[^']*'/, 'string']
],
whitespace: [
[/\s+/, 'white'],
[/(^#.*$)/, 'comment']
]
}
}

@ -2,8 +2,9 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint
import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view'
import Editor, { loader } from '@monaco-editor/react'
import { reducerActions, reducerListener, initialState } from './actions/editor'
import { language, conf } from './syntax'
import { cairoLang, cairoConf } from './cairoSyntax'
import { solidityTokensProvider, solidityLanguageConfig } from './syntaxes/solidity'
import { cairoTokensProvider, cairoLanguageConfig } from './syntaxes/cairo'
import { zokratesTokensProvider, zokratesLanguageConfig } from './syntaxes/zokrates'
import './remix-ui-editor.css'
import { loadTypes } from './web-types'
@ -255,6 +256,8 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-solidity')
} else if (file.language === 'cairo') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-cairo')
} else if (file.language === 'zokrates') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-zokrates')
}
}, [props.currentFile])
@ -464,12 +467,17 @@ export const EditorUI = (props: EditorUIProps) => {
// Register a new language
monacoRef.current.languages.register({ id: 'remix-solidity' })
monacoRef.current.languages.register({ id: 'remix-cairo' })
monacoRef.current.languages.register({ id: 'remix-zokrates' })
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', language)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', conf)
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', solidityTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', solidityLanguageConfig)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoLanguageConfig)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf)
monacoRef.current.languages.setMonarchTokensProvider('remix-zokrates', zokratesTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-zokrates', zokratesLanguageConfig)
loadTypes(monacoRef.current)
}

@ -0,0 +1,132 @@
/* eslint-disable */
export const cairoLanguageConfig = {
comments: {
lineComment: "#",
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
["%{", "%}"],
],
autoClosingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: "%{", close: "%}" },
{ open: "'", close: "'", notIn: ["string", "comment"] },
],
surroundingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: "%{", close: "%}" },
{ open: "'", close: "'" },
],
}
export const cairoTokensProvider = {
defaultToken: "",
tokenPostfix: ".cairo",
brackets: [
{ token: "delimiter.curly", open: "{", close: "}" },
{ token: "delimiter.parenthesis", open: "(", close: ")" },
{ token: "delimiter.square", open: "[", close: "]" },
{ token: "delimiter.curly", open: "%{", close: "%}" },
],
keywords: [
// control
"if",
"else",
"end",
// meta
"alloc_locals",
"as",
"assert",
"cast",
"const",
"dw",
"felt",
"from",
"func",
"import",
"let",
"local",
"member",
"nondet",
"return",
"static_assert",
"struct",
"tempvar",
"with_attr",
"with",
// register
"ap",
"fp",
// opcode
"call",
"jmp",
"ret",
"abs",
"rel",
],
operators: ["=", ":", "==", "++", "+", "-", "*", "**", "/", "&", "%", "_"],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
numberDecimal: /[+-]?[0-9]+/,
numberHex: /[+-]?0x[0-9a-fA-F]+/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
"@keywords": { token: "keyword.$0" },
"@default": "identifier",
},
},
],
// whitespace
{ include: "@whitespace" },
// directives
[/^%[a-zA-Z]\w*/, "tag"],
// delimiters and operators
[/[{}()\[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[
/@symbols/,
{
cases: {
"@operators": "delimiter",
"@default": "",
},
},
],
// numbers
[/(@numberHex)/, "number.hex"],
[/(@numberDecimal)/, "number"],
// strings
[/'[^']*'/, "string"],
],
whitespace: [
[/\s+/, "white"],
[/(^#.*$)/, "comment"],
],
},
}

@ -1,5 +1,5 @@
/* eslint-disable */
export const conf = {
export const solidityLanguageConfig = {
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
@ -19,7 +19,7 @@ export const conf = {
]
}
export const language = {
export const solidityTokensProvider = {
defaultToken: '',
tokenPostfix: '.sol',

@ -0,0 +1,144 @@
/* eslint-disable */
export const zokratesLanguageConfig = {
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
['<', '>']
],
autoClosingPairs: [
{ open: '"', close: '"', notIn: ['string', 'comment'] },
{ open: '{', close: '}', notIn: ['string', 'comment'] },
{ open: '[', close: ']', notIn: ['string', 'comment'] },
{ open: '(', close: ')', notIn: ['string', 'comment'] },
{ open: '<', close: '>', notIn: ['string', 'comment'] }
]
}
export const zokratesTokensProvider = {
defaultToken: "",
tokenPostfix: ".zok",
keywords: [
"log",
"assert",
"as",
"bool",
"const",
"def",
"else",
"false",
"field",
"for",
"if",
"import",
"from",
"in",
"mut",
"private",
"public",
"return",
"struct",
"true",
"type",
"u8",
"u16",
"u32",
"u64",
],
typeKeywords: ["bool", "field", "u8", "u16", "u32", "u64"],
operators: [
"=",
">",
"<",
"!",
"?",
":",
"==",
"<=",
">=",
"!=",
"&&",
"||",
"+",
"-",
"*",
"**",
"/",
"&",
"|",
"^",
"%",
"<<",
">>",
],
decimalSuffix: /(u16|u32|u64|u8|f)?/,
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
escapes:
/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z]\w*/,
{
cases: {
"@typeKeywords": "type.identifier",
"@keywords": "keyword",
"@default": "identifier",
},
},
],
// whitespace
{ include: "@whitespace" },
// delimiters and operators
[/[{}()\[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[/@symbols/, { cases: { "@operators": "operator", "@default": "" } }],
// numbers
[/0[xX][0-9a-fA-F]+/, "number.hex"],
[/\d+(@decimalSuffix)/, "number"],
// delimiter
[/[;,.]/, "delimiter"],
// strings
[/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string
[/"/, { token: "string.quote", bracket: "@open", next: "@string" }],
],
comment: [
[/[^\/*]+/, "comment"],
[/\/\*/, "comment", "@push"], // nested comment
["\\*/", "comment", "@pop"],
[/[\/*]/, "comment"],
],
string: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
whitespace: [
[/[ \t\r\n]+/, "white"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
],
},
}

@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect, ReactElement } from 'react' // eslint-disable-line
import * as semver from 'semver'
import { eachOfSeries } from 'async' // eslint-disable-line
import type Web3 from 'web3'
import { canUseWorker, urlFromVersion } from '@remix-project/remix-solidity'
@ -154,8 +155,23 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
await setCurrentPath(defaultPath)
})
const truncateVersion = (version: string) => {
const tmp: RegExpExecArray | null = /^(\d+.\d+.\d+)/.exec(version)
return tmp ? tmp[1] : version
}
testTab.fileManager.events.on('noFileSelected', async () => { await updateForNewCurrent() })
testTab.fileManager.events.on('currentFileChanged', async (file: string) => await updateForNewCurrent(file))
testTab.fileManager.events.on('currentFileChanged', async (file: string) => {
await updateForNewCurrent(file)
})
testTab.on('solidity', 'compilerLoaded', async (version: string) => {
const { currentVersion } = testTab.compileTab.getCurrentCompilerConfig()
if (!semver.gt(truncateVersion(currentVersion), '0.4.12')) {
setDisableRunButton(true)
setRunButtonTitle('Please select Solidity compiler version greater than 0.4.12.')
}
})
}, []) // eslint-disable-line

@ -3,16 +3,20 @@ import React from 'react' //eslint-disable-line
interface StaticAnalyserButtonProps {
onClick: (event) => void
buttonText: string,
disabled?: boolean
disabled?: boolean,
title?: string
}
const StaticAnalyserButton = ({
onClick,
buttonText,
disabled
disabled,
title
}: StaticAnalyserButtonProps) => {
let classList = "btn btn-sm w-25 btn-primary"
classList += disabled ? " disabled" : ""
return (
<button className="btn btn-sm w-25 btn-primary" onClick={onClick} disabled={disabled}>
<button className={classList} disabled={disabled} title={title} onClick={onClick}>
{buttonText}
</button>
)

@ -2,6 +2,7 @@ import React, { useEffect, useState, useReducer, useRef } from 'react' // eslint
import Button from './Button/StaticAnalyserButton' // eslint-disable-line
import { util } from '@remix-project/remix-lib'
import _ from 'lodash'
import * as semver from 'semver'
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' // eslint-disable-line
import { RemixUiCheckbox } from '@remix-ui/checkbox' // eslint-disable-line
import ErrorRenderer from './ErrorRenderer' // eslint-disable-line
@ -64,14 +65,30 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
const [autoRun, setAutoRun] = useState(true)
const [slitherEnabled, setSlitherEnabled] = useState(false)
const [showSlither, setShowSlither] = useState(false)
const [isSupportedVersion, setIsSupportedVersion] = useState(false)
let [showLibsWarning, setShowLibsWarning] = useState(false) // eslint-disable-line prefer-const
const [categoryIndex, setCategoryIndex] = useState(groupedModuleIndex(groupedModules))
const [warningState, setWarningState] = useState({})
const [runButtonTitle, setRunButtonTitle] = useState<string>('Run Static Analysis')
const warningContainer = useRef(null)
const allWarnings = useRef({})
const [state, dispatch] = useReducer(analysisReducer, initialState)
const setDisableForRun = (version: string) => {
const truncateVersion = (version: string) => {
const tmp: RegExpExecArray | null = /^(\d+.\d+.\d+)/.exec(version)
return tmp ? tmp[1] : version
}
if (version != '' && !semver.gt(truncateVersion(version), '0.4.12')) {
setIsSupportedVersion(false)
setRunButtonTitle('Sselect Solidity compiler version greater than 0.4.12.')
} else {
setIsSupportedVersion(true)
setRunButtonTitle('Run static analysis')
}
}
useEffect(() => {
compilation(props.analysisModule, dispatch)
}, [props])
@ -91,6 +108,10 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
return () => { }
}, [state])
useEffect(() => {
props.analysisModule.call('solidity', 'getCompilerState').then((compilerState) => setDisableForRun(compilerState.currentVersion))
}, [])
useEffect(() => {
props.analysisModule.on('filePanel', 'setWorkspace', (currentWorkspace) => {
// Reset warning state
@ -119,20 +140,24 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
setSlitherEnabled(false)
}
})
props.analysisModule.on('solidity', 'compilerLoaded', async (version: string) => {
setDisableForRun(version)
})
return () => { }
}, [props])
const message = (name, warning, more, fileName, locationString) : string => {
return (`
<span className='d-flex flex-column'>
<span className='h6 font-weight-bold'>${name}</span>
${warning}
${more
? (<span><a href={more} target='_blank'>more</a></span>)
: (<span> </span>)
}
<span className="" title={Position in ${fileName}}>Pos: ${locationString}</span>
</span>`
<span className='d-flex flex-column'>
<span className='h6 font-weight-bold'>${name}</span>
${warning}
${more
? (<span><a href={more} target='_blank'>more</a></span>)
: (<span> </span>)
}
<span className="" title={Position in ${fileName}}>Pos: ${locationString}</span>
</span>`
)
}
@ -183,6 +208,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
}
const run = async (lastCompilationResult, lastCompilationSource, currentFile) => {
if (!isSupportedVersion) return
if (state.data !== null) {
if (lastCompilationResult && (categoryIndex.length > 0 || slitherEnabled)) {
const warningMessage = []
@ -474,7 +500,12 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
label="Autorun"
onChange={() => {}}
/>
<Button buttonText="Run" onClick={async () => await run(state.data, state.source, state.file)} disabled={(state.data === null || categoryIndex.length === 0) && !slitherEnabled }/>
<Button
buttonText="Run"
title={runButtonTitle}
onClick={async () => await run(state.data, state.source, state.file)}
disabled={(state.data === null || categoryIndex.length === 0) && !slitherEnabled || !isSupportedVersion }
/>
</div>
{ showSlither &&
<div className="d-flex mt-2" id="enableSlitherAnalysis">
@ -520,15 +551,15 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
{Object.entries(warningState).length > 0 &&
<div id='staticanalysisresult' >
<RemixUiCheckbox
id="showLibWarnings"
name="showLibWarnings"
categoryId="showLibWarnings"
title="when checked, the results are also displayed for external contract libraries"
inputType="checkbox"
checked={showLibsWarning}
label="Show warnings for external libraries"
onClick={handleShowLibsWarning}
onChange={() => {}}
id="showLibWarnings"
name="showLibWarnings"
categoryId="showLibWarnings"
title="when checked, the results are also displayed for external contract libraries"
inputType="checkbox"
checked={showLibsWarning}
label="Show warnings for external libraries"
onClick={handleShowLibsWarning}
onChange={() => {}}
/>
<br/>
<div className="mb-4">
@ -541,7 +572,6 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
<div data-id={`staticAnalysisModule${x.warningModuleName}${i}`} id={`staticAnalysisModule${x.warningModuleName}${i}`} key={i}>
<ErrorRenderer name={`staticAnalysisModule${x.warningModuleName}${i}`} message={x.msg} opt={x.options} warningErrors={ x.warningErrors} editor={props.analysisModule}/>
</div>
) : null
))}
</div>

@ -252,6 +252,7 @@
"@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.3.0",
"@types/request": "^2.48.7",
"@types/semver": "^7.3.10",
"@types/tape": "^4.13.0",
"@types/ws": "^7.2.4",
"@typescript-eslint/eslint-plugin": "^4.32.0",

@ -4637,6 +4637,11 @@
integrity sha512-NxxZZek50ylIACiXebKQYHD3D4One3WXOasEXWazL6aTfYbZob7ClNKxUpg8I4/oWArX87oPWvj1cHKqfel3Hg==
dependencies:
"@types/ws" "*"
"@types/semver@^7.3.10":
version "7.3.10"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.10.tgz#5f19ee40cbeff87d916eedc8c2bfe2305d957f73"
integrity sha512-zsv3fsC7S84NN6nPK06u79oWgrPVd0NvOyqgghV1haPaFcVxIrP4DLomRwGAXk0ui4HZA7mOcSFL98sMVW9viw==
"@types/source-list-map@*":
version "0.1.2"

Loading…
Cancel
Save