Merge pull request #3838 from ethereum/ssa-qa-fixes

Ssa Qa Fixes
0.34.0
yann300 1 year ago committed by GitHub
commit bd494e84f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      apps/remix-ide-e2e/src/tests/staticAnalysis.test.ts
  2. 14
      apps/remix-ide/src/app/tabs/analysis-tab.js
  3. 8
      apps/solhint/src/app/SolhintPluginClient.ts
  4. 12
      libs/remix-ui/static-analyser/src/lib/actions/staticAnalysisActions.ts
  5. 21
      libs/remix-ui/static-analyser/src/lib/components/BasicTitle.tsx
  6. 10
      libs/remix-ui/static-analyser/src/lib/reducers/staticAnalysisReducer.ts
  7. 1262
      libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx
  8. 46
      libs/remix-ui/static-analyser/src/staticanalyser.d.ts
  9. 38
      libs/remix-ui/vertical-icons-panel/src/lib/components/Badge.tsx

@ -11,7 +11,7 @@ contract test1 { address test = tx.origin; }
contract test2 {}
contract TooMuchGas {
uint x;
fallback() external {
fallback() external {
x++;
uint test;
uint test1;
@ -43,18 +43,18 @@ module.exports = {
.click('*[id="staticAnalysisRunBtn"]')
.waitForElementPresent('#staticanalysisresult .warning', 5000)
// Check warning count
.click('*[data-rb-event-key="basic"]')
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '1')
.click('*[data-rb-event-key="remix"]')
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount"]', '1')
.verify.elementPresent('input[name="showLibWarnings"]')
.verify.not.elementPresent('input[name="showLibWarnings"]:checked')
.verify.elementPresent('label[id="headingshowLibWarnings"]')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.click('*[data-rb-event-key="basic"]')
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '382')
.click('*[data-rb-event-key="remix"]')
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount', '382')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '1')
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount', '1')
.end()
}
}

@ -37,6 +37,7 @@ class AnalysisTab extends ViewPlugin {
'offsettolinecolumnconverter').api
}
this.dispatch = null
this.hints = []
}
async onActivation () {
@ -47,10 +48,19 @@ class AnalysisTab extends ViewPlugin {
}
this.event.register('staticAnaysisWarning', (count) => {
let payloadType = ''
const error = this.hints.find(hint => hint.type === 'error')
const warning = this.hints.find(hints => hints.type === 'warning')
if (error) {
payloadType = 'error'
} else {
payloadType = 'warning'
}
if (count > 0) {
this.emit('statusChanged', { key: count, title: `${count} warning${count === 1 ? '' : 's'}`, type: 'warning' })
this.emit('statusChanged', { key: count, title: payloadType === 'error' ? `You have some problem${count === 1 ? '' : 's'}` : 'You have some warnings', type: payloadType })
} else if (count === 0) {
this.emit('statusChanged', { key: 'succeed', title: 'no warning', type: 'success' })
this.emit('statusChanged', { key: 'succeed', title: 'no warnings or errors', type: 'success' })
} else {
// count ==-1 no compilation result
this.emit('statusChanged', { key: 'none' })

@ -85,10 +85,14 @@ export class SolHint extends PluginClient {
const reports: Array<Report> = reporters.reports
const hints = reports.map((report: Report) => {
return {
formattedMessage: `${report.message}\n${report.fix ? report.fix : ''}`,
formattedMessage: `${report.message}\n ${report.fix ? report.fix : ''}`,
type: this.severity[report.severity] || 'error',
column: report.column,
line: report.line - 1
line: report.line - 1,
message: report.message,
ruleId: report.ruleId,
severity: report.severity,
fix: report.fix
}
})

@ -44,24 +44,22 @@ export const compilation = (analysisModule: AnalysisTab,
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function run (lastCompilationResult, lastCompilationSource, currentFile: string, state: RemixUiStaticAnalyserState, props: RemixUiStaticAnalyserProps, isSupportedVersion, showSlither, categoryIndex: number[], groupedModules, runner, _paq, message, showWarnings, allWarnings: React.RefObject<any>, warningContainer: React.RefObject<any>, calculateWarningStateEntries: (e:[string, any][]) => {length: number, errors: any[] }, warningState, setHints: React.Dispatch<React.SetStateAction<SolHintReport[]>>, hints: SolHintReport[], setSlitherWarnings: React.Dispatch<React.SetStateAction<any[]>>, setSsaWarnings: React.Dispatch<React.SetStateAction<any[]>>,
slitherEnabled: boolean, setStartAnalysis: React.Dispatch<React.SetStateAction<boolean>>) {
slitherEnabled: boolean, setStartAnalysis: React.Dispatch<React.SetStateAction<boolean>>, solhintEnabled: boolean, basicEnabled: boolean) {
setStartAnalysis(true)
setHints([])
setSsaWarnings([])
setSlitherWarnings([])
if (!isSupportedVersion) return
if (state.data !== null) {
if (lastCompilationResult && (categoryIndex.length > 0 || showSlither)) {
if (lastCompilationResult && (solhintEnabled || basicEnabled || showSlither)) {
const warningMessage = []
const warningErrors = []
props.analysisModule.hints = []
// Run solhint
_paq.push(['trackEvent', 'solidityStaticAnalyzer', 'analyze', 'solHint'])
const hintsResult = await props.analysisModule.call('solhint', 'lint', state.file)
props.analysisModule.hints = solhintEnabled === false ? 0 : hintsResult
setHints(hintsResult)
const warningResult = calculateWarningStateEntries(Object.entries(warningState))
props.analysisModule.emit('statusChanged', { key: hints.length+warningResult.length,
title: `${hints.length+warningResult.length} warning${hints.length+warningResult.length === 1 ? '' : 's'}`, type: 'warning'})
// Remix Analysis
_paq.push(['trackEvent', 'solidityStaticAnalyzer', 'analyze', 'remixAnalyzer'])
const results = runner.run(lastCompilationResult, categoryIndex)

@ -1,9 +1,11 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import { ErrorRendererOptions } from '../../staticanalyser'
type BasicTitleProps = {
warningStateEntries: any
ssaWarnings: any[]
hideWarnings?: boolean
showLibsWarnings?: boolean
}
type warningResultOption = {
@ -30,15 +32,22 @@ export function calculateWarningStateEntries(entries: [string, any][]) {
}
export function BasicTitle(props: BasicTitleProps) {
const [filteredTotal, setFilteredTotal] = useState(0)
useEffect(() => {
setFilteredTotal(props.ssaWarnings.filter(x => !x.options.isLibrary && x.hasWarning).length)
}, [props, props.ssaWarnings.filter(x => !x.options.isLibrary && x.hasWarning).length])
return (
<span>Remix{props.warningStateEntries.length > 0 ? !props.hideWarnings ? <i data-id="StaticAnalysisErrorCount" className={`badge ${calculateWarningStateEntries(props.warningStateEntries).length > 0 ? 'badge-warning' : 'badge-danger'} rounded-circle ml-1 text-center`}>{calculateWarningStateEntries(props.warningStateEntries).length}</i>: (
<i className="badge badge-warning rounded-circle ml-1 text-center">
<span id="ssaRemixtab">Remix{props.ssaWarnings.length > 0 ? !props.hideWarnings ? !props.showLibsWarnings ? <span data-id="RemixStaticAnalysisErrorCount" className={`badge ${props.ssaWarnings.filter(x => x.hasWarning).length > 0 ? 'badge-warning' : props.ssaWarnings.filter(x => x.options.type === 'errors').length > 0 ? 'badge-danger' : 'badge-info'} badge-pill mx-1 ml-1 text-center`}>
{filteredTotal}
</span>: (
<span data-id="RemixStaticAnalysisErrorCount" className={`badge ${props.ssaWarnings.filter(x => x.options.type !== 'warning' && x.options.type !== 'error').length > 0 ? 'badge-info' : props.ssaWarnings.filter(x => x.options.type === 'errors').length > 0 ? 'badge-danger' : 'badge-warning'} badge-pill mx-1 ml-1 text-center`}>
{
calculateWarningStateEntries(props.warningStateEntries).errors.length
props.ssaWarnings.length
}
</i>
) : null}
</span>
) : null : null}
</span>
)
}

@ -1,3 +1,4 @@
import { CompilationResult, SourceWithTarget } from "@remixproject/plugin-api"
import { RemixUiStaticAnalyserReducerActionType, RemixUiStaticAnalyserState } from "../../staticanalyser"
export const initialState: RemixUiStaticAnalyserState = {
@ -26,3 +27,12 @@ export const analysisReducer = (state: RemixUiStaticAnalyserState,
return initialState
}
}
type someReducerState = {
solhintEnabled?: boolean
basicEnabled?: boolean
slitherEnabled?: boolean
isSupportedVersion?: boolean
compiledState?: { data: CompilationResult, langVersion: string, fileName: string, source: SourceWithTarget, input: string }
}

@ -4,21 +4,29 @@ import { ViewPlugin } from '@remixproject/engine-web';
import { EventEmitter } from 'events';
import Registry from '../state/registry';
export declare class AnalysisTab extends ViewPlugin {
event: EventManager;
events: EventEmitter;
registry: Registry;
element: HTMLDivElement;
_components: any;
_deps: {
offsetToLineColumnConverter: any;
};
dispatch: any;
constructor();
onActivation(): Promise<void>;
setDispatch(dispatch: any): void;
render(): JSX.Element;
updateComponent(state: any): JSX.Element;
renderComponent(): void;
event: EventManager;
events: EventEmitter;
hints: {
formattedMessage: string;
type: any;
column: number;
line: number;
}[]
internalCount: number
registry: Registry;
element: HTMLDivElement;
_components: any;
_deps: {
offsetToLineColumnConverter: any;
};
dispatch: any;
constructor();
onActivation(): Promise<void>;
changedStatus(payload: any[]): Promise<void>;
setDispatch(dispatch: any): void;
render(): JSX.Element;
updateComponent(state: any): JSX.Element;
renderComponent(): void;
}
type RemixUiStaticAnalyserState = {
@ -51,10 +59,10 @@ type RemixUiStaticAnalyserReducerActionType = {
interface ErrorRendererProps {
message: any;
opt: ErrorRendererOptions,
warningErrors: any
options: ErrorRendererOptions,
hasWarning: boolean,
editor: any,
name: string,
warningModuleName: string,
}
type ErrorRendererOptions = {
@ -135,4 +143,4 @@ export type SlitherAnalysisResults = {
count: number,
data: SlitherAnalysisResultType[]
status: boolean
}
}

@ -48,18 +48,32 @@ function Badge ({ badgeStatus }: BadgeProps) {
return (
<>
{
badgeStatus && checkStatusKeyValue(badgeStatus.key, badgeStatus.type) ? (
<i
className={`${resolveClasses(badgeStatus.key, badgeStatus.type!)}`}
aria-hidden="true"
>
{ badgeStatus.pluginName && badgeStatus.pluginName === 'solidityStaticAnalysis' ? badgeStatus.type === 'warning' || badgeStatus.type === 'error' ? <span>
<i className="far fa-exclamation-triangle"></i></span>
: <span>&nbsp;</span> : badgeStatus.text }
</i>
) : null
}
{badgeStatus && checkStatusKeyValue(badgeStatus.key, badgeStatus.type) ? (
<CustomTooltip
placement={"right"}
tooltipClasses="text-nowrap"
tooltipId="verticalItemsbadge"
tooltipText={badgeStatus.title}
>
<i
className={`${resolveClasses(badgeStatus.key, badgeStatus.type!)}`}
aria-hidden="true"
>
{badgeStatus.pluginName &&
badgeStatus.pluginName === "solidityStaticAnalysis" ? (
badgeStatus.type === "warning" || badgeStatus.type === "error" || badgeStatus.type === "danger" ? (
<span>
<i className="far fa-exclamation-triangle"></i>
</span>
) : (
<span>&nbsp;</span>
)
) : (
badgeStatus.text
)}
</i>
</CustomTooltip>
) : null}
</>
)
}

Loading…
Cancel
Save