commit
382ac8ecaa
@ -0,0 +1,84 @@ |
|||||||
|
'use strict' |
||||||
|
|
||||||
|
import { NightwatchBrowser } from 'nightwatch' |
||||||
|
import init from '../helpers/init' |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
|
||||||
|
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
||||||
|
init(browser, done, 'http://127.0.0.1:8080', true) |
||||||
|
}, |
||||||
|
'Should add error marker': function (browser: NightwatchBrowser) { |
||||||
|
browser |
||||||
|
.openFile('contracts') |
||||||
|
.openFile('contracts/1_Storage.sol') |
||||||
|
.addFile('scripts/adderror.ts', {content: addErrorMarker}) |
||||||
|
.pause(4000) |
||||||
|
.executeScriptInTerminal('remix.exeCurrent()') |
||||||
|
.pause(4000) |
||||||
|
.openFile('contracts/1_Storage.sol') |
||||||
|
.useXpath() |
||||||
|
.waitForElementVisible("//*[@class='cdr squiggly-error']") |
||||||
|
.waitForElementVisible("//*[@class='cdr squiggly-warning']") |
||||||
|
}, |
||||||
|
'Should clear error marker': function (browser: NightwatchBrowser) { |
||||||
|
browser
|
||||||
|
.useCss() |
||||||
|
.addFile('scripts/clear.ts', {content: clearMarkers}) |
||||||
|
.pause(4000) |
||||||
|
.executeScriptInTerminal('remix.exeCurrent()') |
||||||
|
.pause(4000) |
||||||
|
.openFile('contracts/1_Storage.sol') |
||||||
|
.useXpath() |
||||||
|
.waitForElementNotPresent("//*[@class='cdr squiggly-error']") |
||||||
|
.waitForElementNotPresent("//*[@class='cdr squiggly-warning']") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const clearMarkers =` |
||||||
|
(async () => { |
||||||
|
await remix.call('editor', 'clearErrorMarkers' as any, ['contracts/1_Storage.sol']) |
||||||
|
})()` |
||||||
|
|
||||||
|
const addErrorMarker = ` |
||||||
|
(async () => { |
||||||
|
|
||||||
|
|
||||||
|
let errors = [ |
||||||
|
{ |
||||||
|
position: { |
||||||
|
start: { |
||||||
|
line: 10, |
||||||
|
column: 1, |
||||||
|
}, |
||||||
|
end: { |
||||||
|
line: 10, |
||||||
|
column: 10 |
||||||
|
} |
||||||
|
}, |
||||||
|
message: 'testing', |
||||||
|
severity: 'error', |
||||||
|
file: 'contracts/1_Storage.sol' |
||||||
|
}, |
||||||
|
{ |
||||||
|
position: { |
||||||
|
start: { |
||||||
|
line: 18, |
||||||
|
column: 1, |
||||||
|
}, |
||||||
|
end: { |
||||||
|
line: 18, |
||||||
|
column: 10 |
||||||
|
} |
||||||
|
}, |
||||||
|
message: 'testing2', |
||||||
|
severity: 'warning', |
||||||
|
file: 'contracts/1_Storage.sol' |
||||||
|
}, |
||||||
|
] |
||||||
|
|
||||||
|
|
||||||
|
await remix.call('editor', 'addErrorMarker' as any, errors) |
||||||
|
|
||||||
|
|
||||||
|
})()` |
@ -1,75 +0,0 @@ |
|||||||
'use strict' |
|
||||||
import { Plugin } from '@remixproject/engine' |
|
||||||
import * as packageJson from '../../../../package.json' |
|
||||||
import { sourceMappingDecoder } from '@remix-project/remix-debug' |
|
||||||
|
|
||||||
const profile = { |
|
||||||
name: 'offsetToLineColumnConverter', |
|
||||||
methods: ['offsetToLineColumn'], |
|
||||||
events: [], |
|
||||||
version: packageJson.version |
|
||||||
} |
|
||||||
|
|
||||||
export class OffsetToLineColumnConverter extends Plugin { |
|
||||||
constructor () { |
|
||||||
super(profile) |
|
||||||
this.lineBreakPositionsByContent = {} |
|
||||||
this.sourceMappingDecoder = sourceMappingDecoder |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Convert offset representation with line/column representation. |
|
||||||
* This is also used to resolve the content: |
|
||||||
* @arg file is the index of the file in the content sources array and content sources array does have filename as key and not index. |
|
||||||
* So we use the asts (which references both index and filename) to look up the actual content targeted by the @arg file index. |
|
||||||
* @param {{start, length}} rawLocation - offset location |
|
||||||
* @param {number} file - The index where to find the source in the sources parameters |
|
||||||
* @param {Object.<string, {content}>} sources - Map of content sources |
|
||||||
* @param {Object.<string, {ast, id}>} asts - Map of content sources |
|
||||||
*/ |
|
||||||
offsetToLineColumn (rawLocation, file, sources, asts) { |
|
||||||
if (!this.lineBreakPositionsByContent[file]) { |
|
||||||
const sourcesArray = Object.keys(sources) |
|
||||||
if (!asts || (file === 0 && sourcesArray.length === 1)) { |
|
||||||
// if we don't have ast, we process the only one available content (applicable also for compiler older than 0.4.12)
|
|
||||||
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[sourcesArray[0]].content) |
|
||||||
} else { |
|
||||||
for (var filename in asts) { |
|
||||||
const source = asts[filename] |
|
||||||
if (source.id === file) { |
|
||||||
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Convert offset representation with line/column representation. |
|
||||||
* @param {{start, length}} rawLocation - offset location |
|
||||||
* @param {number} file - The index where to find the source in the sources parameters |
|
||||||
* @param {string} content - source |
|
||||||
*/ |
|
||||||
offsetToLineColumnWithContent (rawLocation, file, content) { |
|
||||||
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(content) |
|
||||||
return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Clear the cache |
|
||||||
*/ |
|
||||||
clear () { |
|
||||||
this.lineBreakPositionsByContent = {} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* called by plugin API |
|
||||||
*/ |
|
||||||
activate () { |
|
||||||
this.on('solidity', 'compilationFinished', () => { |
|
||||||
this.clear() |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,161 +0,0 @@ |
|||||||
export const Ballot = { |
|
||||||
name: 'browser/ballot.vy', |
|
||||||
content: `# Voting with delegation.
|
|
||||||
|
|
||||||
# Information about voters |
|
||||||
struct Voter: |
|
||||||
# weight is accumulated by delegation |
|
||||||
weight: int128 |
|
||||||
# if true, that person already voted (which includes voting by delegating) |
|
||||||
voted: bool |
|
||||||
# person delegated to |
|
||||||
delegate: address |
|
||||||
# index of the voted proposal, which is not meaningful unless 'voted' is True. |
|
||||||
vote: int128 |
|
||||||
|
|
||||||
# Users can create proposals |
|
||||||
struct Proposal: |
|
||||||
# short name (up to 32 bytes) |
|
||||||
name: bytes32 |
|
||||||
# number of accumulated votes |
|
||||||
voteCount: int128 |
|
||||||
|
|
||||||
voters: public(map(address, Voter)) |
|
||||||
proposals: public(map(int128, Proposal)) |
|
||||||
voterCount: public(int128) |
|
||||||
chairperson: public(address) |
|
||||||
int128Proposals: public(int128) |
|
||||||
|
|
||||||
|
|
||||||
@public |
|
||||||
@constant |
|
||||||
def delegated(addr: address) -> bool: |
|
||||||
return self.voters[addr].delegate != ZERO_ADDRESS |
|
||||||
|
|
||||||
|
|
||||||
@public |
|
||||||
@constant |
|
||||||
def directlyVoted(addr: address) -> bool: |
|
||||||
return self.voters[addr].voted and (self.voters[addr].delegate == ZERO_ADDRESS) |
|
||||||
|
|
||||||
|
|
||||||
# Setup global variables |
|
||||||
@public |
|
||||||
def __init__(_proposalNames: bytes32[2]): |
|
||||||
self.chairperson = msg.sender |
|
||||||
self.voterCount = 0 |
|
||||||
for i in range(2): |
|
||||||
self.proposals[i] = Proposal({ |
|
||||||
name: _proposalNames[i], |
|
||||||
voteCount: 0 |
|
||||||
}) |
|
||||||
self.int128Proposals += 1 |
|
||||||
|
|
||||||
# Give a 'voter' the right to vote on this ballot. |
|
||||||
# This may only be called by the 'chairperson'. |
|
||||||
@public |
|
||||||
def giveRightToVote(voter: address): |
|
||||||
# Throws if the sender is not the chairperson. |
|
||||||
assert msg.sender == self.chairperson |
|
||||||
# Throws if the voter has already voted. |
|
||||||
assert not self.voters[voter].voted |
|
||||||
# Throws if the voter's voting weight isn't 0. |
|
||||||
assert self.voters[voter].weight == 0 |
|
||||||
self.voters[voter].weight = 1 |
|
||||||
self.voterCount += 1 |
|
||||||
|
|
||||||
# Used by 'delegate' below, and can be called by anyone. |
|
||||||
@public |
|
||||||
def forwardWeight(delegate_with_weight_to_forward: address): |
|
||||||
assert self.delegated(delegate_with_weight_to_forward) |
|
||||||
# Throw if there is nothing to do: |
|
||||||
assert self.voters[delegate_with_weight_to_forward].weight > 0 |
|
||||||
|
|
||||||
target: address = self.voters[delegate_with_weight_to_forward].delegate |
|
||||||
for i in range(4): |
|
||||||
if self.delegated(target): |
|
||||||
target = self.voters[target].delegate |
|
||||||
# The following effectively detects cycles of length <= 5, |
|
||||||
# in which the delegation is given back to the delegator. |
|
||||||
# This could be done for any int128ber of loops, |
|
||||||
# or even infinitely with a while loop. |
|
||||||
# However, cycles aren't actually problematic for correctness; |
|
||||||
# they just result in spoiled votes. |
|
||||||
# So, in the production version, this should instead be |
|
||||||
# the responsibility of the contract's client, and this |
|
||||||
# check should be removed. |
|
||||||
assert target != delegate_with_weight_to_forward |
|
||||||
else: |
|
||||||
# Weight will be moved to someone who directly voted or |
|
||||||
# hasn't voted. |
|
||||||
break |
|
||||||
|
|
||||||
weight_to_forward: int128 = self.voters[delegate_with_weight_to_forward].weight |
|
||||||
self.voters[delegate_with_weight_to_forward].weight = 0 |
|
||||||
self.voters[target].weight += weight_to_forward |
|
||||||
|
|
||||||
if self.directlyVoted(target): |
|
||||||
self.proposals[self.voters[target].vote].voteCount += weight_to_forward |
|
||||||
self.voters[target].weight = 0 |
|
||||||
|
|
||||||
# To reiterate: if target is also a delegate, this function will need |
|
||||||
# to be called again, similarly to as above. |
|
||||||
|
|
||||||
# Delegate your vote to the voter 'to'. |
|
||||||
@public |
|
||||||
def delegate(to: address): |
|
||||||
# Throws if the sender has already voted |
|
||||||
assert not self.voters[msg.sender].voted |
|
||||||
# Throws if the sender tries to delegate their vote to themselves or to |
|
||||||
# the default address value of 0x0000000000000000000000000000000000000000 |
|
||||||
# (the latter might not be problematic, but I don't want to think about it). |
|
||||||
assert to != msg.sender |
|
||||||
assert to != ZERO_ADDRESS |
|
||||||
|
|
||||||
self.voters[msg.sender].voted = True |
|
||||||
self.voters[msg.sender].delegate = to |
|
||||||
|
|
||||||
# This call will throw if and only if this delegation would cause a loop |
|
||||||
# of length <= 5 that ends up delegating back to the delegator. |
|
||||||
self.forwardWeight(msg.sender) |
|
||||||
|
|
||||||
# Give your vote (including votes delegated to you) |
|
||||||
# to proposal 'proposals[proposal].name'. |
|
||||||
@public |
|
||||||
def vote(proposal: int128): |
|
||||||
# can't vote twice |
|
||||||
assert not self.voters[msg.sender].voted |
|
||||||
# can only vote on legitimate proposals |
|
||||||
assert proposal < self.int128Proposals |
|
||||||
|
|
||||||
self.voters[msg.sender].vote = proposal |
|
||||||
self.voters[msg.sender].voted = True |
|
||||||
|
|
||||||
# transfer msg.sender's weight to proposal |
|
||||||
self.proposals[proposal].voteCount += self.voters[msg.sender].weight |
|
||||||
self.voters[msg.sender].weight = 0 |
|
||||||
|
|
||||||
# Computes the winning proposal taking all |
|
||||||
# previous votes into account. |
|
||||||
@public |
|
||||||
@constant |
|
||||||
def winningProposal() -> int128: |
|
||||||
winning_vote_count: int128 = 0 |
|
||||||
winning_proposal: int128 = 0 |
|
||||||
for i in range(2): |
|
||||||
if self.proposals[i].voteCount > winning_vote_count: |
|
||||||
winning_vote_count = self.proposals[i].voteCount |
|
||||||
winning_proposal = i |
|
||||||
return winning_proposal |
|
||||||
|
|
||||||
# Calls winningProposal() function to get the index |
|
||||||
# of the winner contained in the proposals array and then |
|
||||||
# returns the name of the winner |
|
||||||
@public |
|
||||||
@constant |
|
||||||
def winnerName() -> bytes32: |
|
||||||
return self.proposals[self.winningProposal()].name |
|
||||||
|
|
||||||
` |
|
||||||
} |
|
||||||
|
|
@ -1,4 +1,5 @@ |
|||||||
export * from './lib/remix-ui-helper' |
export * from './lib/remix-ui-helper' |
||||||
|
export * from './lib/bleach' |
||||||
export * from './lib/helper-components' |
export * from './lib/helper-components' |
||||||
export * from './lib/components/PluginViewWrapper' |
export * from './lib/components/PluginViewWrapper' |
||||||
export * from './lib/components/custom-dropdown' |
export * from './lib/components/custom-dropdown' |
Loading…
Reference in new issue