Merge pull request #819 from ethereum/dynamicHighlight

Dynamic highlight
pull/1/head
yann300 7 years ago committed by GitHub
commit e87fb64ec2
  1. 14
      assets/css/browser-solidity.css
  2. 39
      src/app.js
  3. 102
      src/app/editor/contextualListener.js
  4. 4
      src/app/editor/editor.js

@ -290,6 +290,20 @@ input[type="file"] {
display: none; display: none;
} }
.highlightreference {
position:absolute;
z-index:20;
background-color: lightgrey;
opacity: 0.7
}
.highlightreferenceline {
position:absolute;
z-index:20;
background-color: hsla(229, 75%, 87%, .5); /* lightBlue in style-guide.js*/
opacity: 0.7
}
.highlightcode { .highlightcode {
position:absolute; position:absolute;
z-index:20; z-index:20;

@ -34,6 +34,7 @@ var TxLogger = require('./app/execution/txLogger')
var EventsDecoder = require('./app/execution/eventsDecoder') var EventsDecoder = require('./app/execution/eventsDecoder')
var handleImports = require('./app/compiler/compiler-imports') var handleImports = require('./app/compiler/compiler-imports')
var FileManager = require('./app/files/fileManager') var FileManager = require('./app/files/fileManager')
var ContextualListener = require('./app/editor/contextualListener')
var styleGuide = remix.ui.styleGuide var styleGuide = remix.ui.styleGuide
var styles = styleGuide() var styles = styleGuide()
@ -385,6 +386,44 @@ function run () {
}) })
var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event)
// ---------------- ContextualListener -----------------------
this._components.contextualListener = new ContextualListener({
getCursorPosition: () => {
return this._components.editor.getCursorPosition()
},
getCompilationResult: () => {
return compiler.lastCompilationResult
},
highlight: (position, node) => {
if (compiler.lastCompilationResult && compiler.lastCompilationResult.data && compiler.lastCompilationResult.data.sourceList[position.file] === config.get('currentFile')) {
position = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult)
var css = 'highlightreference'
if (node.children && node.children.length) {
// If node has children, highlight the entire line. if not, just highlight the current source position of the node.
css = 'highlightreferenceline'
position = {
start: {
line: position.start.line,
column: 0
},
end: {
line: position.start.line + 1,
column: 0
}
}
}
return editor.addMarker(position, config.get('currentFile'), css)
}
return null
},
stopHighlighting: (event) => {
editor.removeMarker(event.eventId, event.fileTarget)
}
}, {
compiler: compiler.event,
editor: editor.event
})
// ----------------- Renderer ----------------- // ----------------- Renderer -----------------
var rendererAPI = { var rendererAPI = {
error: (file, error) => { error: (file, error) => {

@ -0,0 +1,102 @@
'use strict'
var SourceMappingDecoder = require('ethereum-remix').util.SourceMappingDecoder
var AstWalker = require('ethereum-remix').util.AstWalker
class ContextualListener {
constructor (api, events) {
this._api = api
this._index = {
Declarations: {},
FlatReferences: {}
}
this._activeHighlights = []
events.compiler.register('compilationFinished', (success, data, source) => {
this._stopHighlighting()
this._index = {
Declarations: {},
FlatReferences: {}
}
if (success) {
this._buildIndex(data, source)
}
})
events.editor.register('sessionSwitched', () => { this._stopHighlighting() })
events.editor.register('contentChanged', () => { this._stopHighlighting() })
this.sourceMappingDecoder = new SourceMappingDecoder()
this.astWalker = new AstWalker()
setInterval(() => {
this._highlightItems(api.getCursorPosition(), api.getCompilationResult())
}, 1000)
}
_highlightItems (cursorPosition, compilationResult) {
if (this.currentPosition === cursorPosition) return
this._stopHighlighting()
this.currentPosition = cursorPosition
if (compilationResult && compilationResult.data && compilationResult.source) {
var nodes = this.sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[compilationResult.source.target])
if (nodes && nodes.length && nodes[nodes.length - 1]) {
this._highlightExpressions(nodes[nodes.length - 1], compilationResult)
}
}
}
_buildIndex (compilationResult, source) {
if (compilationResult && compilationResult.sources) {
var self = this
var callback = {}
callback['*'] = function (node) {
if (node && node.attributes && node.attributes.referencedDeclaration) {
if (!self._index['Declarations'][node.attributes.referencedDeclaration]) {
self._index['Declarations'][node.attributes.referencedDeclaration] = []
}
self._index['Declarations'][node.attributes.referencedDeclaration].push(node)
}
self._index['FlatReferences'][node.id] = node
return true
}
this.astWalker.walk(compilationResult.sources[source.target].AST, callback)
}
}
_highlight (node, compilationResult) {
if (!node) return
var position = this.sourceMappingDecoder.decode(node.src)
var eventId = this._api.highlight(position, node)
if (eventId) {
this._activeHighlights.push({ eventId, position, fileTarget: compilationResult.source.target })
}
}
_highlightExpressions (node, compilationResult) {
var self = this
function highlights (id) {
if (self._index['Declarations'] && self._index['Declarations'][id]) {
var refs = self._index['Declarations'][id]
for (var ref in refs) {
var node = refs[ref]
self._highlight(node, compilationResult)
}
}
}
if (node.attributes && node.attributes.referencedDeclaration) {
highlights(node.attributes.referencedDeclaration)
var current = this._index['FlatReferences'][node.attributes.referencedDeclaration]
this._highlight(current, compilationResult)
} else {
highlights(node.id)
}
}
_stopHighlighting () {
for (var event in this._activeHighlights) {
this._api.stopHighlighting(this._activeHighlights[event])
}
this._activeHighlights = []
}
}
module.exports = ContextualListener

@ -140,6 +140,10 @@ function Editor (opts = {}) {
return currentSession return currentSession
} }
this.getCursorPosition = function () {
return editor.session.doc.positionToIndex(editor.getCursorPosition(), 0)
}
this.discard = function (path) { this.discard = function (path) {
if (currentSession !== path) { if (currentSession !== path) {
delete sessions[path] delete sessions[path]

Loading…
Cancel
Save