pi-revit 0.2.13 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,44 @@ Format follows [Keep a Changelog](https://keepachangelog.com/); version headers
7
7
  Every published version gets an entry with **Added** / **Changed** / **Fixed** sections
8
8
  describing what the user will notice — not internal refactors.
9
9
 
10
+ ## [0.2.15] - 2026-08-21
11
+
12
+ ### Fixed
13
+ - `set_parameters`: the "parameter not found" error now mentions that display names are
14
+ localized and points to the language-independent BuiltInParameter enum name — the same
15
+ guidance `get_element_details` and `get_elements` already give. Previously it only
16
+ suggested the type-parameter cause, which sent the caller down the wrong path in
17
+ non-English UIs.
18
+ - `get_elements`: the "filter parameter not found on any probed element" warning now
19
+ appears only when the query returned zero matches — that is where it distinguishes
20
+ "unknown parameter name" from "no matching elements". Next to real matches it was noise
21
+ (an unscoped query's probe window can simply miss the elements that carry the parameter).
22
+
23
+ Requires redeploying the Revit add-in (`scripts\deploy.ps1` with Revit closed, then
24
+ restart Revit).
25
+
26
+ ## [0.2.14] - 2026-08-21
27
+
28
+ ### Fixed
29
+ - `get_elements`: text filter rules now compare case-insensitively on the post-scan path,
30
+ matching Revit's own collector rules (which ignore case -- verified empirically). The
31
+ same string rule previously matched case-insensitively when it ran inside the collector
32
+ but case-sensitively when it fell back to the per-element scan, so merely scoping a
33
+ query could change its results.
34
+ - `search_api_docs`: queries in C# accessor spelling -- `Element.get_Parameter(BuiltInParameter)`,
35
+ `get_BoundingBox(View` -- now resolve to the documented property or indexer
36
+ (`Element.Parameter`, `Element.BoundingBox`), with a note explaining the rewrite. Members
37
+ documented with a literal `get_`/`set_` prefix still match directly; the rewrite is only
38
+ a fallback. Three benchmark probes added.
39
+
40
+ Also investigated and cleared, no change needed: `Element.BoundingBox` and
41
+ `LocationCurve.Curve` document null returns -- not exceptions -- for elements without
42
+ geometry, so the suspected one-bad-element batch failure in `get_element_details` does
43
+ not exist per the API contract.
44
+
45
+ Requires redeploying the Revit add-in (`scripts\deploy.ps1` with Revit closed, then
46
+ restart Revit).
47
+
10
48
  ## [0.2.13] - 2026-08-21
11
49
 
12
50
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-revit",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "Native Pi connector for Autodesk Revit. Run npx.cmd -y pi-revit for the full Windows install.",
5
5
  "author": "Ahmad Altahlawi",
6
6
  "license": "MIT",
@@ -209,6 +209,10 @@ probe("System-qualified alias", "ParameterFilterElement.Create(Document, System.
209
209
  probe("factory rewrite", "Document.Create.NewRoom(Level, UV")
210
210
  probe("factory inherited member", "Document.Create.NewFamilyInstance")
211
211
  probe("factory honesty control", "Document.Create.Banana", expect_nonzero=False)
212
+ # 0.2.14: C# accessor spelling (get_X/set_X) resolves to the documented property/indexer
213
+ probe("accessor indexer", "Element.get_Parameter(BuiltInParameter")
214
+ probe("accessor property", "Element.get_BoundingBox(View")
215
+ probe("literal get_ member", "LocationCurve.get_ElementsAtJoin")
212
216
  print("C done", flush=True)
213
217
  R["C complex-syntax"] = C
214
218
 
@@ -147,7 +147,10 @@ namespace RevitBridge.Tools
147
147
  string scope = DescribeScope(categoryInput, classInput, inActiveView);
148
148
 
149
149
  if (countOnly && postPredicate is null)
150
- return CountResult(scope, CreateCollector().GetElementCount(), filterWarnings);
150
+ {
151
+ int quickCount = CreateCollector().GetElementCount();
152
+ return CountResult(scope, quickCount, quickCount > 0 ? Array.Empty<string>() : filterWarnings);
153
+ }
151
154
 
152
155
  var rows = countOnly ? null : new List<Dictionary<string, object?>>(Math.Min(limit, 256));
153
156
  int total = 0;
@@ -160,6 +163,12 @@ namespace RevitBridge.Tools
160
163
  total++;
161
164
  }
162
165
 
166
+ // A found match proves the query worked: the not-found-on-probes warning is
167
+ // load-bearing only next to a zero, where it distinguishes 'unknown parameter
168
+ // name' from 'no matching elements'. Beside real matches it is just noise.
169
+ if (total > 0)
170
+ filterWarnings = Array.Empty<string>();
171
+
163
172
  if (rows is null)
164
173
  return CountResult(scope, total, filterWarnings);
165
174
 
@@ -563,14 +572,18 @@ namespace RevitBridge.Tools
563
572
  {
564
573
  case StorageType.String:
565
574
  {
575
+ // Case-insensitive to match Revit's own collector: ParameterFilterRuleFactory
576
+ // string rules ignore case (verified on Revit 2025 -- a promoted equals rule
577
+ // matched 'CaseProbe' for the query 'caseprobe'). The same rule must not turn
578
+ // case-sensitive merely because it fell back to the post-scan path.
566
579
  string actual = parameter.AsString() ?? string.Empty;
567
580
  string target = ValueAsString(rule.Value);
568
581
  return rule.Op switch
569
582
  {
570
- RuleOp.Equals => string.Equals(actual, target, StringComparison.Ordinal),
571
- RuleOp.NotEquals => !string.Equals(actual, target, StringComparison.Ordinal),
572
- RuleOp.Contains => actual.Contains(target, StringComparison.Ordinal),
573
- _ => Compare(string.CompareOrdinal(actual, target), rule.Op),
583
+ RuleOp.Equals => string.Equals(actual, target, StringComparison.OrdinalIgnoreCase),
584
+ RuleOp.NotEquals => !string.Equals(actual, target, StringComparison.OrdinalIgnoreCase),
585
+ RuleOp.Contains => actual.Contains(target, StringComparison.OrdinalIgnoreCase),
586
+ _ => Compare(string.Compare(actual, target, StringComparison.OrdinalIgnoreCase), rule.Op),
574
587
  };
575
588
  }
576
589
  case StorageType.Double:
@@ -155,6 +155,20 @@ namespace RevitBridge.Tools
155
155
  candidates.Add((bareMember, $"'{owner}Create.{bareMember}' is a Creation-factory call; its docs live on the factory class (e.g. ItemFactoryBase) — matched by member name '{bareMember}'."));
156
156
  }
157
157
 
158
+ // C# spells property and indexer accessors 'get_X'/'set_X' (element.get_Parameter(...),
159
+ // wall.get_BoundingBox(view)), but the XML mostly documents the underlying property
160
+ // ('Element.Parameter', 'Element.BoundingBox'). Members documented WITH a literal
161
+ // prefix (LocationCurve.get_ElementsAtJoin) match the untouched query first --
162
+ // candidates run in order and this rewrite is only reached when the literal
163
+ // spelling found nothing.
164
+ {
165
+ string accessor = q.Replace(".get_", ".", StringComparison.Ordinal).Replace(".set_", ".", StringComparison.Ordinal);
166
+ if (accessor.StartsWith("get_", StringComparison.Ordinal) || accessor.StartsWith("set_", StringComparison.Ordinal))
167
+ accessor = accessor["get_".Length..];
168
+ if (accessor != q)
169
+ candidates.Add((accessor, "'get_X' / 'set_X' is the C# accessor spelling of property or indexer 'X'; matched without the prefix."));
170
+ }
171
+
158
172
  foreach (var (candidate, note) in candidates)
159
173
  {
160
174
  var (top, total) = RunScoring(index, candidate, kindFilter, maxResults);
@@ -156,7 +156,7 @@ namespace RevitBridge.Tools
156
156
  {
157
157
  if (nameTarget)
158
158
  return SetElementName(element, update);
159
- throw new InvalidOperationException($"Parameter '{update.ParameterInput}' not found on element {update.ElementId} ('{element.Name}'). Type parameters live on the element type — pass its id instead.");
159
+ throw new InvalidOperationException($"Parameter '{update.ParameterInput}' not found on element {update.ElementId} ('{element.Name}'). Display names are localized in non-English Revit UIs — prefer the language-independent BuiltInParameter enum name (e.g. ALL_MODEL_INSTANCE_COMMENTS; get_element_details reports each parameter's builtInParameter). Type parameters live on the element type — pass the type's id instead.");
160
160
  }
161
161
 
162
162
  if (parameter.IsReadOnly)