diff --git a/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx b/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx index 46a1941b2b..7521210123 100644 --- a/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx +++ b/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx @@ -3,13 +3,12 @@ import React, { useEffect, useState, useReducer, useRef, Fragment } from 'react' // eslint-disable-line import Button from './Button/StaticAnalyserButton' // eslint-disable-line import { util } from '@remix-project/remix-lib' -import { Status } from '@remixproject/plugin-utils' 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 -import { compilation, runLinting, runSlitherAnalysis } from './actions/staticAnalysisActions' +import { compilation } from './actions/staticAnalysisActions' import { initialState, analysisReducer } from './reducers/staticAnalysisReducer' import { CodeAnalysis } from '@remix-project/remix-analyzer' import Tab from 'react-bootstrap/Tab' @@ -17,7 +16,6 @@ import Tabs from 'react-bootstrap/Tabs' import { AnalysisTab, SolHintReport } from '../staticanalyser' import { run } from './actions/staticAnalysisActions' import { BasicTitle, calculateWarningStateEntries } from './components/BasicTitle' -import { BasicTabBody } from './components/BasicTabBody' declare global { interface Window { @@ -76,14 +74,13 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { const [slitherEnabled, setSlitherEnabled] = useState(false) const [startAnalysis, setStartAnalysis] = useState(false) const [isSupportedVersion, setIsSupportedVersion] = useState(false) - const [showLibsWarning, setShowLibsWarning] = useState(false) // eslint-disable-line prefer-const + let [showLibsWarning, setShowLibsWarning] = useState(false) // eslint-disable-line prefer-const const [categoryIndex, setCategoryIndex] = useState(groupedModuleIndex(groupedModules)) const [warningState, setWarningState] = useState({}) const [hideWarnings, setHideWarnings] = useState(false) const [hints, setHints] = useState([]) const [slitherWarnings, setSlitherWarnings] = useState([]) const [ssaWarnings, setSsaWarnings] = useState([]) - const [tabKey, setTabKey] = useState('basic') const warningContainer = useRef(null) const allWarnings = useRef({}) @@ -110,38 +107,22 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { } useEffect(() => { - setWarningState({}) - allWarnings.current = {} - setHints([]) - setSlitherWarnings([]) - setSsaWarnings([]) compilation(props.analysisModule, dispatch) - props.event.trigger('staticAnaysisWarning', [-1]) }, [props]) - useEffect(() => { - allWarnings.current = {} - setWarningState({}) - setHints([]) - setSlitherWarnings([]) - setSsaWarnings([]) - const runAnalysis = async () => { - await run(state.data, state.source, state.file, state, props, isSupportedVersion, showSlither, categoryIndex, groupedModules, runner,_paq, message, showWarnings, allWarnings, warningContainer,calculateWarningStateEntries, warningState, setHints, hints, setSlitherWarnings, setSsaWarnings, slitherEnabled, setStartAnalysis, solhintEnabled, basicEnabled) - } - return () => { } - }, [state]) + // useEffect(() => { + // setWarningState({}) + // const runAnalysis = async () => { + // await run(state.data, state.source, state.file, state, props, isSupportedVersion, showSlither, categoryIndex, groupedModules, runner,_paq, message, showWarnings, allWarnings, warningContainer,calculateWarningStateEntries, warningState, setHints, hints, setSlitherWarnings, setSsaWarnings, slitherEnabled, setStartAnalysis, solhintEnabled) + // } + // props.event.trigger('staticAnaysisWarning', []) + // return () => { } + // }, [state]) useEffect(() => { props.analysisModule.call('solidity', 'getCompilerState').then((compilerState) => setDisableForRun(compilerState.currentVersion)) }, []) - useEffect(() => { - props.analysisModule.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => { - props.event.trigger('staticAnaysisWarning', [-1]) - }) - return () => { props.event.trigger('staticAnalysisWarning', [-1]) } - }, [state.data, state.source]) - useEffect(() => { const checkRemixdActive = async () => { const remixdActive = await props.analysisModule.call('manager', 'isActive', 'remixd') @@ -156,10 +137,9 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { useEffect(() => { props.analysisModule.on('filePanel', 'setWorkspace', (currentWorkspace) => { // Reset warning state - allWarnings.current = {} - setWarningState({}) + setWarningState([]) // Reset badge - props.event.trigger('staticAnaysisWarning', [-1]) + props.event.trigger('staticAnaysisWarning', []) // Reset state dispatch({ type: '', payload: initialState }) setHints([]) @@ -179,13 +159,13 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { // Hide 'Enable Slither Analysis' checkbox if (plugin.name === 'remixd') { // Reset warning state - setWarningState({}) + setWarningState([]) setHints([]) setSlitherWarnings([]) setSlitherEnabled(false) setSsaWarnings([]) // Reset badge - props.event.trigger('staticAnaysisWarning', [-1]) + props.event.trigger('staticAnaysisWarning', []) // Reset state dispatch({ type: '', payload: initialState }) setShowSlither(false) @@ -198,12 +178,13 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { return () => { } }, [props]) - const hintErrors = hints && hints.filter(hint => hint.type === 'error') + const hintErrors = hints.filter(hint => hint.type === 'error') const noLibSlitherWarnings = slitherWarnings.filter(w => !w.options.isLibrary) const slitherErrors = noLibSlitherWarnings.filter(slitherError => slitherError.options.type === 'error') const remixAnalysisNoLibs = ssaWarnings.filter(ssa => ssa.options.isLibrary === false) const remixAnalysisLessWarnings = ssaWarnings.filter(ssa => ssa.options.type !== 'warning') +//#region PreviousCode (message, filterWarnings, showWarnings, handleCheckSingle, categoryItem, categorySection) const message = (name: string, warning: any, more?: string, fileName?: string, locationString?: string) : string => { return (` @@ -238,90 +219,10 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { } } } - if (ssaWarnings.length > 0 && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [ssaWarnings.length]) - setWarningState(newWarningState) - } + props.event.trigger('staticAnaysisWarning', [newWarningCount]) + setWarningState(newWarningState) } - useEffect(() => { - // if hideWarnings is true - if(basicEnabled && hideWarnings && !solhintEnabled && !slitherEnabled && state.data && state.source !== null ) { - props.event.trigger('staticAnaysisWarning', - [hideWarnings ? remixAnalysisLessWarnings.length : remixAnalysisNoLibs.length]) - } - if (solhintEnabled && hideWarnings && !basicEnabled && !slitherEnabled && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [hideWarnings ? hintErrors.length : hints?.length]) - } - if (solhintEnabled && basicEnabled && hideWarnings && !slitherEnabled && !showLibsWarning - && state.data && state.source !== null) { - console.log('solhint and remix are enabled here') - props.event.trigger('staticAnaysisWarning', [hideWarnings - ? hintErrors.length + remixAnalysisNoLibs.filter(x => x.options.type !== 'warning').length : hints?.length + remixAnalysisNoLibs.length]) - } - if (slitherEnabled && hideWarnings && !basicEnabled && !solhintEnabled && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [hideWarnings ? slitherErrors.length : slitherWarnings.length]) - } - if (slitherEnabled && basicEnabled && solhintEnabled && hideWarnings && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [hideWarnings - ? hintErrors.length + remixAnalysisLessWarnings.length + slitherErrors.length - : hints?.length + ssaWarnings.length + slitherWarnings.length]) - } - }, [hideWarnings, state]) - - useEffect(() => { - // if showLibsWarning is true - if(basicEnabled && !solhintEnabled && !slitherEnabled && !hideWarnings && state.data && state.source !== null ) { - props.event.trigger('staticAnaysisWarning', - [showLibsWarning ? ssaWarnings.length : remixAnalysisNoLibs.length]) - } - if (solhintEnabled && !basicEnabled && !slitherEnabled && !hideWarnings && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [showLibsWarning ? hints?.length : hints?.length]) - } - if (solhintEnabled && basicEnabled && !slitherEnabled && !hideWarnings && state.data && state.source !== null && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [showLibsWarning - ? hints?.length + ssaWarnings.length : hints?.length + remixAnalysisNoLibs.length]) - } - if (slitherEnabled && !basicEnabled && !solhintEnabled && !hideWarnings && state.data && state.source !== null && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [showLibsWarning && noLibSlitherWarnings.length]) - } - if (slitherEnabled && basicEnabled && solhintEnabled && !hideWarnings && state.data && state.source !== null && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [showLibsWarning - ? hints?.length + ssaWarnings.length + slitherWarnings.length : hints?.length + remixAnalysisNoLibs.length + noLibSlitherWarnings.length]) - } - }, [showLibsWarning, state]) - - useEffect(() => { - if(basicEnabled && solhintEnabled && !slitherEnabled && !hideWarnings && !showLibsWarning && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [hints?.length + remixAnalysisNoLibs.length]) - } - - if(solhintEnabled && basicEnabled && slitherEnabled && !hideWarnings && !showLibsWarning && state.data && state.source !== null) { - props.analysisModule.hints = [] - props.event.trigger('staticAnaysisWarning', [hints?.length + remixAnalysisNoLibs.length + slitherWarnings.length]) - } - if(solhintEnabled && basicEnabled && !slitherEnabled && hideWarnings && showLibsWarning && state.data && state.source !== null) { - props.event.trigger('staticAnaysisWarning', [hintErrors.length + remixAnalysisLessWarnings.length]) - } - // props.event.trigger('staticAnaysisWarning', [-1]) - }, [ssaWarnings.length, remixAnalysisNoLibs.length, remixAnalysisLessWarnings.length, hints?.length, hintErrors?.length, state, state.data, state.source]) - - useEffect(() => { - if(solhintEnabled === false) { - props.analysisModule.hints = [] - } - }, [solhintEnabled]) - - useEffect(() => { - if(solhintEnabled && basicEnabled) { - if(ssaWarnings.length > 0 && hints.length > 0) { - props.event.trigger('staticAnaysisWarning', [ssaWarnings.length + hints.length]) - } - } - }, [showLibsWarning]) - - - const showWarnings = (warningMessage, groupByKey) => { const resultArray = [] warningMessage.map(x => { @@ -371,32 +272,6 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { } } - const handleSlitherEnabled = async () => { - const checkRemixd = await props.analysisModule.call('manager', 'isActive', 'remixd') - if (showSlither) { - setShowSlither(false) - } - if(!showSlither) { - setShowSlither(true) - } - } - - const handleBasicEnabled = () => { - if (basicEnabled) { - setBasicEnabled(false) - } else { - setBasicEnabled(true) - } - } - - const handleLinterEnabled = () => { - if (solhintEnabled) { - setSolhintEnabled(false) - } else { - setSolhintEnabled(true) - } - } - const handleCheckSingle = (event, _index) => { _index = _index.toString() if (categoryIndex.includes(_index)) { @@ -406,15 +281,6 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { } } - const handleShowLibsWarning = () => { - if (showLibsWarning) { - setShowLibsWarning(false) - } else { - filterWarnings() - setShowLibsWarning(true) - } - } - const categoryItem = (categoryId, item, i) => { return (
@@ -470,6 +336,95 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
) } +//#endregion +// useEffect(() => { +// if(hints.length > 0) { +// props.event.trigger('staticAnaysisWarning', [hints.length]) +// } +// },[hints.length]) + +useEffect(() => { + if(!hideWarnings && !showLibsWarning) { + const slitherTotal = (slitherWarnings && state.data && state.source !== null ? slitherWarnings.filter(x => !x.options.isLibrary && x.hasWarning).length : 0) + const ssaTotal = ssaWarnings && state.data && state.source !== null ? ssaWarnings.filter(x => !x.options.isLibrary && x.hasWarning).length : 0 + const hintsTotal = hints && state.data && state.source !== null ? hints.length : 0 + console.log('hideWarnings & showLibsWarning are unchecked', { slitherTotal, ssaTotal, hintsTotal }) + props.event.trigger('staticAnaysisWarning', [slitherTotal + ssaTotal + hintsTotal]) + } + if(!hideWarnings && showLibsWarning) { + props.event.trigger('staticAnaysisWarning', [ + slitherWarnings.length + + ssaWarnings.length + + hints.length + ]) + } + if(hideWarnings) { + const slitherTotal = (slitherWarnings && state.data && state.source !== null ? slitherWarnings.filter(x => x.options.type === 'error').length : 0) + const ssaTotal = ssaWarnings && state.data && state.source !== null ? ssaWarnings.filter(x => x.options.type === 'error').length : 0 + const hintsTotal = hints && state.data && state.source !== null ? hints.filter(x => x.type === 'error').length : 0 + console.log('hideWarnings is enabled', { slitherTotal, ssaTotal, hintsTotal }) + props.event.trigger('staticAnaysisWarning', [slitherTotal + ssaTotal + hintsTotal]) + } +}, [hideWarnings, showLibsWarning]) + +useEffect(() => { + const slitherTotal = slitherWarnings && state.data && state.source !== null + ? slitherWarnings.filter((x) => !x.options.isLibrary && x.hasWarning).length + : 0 + const ssaTotal = ssaWarnings && state.data && state.source !== null + ? ssaWarnings.filter((x) => !x.options.isLibrary && x.hasWarning).length + : 0 + const hintsTotal = hints && state.data && state.source !== null ? hints.length : 0 + console.log('hideWarnings & showLibsWarning are unchecked and lengths have changed', { slitherTotal, ssaTotal, hintsTotal }) + props.event.trigger('staticAnaysisWarning', [slitherTotal + ssaTotal + hintsTotal]) +}, [hints.length, slitherWarnings.length, ssaWarnings.length]) + +useEffect(() => { + const slitherTotal = slitherWarnings && slitherEnabled && showSlither && state.data && state.source !== null + ? slitherWarnings.filter((x) => !x.options.isLibrary && x.hasWarning).length + : 0 + const ssaTotal = ssaWarnings && basicEnabled && state.data && state.source !== null + ? ssaWarnings.filter((x) => !x.options.isLibrary && x.hasWarning).length + : 0 + const hintsTotal = hints && solhintEnabled && state.data && state.source !== null ? hints.length : 0 + console.log('hideWarnings & showLibsWarning are unchecked and tools could be checked or unchecked', { slitherTotal, ssaTotal, hintsTotal }) + props.event.trigger('staticAnaysisWarning', [slitherTotal + ssaTotal + hintsTotal]) +}, [solhintEnabled, basicEnabled, slitherEnabled, showSlither]) + + const handleSlitherEnabled = async () => { + const checkRemixd = await props.analysisModule.call('manager', 'isActive', 'remixd') + if (showSlither) { + setShowSlither(false) + } + if(!showSlither) { + setShowSlither(true) + } + } + + const handleBasicEnabled = () => { + if (basicEnabled) { + setBasicEnabled(false) + } else { + setBasicEnabled(true) + } + } + + const handleLinterEnabled = () => { + if (solhintEnabled) { + setSolhintEnabled(false) + } else { + setSolhintEnabled(true) + } + } + + const handleShowLibsWarning = () => { + if (showLibsWarning) { + setShowLibsWarning(false) + } else { + setShowLibsWarning(true) + } + filterWarnings() + } const handleHideWarnings = () => { setHideWarnings(!hideWarnings) @@ -480,12 +435,12 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { tabKey: "linter", child: ( <> - {solhintEnabled && hints?.length > 0 ? ( + {hints.length > 0 ? (
{!hideWarnings - ? hints?.map((hint, index) => ( + ? hints.map((hint, index) => (
{ {hint.formattedMessage} + {hint.type}
{`${hint.column}:${hint.line}`}
@@ -568,22 +524,22 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
- ) : state.data && state.file.length > 0 && state.source && startAnalysis && hints?.length > 0 ? Loading... : Nothing to report} + ) : state.data && state.file.length > 0 && state.source && startAnalysis && hints.length > 0 ? Loading... : Nothing to report} ), title: ( - Solhint - {hints && hints?.length > 0 ? ( + Linter + {hints.length > 0 ? ( hideWarnings ? ( - x.type === 'error').length > 0 - ? `badge-danger` : 'badge-warning'} badge-pill px-1 ml-1 text-center`}> + x.type === 'error').length > 0 + ? `badge-danger` : 'badge-warning'} rounded-circle ml-1 text-center`}> {hintErrors.length} ) : ( - x.type === 'error').length > 0 - ? `badge-danger` : 'badge-warning'} badge-pill px-1 ml-1 text-center`}> - {hints?.length} + x.type === 'error').length > 0 + ? `badge-danger` : 'badge-warning'} rounded-circle ml-1 text-center`}> + {hints.length} ) ) : null} @@ -594,26 +550,56 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { tabKey: "basic", title: ( ), child: ( - + <> + {Object.entries(warningState).length > 0 ? ( +
+
+ {Object.entries(warningState).map((element, index) => ( +
+ { + !hideWarnings && !showLibsWarning && ssaWarnings.length > 0 ? ssaWarnings.filter(x => !x.options.isLibrary).map((x, i) => ( +
+ +
+ )) : !hideWarnings && showLibsWarning && ssaWarnings.length > 0 ? ssaWarnings.map((x, i) => ( +
+ +
+ )) : null + } +
+ ))} +
+
+ ) : state.data && state.file.length > 0 && state.source && startAnalysis && Object.entries(warningState).length > 0 ? Loading... : Nothing to report} + ), }, { @@ -621,18 +607,18 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { title: ( Slither - {slitherWarnings && slitherWarnings?.length > 0 ? ( + {slitherWarnings.length > 0 ? ( hideWarnings ? ( - - {slitherErrors?.length} + + {slitherErrors.length} - ) : showLibsWarning === true && hideWarnings === false ? ( - 0 ? `badge-danger` : 'badge-warning'} badge-pill px-1 ml-1 text-center`}> + ) : showLibsWarning && !hideWarnings ? ( + 0 ? `badge-danger` : 'badge-warning'} badge-pill mx-1 ml-1 text-center`}> {slitherWarnings.length} ) : ( - 0 ? `badge-danger` : 'badge-warning'} badge-pill px-1 ml-1 text-center`}> - {noLibSlitherWarnings?.length} + 0 ? `badge-danger` : 'badge-warning'} badge-pill mx-1 ml-1 text-center`}> + {noLibSlitherWarnings.length} ) ) : null} @@ -640,12 +626,12 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { ), child: ( <> - {slitherWarnings?.length > 0 ? ( + {slitherWarnings.length > 0 ? (
{!hideWarnings - ? showLibsWarning ? slitherWarnings && slitherWarnings?.map((warning, index) => ( + ? showLibsWarning ? slitherWarnings.map((warning, index) => (
{ ), }, - ]; + ] const checkBasicStatus = () => { return Object.values(groupedModules).map((value: any) => { @@ -720,8 +706,10 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { return x._index.toString() })) }).flat().every(el => categoryIndex.includes(el))} - onClick={handleBasicEnabled} label="Remix" + onClick={() => { + handleCheckAllModules(groupedModules) + }} onChange={() => {}} tooltipPlacement={'bottom-start'} optionalClassName="mr-3" @@ -730,7 +718,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { { label="Slither" onChange={() => {}} optionalClassName="mr-3" - title={slitherEnabled ? "Slither runs Slither static analysis." : "To run Slither analysis, Remix IDE must be connected to your local filesystem with Remixd."} + title={slitherEnabled ? "Slither runs Slither static analysis" : "To run Slither analysis, Remix IDE must be connected to your local filesystem with Remixd"} />
{state.data && state.file.length > 0 && state.source ?