mirror of
https://github.com/embarklabs/embark.git
synced 2025-01-11 06:16:01 +00:00
Fiddle now showing compilation warnings and errors
This commit is contained in:
parent
52cec0a29e
commit
70f5a09d47
@ -3,6 +3,7 @@ import AceEditor from 'react-ace';
|
||||
import 'brace/mode/javascript';
|
||||
import 'brace/theme/tomorrow_night_blue';
|
||||
import 'ace-mode-solidity/build/remix-ide/mode-solidity';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Fiddle = ({onCodeChange, value}) => {
|
||||
|
||||
@ -23,4 +24,9 @@ const Fiddle = ({onCodeChange, value}) => {
|
||||
);
|
||||
};
|
||||
|
||||
Fiddle.propTypes = {
|
||||
onCodeChange: PropTypes.func,
|
||||
value: PropTypes.string
|
||||
};
|
||||
|
||||
export default Fiddle;
|
||||
|
134
embark-ui/src/components/FiddleResults.js
Normal file
134
embark-ui/src/components/FiddleResults.js
Normal file
@ -0,0 +1,134 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Card, List, Badge} from 'tabler-react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class FiddleResults extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
errors: props.compilationResult.errors
|
||||
};
|
||||
}
|
||||
|
||||
static _removeClass(elems, className){
|
||||
for(let elem of elems) {
|
||||
elem.className = elem.className.replace(className, '').replace(' ', ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static _toggleClass(elems, className){
|
||||
for(let elem of elems) {
|
||||
if(elem.className.indexOf(className) > -1){
|
||||
FiddleResults._removeClass([elem], className);
|
||||
}
|
||||
else{
|
||||
elem.className = (elem.className.length > 0 ? elem.className + ' ' : '') + className;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleCollapse(e) {
|
||||
const collapsedClassName = 'card-collapsed';
|
||||
const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', '');
|
||||
const elems = document.getElementsByClassName(className + '-card');
|
||||
FiddleResults._toggleClass(elems, collapsedClassName);
|
||||
}
|
||||
|
||||
toggleFullscreen(e) {
|
||||
const collapsedClassName = 'card-collapsed';
|
||||
const fullscreenClassName = 'card-fullscreen';
|
||||
const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', '');
|
||||
const elems = document.getElementsByClassName(className + '-card');
|
||||
FiddleResults._toggleClass(elems, fullscreenClassName);
|
||||
FiddleResults._removeClass(elems, collapsedClassName);
|
||||
}
|
||||
|
||||
render(){
|
||||
const warningObjs = this.props.compilationResult.errors.filter(error => {
|
||||
return error.severity === 'warning';
|
||||
});
|
||||
const errorObjs = this.props.compilationResult.errors.filter(error => {
|
||||
return error.severity === 'error';
|
||||
});
|
||||
const warnings = warningObjs.map((warning, index) => {
|
||||
return (
|
||||
<List.GroupItem key={index} action>
|
||||
<Badge color="warning" className="mr-1" key={index}>
|
||||
Lines {warning.sourceLocation.start}-{warning.sourceLocation.end}
|
||||
</Badge>
|
||||
{warning.formattedMessage}
|
||||
</List.GroupItem>
|
||||
);
|
||||
});
|
||||
const errors = errorObjs.map((error, index) => {
|
||||
return (
|
||||
<List.GroupItem key={index} action>
|
||||
<Badge color="danger" className="mr-1" key={index}>
|
||||
Lines {error.sourceLocation.start}-{error.sourceLocation.end}
|
||||
</Badge>
|
||||
{error.formattedMessage}
|
||||
</List.GroupItem>
|
||||
);
|
||||
});
|
||||
const errorsCard = <Card
|
||||
isCollapsible={true}
|
||||
isFullscreenable={true}
|
||||
statusColor="red"
|
||||
statusSide="true"
|
||||
className="errors-card"
|
||||
key="errors">
|
||||
<Card.Header>
|
||||
<Card.Title color="red">Errors <Badge color="danger" className="mr-1">{errors.length}</Badge></Card.Title>
|
||||
<Card.Options className="errors">
|
||||
<Card.OptionsItem key="0" type="collapse" icon="chevron-up" onClick={this.toggleCollapse}/>
|
||||
<Card.OptionsItem key="1" type="fullscreen" icon="maximize" onClick={this.toggleFullscreen}/>
|
||||
</Card.Options>
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
<List.Group>
|
||||
{errors}
|
||||
</List.Group>
|
||||
</Card.Body>
|
||||
</Card>;
|
||||
const warningsCard = <Card
|
||||
isCollapsible={true}
|
||||
isFullscreenable={true}
|
||||
statusColor="warning"
|
||||
statusSide="true"
|
||||
className="warnings-card"
|
||||
key="warnings">
|
||||
<Card.Header>
|
||||
<Card.Title color="warning">Warnings <Badge color="warning" className="mr-1">{warnings.length}</Badge></Card.Title>
|
||||
<Card.Options className="warnings">
|
||||
<Card.OptionsItem key="0" type="collapse" icon="chevron-up" onClick={this.toggleCollapse}/>
|
||||
<Card.OptionsItem key="1" type="fullscreen" icon="maximize" onClick={this.toggleFullscreen}/>
|
||||
</Card.Options>
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
<List.Group>
|
||||
{warnings}
|
||||
</List.Group>
|
||||
</Card.Body>
|
||||
</Card>;
|
||||
|
||||
let renderings = [];
|
||||
if(!this.state.errors){
|
||||
return 'Compilation successful (add green tick mark)';
|
||||
}
|
||||
if(errors.length) renderings.push(errorsCard);
|
||||
if(warnings.length) renderings.push(warningsCard);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{renderings}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FiddleResults.propTypes = {
|
||||
compilationResult: PropTypes.object
|
||||
};
|
||||
|
||||
export default FiddleResults;
|
@ -1,29 +1,49 @@
|
||||
/* eslint multiline-ternary: "off" */
|
||||
/* eslint operator-linebreak: "off" */
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {fetchCodeCompilation} from '../actions';
|
||||
import Fiddle from '../components/Fiddle';
|
||||
import FiddleResults from '../components/FiddleResults';
|
||||
|
||||
class FiddleContainer extends Component {
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = { value: ''};
|
||||
super(props);
|
||||
this.state = {
|
||||
value: ''
|
||||
};
|
||||
this.compileTimeout = null;
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
if(this.state.value){
|
||||
this.props.fetchCodeCompilation(this.state.value);
|
||||
}
|
||||
}
|
||||
|
||||
onCodeChange(newValue) {
|
||||
this.setState({value: newValue});
|
||||
this.props.fetchCodeCompilation(newValue);
|
||||
if(this.compileTimeout) clearTimeout(this.compileTimeout);
|
||||
this.compileTimeout = setTimeout(() => {
|
||||
this.props.fetchCodeCompilation(newValue);
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fiddles } = this.props;
|
||||
|
||||
const {fiddles} = this.props;
|
||||
|
||||
let renderings = [<Fiddle key="0" value={this.state.value} onCodeChange={(n) => this.onCodeChange(n)} />];
|
||||
if(fiddles.compilationResult) {
|
||||
renderings.push(<FiddleResults key="1" compilationResult={fiddles.compilationResult}/>);
|
||||
}
|
||||
else renderings.push('Nothing to compile');
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Fiddle value={this.state.value} onCodeChange={(n) => this.onCodeChange(n)} />
|
||||
<h2>Result</h2>
|
||||
<p>{ fiddles.data ? JSON.stringify(fiddles.data) : 'No compilation results yet'}</p>
|
||||
<React.Fragment>
|
||||
{renderings}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -24,3 +24,6 @@
|
||||
.text__new-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
.card.card-fullscreen{
|
||||
z-index:4;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import {RECEIVE_COMPILE_CODE, RECEIVE_COMPILE_CODE_ERROR} from "../actions";
|
||||
export default function processes(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case RECEIVE_COMPILE_CODE:
|
||||
return Object.assign({}, state, {data: action.compilationResult});
|
||||
return Object.assign({}, state, {compilationResult: action.compilationResult});
|
||||
case RECEIVE_COMPILE_CODE_ERROR:
|
||||
return Object.assign({}, state, {error: true});
|
||||
default:
|
||||
|
@ -157,16 +157,19 @@ export function *watchCommunicationVersion() {
|
||||
yield takeEvery(actions.MESSAGE_VERSION[actions.REQUEST], fetchCommunicationVersion);
|
||||
}
|
||||
|
||||
export function* fetchCodeCompilation(action) {
|
||||
export function *fetchCodeCompilation(action) {
|
||||
try {
|
||||
const codeCompilationResult = yield call(api.fetchCodeCompilation, action.codeToCompile);
|
||||
yield put(actions.receiveCodeCompilation(codeCompilationResult));
|
||||
const compilationResponse = yield call(api.fetchCodeCompilation, action.codeToCompile);
|
||||
if(compilationResponse.status !== 200){
|
||||
yield put(actions.receiveCodeCompilationError(compilationResponse.data));
|
||||
}
|
||||
else yield put(actions.receiveCodeCompilation(compilationResponse.data));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveCodeCompilationError(e));
|
||||
}
|
||||
}
|
||||
|
||||
export function* watchFetchCodeCompilation() {
|
||||
export function *watchFetchCodeCompilation() {
|
||||
yield takeEvery(actions.FETCH_COMPILE_CODE, fetchCodeCompilation);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Solidity {
|
||||
|
||||
this.events.setCommandHandler("contract:compile", (contractCode, cb) => {
|
||||
const input = {'fiddler': {content: contractCode.replace(/\r\n/g, '\n')}};
|
||||
this.compile_solidity_code(input, {}, cb);
|
||||
this.compile_solidity_code(input, {}, true, cb);
|
||||
});
|
||||
|
||||
embark.registerAPICall(
|
||||
@ -26,15 +26,38 @@ class Solidity {
|
||||
'/embark-api/contract/compile',
|
||||
(req, res) => {
|
||||
console.log('=====> POST contract/compile, req = ' + JSON.stringify(req.body));
|
||||
this.events.request("contract:compile", req.body.code, (error, compilationResult) => {
|
||||
console.log('=====> POST contract/compile, result = ' + JSON.stringify(compilationResult));
|
||||
res.send(JSON.stringify({compilationResult}));
|
||||
this.events.request("contract:compile", req.body.code, (errors, compilationResult) => {
|
||||
console.log('=====> POST contract/compile, errors = ' + JSON.stringify(errors));
|
||||
console.log('=====> POST contract/compile, compilationResult = ' + JSON.stringify(compilationResult));
|
||||
res.send({errors:errors, compilationResult: compilationResult});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
compile_solidity_code(codeInputs, originalFilepaths, cb){
|
||||
_compile(jsonObj, returnAllErrors, callback){
|
||||
this.solcW.compile(jsonObj, (err, output) => {
|
||||
if(err){
|
||||
return callback(err);
|
||||
}
|
||||
if(output.errors && returnAllErrors){
|
||||
return callback(output.errors);
|
||||
}
|
||||
if (output.errors) {
|
||||
for (let i=0; i<output.errors.length; i++) {
|
||||
if (output.errors[i].type === 'Warning') {
|
||||
this.logger.warn(output.errors[i].formattedMessage);
|
||||
}
|
||||
if (output.errors[i].type === 'Error' || output.errors[i].severity === 'error') {
|
||||
return callback(new Error("Solidity errors: " + output.errors[i].formattedMessage).message);
|
||||
}
|
||||
}
|
||||
}
|
||||
callback(null, output);
|
||||
});
|
||||
}
|
||||
|
||||
compile_solidity_code(codeInputs, originalFilepaths, returnAllErrors, cb){
|
||||
const self = this;
|
||||
|
||||
async.waterfall([
|
||||
@ -204,7 +227,7 @@ class Solidity {
|
||||
);
|
||||
},
|
||||
function compile(callback) {
|
||||
self.compile_solidity_code(input, originalFilepath, callback);
|
||||
self.compile_solidity_code(input, originalFilepath, false, callback);
|
||||
}
|
||||
], function (err, result) {
|
||||
cb(err, result);
|
||||
|
Loading…
x
Reference in New Issue
Block a user