Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 28x 23x 13x 8x 8x 32x 13x 3x 1x 18x 13x 13x 13x 13x 13x 23x 32x 20x 20x 32x 6x 6x 13x 13x 13x 18x | import { useMemo } from "react";
import {
analyzeStaticIO,
analyzeStaticIOProject,
type StaticIOCall,
} from "@shared/io-registry-parser";
import type { PinMode } from "@shared/types/arduino.types";
import type { SourceProject } from "@shared/source-project";
interface SketchAnalysisResult {
analogPins: number[]; // concrete Arduino pin numbers (A0 -> 14)
varMap: Record<string, number>;
detectedPinModes: Record<number, PinMode>;
pendingPinConflicts: number[]; // pins that are both used as analogRead and declared via pinMode
digitalPinsFromPinMode: number[];
}
function toAnalogBoardPin(pinId: number): number | undefined {
if (pinId >= 0 && pinId <= 5) return pinId + 14;
Eif (pinId >= 14 && pinId <= 19) return pinId;
return undefined;
}
function projectVarMap(symbols: Record<string, number>): Record<string, number> {
return Object.fromEntries(
Object.entries(symbols).flatMap(([name, pinId]) => {
const analogPin = toAnalogBoardPin(pinId);
return analogPin === undefined ? [] : [[name, analogPin]];
}),
);
}
function isVisibleAnalogRead(call: StaticIOCall): boolean {
return call.op === "analogRead" && call.loopBody !== "braceless";
}
function analyzeSource(source: string | SourceProject | null | undefined) {
if (typeof source === "string") return analyzeStaticIO(source);
if (source) return analyzeStaticIOProject(source);
return { pins: [], unresolvedCalls: [], symbols: {} };
}
// Hook: pure projection of the canonical static I/O analysis for board state.
export function useSketchAnalysis(
source: string | SourceProject | null | undefined,
): SketchAnalysisResult {
return useMemo(() => {
const analysis = analyzeSource(source);
const analogPins = new Set<number>();
const pinModePins = new Set<number>();
const detectedPinModes: Record<number, PinMode> = {};
for (const { pinId, calls } of analysis.pins) {
for (const call of calls) {
if (isVisibleAnalogRead(call)) {
const analogPin = toAnalogBoardPin(pinId);
Eif (analogPin !== undefined) analogPins.add(analogPin);
}
if (call.op === "pinMode" && call.mode !== undefined) {
pinModePins.add(pinId);
detectedPinModes[pinId] = call.mode;
}
}
}
const sortedAnalogPins = [...analogPins].sort((a, b) => a - b);
const sortedPinModePins = [...pinModePins].sort((a, b) => a - b);
return {
analogPins: sortedAnalogPins,
varMap: projectVarMap(analysis.symbols),
detectedPinModes,
pendingPinConflicts: sortedAnalogPins.filter((pin) =>
pinModePins.has(pin)
),
digitalPinsFromPinMode: sortedPinModePins,
};
}, [source]);
}
|