Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | 1x 1x 1x 8x 6x 8x 8x 1x 105x 1x 1x 110x 110x 1x 1x 1x 1x 16x 1x 2x 2x 2x 52x 3x 52x 2x 2x 2x 2x 2x 52x 1x 52x 2x 2x 4x 3x 1x | import { isAstNode, AstWalker } from './astWalker'; import { AstNode, LineColPosition, LineColRange, Location } from "./types"; import { util } from "@remix-project/remix-lib"; export declare interface SourceMappings { // eslint-disable-next-line @typescript-eslint/no-misused-new new(): SourceMappings; } /** * Turn an character offset into a "LineColPosition". * * @param offset The character offset to convert. */ export function lineColPositionFromOffset(offset: number, lineBreaks: Array<number>): LineColPosition { let line: number = util.findLowerBound(offset, lineBreaks); if (lineBreaks[line] !== offset) { line += 1; } const beginColumn = line === 0 ? 0 : (lineBreaks[line - 1] + 1); return <LineColPosition>{ line: line + 1, character: (offset - beginColumn) + 1 } } /** * Turn a solc AST's "src" attribute string (s:l:f) * into a Location * * @param astNode The object to convert. */ export function sourceLocationFromAstNode(astNode: AstNode): Location | null { if (isAstNode(astNode) && astNode.src) { return sourceLocationFromSrc(astNode.src) } return null; } /** * Break out fields of solc AST's "src" attribute string (s:l:f) * into its "start", "length", and "file index" components * and return that as a Location * * @param src A solc "src" field. * @returns {Location} */ export function sourceLocationFromSrc(src: string): Location { const split = src.split(':') return <Location>{ start: parseInt(split[0], 10), length: parseInt(split[1], 10), file: parseInt(split[2], 10) } } /** * Routines for retrieving solc AST object(s) using some criteria, usually * includng "src' information. */ export class SourceMappings { readonly source: string; readonly lineBreaks: Array<number>; constructor(source: string) { this.source = source; // Create a list of line offsets which will be used to map between // character offset and line/column positions. const lineBreaks: Array<number> = []; for (let pos = source.indexOf('\n'); pos >= 0; pos = source.indexOf('\n', pos + 1)) { lineBreaks.push(pos) } this.lineBreaks = lineBreaks; }; /** * Get a list of nodes that are at the given "position". * * @param astNodeType Type of node to return or null. * @param position Character offset where AST node should be located. */ nodesAtPosition(astNodeType: string | null, position: Location, ast: AstNode): Array<AstNode> { const astWalker = new AstWalker() const found: Array<AstNode> = []; const callback = function(node: AstNode): boolean { const nodeLocation = sourceLocationFromAstNode(node); if (nodeLocation && nodeLocation.start == position.start && nodeLocation.length == position.length) { if (!astNodeType || astNodeType === node.nodeType) { found.push(node) } } return true; } astWalker.walkFull(ast, callback); return found; } /** * Retrieve the first "astNodeType" that includes the source map at arg instIndex, or "null" if none found. * * @param astNodeType nodeType that a found ASTNode must be. Use "null" if any ASTNode can match. * @param sourceLocation "src" location that the AST node must match. */ findNodeAtSourceLocation(astNodeType: string | undefined, sourceLocation: Location, ast: AstNode | null): AstNode | null { const astWalker = new AstWalker() let found = null; /* FIXME: Looking at AST walker code, I don't understand a need to return a boolean. */ const callback = function(node: AstNode) { const nodeLocation = sourceLocationFromAstNode(node); if (nodeLocation && nodeLocation.start == sourceLocation.start && nodeLocation.length == sourceLocation.length) { if (astNodeType == undefined || astNodeType === node.nodeType) { found = node; } } return true; } astWalker.walkFull(ast, callback); return found; } /** * Retrieve the line/column range position for the given source-mapping string. * * @param src Solc "src" object containing attributes {source} and {length}. */ srcToLineColumnRange(src: string): LineColRange { const sourceLocation = sourceLocationFromSrc(src); if (sourceLocation.start >= 0 && sourceLocation.length >= 0) { return <LineColRange>{ start: lineColPositionFromOffset(sourceLocation.start, this.lineBreaks), end: lineColPositionFromOffset(sourceLocation.start + sourceLocation.length, this.lineBreaks) } } else { return <LineColRange>{ start: null, end: null } } } } |