Skip to content

Commit

Permalink
[language-css] Add scope tests parentOfType and childOfType
Browse files Browse the repository at this point in the history
…to support scenarios where you need to check parent/child relationship to an `ERROR` node, or to several different kinds of nodes at once.
  • Loading branch information
savetheclocktower committed Jan 12, 2025
1 parent e936047 commit 159542a
Showing 1 changed file with 29 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/scope-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -745,8 +745,20 @@ ScopeResolver.TESTS = {
return false;
},

// Passes if there's an ancestor, but fails if the ancestor type matches
// the second,third,etc argument
// Passes if this node's parent is of the given type(s).
//
// Only rarely needed, but may be useful when dealing with ERROR nodes.
childOfType(node, type) {
if (!node.parent) return false;
let multiple = type.includes(' ');
let target = multiple ? type.split(/\s+/) : type;
return multiple ? target.includes(node.parent.type) : node.parent.type === type;
},

// Takes at least two node types (separated by spaces) and starts traversing
// up the node's parent chain. Passes if the first node type is encountered
// before any of the rest; fails if any of the rest are reached before the
// first.
ancestorTypeNearerThan(node, types) {
let [target, ...rejected] = types.split(/\s+/);
rejected = new Set(rejected)
Expand All @@ -766,9 +778,21 @@ ScopeResolver.TESTS = {
return descendants.length > 0;
},

// Passes if this node has at least one child of the given type(s).
//
// Only rarely needed, but may be useful when dealing with ERROR nodes.
parentOfType(node, type) {
if (node.childCount === 0) return false;
let multiple = type.includes(' ');
let target = multiple ? type.split(/\s+/) : type;
return node.children.some(c => {
return multiple ? target.includes(c.type) : c.type === target;
});
},

// Passes if this range (after adjustments) has previously had data stored at
// the given key.
rangeWithData(node, rawValue, existingData) {
rangeWithData(_node, rawValue, existingData) {
if (existingData === undefined) { return false; }
let [key, value] = interpretPossibleKeyValuePair(rawValue, false);

Expand All @@ -782,7 +806,7 @@ ScopeResolver.TESTS = {

// Passes if one of this node's ancestors has stored data at the given key
// for its inherent range (ignoring adjustments).
descendantOfNodeWithData(node, rawValue, existingData, instance) {
descendantOfNodeWithData(node, rawValue, _existingData, instance) {
let current = node;
let [key, value] = interpretPossibleKeyValuePair(rawValue, false);

Expand Down Expand Up @@ -818,7 +842,7 @@ ScopeResolver.TESTS = {
// Passes only when a given config option is present and truthy. Accepts
// either (a) a configuration key or (b) a configuration key and value
// separated by a space.
config(node, rawValue, existingData, instance) {
config(_node, rawValue, _existingData, instance) {
let [key, value] = interpretPossibleKeyValuePair(rawValue, true);

// Invalid predicates should be ignored.
Expand Down

0 comments on commit 159542a

Please sign in to comment.