2026TypeScript · VS Code Extension API · tree-sitter · hyparquet · esbuild

PolarSense

VS Code-extensie. Bekijk de rijen van databestanden, kolomstatistieken en grafieken + aanvulling van kolomnamen, controle op typfouten en statistieken bij hover voor polars, pandas en duckdb.

Het probleem

De autoaanvulling stopt bij het aanhalingsteken.

Je schrijft een polars-query, je grijpt naar een kolom, en de editor heeft niets te zeggen — want kolomnamen zijn strings, en geen enkele typechecker kijkt in een string. Dus schakel je naar een terminal, print je het schema, lees je er een naam af, kom je terug, tik je hem in, sla je één letter mis, en kom je er pas tijdens het uitvoeren achter, na een scan waarvoor je betaald hebt. Tien keer per uur, op een bestand waarvan je de kolommen half onthouden hebt.

De voor de hand liggende oplossing is de code uitvoeren. Een kernel starten, polars importeren, genoeg van het script draaien om een echt DataFrame in het geheugen te hebben, en het dat vragen. Elk bestaand antwoord op dit probleem werkt zo, en ik heb het verworpen.

Wat ik koos

Het schema ligt al op schijf. De footer van een parquet-bestand legt het vast. De headerrij van een CSV net zo goed, en ook de schema-flatbuffer van Arrow IPC, het commitlog van Delta, de metadata-pointer van Iceberg, de headerrij binnen de zip van een .xlsx. PolarSense opent het bestand waar je frame werkelijk vandaan komt, leest dat, en biedt de namen aan.

Het importeert nooit polars, start nooit een Python-interpreter, voert nooit een regel van je code uit. Voor parquet is de hele lees-operatie twee byte-ranges uit de footer, dus een bestand van vier miljoen rijen kost precies wat een bestand van tweehonderd rijen kost. Schema's worden gelezen wanneer een bestand opengaat in plaats van wanneer je er als eerste om vraagt, en gecachet op mtime en grootte: de eerste aanvulling is al een cache hit.

De andere helft van het werk is weten uit welk bestand het frame onder je cursor komt, en welke vorm het heeft tegen de tijd dat het daar aankomt. Toewijzingen worden door het bestand heen gevolgd; een method chain wordt gevolgd; een select versmalt, een rename hernoemt, een join biedt beide kanten aan met gesuffixeerde botsingen, een group_by().agg() geeft sleutels plus aggregaten terug, een unnest zet de velden van een struct op zijn plaats. Paden hoeven geen letterlijke strings te zijn — moduleconstanten, f-strings, os.path.join, Path(__file__).parent / "sales.parquet" vouwen eerst samen tot een pad. Imports worden twee sprongen ver de workspace in gevolgd, dus een laadfunctie in een ander bestand lost alsnog op.

Wat ik verwierp

De code uitvoeren. Het is het juiste antwoord voor de gevallen die statisch lezen niet bereikt, en het betekent een editor-extensie die het script van een onbekende repository uitvoert op het moment dat je hem opent. Neveneffecten, credentials, een DROP TABLE in een migratiescript, en een koude start die je bij elke toetsaanslag voelt. Een autoaanvulling is dat niet waard, en "leest bytes, voert niets uit" is het hele product.

De workspace op de achtergrond indexeren. Verworpen om dezelfde reden waarom een linter die site-packages doorloopt onaangenaam is: alleen de modules die je geopende bestand echt importeert worden gelezen, en er draait niets zolang je niets vraagt.

Gokken. Dit was de moeilijke, en hij komt op vier plaatsen terug. De waarschuwing voor een onbekende kolom blijft volledig stil zodra iets tussen het bestand en de cursor niet gemodelleerd kon worden — een onleesbare selector, een niet-gemodelleerde reshape, een bestand dat niet geopend kon worden — want een diagnostic die wolf roept wordt uitgezet en nooit meer aangezet. Waarde-aanvulling biedt boven vijftig verschillende waarden helemaal niets meer aan, in plaats van een afgekapte lijst, want honderd van vier miljoen order-id's zijn een bewering over hoeveel er zijn, en een onjuiste. Een lezing die niet elke rij dekte zegt dat op elk item. En pyarrow wordt ronduit niet ondersteund: read_table betekent parquet in pyarrow en CSV in pandas, en die uit elkaar houden vereist weten uit welke module de aanroep kwam.

Wat het kostte

Sommige reshapes zijn niet te beantwoorden zonder rijen te lezen. pivot, to_dummies en een transpose zonder expliciete namen halen hun uitvoerkolommen uit de waarden in het bestand in plaats van uit iets dat in de code geschreven staat. De extensie houdt de kolommen die ze had, sorteert ze onder de zekere antwoorden, en markeert ze als gok.

SQL wordt gescand, niet geparseerd — literals en commentaar gemaskeerd, en dan is wat op FROM en JOIN volgt een tabel. Dus elke tabel in een statement is overal in dat statement in scope, een join biedt beide kanten aan als onzeker, en SQL-posities worden helemaal niet op typefouten gecontroleerd.

De afweging die me nog steeds stoort zijn de preview-panelen. Ze beschrijven het bestand, niet het frame: de kolommen zijn correct versmald door alles op weg naar je cursor, maar het aantal rijen, de bestandsgrootte en de codec horen bij het bestand erachter, en een filter verandert daar niets aan. Ze zeggen transforms not applied in plaats van vier miljoen rijen te tonen en dat het frame te noemen. Dat gat dichten betekent je code uitvoeren — wat het graph-paneel nu doet, in een notebook met een levende kernel, opt-in en alleen-lezen, en de eerste keer om toestemming vragend. Dat is de enige plek waar de regel van niet-uitvoeren gebroken wordt. Ze wordt bewust gebroken, in één functie, achter een instelling, en hardop gezegd in plaats van stilletjes veralgemeend.

Het resultaat

Gepubliceerd op de VS Code Marketplace. Het aantal installaties is nog geen getal dat het citeren waard is, dus hier zijn de getallen die eerlijk zijn: zeven bestandsformaten gelezen, ongeveer veertig aanvulpunten verspreid over polars, pandas en duckdb, een gepackagede extensie van ruwweg 200 kB die geen enkele node_modules meedraagt, geen telemetrie, en niets dat de machine verlaat behalve byte-ranges van de bestanden die je aanwijst.

← Al het werk