index.js (1839B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 import { buildScopeList, parseSourceScopes } from "./visitor"; 6 7 const parsedScopesCache = new Map(); 8 9 export default function getScopes(location) { 10 const sourceId = location.source.id; 11 let parsedScopes = parsedScopesCache.get(sourceId); 12 if (!parsedScopes) { 13 parsedScopes = parseSourceScopes(sourceId); 14 parsedScopesCache.set(sourceId, parsedScopes); 15 } 16 return parsedScopes ? findScopes(parsedScopes, location) : []; 17 } 18 19 export function clearScopes(sourceIds) { 20 for (const sourceId of sourceIds) { 21 parsedScopesCache.delete(sourceId); 22 } 23 } 24 25 export { buildScopeList }; 26 27 /** 28 * Searches all scopes and their bindings at the specific location. 29 */ 30 function findScopes(scopes, location) { 31 // Find inner most in the tree structure. 32 let searchInScopes = scopes; 33 const found = []; 34 while (searchInScopes) { 35 const foundOne = searchInScopes.some(s => { 36 if ( 37 compareLocations(s.start, location) <= 0 && 38 compareLocations(location, s.end) < 0 39 ) { 40 // Found the next scope, trying to search recusevly in its children. 41 found.unshift(s); 42 searchInScopes = s.children; 43 return true; 44 } 45 return false; 46 }); 47 if (!foundOne) { 48 break; 49 } 50 } 51 return found.map(i => ({ 52 type: i.type, 53 scopeKind: i.scopeKind, 54 displayName: i.displayName, 55 start: i.start, 56 end: i.end, 57 bindings: i.bindings, 58 })); 59 } 60 61 function compareLocations(a, b) { 62 // According to type of Location.column can be undefined, if will not be the 63 // case here, ignoring flow error. 64 return a.line == b.line ? a.column - b.column : a.line - b.line; 65 }