You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
3.**Explicit Routing**: For each block, route to appropriate processor:
83
85
```javascript
84
86
constdirectiveProcessingFuncs= {
@@ -139,26 +141,60 @@ if (!isGlobalPartial) {
139
141
140
142
## Implementation Details
141
143
144
+
### parseDirectiveBlocks() Function
145
+
146
+
Parses all directive blocks from the AST in a single pass and returns block objects containing:
147
+
148
+
-`startNode`: Reference to the BEGIN comment node
149
+
-`endNode`: Reference to the END comment node
150
+
-`startLine`: Line number where BEGIN comment appears (for error messages)
151
+
-`endLine`: Line number where END comment appears (for error messages)
152
+
-`content`: The directive content (e.g., "TFEnterprise:only name:project-remote-state")
153
+
154
+
**Why node references instead of line numbers?**
155
+
156
+
When multiple partials are included in a file, each partial's AST nodes retain their original line numbers from the source file. This means multiple partials can have overlapping line ranges (e.g., both starting at line 1). Using actual node object references ensures we match the exact BEGIN/END pair, not just any nodes at those line numbers.
157
+
142
158
### removeNodesInRange() Function
143
159
144
-
This is the core function that removes content between BEGIN/END comments. Key behaviors:
160
+
This is the core function that removes content between BEGIN/END comments using node identity matching.
161
+
162
+
**Key Algorithm:**
163
+
```javascript
164
+
// Check if this is the START node
165
+
if (node === startNode) {
166
+
insideRange =true
167
+
nodesToRemove.add(node)
168
+
}
169
+
170
+
// Check if this is the END node
171
+
if (node === endNode) {
172
+
nodesToRemove.add(node)
173
+
insideRange =false
174
+
}
175
+
176
+
// If inside range, mark for removal
177
+
if (insideRange) {
178
+
nodesToRemove.add(node)
179
+
}
180
+
```
181
+
182
+
**Why node identity matching?**
183
+
184
+
Using `node === startNode` comparison ensures we match the exact node objects that were identified during parsing. This is critical when:
185
+
- Multiple partials contain the same directive name (e.g., both have `TFEnterprise:only name:project-remote-state`)
186
+
- Partial AST nodes have overlapping line numbers from their source files
187
+
- Same directive appears multiple times in sequence
145
188
146
189
**Handles Partial Content:**
147
-
- Nodes from included partials may have position data from the partial file (e.g., lines 1-20), not the parent file (e.g., lines 37-45)
148
-
- Tracks an `insideRange` state: once a BEGIN comment is found, all subsequent nodes are removed until the END comment
149
-
- Nodes without position data or with mismatched position data are treated as partial content and removed when `insideRange` is true
190
+
- Once BEGIN node is found, all subsequent nodes are marked for removal until END node
191
+
- Recurses into children to handle nested structures
150
192
151
193
**Recurse-First Algorithm:**
152
194
- Processes children BEFORE deciding parent's fate
153
195
- Finds nested END comments even when parent is marked for removal
154
196
- Parent nodes that contained removed children are also removed (if empty)
155
197
156
-
**Critical Edge Case - Same-Line Directive Comments:**
157
-
- When two directive blocks have comments on the same line (e.g., `<!-- END: TFC:only --> <!-- BEGIN: TFEnterprise:only -->`), the function tracks `lastEndLine`
158
-
- After finding an END comment, it skips any BEGIN comments on that same line
159
-
- This prevents starting a new unrelated range removal operation
160
-
-**Why**: `removeNodesInRange()` is designed to remove ONE specific range, not multiple overlapping ranges
0 commit comments