Skip to content

Commit 3a3cad8

Browse files
authored
preserve-comments (#40)
* something working !?! * Use comment.raw property instead of value * Simplify locStart and locEnd * Simplify printComment * Update snapshots * Remove unused properties from parsed comments * Fix linter errors * moar eslint * add Franco Victorio as contributor * v1.0.0-alpha.4 * update clean
1 parent 78f5dc1 commit 3a3cad8

8 files changed

Lines changed: 154 additions & 13 deletions

File tree

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "prettier-plugin-solidity",
3-
"version": "1.0.0-alpha.3",
3+
"version": "1.0.0-alpha.4",
44
"description": "prettier plugin for solidity",
55
"main": "src",
66
"scripts": {
@@ -33,6 +33,10 @@
3333
{
3434
"email": "[email protected]",
3535
"name": "Jed Fox"
36+
},
37+
{
38+
"email": "[email protected]",
39+
"name": "Franco Victorio"
3640
}
3741
],
3842
"license": "MIT",
@@ -51,6 +55,7 @@
5155
"jest-watch-typeahead": "^0.2.0"
5256
},
5357
"dependencies": {
58+
"extract-comments": "^1.0.0",
5459
"prettier": "^1.14.2",
5560
"solidity-parser-antlr": "^0.3.1"
5661
}

src/clean.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// eslint-disable-next-line no-unused-vars
22
const clean = (ast, newObj, parent) => {
3-
['loc', 'range'].forEach(name => {
3+
['code', 'codeStart', 'loc', 'range'].forEach(name => {
44
delete newObj[name]; // eslint-disable-line no-param-reassign
55
});
66
};

src/index.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,38 @@ const languages = [
1515
const parsers = {
1616
'solidity-parse': {
1717
astFormat: 'solidity-ast',
18+
locEnd: node => node.range[1],
19+
locStart: node => node.range[0],
1820
parse
1921
}
2022
};
2123

24+
function canAttachComment(node) {
25+
return (
26+
node.type && node.type !== 'BlockComment' && node.type !== 'LineComment'
27+
);
28+
}
29+
30+
function printComment(commentPath) {
31+
const comment = commentPath.getValue();
32+
switch (comment.type) {
33+
case 'BlockComment': {
34+
return `/*${comment.raw}*/`;
35+
}
36+
case 'LineComment':
37+
return `//${comment.raw.trimRight()}`;
38+
default:
39+
throw new Error(`Not a comment: ${JSON.stringify(comment)}`);
40+
}
41+
}
42+
2243
// https://prettier.io/docs/en/plugins.html#printers
2344
const printers = {
2445
'solidity-ast': {
46+
canAttachComment,
47+
massageAstNode,
2548
print,
26-
massageAstNode
49+
printComment
2750
}
2851
};
2952

src/parser.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
const extract = require('extract-comments');
12
// https://prettier.io/docs/en/plugins.html#parsers
23
const parser = require('solidity-parser-antlr');
34

4-
const parse = text => parser.parse(text, { loc: true, range: true });
5+
const parse = text => {
6+
const parsed = parser.parse(text, { loc: true, range: true });
7+
parsed.comments = extract(text);
8+
return parsed;
9+
};
510

611
module.exports = parse;

src/printer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ function genericPrint(path, options, print) {
427427
// @TODO
428428
return '';
429429
default:
430-
throw new Error(`unknown type: ${JSON.stringify(node.type)}`);
430+
throw new Error(`Unknown type: ${JSON.stringify(node.type)}`);
431431
}
432432
}
433433

tests/BasicIterator/__snapshots__/jsfmt.spec.js.snap

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,26 @@ contract BasicIterator {
4646
}
4747
}
4848
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49+
/*
50+
This is a very simple demonstration of a while loops. Same as JS/c.
51+
*/
52+
4953
5054
contract BasicIterator {
51-
address creator;
52-
uint8[10] integers;
55+
address creator; // reserve one "address"-type spot
56+
uint8[10] integers; // reserve a chunk of storage for 10 8-bit unsigned integers in an array
5357
5458
function BasicIterator() {
55-
creator = msg.sender;
56-
uint8 x = 0;
57-
while (x < integers.length) {
58-
integers[x] = x;
59+
creator = msg.sender; // set the creator address
60+
uint8 x = 0; // initialize an 8-bit, unsigned integer to zero
61+
while (x < integers.length) { // the variable integers was initialized to length 10
62+
integers[x] = x; // set integers to [0,1,2,3,4,5,6,7,8,9] over ten iterations
5963
x++;
6064
}
6165
}
6266
63-
function getSum() constant returns(uint) {
67+
function getSum() constant returns(uint) { // "constant" just means this function returns something to the caller
68+
// which is immediately followed by what type gets returned, in this case a full uint256
6469
uint8 sum = 0;
6570
uint8 x = 0;
6671
while (x < integers.length) {
@@ -69,10 +74,14 @@ contract BasicIterator {
6974
}
7075
return sum;
7176
}
77+
/**********
78+
Standard kill() function to recover funds
79+
**********/
80+
7281
7382
function kill() {
7483
if (msg.sender == creator) {
75-
suicide(creator);
84+
suicide(creator); // kills this contract and sends remaining funds back to creator
7685
}
7786
}
7887
}

tests/SimpleAuction/__snapshots__/jsfmt.spec.js.snap

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,48 +128,105 @@ contract SimpleAuction {
128128
pragma solidity ^0.4.22;
129129
130130
contract SimpleAuction {
131+
// Parameters of the auction. Times are either
132+
// absolute unix timestamps (seconds since 1970-01-01)
133+
// or time periods in seconds.
131134
address public beneficiary;
132135
uint public auctionEnd;
136+
// Current state of the auction.
133137
address public highestBidder;
134138
uint public highestBid;
139+
// Allowed withdrawals of previous bids
135140
mapping(address => uint) pendingReturns;
141+
// Set to true at the end, disallows any change
136142
bool ended;
143+
// Events that will be fired on changes.
137144
event HighestBidIncreased(address bidder, uint amount);
138145
event AuctionEnded(address winner, uint amount);
146+
// The following is a so-called natspec comment,
147+
// recognizable by the three slashes.
148+
// It will be shown when the user is asked to
149+
// confirm a transaction.
150+
151+
/// Create a simple auction with \`_biddingTime\`
152+
/// seconds bidding time on behalf of the
153+
/// beneficiary address \`_beneficiary\`.
139154
140155
constructor(uint _biddingTime, address _beneficiary) public {
141156
beneficiary = _beneficiary;
142157
auctionEnd = now + _biddingTime;
143158
}
159+
/// Bid on the auction with the value sent
160+
/// together with this transaction.
161+
/// The value will only be refunded if the
162+
/// auction is not won.
144163
145164
function bid() public payable {
165+
// No arguments are necessary, all
166+
// information is already part of
167+
// the transaction. The keyword payable
168+
// is required for the function to
169+
// be able to receive Ether.
170+
171+
// Revert the call if the bidding
172+
// period is over.
146173
require(now <= auctionEnd, "Auction already ended.");
174+
// If the bid is not higher, send the
175+
// money back.
147176
require(msg.value > highestBid, "There already is a higher bid.");
148177
if (highestBid != 0) {
178+
// Sending back the money by simply using
179+
// highestBidder.send(highestBid) is a security risk
180+
// because it could execute an untrusted contract.
181+
// It is always safer to let the recipients
182+
// withdraw their money themselves.
149183
pendingReturns[highestBidder] += highestBid;
150184
}
151185
highestBidder = msg.sender;
152186
highestBid = msg.value;
153187
emit HighestBidIncreased(msg.sender, msg.value);
154188
}
189+
/// Withdraw a bid that was overbid.
155190
156191
function withdraw() public returns(bool) {
157192
uint amount = pendingReturns[msg.sender];
158193
if (amount > 0) {
194+
// It is important to set this to zero because the recipient
195+
// can call this function again as part of the receiving call
196+
// before \`send\` returns.
159197
pendingReturns[msg.sender] = 0;
160198
if (!msg.sender.send(amount)) {
199+
// No need to call throw here, just reset the amount owing
161200
pendingReturns[msg.sender] = amount;
162201
return false;
163202
}
164203
}
165204
return true;
166205
}
206+
/// End the auction and send the highest bid
207+
/// to the beneficiary.
167208
168209
function auctionEnd() public {
210+
// It is a good guideline to structure functions that interact
211+
// with other contracts (i.e. they call functions or send Ether)
212+
// into three phases:
213+
// 1. checking conditions
214+
// 2. performing actions (potentially changing conditions)
215+
// 3. interacting with other contracts
216+
// If these phases are mixed up, the other contract could call
217+
// back into the current contract and modify the state or cause
218+
// effects (ether payout) to be performed multiple times.
219+
// If functions called internally include interaction with external
220+
// contracts, they also have to be considered interaction with
221+
// external contracts.
222+
223+
// 1. Conditions
169224
require(now >= auctionEnd, "Auction not yet ended.");
170225
require(!ended, "auctionEnd has already been called.");
226+
// 2. Effects
171227
ended = true;
172228
emit AuctionEnded(highestBidder, highestBid);
229+
// 3. Interaction
173230
beneficiary.transfer(highestBid);
174231
}
175232
}

tests/__snapshots__/jsfmt.spec.js.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ contract Inbox {
2525
}
2626
2727
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28+
// This comment spans one line
29+
30+
/*
31+
This
32+
comment
33+
spans
34+
multiple
35+
lines.
36+
*/
37+
2838
pragma solidity ^0.4.23;
2939
3040
contract Inbox {
@@ -119,6 +129,11 @@ contract Ownable {
119129
}
120130
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121131
pragma solidity ^0.4.24;
132+
/**
133+
* @title Ownable
134+
* @dev The Ownable contract has an owner address, and provides basic authorization control
135+
* functions, this simplifies the implementation of "user permissions".
136+
*/
122137
123138
contract Ownable {
124139
address private _owner;
@@ -127,31 +142,58 @@ contract Ownable {
127142
address indexed previousOwner,
128143
address indexed newOwner
129144
);
145+
/**
146+
* @dev The Ownable constructor sets the original \`owner\` of the contract to the sender
147+
* account.
148+
*/
130149
131150
constructor() public {
132151
_owner = msg.sender;
133152
}
153+
/**
154+
* @return the address of the owner.
155+
*/
134156
135157
function owner() public view returns(address) {
136158
return _owner;
137159
}
160+
/**
161+
* @dev Throws if called by any account other than the owner.
162+
*/
138163
modifier onlyOwner() {
139164
require(isOwner());
140165
_;
141166
}
167+
/**
168+
* @return true if \`msg.sender\` is the owner of the contract.
169+
*/
142170
143171
function isOwner() public view returns(bool) {
144172
return msg.sender == _owner;
145173
}
174+
/**
175+
* @dev Allows the current owner to relinquish control of the contract.
176+
* @notice Renouncing to ownership will leave the contract without an owner.
177+
* It will not be possible to call the functions with the \`onlyOwner\`
178+
* modifier anymore.
179+
*/
146180
147181
function renounceOwnership() public onlyOwner {
148182
emit OwnershipRenounced(_owner);
149183
_owner = address(0);
150184
}
185+
/**
186+
* @dev Allows the current owner to transfer control of the contract to a newOwner.
187+
* @param newOwner The address to transfer ownership to.
188+
*/
151189
152190
function transferOwnership(address newOwner) public onlyOwner {
153191
_transferOwnership(newOwner);
154192
}
193+
/**
194+
* @dev Transfers control of the contract to a newOwner.
195+
* @param newOwner The address to transfer ownership to.
196+
*/
155197
156198
function _transferOwnership(address newOwner) internal {
157199
require(newOwner != address(0));

0 commit comments

Comments
 (0)