Skip to content

Commit ab0f4b4

Browse files
committed
docs: update contribution guide with forks, PRs, and final results
Add upstream contribution status: 3 graphify PRs (safishamsi#440-safishamsi#442), 1 tree-sitter-razor PR (safishamsi#19), 1 tree-sitter-fsharp issue (safishamsi#176). Document fork locations, blocked PRs, and final test metrics. Fix document structure (reorder commit 7, remove duplicated sections). Made-with: Cursor
1 parent 3ab720e commit ab0f4b4

1 file changed

Lines changed: 81 additions & 60 deletions

File tree

FSHARP_CONTRIBUTION_GUIDE.md

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,49 @@
1-
# F# Support for Graphify — Contribution Guide
1+
# F#, Razor/Blazor & Cross-Language Improvements for Graphify
22

3-
This document describes the changes made on branch `fix/fsharp-graph-quality` to add F# language support to graphify and fix several cross-language graph quality issues. Each commit is designed to be cherry-picked independently for separate upstream PRs.
3+
This document describes the changes made on branch `fix/fsharp-graph-quality` to add F# and Razor/Blazor language support to graphify and fix several cross-language graph quality issues. Each commit is designed to be cherry-picked independently for separate upstream PRs.
44

5-
## Prerequisites
5+
## Upstream Contributions
66

7-
Before these changes can be upstreamed, the [tree-sitter-fsharp](https://github.com/ionide/tree-sitter-fsharp) project needs to publish Python bindings to PyPI. Currently, `tree-sitter-fsharp` has `"python": false` in its `tree-sitter.json` and no PyPI package exists. The grammar itself works (v0.3.0), and Python bindings can be built locally from source using `setup.py` (see below).
7+
### Forks
88

9-
Once `tree-sitter-fsharp` is on PyPI, it can be added to graphify's optional dependencies just like other language grammars.
9+
| Upstream | Fork | Local path |
10+
|----------|------|------------|
11+
| [safishamsi/graphify](https://github.com/safishamsi/graphify) | [V0v1kkk/graphify](https://github.com/V0v1kkk/graphify) | `/home/vladimir/GitRoot/external/graphify` |
12+
| [tris203/tree-sitter-razor](https://github.com/tris203/tree-sitter-razor) | [V0v1kkk/tree-sitter-razor](https://github.com/V0v1kkk/tree-sitter-razor) | `/home/vladimir/GitRoot/external/tree-sitter-razor` |
13+
| [ionide/tree-sitter-fsharp](https://github.com/ionide/tree-sitter-fsharp) | [V0v1kkk/tree-sitter-fsharp](https://github.com/V0v1kkk/tree-sitter-fsharp) | `/home/vladimir/GitRoot/external/tree-sitter-fsharp` |
14+
15+
### Submitted Issues & Pull Requests
16+
17+
**graphify** — 3 unblocked PRs submitted:
18+
19+
| Issue | PR | Branch | Description | Status |
20+
|-------|----|--------|-------------|--------|
21+
| [#437](https://github.com/safishamsi/graphify/issues/437) | [#440](https://github.com/safishamsi/graphify/pull/440) | `fix/bcl-method-blocklist` | BCL method blocklist for cross-file inference | Awaiting review |
22+
| [#438](https://github.com/safishamsi/graphify/issues/438) | [#441](https://github.com/safishamsi/graphify/pull/441) | `fix/node-id-collisions` | Disambiguate colliding node IDs from same-name files | Awaiting review |
23+
| [#439](https://github.com/safishamsi/graphify/issues/439) | [#442](https://github.com/safishamsi/graphify/pull/442) | `fix/merge-stub-nodes` | Merge stub nodes with real cross-language definitions | Awaiting review |
24+
25+
**tree-sitter-razor** — 1 bug fix PR:
26+
27+
| Issue | PR | Branch | Description | Status |
28+
|-------|----|--------|-------------|--------|
29+
| [#18](https://github.com/tris203/tree-sitter-razor/issues/18) | [#19](https://github.com/tris203/tree-sitter-razor/pull/19) | `fix/python-scanner` | Include `scanner.c` in Python bindings `setup.py` | Awaiting review |
30+
31+
**tree-sitter-fsharp** — 1 feature request:
32+
33+
| Issue | Description | Status |
34+
|-------|-------------|--------|
35+
| [#176](https://github.com/ionide/tree-sitter-fsharp/issues/176) | Publish Python bindings to PyPI | Awaiting response |
36+
37+
### Blocked PRs (not yet submitted)
38+
39+
| Commits | Description | Blocked on |
40+
|---------|-------------|------------|
41+
| 1 + 2 | F# language support | tree-sitter-fsharp PyPI ([#176](https://github.com/ionide/tree-sitter-fsharp/issues/176)) |
42+
| 6 | Resolve F# `open` statements | F# support PR (commits 1+2) |
43+
| 7 | Razor/Blazor extractor | Can be submitted independently (tree-sitter-razor builds from source) |
44+
| 8 | Deep extraction (F#/Razor parts) | F# and Razor PRs; C# parts could be extracted independently |
45+
46+
---
1047

1148
## Commits (in order)
1249

@@ -43,6 +80,7 @@ Registers `.fs` and `.fsx` in `_DISPATCH`.
4380

4481
**Files:** `graphify/extract.py`
4582
**PR scope:** Independent improvement, benefits all .NET languages (C#, F#)
83+
**Submitted:** [PR #440](https://github.com/safishamsi/graphify/pull/440)
4684

4785
Adds a blocklist of ~120 common .NET BCL/framework method names (`Contains`, `Equals`, `ToString`, `Where`, `Select`, `ListAsync`, `CreateDbContext`, etc.) that are skipped during cross-file call resolution.
4886

@@ -56,6 +94,7 @@ Adds a blocklist of ~120 common .NET BCL/framework method names (`Contains`, `Eq
5694

5795
**Files:** `graphify/extract.py`
5896
**PR scope:** Independent improvement, benefits all languages
97+
**Submitted:** [PR #441](https://github.com/safishamsi/graphify/pull/441)
5998

6099
Adds a post-extraction pass that detects when multiple files produce nodes with the same ID (because `_make_id(stem, name)` uses only the file stem). When collisions are found, the parent directory name is prepended to disambiguate.
61100

@@ -69,6 +108,7 @@ Adds a post-extraction pass that detects when multiple files produce nodes with
69108

70109
**Files:** `graphify/extract.py`
71110
**PR scope:** Cross-language improvement, benefits C#/F# mixed projects
111+
**Submitted:** [PR #442](https://github.com/safishamsi/graphify/pull/442)
72112

73113
Adds a post-extraction pass that merges stub nodes (empty `source_file`) with real definitions by matching labels. Prioritizes definition files (`Interfaces.fs`, `Domain.fs`, `Types.fs`, `Contracts.fs`, `Abstractions.fs`).
74114

@@ -87,6 +127,33 @@ Adds a post-extraction pass that resolves F# `open` import targets to actual fil
87127

88128
---
89129

130+
### 7. `337f088` — feat: add Razor/Blazor extractor with tree-sitter-razor
131+
132+
**Files:** `graphify/detect.py`, `graphify/extract.py`
133+
**PR scope:** Main feature PR, depends on tree-sitter-razor (can be built from source)
134+
**Depends on:** Commit 1 (extension registration pattern)
135+
136+
Adds `extract_razor()` function that parses `.razor` files using
137+
[tris203/tree-sitter-razor](https://github.com/tris203/tree-sitter-razor) and extracts:
138+
- `@inject` directives as service dependency edges
139+
- `@using` directives as import edges
140+
- `@implements` directives as inherits edges
141+
- Blazor component references (`<StatusBadge>`, `<SubmitBookDialog>`) excluding FluentUI and framework-internal components
142+
- Method declarations from `@code { }` blocks
143+
- Static method calls (`ClassName.Method()`) from `@code` blocks
144+
145+
**Problem:** In Blazor projects, many C# classes (e.g. `DashboardFilterHelper`) are only
146+
referenced from `.razor` files. Without Razor support, these classes appear as completely
147+
disconnected graph components despite being core to the application.
148+
149+
**Impact:** Main graph component grew from 915 to 995 nodes. `DashboardFilterHelper` and
150+
its 27-node cluster joined the main component.
151+
152+
**Note:** `tree-sitter-razor` has a `setup.py` but the upstream version is missing `scanner.c`
153+
in the sources list. Fix submitted: [tree-sitter-razor PR #19](https://github.com/tris203/tree-sitter-razor/pull/19).
154+
155+
---
156+
90157
### 8. `478bdcb` — fix: deep extraction improvements for C# and F#
91158

92159
**Files:** `graphify/extract.py`
@@ -113,21 +180,11 @@ Multiple fixes to the C#, F#, and Razor extractors:
113180

114181
---
115182

116-
## Updated PR Strategy
117-
118-
1. **PR 1 (Commits 1 + 2):** "Add F# language support" — blocked on tree-sitter-fsharp PyPI.
119-
2. **PR 2 (Commit 3):** "Add BCL method blocklist" — **submit now**.
120-
3. **PR 3 (Commit 4):** "Fix node ID collisions" — **submit now**.
121-
4. **PR 4 (Commit 5):** "Merge stub nodes" — **submit now**.
122-
5. **PR 5 (Commit 6):** "Resolve F# open statements" — depends on PR 1.
123-
6. **PR 6 (Commit 7):** "Add Razor/Blazor support" — can be submitted independently.
124-
7. **PR 7 (Commit 8):** "Deep extraction improvements" — **submit now** (C# parts are generic; F#/Razor parts depend on PRs 1, 6).
183+
## Local Build Instructions
125184

126-
PRs 2, 3, 4, and the C# parts of 7 are independent improvements that benefit all languages and can be submitted right away.
185+
### tree-sitter-fsharp Python Bindings
127186

128-
## Local Build: tree-sitter-fsharp Python Bindings
129-
130-
Until tree-sitter-fsharp publishes to PyPI, build locally:
187+
Until tree-sitter-fsharp publishes to PyPI ([#176](https://github.com/ionide/tree-sitter-fsharp/issues/176)), build locally:
131188

132189
```bash
133190
git clone https://github.com/ionide/tree-sitter-fsharp /path/to/tree-sitter-fsharp
@@ -164,51 +221,13 @@ INIT
164221
pip install -e .
165222
```
166223

167-
### 7. `337f088` — feat: add Razor/Blazor extractor with tree-sitter-razor
168-
169-
**Files:** `graphify/detect.py`, `graphify/extract.py`
170-
**PR scope:** Main feature PR, depends on tree-sitter-razor (can be built from source)
171-
**Depends on:** Commit 1 (extension registration pattern)
172-
173-
Adds `extract_razor()` function that parses `.razor` files using
174-
[tris203/tree-sitter-razor](https://github.com/tris203/tree-sitter-razor) and extracts:
175-
- `@inject` directives as service dependency edges
176-
- `@using` directives as import edges
177-
- `@implements` directives as inherits edges
178-
- Blazor component references (`<StatusBadge>`, `<SubmitBookDialog>`) excluding FluentUI and framework-internal components
179-
- Method declarations from `@code { }` blocks
180-
- Static method calls (`ClassName.Method()`) from `@code` blocks
181-
182-
**Problem:** In Blazor projects, many C# classes (e.g. `DashboardFilterHelper`) are only
183-
referenced from `.razor` files. Without Razor support, these classes appear as completely
184-
disconnected graph components despite being core to the application.
185-
186-
**Impact:** Main graph component grew from 915 to 995 nodes. `DashboardFilterHelper` and
187-
its 27-node cluster joined the main component.
188-
189-
**Note:** `tree-sitter-razor` has a `setup.py` but the upstream version is missing `scanner.c`
190-
in the sources list. Fix: add `"src/scanner.c"` to the `ext_modules` sources in `setup.py`.
191-
192-
---
193-
194-
## Updated PR Strategy
195-
196-
1. **PR 1 (Commits 1 + 2):** "Add F# language support" — blocked on tree-sitter-fsharp PyPI.
197-
2. **PR 2 (Commit 3):** "Add BCL method blocklist" — **submit now**.
198-
3. **PR 3 (Commit 4):** "Fix node ID collisions" — **submit now**.
199-
4. **PR 4 (Commit 5):** "Merge stub nodes" — **submit now**.
200-
5. **PR 5 (Commit 6):** "Resolve F# open statements" — depends on PR 1.
201-
6. **PR 6 (Commit 7):** "Add Razor/Blazor support" — can be submitted independently (tree-sitter-razor builds from source).
202-
203-
---
204-
205-
## Local Build: tree-sitter-razor Python Bindings
224+
### tree-sitter-razor Python Bindings
206225

207226
```bash
208227
git clone https://github.com/tris203/tree-sitter-razor /path/to/tree-sitter-razor
209228
cd /path/to/tree-sitter-razor
210229

211-
# Fix setup.py: add scanner.c to sources
230+
# Fix setup.py: add scanner.c to sources (PR #19 pending)
212231
# In setup.py, change:
213232
# sources=["bindings/python/tree_sitter_razor/binding.c", "src/parser.c"]
214233
# To:
@@ -221,14 +240,14 @@ pip install -e .
221240

222241
## Test Results
223242

224-
Tested on a mixed F#/C#/Blazor project (BooksKnowledgeDistillation):
243+
Tested on a mixed F#/C#/Blazor project (BooksKnowledgeDistillation, 141 code files):
225244

226245
| Metric | Before | After all fixes |
227246
|--------|--------|-----------------|
228247
| Nodes | 1055 | 1127 |
229248
| Edges | 1699 | 2177 |
230249
| INFERRED edges | 538 | 362 |
231-
| Communities | 57 | 44 |
250+
| Communities | 57 | 44 (all labeled) |
232251
| Isolated (degree=0) | 119 | 3 |
233252
| Main component | 915 | 1058 |
234253
| Disconnected components | 24 | 20 |
@@ -240,3 +259,5 @@ Tested on a mixed F#/C#/Blazor project (BooksKnowledgeDistillation):
240259
| BookDbContext | disconnected | in main component |
241260
| PipelineMetrics | disconnected | in main component |
242261
| ApiKeyMiddleware | disconnected | in main component |
262+
263+
The remaining 20 disconnected components are genuinely isolated code: Python utility scripts, JavaScript files, test classes without external references, unused Blazor components, and legacy code.

0 commit comments

Comments
 (0)