Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
e4edffa569 | |||
c28bad267a | |||
81f92bc7f9 | |||
58dc3382eb | |||
f7f7d9fa2c | |||
8c3408fda3 | |||
7c9f1248d4 | |||
89dd4fb039 | |||
fdeb2b3f49 | |||
65c455ae7c | |||
c3e12e5ff7 | |||
4dce1612c1 | |||
1b98897120 | |||
3b2abe5814 | |||
dddcd5ff46 | |||
cfbb03765e | |||
0d0dd1019b | |||
de2b1b3bea |
16
.github/workflows/e2e-tests.yml
vendored
@ -1,7 +1,9 @@
|
||||
name: E2E Tests
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- main
|
||||
- all-e2e # this bypasses `fixme()` using `orRunWhenFullSuiteEnabled()`
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: 0 * * * * # hourly
|
||||
@ -15,7 +17,6 @@ permissions:
|
||||
pull-requests: write
|
||||
actions: read
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
conditions:
|
||||
@ -67,14 +68,16 @@ jobs:
|
||||
- name: Display conditions
|
||||
shell: bash
|
||||
run: |
|
||||
# For debugging purposes.
|
||||
# For debugging purposes
|
||||
set -euo pipefail
|
||||
echo "GITHUB_REF: $GITHUB_REF"
|
||||
echo "GITHUB_HEAD_REF: $GITHUB_HEAD_REF"
|
||||
echo "GITHUB_BASE_REF: $GITHUB_BASE_REF"
|
||||
echo "significant: ${{ steps.path-changes.outputs.significant }}"
|
||||
echo "should-run: ${{ steps.should-run.outputs.should-run }}"
|
||||
|
||||
|
||||
prepare-wasm:
|
||||
# seperate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||
# separate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||
needs: conditions
|
||||
steps:
|
||||
@ -160,7 +163,6 @@ jobs:
|
||||
path: |
|
||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||
|
||||
|
||||
snapshots:
|
||||
name: playwright:snapshots:ubuntu
|
||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||
@ -243,7 +245,7 @@ jobs:
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
||||
- name: check for changes
|
||||
- name: Check for changes
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.ref != 'refs/heads/main' }}
|
||||
shell: bash
|
||||
id: git-check
|
||||
|
4
.github/workflows/static-analysis.yml
vendored
@ -141,13 +141,13 @@ jobs:
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||
run: yarn playwright install chromium --with-deps
|
||||
|
||||
- name: run unit tests
|
||||
- name: Run unit tests
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||
run: xvfb-run -a yarn test:unit
|
||||
env:
|
||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
|
||||
- name: check for changes
|
||||
- name: Check for changes
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||
id: git-check
|
||||
run: |
|
||||
|
14
.github/workflows/update-e2e-branch.yml
vendored
@ -14,10 +14,19 @@ permissions:
|
||||
jobs:
|
||||
update-branch:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- shell: bash
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Sync with main
|
||||
run: |
|
||||
# checkout our branch
|
||||
git checkout all-e2e || git checkout -b all-e2e
|
||||
@ -26,4 +35,5 @@ jobs:
|
||||
# reset to main
|
||||
git reset --hard origin/main
|
||||
# force push it
|
||||
git remote set-url origin https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git
|
||||
git push --force origin all-e2e
|
||||
|
32
Makefile
@ -20,8 +20,12 @@ $(WASM_PACK):
|
||||
###############################################################################
|
||||
# BUILD
|
||||
|
||||
RUST_SOURCES := $(wildcard rust/*) $(wildcard rust/**/*)
|
||||
TYPESCRIPT_SOURCES := $(wildcard src/**/*.tsx) $(wildcard src/**/*.ts)
|
||||
CARGO_SOURCES := rust/.cargo/config.toml $(wildcard rust/Cargo.*) $(wildcard rust/**/Cargo.*)
|
||||
RUST_SOURCES := $(wildcard rust/**/*.rs)
|
||||
|
||||
REACT_SOURCES := $(wildcard src/*.tsx) $(wildcard src/**/*.tsx)
|
||||
TYPESCRIPT_SOURCES := tsconfig.* $(wildcard src/*.ts) $(wildcard src/**/*.ts)
|
||||
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
|
||||
|
||||
.PHONY: build
|
||||
build: build-web build-desktop
|
||||
@ -32,13 +36,13 @@ build-web: public/kcl_wasm_lib_bg.wasm build/index.html
|
||||
.PHONY: build-desktop
|
||||
build-desktop: public/kcl_wasm_lib_bg.wasm .vite/build/main.js
|
||||
|
||||
public/kcl_wasm_lib_bg.wasm: $(RUST_SOURCES)
|
||||
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES)$(RUST_SOURCES)
|
||||
yarn build:wasm
|
||||
|
||||
build/index.html: $(TYPESCRIPT_SOURCES)
|
||||
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||
yarn build:local
|
||||
|
||||
.vite/build/main.js: $(TYPESCRIPT_SOURCES)
|
||||
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||
yarn tronb:vite:dev
|
||||
|
||||
###############################################################################
|
||||
@ -73,19 +77,29 @@ run-desktop: install build-desktop ## Start the desktop app
|
||||
###############################################################################
|
||||
# TEST
|
||||
|
||||
GREP ?= ""
|
||||
E2E_WORKERS ?= 1
|
||||
E2E_FAILURES ?= 1
|
||||
E2E_GREP ?= ""
|
||||
|
||||
.PHONY: test
|
||||
test: test-unit test-e2e
|
||||
|
||||
.PHONY: test-unit
|
||||
test-unit: install ## Run the unit tests
|
||||
@ nc -z localhost 3000 || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
||||
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
||||
yarn test:unit
|
||||
|
||||
.PHONY: test-e2e
|
||||
test-e2e: install build-desktop ## Run the e2e tests
|
||||
yarn test:playwright:electron --workers=1 --grep=$(GREP)
|
||||
test-e2e: test-e2e-desktop
|
||||
|
||||
.PHONY: test-e2e-web
|
||||
test-e2e-web: install build-web ## Run the web e2e tests
|
||||
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
||||
yarn chrome:test --headed --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep=$(E2E_GREP)
|
||||
|
||||
.PHONY: test-e2e-desktop
|
||||
test-e2e-desktop: install build-desktop ## Run the desktop e2e tests
|
||||
yarn test:playwright:electron --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep=$(E2E_GREP)
|
||||
|
||||
###############################################################################
|
||||
# CLEAN
|
||||
|
@ -10,10 +10,10 @@ Construct a circle derived from 3 points.
|
||||
|
||||
```js
|
||||
circleThreePoint(
|
||||
sketchSurfaceOrGroup: SketchOrSurface,
|
||||
p1: [number],
|
||||
p2: [number],
|
||||
p3: [number],
|
||||
sketchSurfaceOrGroup: SketchOrSurface,
|
||||
tag?: TagDeclarator,
|
||||
): Sketch
|
||||
```
|
||||
@ -23,10 +23,10 @@ circleThreePoint(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSurfaceOrGroup` | [`SketchOrSurface`](/docs/kcl/types/SketchOrSurface) | Plane or surface to sketch on. | Yes |
|
||||
| `p1` | [`[number]`](/docs/kcl/types/number) | 1st point to derive the circle. | Yes |
|
||||
| `p2` | [`[number]`](/docs/kcl/types/number) | 2nd point to derive the circle. | Yes |
|
||||
| `p3` | [`[number]`](/docs/kcl/types/number) | 3rd point to derive the circle. | Yes |
|
||||
| `sketchSurfaceOrGroup` | [`SketchOrSurface`](/docs/kcl/types/SketchOrSurface) | Plane or surface to sketch on. | Yes |
|
||||
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | Identifier for the circle to reference elsewhere. | No |
|
||||
|
||||
### Returns
|
||||
|
@ -15,7 +15,7 @@ std::math::E: number = 2.71828182845904523536028747135266250_
|
||||
### Examples
|
||||
|
||||
```js
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({
|
||||
angle = 30,
|
||||
|
@ -17,7 +17,7 @@ std::math::PI: number = 3.14159265358979323846264338327950288_
|
||||
```js
|
||||
circumference = 70
|
||||
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = circumference/ (2 * PI))
|
||||
|
||||
example = extrude(exampleSketch, length = 5)
|
||||
|
@ -15,7 +15,7 @@ std::math::TAU: number = 6.28318530717958647692528676655900577_
|
||||
### Examples
|
||||
|
||||
```js
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({
|
||||
angle = 50,
|
||||
|
@ -61,7 +61,6 @@ layout: manual
|
||||
* [`bezierCurve`](kcl/bezierCurve)
|
||||
* [`ceil`](kcl/ceil)
|
||||
* [`chamfer`](kcl/chamfer)
|
||||
* [`circle`](kcl/circle)
|
||||
* [`circleThreePoint`](kcl/circleThreePoint)
|
||||
* [`close`](kcl/close)
|
||||
* [`cm`](kcl/cm)
|
||||
@ -145,3 +144,5 @@ layout: manual
|
||||
* [`cos`](kcl/std-math-cos)
|
||||
* [`sin`](kcl/std-math-sin)
|
||||
* [`tan`](kcl/std-math-tan)
|
||||
* **std::sketch**
|
||||
* [`circle`](kcl/std-sketch-circle)
|
||||
|
@ -9,7 +9,7 @@ Compute the cosine of a number (in radians).
|
||||
|
||||
|
||||
```js
|
||||
cos(num: number(rad)): number(_)
|
||||
cos(@num: number(rad)): number(_)
|
||||
```
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ cos(num: number(rad)): number(_)
|
||||
### Examples
|
||||
|
||||
```js
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({
|
||||
angle = 30,
|
||||
|
@ -9,7 +9,7 @@ Compute the sine of a number (in radians).
|
||||
|
||||
|
||||
```js
|
||||
sin(num: number(rad)): number(_)
|
||||
sin(@num: number(rad)): number(_)
|
||||
```
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ sin(num: number(rad)): number(_)
|
||||
### Examples
|
||||
|
||||
```js
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({
|
||||
angle = 50,
|
||||
|
@ -9,7 +9,7 @@ Compute the tangent of a number (in radians).
|
||||
|
||||
|
||||
```js
|
||||
tan(num: number(rad)): number(_)
|
||||
tan(@num: number(rad)): number(_)
|
||||
```
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ tan(num: number(rad)): number(_)
|
||||
### Examples
|
||||
|
||||
```js
|
||||
exampleSketch = startSketchOn("XZ")
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({
|
||||
angle = 50,
|
||||
|
55
docs/kcl/std-sketch-circle.md
Normal file
12937
docs/kcl/std.json
@ -10,8 +10,8 @@ A point in two dimensional space.
|
||||
type Point2d = [number; 2]
|
||||
```
|
||||
|
||||
`Point2d` is an alias for a two-element array of [number](/docs/kcl/types/number)s. To write a value
|
||||
with type `Point2d`, use an array, e.g., `[0, 0]` or `[5.0, 3.14]`.
|
||||
[`Point2d`](/docs/kcl/types/Point2d) is an alias for a two-element array of [number](/docs/kcl/types/number)s. To write a value
|
||||
with type [`Point2d`](/docs/kcl/types/Point2d), use an array, e.g., `[0, 0]` or `[5.0, 3.14]`.
|
||||
|
||||
|
||||
|
||||
|
@ -10,8 +10,8 @@ A point in three dimensional space.
|
||||
type Point3d = [number; 3]
|
||||
```
|
||||
|
||||
`Point3d` is an alias for a three-element array of [number](/docs/kcl/types/number)s. To write a value
|
||||
with type `Point3d`, use an array, e.g., `[0, 0, 0]` or `[5.0, 3.14, 6.8]`.
|
||||
[`Point3d`](/docs/kcl/types/Point3d) is an alias for a three-element array of [number](/docs/kcl/types/number)s. To write a value
|
||||
with type [`Point3d`](/docs/kcl/types/Point3d), use an array, e.g., `[0, 0, 0]` or `[5.0, 3.14, 6.8]`.
|
||||
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ mySketch = startSketchOn('XY')
|
||||
|> close()
|
||||
```
|
||||
|
||||
The `mySketch` variable will be an executed `Sketch` object. Executed being past
|
||||
The `mySketch` variable will be an executed [`Sketch`](/docs/kcl/types/Sketch) object. Executed being past
|
||||
tense, because the engine has already executed the commands to create the sketch.
|
||||
|
||||
The previous sketch commands will never be executed again, in this case.
|
||||
|
@ -18,7 +18,7 @@ myPart = startSketchOn('XY')
|
||||
|> extrude(length = 6)
|
||||
```
|
||||
|
||||
The `myPart` variable will be an executed `Solid` object. Executed being past
|
||||
The `myPart` variable will be an executed [`Solid`](/docs/kcl/types/Solid) object. Executed being past
|
||||
tense, because the engine has already executed the commands to create the solid.
|
||||
|
||||
The previous solid commands will never be executed again, in this case.
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
executorInputPath,
|
||||
getUtils,
|
||||
orRunWhenFullSuiteEnabled,
|
||||
runningOnWindows,
|
||||
} from './test-utils'
|
||||
import { join } from 'path'
|
||||
import { FILE_EXT } from 'lib/constants'
|
||||
@ -15,6 +16,9 @@ test.describe('integrations tests', () => {
|
||||
'Creating a new file or switching file while in sketchMode should exit sketchMode',
|
||||
{ tag: '@electron' },
|
||||
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
||||
if (runningOnWindows()) {
|
||||
test.fixme(orRunWhenFullSuiteEnabled())
|
||||
}
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'test-sample')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
|
@ -1071,7 +1071,7 @@ openSketch = startSketchOn(XY)
|
||||
})
|
||||
})
|
||||
|
||||
test('Helix point-and-click', async ({
|
||||
test('Helix point-and-click on default axis', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
@ -1082,29 +1082,26 @@ openSketch = startSketchOn(XY)
|
||||
}) => {
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 620, y: 257 }
|
||||
const expectedOutput = `helix001 = helix( revolutions = 1, angleStart = 360, counterClockWise = false, radius = 5, axis = 'X', length = 5,)`
|
||||
const expectedOutput = `helix001 = helix( revolutions = 1, angleStart = 360, ccw = false, radius = 5, axis = 'X', length = 5,)`
|
||||
const expectedLine = `revolutions=1,`
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// await test.step(`Look for the red of the default plane`, async () => {
|
||||
// await scene.expectPixelColor([96, 52, 52], testPoint, 15)
|
||||
// })
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'revolutions',
|
||||
currentArgValue: '1',
|
||||
currentArgKey: 'axisOrEdge',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
AngleStart: '',
|
||||
Axis: '',
|
||||
AxisOrEdge: '',
|
||||
CounterClockWise: '',
|
||||
Length: '',
|
||||
Radius: '',
|
||||
Revolutions: '',
|
||||
},
|
||||
highlightedHeaderArg: 'revolutions',
|
||||
highlightedHeaderArg: 'axisOrEdge',
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
@ -1114,6 +1111,7 @@ openSketch = startSketchOn(XY)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.progressCmdBar()
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
@ -1179,6 +1177,165 @@ openSketch = startSketchOn(XY)
|
||||
})
|
||||
})
|
||||
|
||||
const helixCases = [
|
||||
{
|
||||
selectionType: 'segment',
|
||||
testPoint: { x: 513, y: 221 },
|
||||
expectedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = seg01, length = 100,)`,
|
||||
expectedEditedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = seg01, length = 50,)`,
|
||||
},
|
||||
{
|
||||
selectionType: 'sweepEdge',
|
||||
testPoint: { x: 564, y: 364 },
|
||||
expectedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = getOppositeEdge(seg01), length = 100,)`,
|
||||
expectedEditedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = getOppositeEdge(seg01), length = 50,)`,
|
||||
},
|
||||
]
|
||||
helixCases.map(
|
||||
({ selectionType, testPoint, expectedOutput, expectedEditedOutput }) => {
|
||||
test(`Helix point-and-click around ${selectionType}`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
page.on('console', console.log)
|
||||
const initialCode = `sketch001 = startSketchOn('XZ')
|
||||
profile001 = startProfileAt([0, 0], sketch001)
|
||||
|> yLine(length = 100)
|
||||
|> line(endAbsolute = [100, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(profile001, length = 100)`
|
||||
|
||||
// One dumb hardcoded screen pixel value
|
||||
const [clickOnEdge] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'axisOrEdge',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
AngleStart: '',
|
||||
AxisOrEdge: '',
|
||||
CounterClockWise: '',
|
||||
Length: '',
|
||||
Radius: '',
|
||||
Revolutions: '',
|
||||
},
|
||||
highlightedHeaderArg: 'axisOrEdge',
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.selectOption({ name: 'Edge' }).click()
|
||||
await clickOnEdge()
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.argumentInput.focus()
|
||||
await page.keyboard.insertText('20')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('0')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.selectOption({ name: 'True' }).click()
|
||||
await page.keyboard.insertText('1')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('100')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
AxisOrEdge: 'Edge',
|
||||
Edge: `1 ${selectionType}`,
|
||||
CounterClockWise: '',
|
||||
Length: '100',
|
||||
Radius: '1',
|
||||
Revolutions: '20',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(expectedOutput)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step(`Edit helix through the feature tree`, async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Helix',
|
||||
0
|
||||
)
|
||||
await operationButton.dblclick()
|
||||
const initialInput = '100'
|
||||
const newInput = '50'
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'length',
|
||||
currentArgValue: initialInput,
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
CounterClockWise: '',
|
||||
Length: initialInput,
|
||||
Radius: '1',
|
||||
Revolutions: '20',
|
||||
},
|
||||
highlightedHeaderArg: 'length',
|
||||
})
|
||||
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
||||
await cmdBar.currentArgumentInput
|
||||
.locator('.cm-content')
|
||||
.fill(newInput)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
CounterClockWise: '',
|
||||
Length: newInput,
|
||||
Radius: '1',
|
||||
Revolutions: '20',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await toolbar.closePane('feature-tree')
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(expectedEditedOutput)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step('Delete helix via feature tree selection', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Helix',
|
||||
0
|
||||
)
|
||||
await operationButton.click({ button: 'left' })
|
||||
await page.keyboard.press('Delete')
|
||||
await editor.expectEditor.not.toContain(expectedEditedOutput)
|
||||
await expect(
|
||||
await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
const loftPointAndClickCases = [
|
||||
{ shouldPreselect: true },
|
||||
{ shouldPreselect: false },
|
||||
|
@ -191,7 +191,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `Expected a tag declarator`
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
|
||||
// black pixel means the scene has been cleared.
|
||||
@ -409,7 +409,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `Expected a tag declarator`
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
|
||||
// black pixel means the scene has been cleared.
|
||||
@ -453,7 +453,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `Expected a tag declarator`
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
}
|
||||
)
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
@ -29,5 +29,5 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"kcl_version": "0.2.52"
|
||||
"kcl_version": "0.2.53"
|
||||
}
|
96
e2e/playwright/test-utils.test.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import {
|
||||
runningOnLinux,
|
||||
runningOnMac,
|
||||
runningOnWindows,
|
||||
orRunWhenFullSuiteEnabled,
|
||||
} from './test-utils'
|
||||
|
||||
describe('platform detection utilities', () => {
|
||||
const originalPlatform = process.platform
|
||||
|
||||
afterAll(() => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
})
|
||||
})
|
||||
|
||||
describe('runningOnLinux', () => {
|
||||
it('returns true on Linux', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
})
|
||||
expect(runningOnLinux()).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false on other platforms', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'darwin',
|
||||
})
|
||||
expect(runningOnLinux()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('runningOnMac', () => {
|
||||
it('returns true on Mac', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'darwin',
|
||||
})
|
||||
expect(runningOnMac()).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false on other platforms', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
})
|
||||
expect(runningOnMac()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('runningOnWindows', () => {
|
||||
it('returns true on Windows', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'win32',
|
||||
})
|
||||
expect(runningOnWindows()).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false on other platforms', () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
})
|
||||
expect(runningOnWindows()).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('utility to bypass unreliable tests', () => {
|
||||
const originalEnv = { ...process.env }
|
||||
|
||||
afterAll(() => {
|
||||
process.env = { ...originalEnv }
|
||||
})
|
||||
it('always runs them on dedicated branch', () => {
|
||||
process.env.GITHUB_EVENT_NAME = 'push'
|
||||
process.env.GITHUB_REF = 'refs/heads/all-e2e'
|
||||
process.env.GITHUB_HEAD_REF = ''
|
||||
process.env.GITHUB_BASE_REF = ''
|
||||
const condition = orRunWhenFullSuiteEnabled()
|
||||
expect(condition).toBe(false)
|
||||
})
|
||||
it('skips them on the main branch', () => {
|
||||
process.env.GITHUB_EVENT_NAME = 'push'
|
||||
process.env.GITHUB_REF = 'refs/heads/main'
|
||||
process.env.GITHUB_HEAD_REF = ''
|
||||
process.env.GITHUB_BASE_REF = ''
|
||||
const condition = orRunWhenFullSuiteEnabled()
|
||||
expect(condition).toBe(true)
|
||||
})
|
||||
it('skips them on pull requests', () => {
|
||||
process.env.GITHUB_EVENT_NAME = 'pull_request'
|
||||
process.env.GITHUB_REF = 'refs/pull/5883/merge'
|
||||
process.env.GITHUB_HEAD_REF = 'my-branch'
|
||||
process.env.GITHUB_BASE_REF = 'main'
|
||||
const condition = orRunWhenFullSuiteEnabled()
|
||||
expect(condition).toBe(true)
|
||||
})
|
||||
})
|
@ -55,8 +55,21 @@ export const commonPoints = {
|
||||
export const editorSelector = '[role="textbox"][data-language="kcl"]'
|
||||
type PaneId = 'variables' | 'code' | 'files' | 'logs'
|
||||
|
||||
export function runningOnLinux() {
|
||||
return process.platform === 'linux'
|
||||
}
|
||||
|
||||
export function runningOnMac() {
|
||||
return process.platform === 'darwin'
|
||||
}
|
||||
|
||||
export function runningOnWindows() {
|
||||
return process.platform === 'win32'
|
||||
}
|
||||
|
||||
export function orRunWhenFullSuiteEnabled() {
|
||||
return process.env.GITHUB_REF !== 'all-e2e'
|
||||
const branch = process.env.GITHUB_REF?.replace('refs/heads/', '')
|
||||
return branch !== 'all-e2e'
|
||||
}
|
||||
|
||||
async function waitForPageLoadWithRetry(page: Page) {
|
||||
|
3
interface.d.ts
vendored
@ -44,6 +44,9 @@ export interface IElectronAPI {
|
||||
rm: typeof fs.rm
|
||||
stat: (path: string) => ReturnType<fs.stat>
|
||||
statIsDirectory: (path: string) => Promise<boolean>
|
||||
canReadWriteDirectory: (
|
||||
path: string
|
||||
) => Promise<{ value: boolean; error: unknown }>
|
||||
path: typeof path
|
||||
mkdir: typeof fs.mkdir
|
||||
join: typeof path.join
|
||||
|
@ -75,17 +75,14 @@ LabeledArgument { ArgumentLabel Equals expression }
|
||||
ArgumentList { "(" commaSep<LabeledArgument | expression> ")" }
|
||||
|
||||
type[@isGroup=Type] {
|
||||
@specialize[@name=PrimitiveType]<
|
||||
identifier,
|
||||
"bool" | "number" | "string" | "tag" | "Sketch" | "SketchSurface" | "Solid" | "Plane"
|
||||
> |
|
||||
PrimitiveType { identifier } |
|
||||
ArrayType { "[" type !member (";" Number "+"?)? "]" } |
|
||||
ObjectType { "{" commaSep<ObjectProperty { PropertyName ":" type }> "}" }
|
||||
}
|
||||
|
||||
VariableDefinition { identifier }
|
||||
|
||||
VariableName { identifier }
|
||||
VariableName { identifier ("::" identifier)*}
|
||||
|
||||
ArgumentLabel { identifier }
|
||||
|
||||
@ -137,7 +134,7 @@ commaSep1NoTrailingComma<term> { term ("," term)* }
|
||||
"(" ")"
|
||||
"{" "}"
|
||||
"[" "]"
|
||||
"," "?" ":" "." ".." ";"
|
||||
"," "?" ":" "." ".." ";" "::"
|
||||
}
|
||||
|
||||
@external propSource kclHighlight from "./highlight"
|
||||
|
@ -18,7 +18,9 @@ const config = defineConfig({
|
||||
environment: 'node',
|
||||
reporters: process.env.GITHUB_ACTIONS
|
||||
? ['dot', 'github-actions']
|
||||
: ['verbose', 'hanging-process'],
|
||||
: // Gotcha: 'hanging-process' is very noisey, turn off by default on localhost
|
||||
// : ['verbose', 'hanging-process'],
|
||||
['verbose'],
|
||||
testTimeout: 1000,
|
||||
hookTimeout: 1000,
|
||||
teardownTimeout: 1000,
|
||||
|
@ -29,7 +29,7 @@
|
||||
"vscode-uri": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.13",
|
||||
"ts-node": "^10.9.2"
|
||||
}
|
||||
}
|
||||
|
@ -116,10 +116,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
|
||||
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
|
||||
|
||||
"@types/node@^22.13.10":
|
||||
version "22.13.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.10.tgz#df9ea358c5ed991266becc3109dc2dc9125d77e4"
|
||||
integrity sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==
|
||||
"@types/node@^22.13.13":
|
||||
version "22.13.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.13.tgz#5e7d110fb509b0d4a43fbf48fa9d6e0f83e1b1e7"
|
||||
integrity sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
|
@ -12,6 +12,7 @@ import { defineConfig, devices } from '@playwright/test'
|
||||
export default defineConfig({
|
||||
timeout: 120_000, // override the default 30s timeout
|
||||
testDir: './e2e/playwright',
|
||||
testIgnore: '*.test.ts', // ignore unit tests
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
|
20
rust/Cargo.lock
generated
@ -1780,7 +1780,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1791,7 +1791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-derive-docs"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1810,7 +1810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-directory-test-macro"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1819,7 +1819,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server"
|
||||
version = "0.2.53"
|
||||
version = "0.2.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1840,7 +1840,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1860,7 +1860,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.53"
|
||||
version = "0.2.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1928,7 +1928,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-python-bindings"
|
||||
version = "0.3.53"
|
||||
version = "0.3.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kcl-lib",
|
||||
@ -1943,7 +1943,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1956,7 +1956,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-to-core"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1970,7 +1970,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-wasm-lib"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
dependencies = [
|
||||
"bson",
|
||||
"console_error_panic_hook",
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/KittyCAD/modeling-api"
|
||||
rust-version = "1.76"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-directory-test-macro"
|
||||
description = "A tool for generating tests from a directory of kcl files"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
edition = "2021"
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
publish = false
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "kcl-language-server"
|
||||
description = "A language server for KCL."
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
version = "0.2.53"
|
||||
version = "0.2.54"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -135,13 +135,13 @@
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/vscode": "^1.97.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||
"@typescript-eslint/parser": "^6.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
||||
"@typescript-eslint/parser": "^8.27.0",
|
||||
"@vscode/test-electron": "^2.4.1",
|
||||
"@vscode/vsce": "^2.30.0",
|
||||
"@vscode/vsce": "^3.3.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.25.1",
|
||||
"glob": "^10.4.3",
|
||||
"glob": "^11.0.1",
|
||||
"mocha": "^11.1.0",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
|
@ -252,7 +252,7 @@
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@eslint-community/regexpp@^4.5.1":
|
||||
"@eslint-community/regexpp@^4.10.0":
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
@ -308,11 +308,6 @@
|
||||
"@types/minimatch" "^5.1.2"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/json-schema@^7.0.12":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
|
||||
"@types/minimatch@^5.1.2":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
@ -330,101 +325,91 @@
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
"@types/semver@^7.5.0":
|
||||
version "7.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
||||
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
|
||||
|
||||
"@types/vscode@^1.97.0":
|
||||
version "1.97.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.97.0.tgz#62ce3a32243019aaa4fc20cee2a3de06bc71af4f"
|
||||
integrity sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^6.6.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3"
|
||||
integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==
|
||||
"@typescript-eslint/eslint-plugin@^8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz#fbef10802365832ee1d1bd5d2117dcec82727a72"
|
||||
integrity sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.5.1"
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/type-utils" "6.21.0"
|
||||
"@typescript-eslint/utils" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
debug "^4.3.4"
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.27.0"
|
||||
"@typescript-eslint/type-utils" "8.27.0"
|
||||
"@typescript-eslint/utils" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.2.4"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/parser@^6.6.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b"
|
||||
integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
|
||||
"@typescript-eslint/parser@^8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.27.0.tgz#3f6beaa83934467eda34ae82ef04090014df8227"
|
||||
integrity sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@typescript-eslint/scope-manager" "8.27.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/typescript-estree" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1"
|
||||
integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==
|
||||
"@typescript-eslint/scope-manager@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz#b51042927067d677fbfc471605cf40d1ffaee482"
|
||||
integrity sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
|
||||
"@typescript-eslint/type-utils@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e"
|
||||
integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==
|
||||
"@typescript-eslint/type-utils@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz#af3c4eefcb64455ee50aae2d7069918467af085c"
|
||||
integrity sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
"@typescript-eslint/utils" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "8.27.0"
|
||||
"@typescript-eslint/utils" "8.27.0"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/types@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
|
||||
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
|
||||
"@typescript-eslint/types@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.27.0.tgz#3dd01ced4c81e798d1106fda0904f8d5c91051aa"
|
||||
integrity sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==
|
||||
|
||||
"@typescript-eslint/typescript-estree@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
|
||||
integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==
|
||||
"@typescript-eslint/typescript-estree@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz#4e02a1056454a84418cc9bce7c00b1c08b03567a"
|
||||
integrity sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "9.0.3"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
minimatch "^9.0.4"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/utils@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134"
|
||||
integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==
|
||||
"@typescript-eslint/utils@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.27.0.tgz#d9c2a4891c6a85b952a9d5f9656c379ab111cf6d"
|
||||
integrity sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@types/json-schema" "^7.0.12"
|
||||
"@types/semver" "^7.5.0"
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
semver "^7.5.4"
|
||||
"@typescript-eslint/scope-manager" "8.27.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/typescript-estree" "8.27.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47"
|
||||
integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==
|
||||
"@typescript-eslint/visitor-keys@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz#4a13e9d7ad7e311a07ea1b178b4c9f848ce11334"
|
||||
integrity sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@vscode/test-electron@^2.4.1":
|
||||
version "2.4.1"
|
||||
@ -497,10 +482,10 @@
|
||||
"@vscode/vsce-sign-win32-arm64" "2.0.2"
|
||||
"@vscode/vsce-sign-win32-x64" "2.0.2"
|
||||
|
||||
"@vscode/vsce@^2.30.0":
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-2.30.0.tgz#7a0c16b20ef529fa291fe9d3c7fe51a2a613f773"
|
||||
integrity sha512-MBYpXdCY1SCdc2u/y11kmJuSODKFyZRpeRTQq5p4rSg05QSjSy5pz6h/BGLNdSahgXfKRBATEkjAcJFdJuDz8Q==
|
||||
"@vscode/vsce@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.3.0.tgz#803e41368a95d35693ce049076503f34f89fde09"
|
||||
integrity sha512-HA/pUyvh/TQWkc4wG7AudPIWUvsR8i4jiWZZgM/a69ncPi9Nm5FDogf/wVEk4EWJs4/UdxU7J6X18dfAwfPbxA==
|
||||
dependencies:
|
||||
"@azure/identity" "^4.1.0"
|
||||
"@vscode/vsce-sign" "^2.0.0"
|
||||
@ -508,19 +493,19 @@
|
||||
chalk "^2.4.2"
|
||||
cheerio "^1.0.0-rc.9"
|
||||
cockatiel "^3.1.2"
|
||||
commander "^6.2.1"
|
||||
commander "^12.1.0"
|
||||
form-data "^4.0.0"
|
||||
glob "^7.0.6"
|
||||
glob "^11.0.0"
|
||||
hosted-git-info "^4.0.2"
|
||||
jsonc-parser "^3.2.0"
|
||||
leven "^3.1.0"
|
||||
markdown-it "^12.3.2"
|
||||
markdown-it "^14.1.0"
|
||||
mime "^1.3.4"
|
||||
minimatch "^3.0.3"
|
||||
parse-semver "^1.1.1"
|
||||
read "^1.0.7"
|
||||
semver "^7.5.2"
|
||||
tmp "^0.2.1"
|
||||
tmp "^0.2.3"
|
||||
typed-rest-client "^1.8.4"
|
||||
url-join "^4.0.1"
|
||||
xml2js "^0.5.0"
|
||||
@ -583,11 +568,6 @@ argparse@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
array-union@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@ -832,10 +812,10 @@ combined-stream@^1.0.8:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
commander@^12.1.0:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
|
||||
integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
@ -932,13 +912,6 @@ diff@^5.2.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531"
|
||||
integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
|
||||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
dom-serializer@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
|
||||
@ -1008,11 +981,6 @@ entities@^4.2.0, entities@^4.4.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
||||
|
||||
entities@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
@ -1071,11 +1039,16 @@ escape-string-regexp@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
|
||||
eslint-visitor-keys@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
|
||||
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
||||
|
||||
events@^3.0.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||
@ -1086,7 +1059,7 @@ expand-template@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||
|
||||
fast-glob@^3.2.9:
|
||||
fast-glob@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
|
||||
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
||||
@ -1153,11 +1126,6 @@ fs-constants@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
@ -1196,7 +1164,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^10.4.3, glob@^10.4.5:
|
||||
glob@^10.4.5:
|
||||
version "10.4.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
|
||||
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
|
||||
@ -1208,29 +1176,17 @@ glob@^10.4.3, glob@^10.4.5:
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^1.11.1"
|
||||
|
||||
glob@^7.0.6:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
glob@^11.0.0, glob@^11.0.1:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9"
|
||||
integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globby@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
|
||||
dependencies:
|
||||
array-union "^2.1.0"
|
||||
dir-glob "^3.0.1"
|
||||
fast-glob "^3.2.9"
|
||||
ignore "^5.2.0"
|
||||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
foreground-child "^3.1.0"
|
||||
jackspeak "^4.0.1"
|
||||
minimatch "^10.0.0"
|
||||
minipass "^7.1.2"
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^2.0.0"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
@ -1321,7 +1277,7 @@ ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ignore@^5.2.0, ignore@^5.2.4:
|
||||
ignore@^5.3.1:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||
@ -1331,15 +1287,7 @@ immediate@~3.0.5:
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||
inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -1429,6 +1377,13 @@ jackspeak@^3.1.2:
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jackspeak@^4.0.1:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b"
|
||||
integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==
|
||||
dependencies:
|
||||
"@isaacs/cliui" "^8.0.2"
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
@ -1521,12 +1476,12 @@ lie@~3.3.0:
|
||||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
|
||||
integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
|
||||
linkify-it@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421"
|
||||
integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
uc.micro "^2.0.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
@ -1591,6 +1546,11 @@ lru-cache@^10.2.0:
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
|
||||
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
|
||||
|
||||
lru-cache@^11.0.0:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
|
||||
integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
@ -1598,23 +1558,24 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
markdown-it@^12.3.2:
|
||||
version "12.3.2"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
|
||||
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
|
||||
markdown-it@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45"
|
||||
integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~2.1.0"
|
||||
linkify-it "^3.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
entities "^4.4.0"
|
||||
linkify-it "^5.0.0"
|
||||
mdurl "^2.0.0"
|
||||
punycode.js "^2.3.1"
|
||||
uc.micro "^2.1.0"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||
mdurl@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0"
|
||||
integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
@ -1654,14 +1615,14 @@ mimic-response@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
minimatch@^10.0.0:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
|
||||
integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.3, minimatch@^3.1.1:
|
||||
minimatch@^3.0.3:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
@ -1777,7 +1738,7 @@ object-inspect@^1.13.1:
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
||||
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
@ -1866,11 +1827,6 @@ path-exists@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
@ -1884,10 +1840,13 @@ path-scurry@^1.11.1:
|
||||
lru-cache "^10.2.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
path-scurry@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580"
|
||||
integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==
|
||||
dependencies:
|
||||
lru-cache "^11.0.0"
|
||||
minipass "^7.1.2"
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
@ -1930,6 +1889,11 @@ pump@^3.0.0:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode.js@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
|
||||
integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
|
||||
|
||||
qs@^6.9.1:
|
||||
version "6.12.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a"
|
||||
@ -2040,10 +2004,10 @@ semver@^5.1.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
||||
semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2:
|
||||
version "7.6.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
|
||||
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
|
||||
semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2:
|
||||
version "7.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
||||
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||
|
||||
serialize-javascript@^6.0.2:
|
||||
version "6.0.2"
|
||||
@ -2115,11 +2079,6 @@ simple-get@^4.0.0:
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
stdin-discarder@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21"
|
||||
@ -2255,7 +2214,7 @@ tar-stream@^2.1.4:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tmp@^0.2.1:
|
||||
tmp@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
|
||||
integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==
|
||||
@ -2267,10 +2226,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
ts-api-utils@^1.0.1:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064"
|
||||
integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==
|
||||
ts-api-utils@^2.0.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91"
|
||||
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
|
||||
|
||||
tslib@^2.2.0, tslib@^2.6.2:
|
||||
version "2.6.2"
|
||||
@ -2303,10 +2262,10 @@ typescript@^5.8.2:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
||||
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
|
||||
integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
|
||||
|
||||
underscore@^1.12.1:
|
||||
version "1.13.6"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.53"
|
||||
version = "0.2.54"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -837,10 +837,10 @@ holeIndex = 6
|
||||
|
||||
// Create the mounting plate extrusion, holes, and fillets
|
||||
part = rectShape([0, 0], 20, 20)
|
||||
|> hole(circle(XY, [-holeIndex, holeIndex], holeRadius), %)
|
||||
|> hole(circle(XY, [holeIndex, holeIndex], holeRadius), %)
|
||||
|> hole(circle(XY, [-holeIndex, -holeIndex], holeRadius), %)
|
||||
|> hole(circle(XY, [holeIndex, -holeIndex], holeRadius), %)
|
||||
|> hole(circle('XY', center = [-holeIndex, holeIndex], radius = holeRadius), %)
|
||||
|> hole(circle('XY', center = [holeIndex, holeIndex], radius = holeRadius), %)
|
||||
|> hole(circle('XY', center = [-holeIndex, -holeIndex], radius = holeRadius), %)
|
||||
|> hole(circle('XY', center = [holeIndex, -holeIndex], radius = holeRadius), %)
|
||||
|> extrude(length = 2)
|
||||
|> fillet(
|
||||
radius = 4,
|
||||
@ -860,7 +860,7 @@ part = rectShape([0, 0], 20, 20)
|
||||
};
|
||||
assert_eq!(
|
||||
err.error.message(),
|
||||
"This function requires a keyword argument 'center'"
|
||||
"The input argument of std::sketch::circle requires a value with type `Sketch | Plane | Face`, but found string (text)"
|
||||
);
|
||||
}
|
||||
|
||||
@ -1347,7 +1347,7 @@ secondSketch = startSketchOn(part001, '')
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([297, 299, 0])], message: "Argument at index 1 was supposed to be type Option<kcl_lib::std::sketch::FaceTag> but found string (text)" }"#
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([297, 299, 0])], message: "Argument at index 1 was supposed to be type Option<FaceTag> but found string (text)" }"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -1983,7 +1983,7 @@ someFunction('INVALID')
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([51, 60, 0]), SourceRange([65, 88, 0])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but found string (text)" }"#
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([51, 60, 0]), SourceRange([65, 88, 0])], message: "Argument at index 0 was supposed to be type SketchData but found string (text)" }"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -2004,7 +2004,7 @@ someFunction('INVALID')
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([103, 113, 0]), SourceRange([126, 155, 0]), SourceRange([159, 182, 0])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but found string (text)" }"#
|
||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([103, 113, 0]), SourceRange([126, 155, 0]), SourceRange([159, 182, 0])], message: "Argument at index 0 was supposed to be type SketchData but found string (text)" }"#
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -467,6 +467,10 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String)
|
||||
});
|
||||
|
||||
let output = hbs.render("kclType", &data)?;
|
||||
let output = cleanup_type_links(
|
||||
&output,
|
||||
ty.referenced_types.iter().filter(|t| !DECLARED_TYPES.contains(&&***t)),
|
||||
);
|
||||
expectorate::assert_contents(format!("../../docs/kcl/{}.md", file_name), &output);
|
||||
|
||||
Ok(())
|
||||
@ -514,6 +518,13 @@ fn generate_function_from_kcl(function: &FnData, file_name: String) -> Result<()
|
||||
});
|
||||
|
||||
let output = hbs.render("function", &data)?;
|
||||
let output = cleanup_type_links(
|
||||
&output,
|
||||
function
|
||||
.referenced_types
|
||||
.iter()
|
||||
.filter(|t| !DECLARED_TYPES.contains(&&***t)),
|
||||
);
|
||||
expectorate::assert_contents(format!("../../docs/kcl/{}.md", file_name), &output);
|
||||
|
||||
Ok(())
|
||||
@ -677,6 +688,12 @@ fn cleanup_type_links<'a>(output: &str, types: impl Iterator<Item = &'a String>)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO handle union types generically rather than special casing them.
|
||||
cleaned_output = cleaned_output.replace(
|
||||
"`Sketch | Plane | Face`",
|
||||
"[`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face)",
|
||||
);
|
||||
|
||||
cleanup_static_links(&cleaned_output)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::str::FromStr;
|
||||
use std::{collections::HashSet, str::FromStr};
|
||||
|
||||
use regex::Regex;
|
||||
use tower_lsp::lsp_types::{
|
||||
@ -9,7 +9,7 @@ use tower_lsp::lsp_types::{
|
||||
use crate::{
|
||||
execution::annotations,
|
||||
parsing::{
|
||||
ast::types::{Annotation, Node, NonCodeNode, VariableKind},
|
||||
ast::types::{Annotation, Node, PrimitiveType, Type, VariableKind},
|
||||
token::NumericSuffix,
|
||||
},
|
||||
ModuleId,
|
||||
@ -59,7 +59,6 @@ impl CollectionVisitor {
|
||||
format!("std::{}::", self.name)
|
||||
};
|
||||
let mut dd = match var.kind {
|
||||
// TODO metadata for args
|
||||
VariableKind::Fn => DocData::Fn(FnData::from_ast(var, qual_name)),
|
||||
VariableKind::Const => DocData::Const(ConstData::from_ast(var, qual_name)),
|
||||
};
|
||||
@ -322,6 +321,8 @@ pub struct FnData {
|
||||
/// Code examples.
|
||||
/// These are tested and we know they compile and execute.
|
||||
pub examples: Vec<(String, ExampleProperties)>,
|
||||
#[allow(dead_code)]
|
||||
pub referenced_types: Vec<String>,
|
||||
}
|
||||
|
||||
impl FnData {
|
||||
@ -332,6 +333,17 @@ impl FnData {
|
||||
};
|
||||
let name = var.declaration.id.name.clone();
|
||||
qual_name.push_str(&name);
|
||||
|
||||
let mut referenced_types = HashSet::new();
|
||||
if let Some(t) = &expr.return_type {
|
||||
collect_type_names(&mut referenced_types, t);
|
||||
}
|
||||
for p in &expr.params {
|
||||
if let Some(t) = &p.type_ {
|
||||
collect_type_names(&mut referenced_types, t);
|
||||
}
|
||||
}
|
||||
|
||||
FnData {
|
||||
name,
|
||||
qual_name,
|
||||
@ -346,6 +358,7 @@ impl FnData {
|
||||
summary: None,
|
||||
description: None,
|
||||
examples: Vec::new(),
|
||||
referenced_types: referenced_types.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,7 +427,7 @@ impl FnData {
|
||||
}
|
||||
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn to_autocomplete_snippet(&self) -> String {
|
||||
pub(super) fn to_autocomplete_snippet(&self) -> String {
|
||||
if self.name == "loft" {
|
||||
return "loft([${0:sketch000}, ${1:sketch001}])${}".to_owned();
|
||||
} else if self.name == "hole" {
|
||||
@ -480,12 +493,12 @@ pub struct ArgData {
|
||||
/// If the argument is required.
|
||||
pub kind: ArgKind,
|
||||
/// Additional information that could be used instead of the type's description.
|
||||
/// This is helpful if the type is really basic, like "u32" -- that won't tell the user much about
|
||||
/// This is helpful if the type is really basic, like "number" -- that won't tell the user much about
|
||||
/// how this argument is meant to be used.
|
||||
pub docs: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ArgKind {
|
||||
Special,
|
||||
// Parameter is whether the arg is optional.
|
||||
@ -495,38 +508,47 @@ pub enum ArgKind {
|
||||
|
||||
impl ArgData {
|
||||
fn from_ast(arg: &crate::parsing::ast::types::Parameter) -> Self {
|
||||
ArgData {
|
||||
let mut result = ArgData {
|
||||
name: arg.identifier.name.clone(),
|
||||
ty: arg.type_.as_ref().map(|t| t.to_string()),
|
||||
// Doc comments are not yet supported on parameters.
|
||||
docs: None,
|
||||
kind: if arg.labeled {
|
||||
ArgKind::Labelled(arg.optional())
|
||||
} else {
|
||||
ArgKind::Special
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn _with_meta(&mut self, _meta: &[Node<NonCodeNode>]) {
|
||||
// TODO use comments for docs (we can't currently get the comments for an argument)
|
||||
result.with_comments(&arg.identifier.pre_comments);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_autocomplete_snippet(&self, index: usize) -> Option<(usize, String)> {
|
||||
match &self.ty {
|
||||
Some(s)
|
||||
if [
|
||||
"Sketch",
|
||||
"SketchSet",
|
||||
"Solid",
|
||||
"SolidSet",
|
||||
"SketchSurface",
|
||||
"SketchOrSurface",
|
||||
]
|
||||
.contains(&&**s) =>
|
||||
{
|
||||
Some((index, format!("${{{}:{}}}", index, "%")))
|
||||
let label = if self.kind == ArgKind::Special {
|
||||
String::new()
|
||||
} else {
|
||||
format!("{} = ", self.name)
|
||||
};
|
||||
match self.ty.as_deref() {
|
||||
Some(s) if ["Sketch", "Solid", "Plane | Face", "Sketch | Plane | Face"].contains(&s) => {
|
||||
Some((index, format!("{label}${{{}:{}}}", index, "%")))
|
||||
}
|
||||
Some("number") if self.kind.required() => Some((index, format!(r#"{label}${{{}:3.14}}"#, index))),
|
||||
Some("Point2d") if self.kind.required() => Some((
|
||||
index + 1,
|
||||
format!(r#"{label}[${{{}:3.14}}, ${{{}:3.14}}]"#, index, index + 1),
|
||||
)),
|
||||
Some("Point3d") if self.kind.required() => Some((
|
||||
index + 2,
|
||||
format!(
|
||||
r#"{label}[${{{}:3.14}}, ${{{}:3.14}}, ${{{}:3.14}}]"#,
|
||||
index,
|
||||
index + 1,
|
||||
index + 2
|
||||
),
|
||||
)),
|
||||
Some("string") if self.kind.required() => Some((index, format!(r#"{label}${{{}:"string"}}"#, index))),
|
||||
Some("bool") if self.kind.required() => Some((index, format!(r#"{label}${{{}:false}}"#, index))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -570,12 +592,19 @@ pub struct TyData {
|
||||
/// Code examples.
|
||||
/// These are tested and we know they compile and execute.
|
||||
pub examples: Vec<(String, ExampleProperties)>,
|
||||
#[allow(dead_code)]
|
||||
pub referenced_types: Vec<String>,
|
||||
}
|
||||
|
||||
impl TyData {
|
||||
fn from_ast(ty: &crate::parsing::ast::types::TypeDeclaration, mut qual_name: String) -> Self {
|
||||
let name = ty.name.name.clone();
|
||||
qual_name.push_str(&name);
|
||||
let mut referenced_types = HashSet::new();
|
||||
if let Some(t) = &ty.alias {
|
||||
collect_type_names(&mut referenced_types, t);
|
||||
}
|
||||
|
||||
TyData {
|
||||
name,
|
||||
qual_name,
|
||||
@ -589,6 +618,7 @@ impl TyData {
|
||||
summary: None,
|
||||
description: None,
|
||||
examples: Vec::new(),
|
||||
referenced_types: referenced_types.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -852,6 +882,66 @@ impl ApplyMeta for TyData {
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyMeta for ArgData {
|
||||
fn apply_docs(
|
||||
&mut self,
|
||||
summary: Option<String>,
|
||||
description: Option<String>,
|
||||
_examples: Vec<(String, ExampleProperties)>,
|
||||
) {
|
||||
let Some(mut docs) = summary else {
|
||||
return;
|
||||
};
|
||||
if let Some(desc) = description {
|
||||
docs.push_str("\n\n");
|
||||
docs.push_str(&desc);
|
||||
}
|
||||
|
||||
self.docs = Some(docs);
|
||||
}
|
||||
|
||||
fn deprecated(&mut self, _deprecated: bool) {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn doc_hidden(&mut self, _doc_hidden: bool) {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn impl_kind(&mut self, _impl_kind: annotations::Impl) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_type_names(acc: &mut HashSet<String>, ty: &Type) {
|
||||
match ty {
|
||||
Type::Primitive(primitive_type) => {
|
||||
acc.insert(collect_type_names_from_primitive(primitive_type));
|
||||
}
|
||||
Type::Array { ty, .. } => {
|
||||
acc.insert(collect_type_names_from_primitive(ty));
|
||||
}
|
||||
Type::Union { tys } => tys.iter().for_each(|t| {
|
||||
acc.insert(collect_type_names_from_primitive(t));
|
||||
}),
|
||||
Type::Object { properties } => properties.iter().for_each(|p| {
|
||||
if let Some(t) = &p.type_ {
|
||||
collect_type_names(acc, t)
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_type_names_from_primitive(ty: &PrimitiveType) -> String {
|
||||
match ty {
|
||||
PrimitiveType::String => "string".to_owned(),
|
||||
PrimitiveType::Number(_) => "number".to_owned(),
|
||||
PrimitiveType::Boolean => "bool".to_owned(),
|
||||
PrimitiveType::Tag => "tag".to_owned(),
|
||||
PrimitiveType::Named(id) => id.name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -927,6 +927,8 @@ fn get_autocomplete_string_from_schema(schema: &schemars::schema::Schema) -> Res
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::docs::kcl_doc::{self, DocData};
|
||||
|
||||
use super::StdLibFn;
|
||||
|
||||
#[test]
|
||||
@ -1007,8 +1009,11 @@ mod tests {
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_circle() {
|
||||
let circle_fn: Box<dyn StdLibFn> = Box::new(crate::std::shapes::Circle);
|
||||
let snippet = circle_fn.to_autocomplete_snippet().unwrap();
|
||||
let data = kcl_doc::walk_prelude();
|
||||
let DocData::Fn(circle_fn) = data.into_iter().find(|d| d.name() == "circle").unwrap() else {
|
||||
panic!();
|
||||
};
|
||||
let snippet = circle_fn.to_autocomplete_snippet();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"circle(${0:%}, center = [${1:3.14}, ${2:3.14}], radius = ${3:3.14})${}"#
|
||||
|
@ -78,15 +78,18 @@ pub(super) fn expect_properties<'a>(
|
||||
}
|
||||
|
||||
pub(super) fn expect_ident(expr: &Expr) -> Result<&str, KclError> {
|
||||
match expr {
|
||||
Expr::Identifier(id) => Ok(&id.name),
|
||||
e => Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "Unexpected settings value, expected a simple name, e.g., `mm`".to_owned(),
|
||||
source_ranges: vec![e.into()],
|
||||
})),
|
||||
if let Expr::Name(name) = expr {
|
||||
if let Some(name) = name.local_ident() {
|
||||
return Ok(*name);
|
||||
}
|
||||
}
|
||||
|
||||
Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "Unexpected settings value, expected a simple name, e.g., `mm`".to_owned(),
|
||||
source_ranges: vec![expr.into()],
|
||||
}))
|
||||
}
|
||||
|
||||
pub(super) fn get_impl(annotations: &[Node<Annotation>], source_range: SourceRange) -> Result<Option<Impl>, KclError> {
|
||||
for attr in annotations {
|
||||
if attr.name.is_some() || attr.properties.is_none() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use async_recursion::async_recursion;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::{
|
||||
engine::ExecutionKind,
|
||||
@ -19,7 +20,7 @@ use crate::{
|
||||
parsing::ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||
CallExpression, CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector,
|
||||
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Node, NodeRef,
|
||||
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef,
|
||||
ObjectExpression, PipeExpression, Program, TagDeclarator, Type, UnaryExpression, UnaryOperator,
|
||||
},
|
||||
source_range::SourceRange,
|
||||
@ -514,15 +515,23 @@ impl ExecutorContext {
|
||||
source_range: SourceRange,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
let path = exec_state.global.module_infos[&module_id].path.clone();
|
||||
let repr = exec_state.global.module_infos[&module_id].take_repr();
|
||||
let mut repr = exec_state.global.module_infos[&module_id].take_repr();
|
||||
// DON'T EARLY RETURN! We need to restore the module repr
|
||||
|
||||
let result = match &repr {
|
||||
let result = match &mut repr {
|
||||
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
|
||||
ModuleRepr::Kcl(program, _) => self
|
||||
ModuleRepr::Kcl(program, cached_items) => {
|
||||
let result = self
|
||||
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
|
||||
.await
|
||||
.map(|(val, _, _)| val),
|
||||
.await;
|
||||
match result {
|
||||
Ok((val, env, items)) => {
|
||||
*cached_items = Some((env, items));
|
||||
Ok(val)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
ModuleRepr::Foreign(geom) => super::import::send_to_engine(geom.clone(), self)
|
||||
.await
|
||||
.map(|geom| Some(KclValue::ImportedGeometry(geom))),
|
||||
@ -578,8 +587,8 @@ impl ExecutorContext {
|
||||
Expr::None(none) => KclValue::from(none),
|
||||
Expr::Literal(literal) => KclValue::from_literal((**literal).clone(), &exec_state.mod_local.settings),
|
||||
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
||||
Expr::Identifier(identifier) => {
|
||||
let value = exec_state.stack().get(&identifier.name, identifier.into())?.clone();
|
||||
Expr::Name(name) => {
|
||||
let value = name.get_result(exec_state, self).await?.clone();
|
||||
if let KclValue::Module { value: module_id, meta } = value {
|
||||
self.exec_module_for_result(module_id, exec_state, ExecutionKind::Normal, metadata.source_range)
|
||||
.await?
|
||||
@ -610,7 +619,11 @@ impl ExecutorContext {
|
||||
if let Some(std_path) = &exec_state.mod_local.settings.std_path {
|
||||
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
||||
KclValue::Function {
|
||||
value: FunctionSource::Std { func, props },
|
||||
value: FunctionSource::Std {
|
||||
func,
|
||||
props,
|
||||
ast: function_expression.clone(),
|
||||
},
|
||||
meta: vec![metadata.to_owned()],
|
||||
}
|
||||
} else {
|
||||
@ -710,10 +723,7 @@ impl BinaryPart {
|
||||
(**literal).clone(),
|
||||
&exec_state.mod_local.settings,
|
||||
)),
|
||||
BinaryPart::Identifier(identifier) => {
|
||||
let value = exec_state.stack().get(&identifier.name, identifier.into())?;
|
||||
Ok(value.clone())
|
||||
}
|
||||
BinaryPart::Name(name) => name.get_result(exec_state, ctx).await.cloned(),
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.execute(exec_state, ctx).await,
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.execute(exec_state, ctx).await,
|
||||
@ -724,6 +734,73 @@ impl BinaryPart {
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<Name> {
|
||||
async fn get_result<'a>(
|
||||
&self,
|
||||
exec_state: &'a mut ExecState,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<&'a KclValue, KclError> {
|
||||
if self.abs_path {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "Absolute paths (names beginning with `::` are not yet supported)".to_owned(),
|
||||
source_ranges: self.as_source_ranges(),
|
||||
}));
|
||||
}
|
||||
|
||||
if self.path.is_empty() {
|
||||
return exec_state.stack().get(&self.name.name, self.into());
|
||||
}
|
||||
|
||||
let mut mem_spec: Option<(EnvironmentRef, Vec<String>)> = None;
|
||||
for p in &self.path {
|
||||
let value = match mem_spec {
|
||||
Some((env, exports)) => {
|
||||
if !exports.contains(&p.name) {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("Item {} not found in module's exported items", p.name),
|
||||
source_ranges: p.as_source_ranges(),
|
||||
}));
|
||||
}
|
||||
|
||||
exec_state
|
||||
.stack()
|
||||
.memory
|
||||
.get_from(&p.name, env, p.as_source_range(), 0)?
|
||||
}
|
||||
None => exec_state.stack().get(&p.name, self.into())?,
|
||||
};
|
||||
|
||||
let KclValue::Module { value: module_id, .. } = value else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"Identifier in path must refer to a module, found {}",
|
||||
value.human_friendly_type()
|
||||
),
|
||||
source_ranges: p.as_source_ranges(),
|
||||
}));
|
||||
};
|
||||
|
||||
mem_spec = Some(
|
||||
ctx.exec_module_for_items(*module_id, exec_state, ExecutionKind::Normal, p.as_source_range())
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
|
||||
let (env, exports) = mem_spec.unwrap();
|
||||
if !exports.contains(&self.name.name) {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("Item {} not found in module's exported items", self.name.name),
|
||||
source_ranges: self.name.as_source_ranges(),
|
||||
}));
|
||||
}
|
||||
|
||||
exec_state
|
||||
.stack()
|
||||
.memory
|
||||
.get_from(&self.name.name, env, self.name.as_source_range(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<MemberExpression> {
|
||||
fn get_result(&self, exec_state: &mut ExecState) -> Result<KclValue, KclError> {
|
||||
let property = Property::try_from(self.computed, self.property.clone(), exec_state, self.into())?;
|
||||
@ -1054,11 +1131,11 @@ async fn inner_execute_pipe_body(
|
||||
impl Node<CallExpressionKw> {
|
||||
#[async_recursion]
|
||||
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||
let fn_name = &self.callee.name;
|
||||
let fn_name = &self.callee;
|
||||
let callsite: SourceRange = self.into();
|
||||
|
||||
// Build a hashmap from argument labels to the final evaluated values.
|
||||
let mut fn_args = HashMap::with_capacity(self.arguments.len());
|
||||
let mut fn_args = IndexMap::with_capacity(self.arguments.len());
|
||||
for arg_expr in &self.arguments {
|
||||
let source_range = SourceRange::from(arg_expr.arg.clone());
|
||||
let metadata = Metadata { source_range };
|
||||
@ -1098,6 +1175,7 @@ impl Node<CallExpressionKw> {
|
||||
format!("`{fn_name}` is deprecated, see the docs for a recommended replacement"),
|
||||
));
|
||||
}
|
||||
|
||||
let op = if func.feature_tree_operation() {
|
||||
let op_labeled_args = args
|
||||
.kw_args
|
||||
@ -1118,10 +1196,34 @@ impl Node<CallExpressionKw> {
|
||||
None
|
||||
};
|
||||
|
||||
let formals = func.args(false);
|
||||
for (label, arg) in &args.kw_args.labeled {
|
||||
match formals.iter().find(|p| &p.name == label) {
|
||||
Some(p) => {
|
||||
if !p.label_required {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!(
|
||||
"The function `{fn_name}` expects an unlabeled first parameter (`{label}`), but it is labelled in the call"
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!("`{label}` is not an argument of `{fn_name}`"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to call the function.
|
||||
let mut return_value = {
|
||||
// Don't early-return in this block.
|
||||
exec_state.mut_stack().push_new_env_for_rust_call();
|
||||
let result = func.std_lib_fn()(exec_state, args).await;
|
||||
exec_state.mut_stack().pop_env();
|
||||
|
||||
if let Some(mut op) = op {
|
||||
op.set_std_lib_call_is_error(result.is_err());
|
||||
@ -1140,10 +1242,9 @@ impl Node<CallExpressionKw> {
|
||||
Ok(return_value)
|
||||
}
|
||||
FunctionKind::UserDefined => {
|
||||
let source_range = SourceRange::from(self);
|
||||
// Clone the function so that we can use a mutable reference to
|
||||
// exec_state.
|
||||
let func = exec_state.stack().get(fn_name, source_range)?.clone();
|
||||
let func = fn_name.get_result(exec_state, ctx).await?.clone();
|
||||
|
||||
// Track call operation.
|
||||
let op_labeled_args = args
|
||||
@ -1153,7 +1254,7 @@ impl Node<CallExpressionKw> {
|
||||
.map(|(k, arg)| (k.clone(), OpArg::new(OpKclValue::from(&arg.value), arg.source_range)))
|
||||
.collect();
|
||||
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
|
||||
name: Some(fn_name.clone()),
|
||||
name: Some(fn_name.to_string()),
|
||||
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
||||
unlabeled_arg: args
|
||||
.kw_args
|
||||
@ -1164,17 +1265,21 @@ impl Node<CallExpressionKw> {
|
||||
source_range: callsite,
|
||||
});
|
||||
|
||||
let return_value = func
|
||||
.call_fn_kw(args, exec_state, ctx.clone(), callsite)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
let Some(fn_src) = func.as_fn() else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "cannot call this because it isn't a function".to_string(),
|
||||
source_ranges: vec![callsite],
|
||||
}));
|
||||
};
|
||||
|
||||
let return_value = fn_src.call_kw(exec_state, ctx, args, callsite).await.map_err(|e| {
|
||||
// Add the call expression to the source ranges.
|
||||
// TODO currently ignored by the frontend
|
||||
e.add_source_ranges(vec![source_range])
|
||||
e.add_source_ranges(vec![callsite])
|
||||
})?;
|
||||
|
||||
let result = return_value.ok_or_else(move || {
|
||||
let mut source_ranges: Vec<SourceRange> = vec![source_range];
|
||||
let mut source_ranges: Vec<SourceRange> = vec![callsite];
|
||||
// We want to send the source range of the original function.
|
||||
if let KclValue::Function { meta, .. } = func {
|
||||
source_ranges = meta.iter().map(|m| m.source_range).collect();
|
||||
@ -1197,7 +1302,7 @@ impl Node<CallExpressionKw> {
|
||||
impl Node<CallExpression> {
|
||||
#[async_recursion]
|
||||
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||
let fn_name = &self.callee.name;
|
||||
let fn_name = &self.callee;
|
||||
let callsite = SourceRange::from(self);
|
||||
|
||||
let mut fn_args: Vec<Arg> = Vec::with_capacity(self.arguments.len());
|
||||
@ -1279,11 +1384,11 @@ impl Node<CallExpression> {
|
||||
let source_range = SourceRange::from(self);
|
||||
// Clone the function so that we can use a mutable reference to
|
||||
// exec_state.
|
||||
let func = exec_state.stack().get(fn_name, source_range)?.clone();
|
||||
let func = fn_name.get_result(exec_state, ctx).await?.clone();
|
||||
|
||||
// Track call operation.
|
||||
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
|
||||
name: Some(fn_name.clone()),
|
||||
name: Some(fn_name.to_string()),
|
||||
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
||||
unlabeled_arg: None,
|
||||
// TODO: Add the arguments for legacy positional parameters.
|
||||
@ -1291,10 +1396,13 @@ impl Node<CallExpression> {
|
||||
source_range: callsite,
|
||||
});
|
||||
|
||||
let return_value = func
|
||||
.call_fn(fn_args, exec_state, ctx.clone(), source_range)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
let Some(fn_src) = func.as_fn() else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "cannot call this because it isn't a function".to_string(),
|
||||
source_ranges: vec![source_range],
|
||||
}));
|
||||
};
|
||||
let return_value = fn_src.call(exec_state, ctx, fn_args, source_range).await.map_err(|e| {
|
||||
// Add the call expression to the source ranges.
|
||||
// TODO currently ignored by the frontend
|
||||
e.add_source_ranges(vec![source_range])
|
||||
@ -1784,6 +1892,27 @@ fn assign_args_to_params_kw(
|
||||
mut args: crate::std::args::KwArgs,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<(), KclError> {
|
||||
for (label, arg) in &args.labeled {
|
||||
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
|
||||
Some(p) => {
|
||||
if !p.labeled {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!(
|
||||
"This function expects an unlabeled first parameter (`{label}`), but it is labelled in the call"
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!("`{label}` is not an argument of this function"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the arguments to the memory. A new call frame should have already
|
||||
// been created.
|
||||
let source_ranges = vec![function_expression.into()];
|
||||
@ -1832,10 +1961,11 @@ fn assign_args_to_params_kw(
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn call_user_defined_function(
|
||||
async fn call_user_defined_function(
|
||||
args: Vec<Arg>,
|
||||
memory: EnvironmentRef,
|
||||
function_expression: NodeRef<'_, FunctionExpression>,
|
||||
@ -1868,7 +1998,7 @@ pub(crate) async fn call_user_defined_function(
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) async fn call_user_defined_function_kw(
|
||||
async fn call_user_defined_function_kw(
|
||||
args: crate::std::args::KwArgs,
|
||||
memory: EnvironmentRef,
|
||||
function_expression: NodeRef<'_, FunctionExpression>,
|
||||
@ -1906,35 +2036,138 @@ impl FunctionSource {
|
||||
&self,
|
||||
exec_state: &mut ExecState,
|
||||
ctx: &ExecutorContext,
|
||||
args: Vec<Arg>,
|
||||
source_range: SourceRange,
|
||||
mut args: Vec<Arg>,
|
||||
callsite: SourceRange,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
match self {
|
||||
FunctionSource::Std { func, props } => {
|
||||
FunctionSource::Std { props, .. } => {
|
||||
if args.len() <= 1 {
|
||||
let args = crate::std::Args::new_kw(
|
||||
KwArgs {
|
||||
unlabeled: args.pop(),
|
||||
labeled: IndexMap::new(),
|
||||
},
|
||||
callsite,
|
||||
ctx.clone(),
|
||||
exec_state.mod_local.pipe_value.clone().map(|v| Arg::new(v, callsite)),
|
||||
);
|
||||
self.call_kw(exec_state, ctx, args, callsite).await
|
||||
} else {
|
||||
Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("{} requires its arguments to be labelled", props.name),
|
||||
source_ranges: vec![callsite],
|
||||
}))
|
||||
}
|
||||
}
|
||||
FunctionSource::User { ast, memory, .. } => {
|
||||
call_user_defined_function(args, *memory, ast, exec_state, ctx).await
|
||||
}
|
||||
FunctionSource::None => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn call_kw(
|
||||
&self,
|
||||
exec_state: &mut ExecState,
|
||||
ctx: &ExecutorContext,
|
||||
mut args: crate::std::Args,
|
||||
callsite: SourceRange,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
match self {
|
||||
FunctionSource::Std { func, ast, props } => {
|
||||
if props.deprecated {
|
||||
exec_state.warn(CompilationError::err(
|
||||
source_range,
|
||||
callsite,
|
||||
format!(
|
||||
"`{}` is deprecated, see the docs for a recommended replacement",
|
||||
props.name
|
||||
),
|
||||
));
|
||||
}
|
||||
let args = crate::std::Args::new(
|
||||
args,
|
||||
source_range,
|
||||
ctx.clone(),
|
||||
exec_state
|
||||
.mod_local
|
||||
.pipe_value
|
||||
.clone()
|
||||
.map(|v| Arg::new(v, source_range)),
|
||||
);
|
||||
|
||||
func(exec_state, args).await.map(Some)
|
||||
for (label, arg) in &mut args.kw_args.labeled {
|
||||
match ast.params.iter().find(|p| &p.identifier.name == label) {
|
||||
Some(p) => {
|
||||
if !p.labeled {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!(
|
||||
"The function `{}` expects an unlabeled first parameter (`{label}`), but it is labelled in the call",
|
||||
props.name
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(ty) = &p.type_ {
|
||||
arg.value = arg
|
||||
.value
|
||||
.coerce(
|
||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range)
|
||||
.unwrap(),
|
||||
exec_state,
|
||||
)
|
||||
.ok_or_else(|| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"{label} requires a value with type `{}`, but found {}",
|
||||
ty.inner,
|
||||
arg.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![callsite],
|
||||
})
|
||||
})?;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
exec_state.err(CompilationError::err(
|
||||
arg.source_range,
|
||||
format!("`{label}` is not an argument of `{}`", props.name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(arg) = &mut args.kw_args.unlabeled {
|
||||
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
|
||||
if let Some(ty) = &p.type_ {
|
||||
arg.value = arg
|
||||
.value
|
||||
.coerce(
|
||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
|
||||
exec_state,
|
||||
)
|
||||
.ok_or_else(|| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"The input argument of {} requires a value with type `{}`, but found {}",
|
||||
props.name,
|
||||
ty.inner,
|
||||
arg.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![callsite],
|
||||
})
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to call the function.
|
||||
exec_state.mut_stack().push_new_env_for_rust_call();
|
||||
let mut result = {
|
||||
// Don't early-return in this block.
|
||||
let result = func(exec_state, args).await;
|
||||
exec_state.mut_stack().pop_env();
|
||||
|
||||
// TODO support recording op into the feature tree
|
||||
result
|
||||
}?;
|
||||
|
||||
update_memory_for_tags_of_geometry(&mut result, exec_state)?;
|
||||
|
||||
Ok(Some(result))
|
||||
}
|
||||
FunctionSource::User { ast, memory, .. } => {
|
||||
call_user_defined_function(args, *memory, ast, exec_state, ctx).await
|
||||
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
|
||||
}
|
||||
FunctionSource::None => unreachable!(),
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ use crate::{
|
||||
errors::KclErrorDetails,
|
||||
execution::{
|
||||
types::{NumericType, PrimitiveType, RuntimeType},
|
||||
ExecState, ExecutorContext, Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
|
||||
Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
|
||||
},
|
||||
parsing::ast::types::{
|
||||
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
||||
},
|
||||
std::{args::Arg, StdFnProps},
|
||||
CompilationError, KclError, ModuleId, SourceRange,
|
||||
std::StdFnProps,
|
||||
KclError, ModuleId, SourceRange,
|
||||
};
|
||||
|
||||
pub type KclObjectFields = HashMap<String, KclValue>;
|
||||
@ -113,6 +113,7 @@ pub enum FunctionSource {
|
||||
None,
|
||||
Std {
|
||||
func: crate::std::StdFn,
|
||||
ast: crate::parsing::ast::types::BoxNode<FunctionExpression>,
|
||||
props: StdFnProps,
|
||||
},
|
||||
User {
|
||||
@ -550,91 +551,10 @@ impl KclValue {
|
||||
Ok(*b)
|
||||
}
|
||||
|
||||
/// If this memory item is a function, call it with the given arguments, return its val as Ok.
|
||||
/// If it's not a function, return Err.
|
||||
pub async fn call_fn(
|
||||
&self,
|
||||
args: Vec<Arg>,
|
||||
exec_state: &mut ExecState,
|
||||
ctx: ExecutorContext,
|
||||
source_range: SourceRange,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
pub fn as_fn(&self) -> Option<&FunctionSource> {
|
||||
match self {
|
||||
KclValue::Function {
|
||||
value: FunctionSource::Std { func, props },
|
||||
..
|
||||
} => {
|
||||
if props.deprecated {
|
||||
exec_state.warn(CompilationError::err(
|
||||
source_range,
|
||||
format!(
|
||||
"`{}` is deprecated, see the docs for a recommended replacement",
|
||||
props.name
|
||||
),
|
||||
));
|
||||
}
|
||||
exec_state.mut_stack().push_new_env_for_rust_call();
|
||||
let args = crate::std::Args::new(
|
||||
args,
|
||||
source_range,
|
||||
ctx.clone(),
|
||||
exec_state
|
||||
.mod_local
|
||||
.pipe_value
|
||||
.clone()
|
||||
.map(|v| Arg::new(v, source_range)),
|
||||
);
|
||||
let result = func(exec_state, args).await.map(Some);
|
||||
exec_state.mut_stack().pop_env();
|
||||
result
|
||||
}
|
||||
KclValue::Function {
|
||||
value: FunctionSource::User { ast, memory, .. },
|
||||
..
|
||||
} => crate::execution::exec_ast::call_user_defined_function(args, *memory, ast, exec_state, &ctx).await,
|
||||
_ => Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "cannot call this because it isn't a function".to_string(),
|
||||
source_ranges: vec![source_range],
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
/// If this is a function, call it by applying keyword arguments.
|
||||
/// If it's not a function, returns an error.
|
||||
pub async fn call_fn_kw(
|
||||
&self,
|
||||
args: crate::std::Args,
|
||||
exec_state: &mut ExecState,
|
||||
ctx: ExecutorContext,
|
||||
callsite: SourceRange,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
match self {
|
||||
KclValue::Function {
|
||||
value: FunctionSource::Std { func: _, props },
|
||||
..
|
||||
} => {
|
||||
if props.deprecated {
|
||||
exec_state.warn(CompilationError::err(
|
||||
callsite,
|
||||
format!(
|
||||
"`{}` is deprecated, see the docs for a recommended replacement",
|
||||
props.name
|
||||
),
|
||||
));
|
||||
}
|
||||
todo!("Implement KCL stdlib fns with keyword args");
|
||||
}
|
||||
KclValue::Function {
|
||||
value: FunctionSource::User { ast, memory, .. },
|
||||
..
|
||||
} => {
|
||||
crate::execution::exec_ast::call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, &ctx)
|
||||
.await
|
||||
}
|
||||
_ => Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "cannot call this because it isn't a function".to_string(),
|
||||
source_ranges: vec![callsite],
|
||||
})),
|
||||
KclValue::Function { value, .. } => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ pub fn lint_should_be_offset_plane(node: Node) -> Result<Vec<Discovered>> {
|
||||
return Ok(vec![]);
|
||||
};
|
||||
|
||||
if call.inner.callee.inner.name != "startSketchOn" {
|
||||
if call.inner.callee.inner.name.name != "startSketchOn" {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ pub fn lint_call_expressions(exp: Node) -> Result<Vec<Discovered>> {
|
||||
return Ok(vec![]);
|
||||
};
|
||||
|
||||
match stdlib.get_either(&exp.callee.name) {
|
||||
match stdlib.get_either(&exp.callee) {
|
||||
FunctionKind::Core(func) => lint_too_many_args_std_lib_function(func, exp),
|
||||
_ => Ok(vec![]),
|
||||
}
|
||||
|
@ -105,16 +105,19 @@ impl Expr {
|
||||
// TODO: LSP hover information for values/types. https://github.com/KittyCAD/modeling-app/issues/1126
|
||||
Expr::None(_) => None,
|
||||
Expr::Literal(_) => None,
|
||||
Expr::Identifier(id) => {
|
||||
if id.contains(pos) {
|
||||
let name = id.name.clone();
|
||||
Some(Hover::Variable {
|
||||
ty: opts
|
||||
.vars
|
||||
Expr::Name(name) => {
|
||||
if name.contains(pos) {
|
||||
let ty = if let Some(name) = name.local_ident() {
|
||||
opts.vars
|
||||
.as_ref()
|
||||
.and_then(|vars| vars.get(&name).and_then(Clone::clone)),
|
||||
name,
|
||||
range: id.as_source_range().to_lsp_range(code),
|
||||
.and_then(|vars| vars.get(&**name).and_then(Clone::clone))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(Hover::Variable {
|
||||
ty,
|
||||
name: name.to_string(),
|
||||
range: name.as_source_range().to_lsp_range(code),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -137,7 +140,7 @@ impl BinaryPart {
|
||||
fn get_hover_value_for_position(&self, pos: usize, code: &str, opts: &HoverOpts) -> Option<Hover> {
|
||||
match self {
|
||||
BinaryPart::Literal(_literal) => None,
|
||||
BinaryPart::Identifier(_identifier) => None,
|
||||
BinaryPart::Name(_identifier) => None,
|
||||
BinaryPart::BinaryExpression(binary_expression) => {
|
||||
binary_expression.get_hover_value_for_position(pos, code, opts)
|
||||
}
|
||||
@ -163,7 +166,7 @@ impl CallExpression {
|
||||
let callee_source_range: SourceRange = self.callee.clone().into();
|
||||
if callee_source_range.contains(pos) {
|
||||
return Some(Hover::Function {
|
||||
name: self.callee.name.clone(),
|
||||
name: self.callee.to_string(),
|
||||
range: callee_source_range.to_lsp_range(code),
|
||||
});
|
||||
}
|
||||
@ -173,7 +176,7 @@ impl CallExpression {
|
||||
if source_range.contains(pos) {
|
||||
return if opts.prefer_sig {
|
||||
Some(Hover::Signature {
|
||||
name: self.callee.name.clone(),
|
||||
name: self.callee.to_string(),
|
||||
parameter_index: index as u32,
|
||||
range: source_range.to_lsp_range(code),
|
||||
})
|
||||
@ -192,7 +195,7 @@ impl CallExpressionKw {
|
||||
let callee_source_range: SourceRange = self.callee.clone().into();
|
||||
if callee_source_range.contains(pos) {
|
||||
return Some(Hover::Function {
|
||||
name: self.callee.name.clone(),
|
||||
name: self.callee.to_string(),
|
||||
range: callee_source_range.to_lsp_range(code),
|
||||
});
|
||||
}
|
||||
@ -202,7 +205,7 @@ impl CallExpressionKw {
|
||||
if source_range.contains(pos) {
|
||||
return if opts.prefer_sig {
|
||||
Some(Hover::Signature {
|
||||
name: self.callee.name.clone(),
|
||||
name: self.callee.to_string(),
|
||||
parameter_index: index as u32,
|
||||
range: source_range.to_lsp_range(code),
|
||||
})
|
||||
@ -215,7 +218,7 @@ impl CallExpressionKw {
|
||||
if id.as_source_range().contains(pos) {
|
||||
return Some(Hover::KwArg {
|
||||
name: id.name.clone(),
|
||||
callee_name: self.callee.name.clone(),
|
||||
callee_name: self.callee.to_string(),
|
||||
range: id.as_source_range().to_lsp_range(code),
|
||||
});
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ impl Backend {
|
||||
None => token_type_index,
|
||||
};
|
||||
|
||||
if self.stdlib_completions.contains_key(&call_expr.callee.name) {
|
||||
if self.stdlib_completions.contains_key(&call_expr.callee.name.name) {
|
||||
// This is a stdlib function.
|
||||
return get_modifier(vec![SemanticTokenModifier::DEFAULT_LIBRARY]);
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ pub(crate) fn read_std(mod_name: &str) -> Option<&'static str> {
|
||||
match mod_name {
|
||||
"prelude" => Some(include_str!("../std/prelude.kcl")),
|
||||
"math" => Some(include_str!("../std/math.kcl")),
|
||||
"sketch" => Some(include_str!("../std/sketch.kcl")),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::parsing::ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, Ascription, BinaryExpression, BinaryPart, BodyItem,
|
||||
CallExpression, CallExpressionKw, DefaultParamVal, ElseIf, Expr, ExpressionStatement, FunctionExpression,
|
||||
Identifier, IfExpression, ImportItem, ImportSelector, ImportStatement, ItemVisibility, KclNone, LabelledExpression,
|
||||
Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, ObjectExpression, ObjectProperty,
|
||||
Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, ObjectExpression, ObjectProperty,
|
||||
Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, TagDeclarator, Type,
|
||||
TypeDeclaration, UnaryExpression, VariableDeclaration, VariableDeclarator, VariableKind,
|
||||
};
|
||||
@ -128,7 +128,7 @@ impl Expr {
|
||||
pub fn compute_digest(&mut self) -> Digest {
|
||||
match self {
|
||||
Expr::Literal(lit) => lit.compute_digest(),
|
||||
Expr::Identifier(id) => id.compute_digest(),
|
||||
Expr::Name(id) => id.compute_digest(),
|
||||
Expr::TagDeclarator(tag) => tag.compute_digest(),
|
||||
Expr::BinaryExpression(be) => be.compute_digest(),
|
||||
Expr::FunctionExpression(fe) => fe.compute_digest(),
|
||||
@ -157,7 +157,7 @@ impl BinaryPart {
|
||||
pub fn compute_digest(&mut self) -> Digest {
|
||||
match self {
|
||||
BinaryPart::Literal(lit) => lit.compute_digest(),
|
||||
BinaryPart::Identifier(id) => id.compute_digest(),
|
||||
BinaryPart::Name(id) => id.compute_digest(),
|
||||
BinaryPart::BinaryExpression(be) => be.compute_digest(),
|
||||
BinaryPart::CallExpression(ce) => ce.compute_digest(),
|
||||
BinaryPart::CallExpressionKw(ce) => ce.compute_digest(),
|
||||
@ -377,6 +377,17 @@ impl Identifier {
|
||||
});
|
||||
}
|
||||
|
||||
impl Name {
|
||||
compute_digest!(|slf, hasher| {
|
||||
hasher.update(slf.name.compute_digest());
|
||||
for p in &mut slf.path {
|
||||
hasher.update(p.compute_digest());
|
||||
}
|
||||
if slf.abs_path {
|
||||
hasher.update([1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
impl TagDeclarator {
|
||||
compute_digest!(|slf, hasher| {
|
||||
let name = slf.name.as_bytes();
|
||||
|
@ -23,7 +23,7 @@ impl Expr {
|
||||
pub fn module_id(&self) -> ModuleId {
|
||||
match self {
|
||||
Expr::Literal(literal) => literal.module_id,
|
||||
Expr::Identifier(identifier) => identifier.module_id,
|
||||
Expr::Name(identifier) => identifier.module_id,
|
||||
Expr::TagDeclarator(tag) => tag.module_id,
|
||||
Expr::BinaryExpression(binary_expression) => binary_expression.module_id,
|
||||
Expr::FunctionExpression(function_expression) => function_expression.module_id,
|
||||
@ -48,7 +48,7 @@ impl BinaryPart {
|
||||
pub fn module_id(&self) -> ModuleId {
|
||||
match self {
|
||||
BinaryPart::Literal(literal) => literal.module_id,
|
||||
BinaryPart::Identifier(identifier) => identifier.module_id,
|
||||
BinaryPart::Name(identifier) => identifier.module_id,
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.module_id,
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.module_id,
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.module_id,
|
||||
|
@ -35,6 +35,7 @@ mod condition;
|
||||
mod literal_value;
|
||||
mod none;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Definition<'a> {
|
||||
Variable(&'a VariableDeclarator),
|
||||
Import(NodeRef<'a, ImportStatement>),
|
||||
@ -166,6 +167,18 @@ impl<T> Node<T> {
|
||||
self.pre_comments = comments;
|
||||
self.comment_start = start;
|
||||
}
|
||||
|
||||
pub fn map_ref<'a, U: 'a>(&'a self, f: fn(&'a T) -> U) -> Node<U> {
|
||||
Node {
|
||||
inner: f(&self.inner),
|
||||
start: self.start,
|
||||
end: self.end,
|
||||
module_id: self.module_id,
|
||||
outer_attrs: self.outer_attrs.clone(),
|
||||
pre_comments: self.pre_comments.clone(),
|
||||
comment_start: self.start,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Node<T> {
|
||||
@ -762,7 +775,7 @@ impl From<&BodyItem> for SourceRange {
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Expr {
|
||||
Literal(BoxNode<Literal>),
|
||||
Identifier(BoxNode<Identifier>),
|
||||
Name(BoxNode<Name>),
|
||||
TagDeclarator(BoxNode<TagDeclarator>),
|
||||
BinaryExpression(BoxNode<BinaryExpression>),
|
||||
FunctionExpression(BoxNode<FunctionExpression>),
|
||||
@ -814,7 +827,7 @@ impl Expr {
|
||||
Expr::FunctionExpression(_func_exp) => None,
|
||||
Expr::CallExpression(_call_exp) => None,
|
||||
Expr::CallExpressionKw(_call_exp) => None,
|
||||
Expr::Identifier(_ident) => None,
|
||||
Expr::Name(_ident) => None,
|
||||
Expr::TagDeclarator(_tag) => None,
|
||||
Expr::PipeExpression(pipe_exp) => Some(&pipe_exp.non_code_meta),
|
||||
Expr::UnaryExpression(_unary_exp) => None,
|
||||
@ -842,7 +855,7 @@ impl Expr {
|
||||
Expr::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value),
|
||||
Expr::CallExpression(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
|
||||
Expr::CallExpressionKw(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
|
||||
Expr::Identifier(_) => {}
|
||||
Expr::Name(_) => {}
|
||||
Expr::TagDeclarator(_) => {}
|
||||
Expr::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value),
|
||||
Expr::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value),
|
||||
@ -857,7 +870,7 @@ impl Expr {
|
||||
pub fn start(&self) -> usize {
|
||||
match self {
|
||||
Expr::Literal(literal) => literal.start,
|
||||
Expr::Identifier(identifier) => identifier.start,
|
||||
Expr::Name(identifier) => identifier.start,
|
||||
Expr::TagDeclarator(tag) => tag.start,
|
||||
Expr::BinaryExpression(binary_expression) => binary_expression.start,
|
||||
Expr::FunctionExpression(function_expression) => function_expression.start,
|
||||
@ -880,7 +893,7 @@ impl Expr {
|
||||
pub fn end(&self) -> usize {
|
||||
match self {
|
||||
Expr::Literal(literal) => literal.end,
|
||||
Expr::Identifier(identifier) => identifier.end,
|
||||
Expr::Name(identifier) => identifier.end,
|
||||
Expr::TagDeclarator(tag) => tag.end,
|
||||
Expr::BinaryExpression(binary_expression) => binary_expression.end,
|
||||
Expr::FunctionExpression(function_expression) => function_expression.end,
|
||||
@ -904,7 +917,7 @@ impl Expr {
|
||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||
match self {
|
||||
Expr::Literal(_literal) => {}
|
||||
Expr::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
Expr::Name(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
Expr::TagDeclarator(ref mut tag) => tag.rename(old_name, new_name),
|
||||
Expr::BinaryExpression(ref mut binary_expression) => {
|
||||
binary_expression.rename_identifiers(old_name, new_name)
|
||||
@ -934,7 +947,7 @@ impl Expr {
|
||||
pub fn get_constraint_level(&self) -> ConstraintLevel {
|
||||
match self {
|
||||
Expr::Literal(literal) => literal.get_constraint_level(),
|
||||
Expr::Identifier(identifier) => identifier.get_constraint_level(),
|
||||
Expr::Name(identifier) => identifier.get_constraint_level(),
|
||||
Expr::TagDeclarator(tag) => tag.get_constraint_level(),
|
||||
Expr::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(),
|
||||
|
||||
@ -967,35 +980,6 @@ impl Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describe this expression's type for a human, for typechecking.
|
||||
/// This is a best-effort function, it's OK to give a shitty string here (but we should work on improving it)
|
||||
pub fn human_friendly_type(&self) -> &'static str {
|
||||
match self {
|
||||
Expr::Literal(node) => match node.inner.value {
|
||||
LiteralValue::Number { .. } => "number",
|
||||
LiteralValue::String(_) => "string (text)",
|
||||
LiteralValue::Bool(_) => "boolean (true/false value)",
|
||||
},
|
||||
Expr::Identifier(_) => "named constant",
|
||||
Expr::TagDeclarator(_) => "tag declarator",
|
||||
Expr::BinaryExpression(_) => "expression",
|
||||
Expr::FunctionExpression(_) => "function definition",
|
||||
Expr::CallExpression(_) => "function call",
|
||||
Expr::CallExpressionKw(_) => "function call",
|
||||
Expr::PipeExpression(_) => "pipeline of function calls",
|
||||
Expr::PipeSubstitution(_) => "left-hand side of a |> pipeline",
|
||||
Expr::ArrayExpression(_) => "array",
|
||||
Expr::ArrayRangeExpression(_) => "array",
|
||||
Expr::ObjectExpression(_) => "object",
|
||||
Expr::MemberExpression(_) => "property of an object/array",
|
||||
Expr::UnaryExpression(_) => "expression",
|
||||
Expr::IfExpression(_) => "if expression",
|
||||
Expr::LabelledExpression(_) => "labelled expression",
|
||||
Expr::AscribedExpression(_) => "type-ascribed expression",
|
||||
Expr::None(_) => "none",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn literal_bool(&self) -> Option<bool> {
|
||||
match self {
|
||||
Expr::Literal(lit) => match lit.value {
|
||||
@ -1028,7 +1012,7 @@ impl Expr {
|
||||
|
||||
pub fn ident_name(&self) -> Option<&str> {
|
||||
match self {
|
||||
Expr::Identifier(ident) => Some(&ident.name),
|
||||
Expr::Name(ident) => Some(&ident.name.name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -1102,7 +1086,7 @@ impl Ascription {
|
||||
#[serde(tag = "type")]
|
||||
pub enum BinaryPart {
|
||||
Literal(BoxNode<Literal>),
|
||||
Identifier(BoxNode<Identifier>),
|
||||
Name(BoxNode<Name>),
|
||||
BinaryExpression(BoxNode<BinaryExpression>),
|
||||
CallExpression(BoxNode<CallExpression>),
|
||||
CallExpressionKw(BoxNode<CallExpressionKw>),
|
||||
@ -1128,7 +1112,7 @@ impl BinaryPart {
|
||||
pub fn get_constraint_level(&self) -> ConstraintLevel {
|
||||
match self {
|
||||
BinaryPart::Literal(literal) => literal.get_constraint_level(),
|
||||
BinaryPart::Identifier(identifier) => identifier.get_constraint_level(),
|
||||
BinaryPart::Name(identifier) => identifier.get_constraint_level(),
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(),
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.get_constraint_level(),
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.get_constraint_level(),
|
||||
@ -1141,7 +1125,7 @@ impl BinaryPart {
|
||||
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
|
||||
match self {
|
||||
BinaryPart::Literal(_) => {}
|
||||
BinaryPart::Identifier(_) => {}
|
||||
BinaryPart::Name(_) => {}
|
||||
BinaryPart::BinaryExpression(ref mut binary_expression) => {
|
||||
binary_expression.replace_value(source_range, new_value)
|
||||
}
|
||||
@ -1162,7 +1146,7 @@ impl BinaryPart {
|
||||
pub fn start(&self) -> usize {
|
||||
match self {
|
||||
BinaryPart::Literal(literal) => literal.start,
|
||||
BinaryPart::Identifier(identifier) => identifier.start,
|
||||
BinaryPart::Name(identifier) => identifier.start,
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.start,
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.start,
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.start,
|
||||
@ -1175,7 +1159,7 @@ impl BinaryPart {
|
||||
pub fn end(&self) -> usize {
|
||||
match self {
|
||||
BinaryPart::Literal(literal) => literal.end,
|
||||
BinaryPart::Identifier(identifier) => identifier.end,
|
||||
BinaryPart::Name(identifier) => identifier.end,
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.end,
|
||||
BinaryPart::CallExpression(call_expression) => call_expression.end,
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.end,
|
||||
@ -1189,7 +1173,7 @@ impl BinaryPart {
|
||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||
match self {
|
||||
BinaryPart::Literal(_literal) => {}
|
||||
BinaryPart::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
BinaryPart::Name(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
BinaryPart::BinaryExpression(ref mut binary_expression) => {
|
||||
binary_expression.rename_identifiers(old_name, new_name)
|
||||
}
|
||||
@ -1418,13 +1402,13 @@ impl Annotation {
|
||||
pub fn new_from_meta_settings(settings: &crate::execution::MetaSettings) -> Annotation {
|
||||
let mut properties: Vec<Node<ObjectProperty>> = vec![ObjectProperty::new(
|
||||
Identifier::new(annotations::SETTINGS_UNIT_LENGTH),
|
||||
Expr::Identifier(Box::new(Identifier::new(&settings.default_length_units.to_string()))),
|
||||
Expr::Name(Box::new(Name::new(&settings.default_length_units.to_string()))),
|
||||
)];
|
||||
|
||||
if settings.default_angle_units != Default::default() {
|
||||
properties.push(ObjectProperty::new(
|
||||
Identifier::new(annotations::SETTINGS_UNIT_ANGLE),
|
||||
Expr::Identifier(Box::new(Identifier::new(&settings.default_angle_units.to_string()))),
|
||||
Expr::Name(Box::new(Name::new(&settings.default_angle_units.to_string()))),
|
||||
));
|
||||
}
|
||||
Annotation {
|
||||
@ -1689,7 +1673,7 @@ pub struct ExpressionStatement {
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub struct CallExpression {
|
||||
pub callee: Node<Identifier>,
|
||||
pub callee: Node<Name>,
|
||||
pub arguments: Vec<Expr>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@ -1701,7 +1685,7 @@ pub struct CallExpression {
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase", tag = "type")]
|
||||
pub struct CallExpressionKw {
|
||||
pub callee: Node<Identifier>,
|
||||
pub callee: Node<Name>,
|
||||
pub unlabeled: Option<Expr>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub arguments: Vec<LabeledArg>,
|
||||
@ -1775,7 +1759,7 @@ impl Node<CallExpressionKw> {
|
||||
impl CallExpression {
|
||||
pub fn new(name: &str, arguments: Vec<Expr>) -> Result<Node<Self>, KclError> {
|
||||
Ok(Node::no_src(Self {
|
||||
callee: Identifier::new(name),
|
||||
callee: Name::new(name),
|
||||
arguments,
|
||||
digest: None,
|
||||
}))
|
||||
@ -1807,7 +1791,7 @@ impl CallExpression {
|
||||
impl CallExpressionKw {
|
||||
pub fn new(name: &str, unlabeled: Option<Expr>, arguments: Vec<LabeledArg>) -> Result<Node<Self>, KclError> {
|
||||
Ok(Node::no_src(Self {
|
||||
callee: Identifier::new(name),
|
||||
callee: Name::new(name),
|
||||
unlabeled,
|
||||
arguments,
|
||||
digest: None,
|
||||
@ -2192,13 +2176,8 @@ impl Node<Identifier> {
|
||||
/// Get the constraint level for this identifier.
|
||||
/// Identifier are always fully constrained.
|
||||
pub fn get_constraint_level(&self) -> ConstraintLevel {
|
||||
match &*self.name {
|
||||
"XY" | "XZ" | "YZ" => ConstraintLevel::None {
|
||||
ConstraintLevel::Full {
|
||||
source_ranges: vec![self.into()],
|
||||
},
|
||||
_ => ConstraintLevel::Full {
|
||||
source_ranges: vec![self.into()],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2223,6 +2202,99 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// A qualified name, e.g., `foo`, `bar::foo`, or `::bar::foo`.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub struct Name {
|
||||
pub name: Node<Identifier>,
|
||||
// The qualifying parts of the name.
|
||||
pub path: NodeList<Identifier>,
|
||||
// The path starts with `::`.
|
||||
pub abs_path: bool,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub digest: Option<Digest>,
|
||||
}
|
||||
|
||||
impl Node<Name> {
|
||||
pub fn get_constraint_level(&self) -> ConstraintLevel {
|
||||
match &*self.name.name {
|
||||
"XY" | "XZ" | "YZ" => ConstraintLevel::None {
|
||||
source_ranges: vec![self.into()],
|
||||
},
|
||||
_ => ConstraintLevel::Full {
|
||||
source_ranges: vec![self.into()],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Name {
|
||||
pub fn new(name: &str) -> Node<Self> {
|
||||
Node::no_src(Name {
|
||||
name: Node::no_src(Identifier {
|
||||
name: name.to_string(),
|
||||
digest: None,
|
||||
}),
|
||||
path: Vec::new(),
|
||||
abs_path: false,
|
||||
digest: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn local_ident(&self) -> Option<Node<&str>> {
|
||||
if self.path.is_empty() && !self.abs_path {
|
||||
Some(self.name.map_ref(|n| &n.name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Rename all identifiers that have the old name to the new given name.
|
||||
fn rename(&mut self, old_name: &str, new_name: &str) {
|
||||
if let Some(n) = self.local_ident() {
|
||||
if n.inner == old_name {
|
||||
self.name.name = new_name.to_owned();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Node<Identifier>> for Node<Name> {
|
||||
fn from(value: Node<Identifier>) -> Self {
|
||||
let start = value.start;
|
||||
let end = value.end;
|
||||
let mod_id = value.module_id;
|
||||
|
||||
Node::new(
|
||||
Name {
|
||||
name: value,
|
||||
path: Vec::new(),
|
||||
abs_path: false,
|
||||
digest: None,
|
||||
},
|
||||
start,
|
||||
end,
|
||||
mod_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.abs_path {
|
||||
f.write_str("::")?;
|
||||
}
|
||||
for p in &self.path {
|
||||
f.write_str(&p.name)?;
|
||||
f.write_str("::")?;
|
||||
}
|
||||
f.write_str(&self.name.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
|
@ -60,11 +60,8 @@ pub fn parse_tokens(mut tokens: TokenStream) -> ParseResult {
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
// Check all the tokens are whitespace or comments.
|
||||
if tokens
|
||||
.iter()
|
||||
.all(|t| t.token_type.is_whitespace() || t.token_type.is_comment())
|
||||
{
|
||||
// Check all the tokens are whitespace.
|
||||
if tokens.iter().all(|t| t.token_type.is_whitespace()) {
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ use super::{
|
||||
DeprecationKind,
|
||||
};
|
||||
use crate::{
|
||||
docs::StdLibFn,
|
||||
errors::{CompilationError, Severity, Tag},
|
||||
execution::types::ArrayLen,
|
||||
parsing::{
|
||||
@ -27,9 +26,9 @@ use crate::{
|
||||
BoxNode, CallExpression, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr,
|
||||
ExpressionStatement, FunctionExpression, Identifier, IfExpression, ImportItem, ImportSelector,
|
||||
ImportStatement, ItemVisibility, LabeledArg, Literal, LiteralIdentifier, LiteralValue, MemberExpression,
|
||||
MemberObject, Node, NodeList, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression, ObjectProperty,
|
||||
Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, Shebang,
|
||||
TagDeclarator, Type, TypeDeclaration, UnaryExpression, UnaryOperator, VariableDeclaration,
|
||||
MemberObject, Name, Node, NodeList, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression,
|
||||
ObjectProperty, Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement,
|
||||
Shebang, TagDeclarator, Type, TypeDeclaration, UnaryExpression, UnaryOperator, VariableDeclaration,
|
||||
VariableDeclarator, VariableKind,
|
||||
},
|
||||
math::BinaryExpressionToken,
|
||||
@ -631,7 +630,7 @@ fn operand(i: &mut TokenSlice) -> PResult<BinaryPart> {
|
||||
}
|
||||
Expr::UnaryExpression(x) => BinaryPart::UnaryExpression(x),
|
||||
Expr::Literal(x) => BinaryPart::Literal(x),
|
||||
Expr::Identifier(x) => BinaryPart::Identifier(x),
|
||||
Expr::Name(x) => BinaryPart::Name(x),
|
||||
Expr::BinaryExpression(x) => BinaryPart::BinaryExpression(x),
|
||||
Expr::CallExpression(x) => BinaryPart::CallExpression(x),
|
||||
Expr::CallExpressionKw(x) => BinaryPart::CallExpressionKw(x),
|
||||
@ -891,7 +890,7 @@ fn object_property_same_key_and_val(i: &mut TokenSlice) -> PResult<Node<ObjectPr
|
||||
key.end,
|
||||
key.module_id,
|
||||
ObjectProperty {
|
||||
value: Expr::Identifier(Box::new(key.clone())),
|
||||
value: Expr::Name(Box::new(key.clone().into())),
|
||||
key,
|
||||
digest: None,
|
||||
},
|
||||
@ -2069,7 +2068,7 @@ fn expr_allowed_in_pipe_expr(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
literal.map(Expr::Literal),
|
||||
fn_call.map(Box::new).map(Expr::CallExpression),
|
||||
fn_call_kw.map(Box::new).map(Expr::CallExpressionKw),
|
||||
nameable_identifier.map(Box::new).map(Expr::Identifier),
|
||||
name.map(Box::new).map(Expr::Name),
|
||||
array,
|
||||
object.map(Box::new).map(Expr::ObjectExpression),
|
||||
pipe_sub.map(Box::new).map(Expr::PipeSubstitution),
|
||||
@ -2088,7 +2087,7 @@ fn possible_operands(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
member_expression.map(Box::new).map(Expr::MemberExpression),
|
||||
literal.map(Expr::Literal),
|
||||
fn_call.map(Box::new).map(Expr::CallExpression),
|
||||
nameable_identifier.map(Box::new).map(Expr::Identifier),
|
||||
name.map(Box::new).map(Expr::Name),
|
||||
binary_expr_in_parens.map(Box::new).map(Expr::BinaryExpression),
|
||||
unnecessarily_bracketed,
|
||||
))
|
||||
@ -2360,6 +2359,35 @@ fn nameable_identifier(i: &mut TokenSlice) -> PResult<Node<Identifier>> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn name(i: &mut TokenSlice) -> PResult<Node<Name>> {
|
||||
let abs_path = opt(double_colon).parse_next(i)?;
|
||||
let mut idents: NodeList<Identifier> = separated(1.., nameable_identifier, double_colon)
|
||||
.parse_next(i)
|
||||
.map_err(|e| e.backtrack())?;
|
||||
|
||||
let mut start = idents[0].start;
|
||||
if let Some(abs_path) = &abs_path {
|
||||
start = abs_path.start;
|
||||
}
|
||||
let abs_path = abs_path.is_some();
|
||||
|
||||
let name = idents.pop().unwrap();
|
||||
let end = name.end;
|
||||
let module_id = name.module_id;
|
||||
|
||||
Ok(Node::new(
|
||||
Name {
|
||||
name,
|
||||
path: idents,
|
||||
abs_path,
|
||||
digest: None,
|
||||
},
|
||||
start,
|
||||
end,
|
||||
module_id,
|
||||
))
|
||||
}
|
||||
|
||||
impl TryFrom<Token> for Node<TagDeclarator> {
|
||||
type Error = CompilationError;
|
||||
|
||||
@ -2671,6 +2699,10 @@ fn plus(i: &mut TokenSlice) -> PResult<Token> {
|
||||
one_of((TokenType::Operator, "+")).parse_next(i)
|
||||
}
|
||||
|
||||
fn double_colon(i: &mut TokenSlice) -> PResult<Token> {
|
||||
TokenType::DoubleColon.parse_from(i)
|
||||
}
|
||||
|
||||
fn equals(i: &mut TokenSlice) -> PResult<Token> {
|
||||
one_of((TokenType::Operator, "="))
|
||||
.context(expected("the equals operator, ="))
|
||||
@ -2851,15 +2883,40 @@ fn uom_for_type(i: &mut TokenSlice) -> PResult<NumericSuffix> {
|
||||
any.try_map(|t: Token| t.value.parse()).parse_next(i)
|
||||
}
|
||||
|
||||
fn comment(i: &mut TokenSlice) -> PResult<Node<String>> {
|
||||
any.verify_map(|token: Token| {
|
||||
let value = match token.token_type {
|
||||
TokenType::LineComment => token.value,
|
||||
TokenType::BlockComment => token.value,
|
||||
_ => return None,
|
||||
};
|
||||
Some(Node::new(value, token.start, token.end, token.module_id))
|
||||
})
|
||||
.context(expected("Comment"))
|
||||
.parse_next(i)
|
||||
}
|
||||
|
||||
fn comments(i: &mut TokenSlice) -> PResult<Node<Vec<String>>> {
|
||||
let comments: Vec<Node<String>> = repeat(1.., (comment, opt(whitespace)).map(|(c, _)| c)).parse_next(i)?;
|
||||
let start = comments[0].start;
|
||||
let module_id = comments[0].module_id;
|
||||
let end = comments.last().unwrap().end;
|
||||
let inner = comments.into_iter().map(|n| n.inner).collect();
|
||||
Ok(Node::new(inner, start, end, module_id))
|
||||
}
|
||||
|
||||
struct ParamDescription {
|
||||
labeled: bool,
|
||||
arg_name: Token,
|
||||
type_: std::option::Option<Node<Type>>,
|
||||
default_value: Option<DefaultParamVal>,
|
||||
comments: Option<Node<Vec<String>>>,
|
||||
}
|
||||
|
||||
fn parameter(i: &mut TokenSlice) -> PResult<ParamDescription> {
|
||||
let (found_at_sign, arg_name, question_mark, _, type_, _ws, default_literal) = (
|
||||
let (_, comments, found_at_sign, arg_name, question_mark, _, type_, _ws, default_literal) = (
|
||||
opt(whitespace),
|
||||
opt(comments),
|
||||
opt(at_sign),
|
||||
any.verify(|token: &Token| !matches!(token.token_type, TokenType::Brace) || token.value != ")"),
|
||||
opt(question_mark),
|
||||
@ -2869,6 +2926,7 @@ fn parameter(i: &mut TokenSlice) -> PResult<ParamDescription> {
|
||||
opt((equals, opt(whitespace), literal).map(|(_, _, literal)| literal)),
|
||||
)
|
||||
.parse_next(i)?;
|
||||
|
||||
Ok(ParamDescription {
|
||||
labeled: found_at_sign.is_none(),
|
||||
arg_name,
|
||||
@ -2883,6 +2941,7 @@ fn parameter(i: &mut TokenSlice) -> PResult<ParamDescription> {
|
||||
return Err(ErrMode::Backtrack(ContextError::from(e)));
|
||||
}
|
||||
},
|
||||
comments,
|
||||
})
|
||||
}
|
||||
|
||||
@ -2892,6 +2951,7 @@ fn parameters(i: &mut TokenSlice) -> PResult<Vec<Parameter>> {
|
||||
let candidates: Vec<_> = separated(0.., parameter, comma_sep)
|
||||
.context(expected("function parameters"))
|
||||
.parse_next(i)?;
|
||||
opt(comma_sep).parse_next(i)?;
|
||||
|
||||
// Make sure all those tokens are valid parameters.
|
||||
let params: Vec<Parameter> = candidates
|
||||
@ -2902,8 +2962,13 @@ fn parameters(i: &mut TokenSlice) -> PResult<Vec<Parameter>> {
|
||||
arg_name,
|
||||
type_,
|
||||
default_value,
|
||||
comments,
|
||||
}| {
|
||||
let identifier = Node::<Identifier>::try_from(arg_name)?;
|
||||
let mut identifier = Node::<Identifier>::try_from(arg_name)?;
|
||||
if let Some(comments) = comments {
|
||||
identifier.comment_start = comments.start;
|
||||
identifier.pre_comments = comments.inner;
|
||||
}
|
||||
|
||||
Ok(Parameter {
|
||||
identifier,
|
||||
@ -2957,76 +3022,6 @@ fn binding_name(i: &mut TokenSlice) -> PResult<Node<Identifier>> {
|
||||
.parse_next(i)
|
||||
}
|
||||
|
||||
/// Typecheck the arguments in a keyword fn call.
|
||||
fn typecheck_all_kw(std_fn: Box<dyn StdLibFn>, args: &[&LabeledArg]) -> PResult<()> {
|
||||
for arg in args {
|
||||
let label = &arg.label;
|
||||
let expr = &arg.arg;
|
||||
if let Some(spec_arg) = std_fn.args(false).iter().find(|spec_arg| spec_arg.name == label.name) {
|
||||
typecheck(spec_arg, &expr)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Type check the arguments in a positional fn call.
|
||||
fn typecheck_all_positional(std_fn: Box<dyn StdLibFn>, args: &[&Expr]) -> PResult<()> {
|
||||
for (i, spec_arg) in std_fn.args(false).iter().enumerate() {
|
||||
let Some(arg) = &args.get(i) else {
|
||||
// The executor checks the number of arguments, so we don't need to check it here.
|
||||
continue;
|
||||
};
|
||||
typecheck(spec_arg, arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck(spec_arg: &crate::docs::StdLibFnArg, arg: &&Expr) -> PResult<()> {
|
||||
match spec_arg.type_.as_ref() {
|
||||
"TagNode" => match &arg {
|
||||
Expr::Identifier(_) => {
|
||||
// These are fine since we want someone to be able to map a variable to a tag declarator.
|
||||
}
|
||||
Expr::TagDeclarator(tag) => {
|
||||
// TODO: Remove this check. It should be redundant.
|
||||
tag.clone()
|
||||
.into_valid_binding_name()
|
||||
.map_err(|e| ErrMode::Cut(ContextError::from(e)))?;
|
||||
}
|
||||
e => {
|
||||
return Err(ErrMode::Cut(
|
||||
CompilationError::fatal(
|
||||
SourceRange::from(*arg),
|
||||
format!(
|
||||
"Expected a tag declarator like `$name`, found {}",
|
||||
e.human_friendly_type()
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
},
|
||||
"TagIdentifier" => match &arg {
|
||||
Expr::Identifier(_) => {}
|
||||
Expr::MemberExpression(_) => {}
|
||||
e => {
|
||||
return Err(ErrMode::Cut(
|
||||
CompilationError::fatal(
|
||||
SourceRange::from(*arg),
|
||||
format!(
|
||||
"Expected a tag identifier like `tagName`, found {}",
|
||||
e.human_friendly_type()
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Either a positional or keyword function call.
|
||||
fn fn_call_pos_or_kw(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
alt((
|
||||
@ -3047,15 +3042,10 @@ fn labelled_fn_call(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
}
|
||||
|
||||
fn fn_call(i: &mut TokenSlice) -> PResult<Node<CallExpression>> {
|
||||
let fn_name = nameable_identifier(i)?;
|
||||
let fn_name = name(i)?;
|
||||
opt(whitespace).parse_next(i)?;
|
||||
let _ = terminated(open_paren, opt(whitespace)).parse_next(i)?;
|
||||
let args = arguments(i)?;
|
||||
|
||||
if let Some(std_fn) = crate::std::get_stdlib_fn(&fn_name.name) {
|
||||
let just_args: Vec<_> = args.iter().collect();
|
||||
typecheck_all_positional(std_fn, &just_args)?;
|
||||
}
|
||||
let end = preceded(opt(whitespace), close_paren).parse_next(i)?.end;
|
||||
|
||||
let result = Node::new_node(
|
||||
@ -3069,17 +3059,15 @@ fn fn_call(i: &mut TokenSlice) -> PResult<Node<CallExpression>> {
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(suggestion) = super::deprecation(&result.callee.name, DeprecationKind::Function) {
|
||||
let callee_str = result.callee.name.name.to_string();
|
||||
if let Some(suggestion) = super::deprecation(&callee_str, DeprecationKind::Function) {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(
|
||||
result.as_source_range(),
|
||||
format!(
|
||||
"Calling `{}` is deprecated, prefer using `{}`.",
|
||||
result.callee.name, suggestion
|
||||
),
|
||||
format!("Calling `{}` is deprecated, prefer using `{}`.", callee_str, suggestion),
|
||||
)
|
||||
.with_suggestion(
|
||||
format!("Replace `{}` with `{}`", result.callee.name, suggestion),
|
||||
format!("Replace `{}` with `{}`", callee_str, suggestion),
|
||||
suggestion,
|
||||
None,
|
||||
Tag::Deprecated,
|
||||
@ -3091,7 +3079,7 @@ fn fn_call(i: &mut TokenSlice) -> PResult<Node<CallExpression>> {
|
||||
}
|
||||
|
||||
fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
|
||||
let fn_name = nameable_identifier(i)?;
|
||||
let fn_name = name(i)?;
|
||||
opt(whitespace).parse_next(i)?;
|
||||
let _ = open_paren.parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
@ -3147,10 +3135,6 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
|
||||
Ok((args, non_code_nodes))
|
||||
},
|
||||
)?;
|
||||
if let Some(std_fn) = crate::std::get_stdlib_fn(&fn_name.name) {
|
||||
let just_args: Vec<_> = args.iter().collect();
|
||||
typecheck_all_kw(std_fn, &just_args)?;
|
||||
}
|
||||
ignore_whitespace(i);
|
||||
opt(comma_sep).parse_next(i)?;
|
||||
let end = close_paren.parse_next(i)?.end;
|
||||
@ -3172,17 +3156,15 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(suggestion) = super::deprecation(&result.callee.name, DeprecationKind::Function) {
|
||||
let callee_str = result.callee.name.name.to_string();
|
||||
if let Some(suggestion) = super::deprecation(&callee_str, DeprecationKind::Function) {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(
|
||||
result.as_source_range(),
|
||||
format!(
|
||||
"Calling `{}` is deprecated, prefer using `{}`.",
|
||||
result.callee.name, suggestion
|
||||
),
|
||||
format!("Calling `{}` is deprecated, prefer using `{}`.", callee_str, suggestion),
|
||||
)
|
||||
.with_suggestion(
|
||||
format!("Replace `{}` with `{}`", result.callee.name, suggestion),
|
||||
format!("Replace `{}` with `{}`", callee_str, suggestion),
|
||||
suggestion,
|
||||
None,
|
||||
Tag::Deprecated,
|
||||
@ -3244,6 +3226,17 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_names() {
|
||||
for (test, expected_len) in [("someVar", 0), ("::foo", 0), ("foo::bar::baz", 2)] {
|
||||
let tokens = crate::parsing::token::lex(test, ModuleId::default()).unwrap();
|
||||
match name.parse(tokens.as_slice()) {
|
||||
Ok(n) => assert_eq!(n.path.len(), expected_len, "Could not parse name from `{test}`: {n:?}"),
|
||||
Err(e) => panic!("Could not parse name from `{test}`: {e:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weird_program_unclosed_paren() {
|
||||
let tokens = crate::parsing::token::lex("fn firstPrime(", ModuleId::default()).unwrap();
|
||||
|
@ -18,33 +18,57 @@ expression: actual
|
||||
"type": "BinaryExpression",
|
||||
"operator": "*",
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"type": "Name",
|
||||
"type": "Name",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"name": "distance",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"commentStart": 0
|
||||
},
|
||||
"path": [],
|
||||
"abs_path": false,
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"commentStart": 0
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"type": "Name",
|
||||
"type": "Name",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"name": "p",
|
||||
"start": 11,
|
||||
"end": 12,
|
||||
"commentStart": 11
|
||||
},
|
||||
"path": [],
|
||||
"abs_path": false,
|
||||
"start": 11,
|
||||
"end": 12,
|
||||
"commentStart": 11
|
||||
},
|
||||
"start": 0,
|
||||
"end": 12,
|
||||
"commentStart": 0
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"type": "Name",
|
||||
"type": "Name",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"name": "FOS",
|
||||
"start": 15,
|
||||
"end": 18,
|
||||
"commentStart": 15
|
||||
},
|
||||
"path": [],
|
||||
"abs_path": false,
|
||||
"start": 15,
|
||||
"end": 18,
|
||||
"commentStart": 15
|
||||
},
|
||||
"start": 0,
|
||||
"end": 18,
|
||||
"commentStart": 0
|
||||
@ -70,21 +94,37 @@ expression: actual
|
||||
"type": "BinaryExpression",
|
||||
"operator": "*",
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"type": "Name",
|
||||
"type": "Name",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"name": "sigmaAllow",
|
||||
"start": 26,
|
||||
"end": 36,
|
||||
"commentStart": 26
|
||||
},
|
||||
"path": [],
|
||||
"abs_path": false,
|
||||
"start": 26,
|
||||
"end": 36,
|
||||
"commentStart": 26
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"type": "Name",
|
||||
"type": "Name",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"name": "width",
|
||||
"start": 39,
|
||||
"end": 44,
|
||||
"commentStart": 39
|
||||
},
|
||||
"path": [],
|
||||
"abs_path": false,
|
||||
"start": 39,
|
||||
"end": 44,
|
||||
"commentStart": 39
|
||||
},
|
||||
"start": 26,
|
||||
"end": 44,
|
||||
"commentStart": 26
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 26,
|
||||
"end": 28,
|
||||
"name": {
|
||||
"commentStart": 26,
|
||||
"end": 28,
|
||||
"name": "XY",
|
||||
"start": 26,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 26,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 12,
|
||||
"end": 25,
|
||||
"name": {
|
||||
"commentStart": 12,
|
||||
"end": 25,
|
||||
"name": "startSketchOn",
|
||||
"start": 12,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 12,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 12,
|
||||
"end": 29,
|
||||
"start": 12,
|
||||
@ -86,12 +102,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 37,
|
||||
"end": 51,
|
||||
"name": {
|
||||
"commentStart": 37,
|
||||
"end": 51,
|
||||
"name": "startProfileAt",
|
||||
"start": 37,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 37,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 37,
|
||||
"end": 62,
|
||||
"start": 37,
|
||||
@ -142,12 +166,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 70,
|
||||
"end": 74,
|
||||
"name": {
|
||||
"commentStart": 70,
|
||||
"end": 74,
|
||||
"name": "line",
|
||||
"start": 70,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 70,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 70,
|
||||
"end": 86,
|
||||
"start": 70,
|
||||
@ -206,12 +238,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 94,
|
||||
"end": 107,
|
||||
"name": {
|
||||
"commentStart": 94,
|
||||
"end": 107,
|
||||
"name": "tangentialArc",
|
||||
"start": 94,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 94,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 94,
|
||||
"end": 119,
|
||||
"start": 94,
|
||||
@ -270,12 +310,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 127,
|
||||
"end": 131,
|
||||
"name": {
|
||||
"commentStart": 127,
|
||||
"end": 131,
|
||||
"name": "line",
|
||||
"start": 127,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 127,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 127,
|
||||
"end": 144,
|
||||
"start": 127,
|
||||
@ -308,12 +356,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 152,
|
||||
"end": 159,
|
||||
"name": {
|
||||
"commentStart": 152,
|
||||
"end": 159,
|
||||
"name": "extrude",
|
||||
"start": 152,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 152,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 152,
|
||||
"end": 170,
|
||||
"start": 152,
|
||||
|
@ -18,13 +18,21 @@ expression: actual
|
||||
},
|
||||
"init": {
|
||||
"argument": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 11,
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 11,
|
||||
"name": "scale",
|
||||
"start": 6,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 5,
|
||||
"end": 11,
|
||||
"operator": "-",
|
||||
|
@ -62,12 +62,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": "line",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 27,
|
||||
"start": 0,
|
||||
|
@ -65,12 +65,20 @@ expression: actual
|
||||
"expression": {
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 62,
|
||||
"end": 78,
|
||||
"name": {
|
||||
"commentStart": 62,
|
||||
"end": 78,
|
||||
"name": "firstPrimeNumber",
|
||||
"start": 62,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 62,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 62,
|
||||
"end": 80,
|
||||
"start": 62,
|
||||
|
@ -83,12 +83,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 54,
|
||||
"end": 59,
|
||||
"name": {
|
||||
"commentStart": 54,
|
||||
"end": 59,
|
||||
"name": "thing",
|
||||
"start": 54,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 54,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 54,
|
||||
"end": 66,
|
||||
"start": 54,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": {
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": "XY",
|
||||
"start": 25,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 25,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": "startSketchOn",
|
||||
"start": 11,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 11,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 11,
|
||||
"end": 28,
|
||||
"start": 11,
|
||||
@ -86,12 +102,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 40,
|
||||
"end": 54,
|
||||
"name": {
|
||||
"commentStart": 40,
|
||||
"end": 54,
|
||||
"name": "startProfileAt",
|
||||
"start": 40,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 40,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 40,
|
||||
"end": 64,
|
||||
"start": 40,
|
||||
@ -163,12 +187,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 76,
|
||||
"end": 80,
|
||||
"name": {
|
||||
"commentStart": 76,
|
||||
"end": 80,
|
||||
"name": "line",
|
||||
"start": 76,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 76,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 76,
|
||||
"end": 117,
|
||||
"start": 76,
|
||||
@ -223,12 +255,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 129,
|
||||
"end": 133,
|
||||
"name": {
|
||||
"commentStart": 129,
|
||||
"end": 133,
|
||||
"name": "line",
|
||||
"start": 129,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 129,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 129,
|
||||
"end": 155,
|
||||
"start": 129,
|
||||
@ -301,12 +341,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 167,
|
||||
"end": 171,
|
||||
"name": {
|
||||
"commentStart": 167,
|
||||
"end": 171,
|
||||
"name": "line",
|
||||
"start": 167,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 167,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 167,
|
||||
"end": 211,
|
||||
"start": 167,
|
||||
@ -317,12 +365,20 @@ expression: actual
|
||||
{
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 223,
|
||||
"end": 228,
|
||||
"name": {
|
||||
"commentStart": 223,
|
||||
"end": 228,
|
||||
"name": "close",
|
||||
"start": 223,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 223,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 223,
|
||||
"end": 230,
|
||||
"start": 223,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": {
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": "XY",
|
||||
"start": 25,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 25,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": "startSketchOn",
|
||||
"start": 11,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 11,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 11,
|
||||
"end": 28,
|
||||
"start": 11,
|
||||
@ -86,12 +102,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 32,
|
||||
"end": 46,
|
||||
"name": {
|
||||
"commentStart": 32,
|
||||
"end": 46,
|
||||
"name": "startProfileAt",
|
||||
"start": 32,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 32,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 32,
|
||||
"end": 56,
|
||||
"start": 32,
|
||||
@ -145,12 +169,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 60,
|
||||
"end": 64,
|
||||
"name": {
|
||||
"commentStart": 60,
|
||||
"end": 64,
|
||||
"name": "line",
|
||||
"start": 60,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 60,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 60,
|
||||
"end": 86,
|
||||
"start": 60,
|
||||
@ -161,12 +193,20 @@ expression: actual
|
||||
{
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 90,
|
||||
"end": 95,
|
||||
"name": {
|
||||
"commentStart": 90,
|
||||
"end": 95,
|
||||
"name": "close",
|
||||
"start": 90,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 90,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 90,
|
||||
"end": 97,
|
||||
"start": 90,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 22,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"commentStart": 22,
|
||||
"end": 24,
|
||||
"name": "XY",
|
||||
"start": 22,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 22,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 8,
|
||||
"end": 21,
|
||||
"name": {
|
||||
"commentStart": 8,
|
||||
"end": 21,
|
||||
"name": "startSketchOn",
|
||||
"start": 8,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 8,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 8,
|
||||
"end": 25,
|
||||
"start": 8,
|
||||
@ -45,13 +61,21 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 44,
|
||||
"end": 45,
|
||||
"name": {
|
||||
"commentStart": 44,
|
||||
"end": 45,
|
||||
"name": "p",
|
||||
"start": 44,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 44,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
{
|
||||
"commentStart": 47,
|
||||
"end": 48,
|
||||
@ -61,12 +85,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 29,
|
||||
"end": 43,
|
||||
"name": {
|
||||
"commentStart": 29,
|
||||
"end": 43,
|
||||
"name": "startProfileAt",
|
||||
"start": 29,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 29,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 29,
|
||||
"end": 49,
|
||||
"start": 29,
|
||||
|
@ -34,12 +34,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 8,
|
||||
"end": 9,
|
||||
"name": {
|
||||
"commentStart": 8,
|
||||
"end": 9,
|
||||
"name": "f",
|
||||
"start": 8,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 8,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 8,
|
||||
"end": 12,
|
||||
"start": 8,
|
||||
@ -69,12 +77,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 16,
|
||||
"end": 17,
|
||||
"name": {
|
||||
"commentStart": 16,
|
||||
"end": 17,
|
||||
"name": "g",
|
||||
"start": 16,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 16,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 16,
|
||||
"end": 23,
|
||||
"start": 16,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 22,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"commentStart": 22,
|
||||
"end": 24,
|
||||
"name": "XY",
|
||||
"start": 22,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 22,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 8,
|
||||
"end": 21,
|
||||
"name": {
|
||||
"commentStart": 8,
|
||||
"end": 21,
|
||||
"name": "startSketchOn",
|
||||
"start": 8,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 8,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 8,
|
||||
"end": 25,
|
||||
"start": 8,
|
||||
@ -45,13 +61,21 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 44,
|
||||
"end": 45,
|
||||
"name": {
|
||||
"commentStart": 44,
|
||||
"end": 45,
|
||||
"name": "p",
|
||||
"start": 44,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 44,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
{
|
||||
"commentStart": 47,
|
||||
"end": 48,
|
||||
@ -61,12 +85,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 29,
|
||||
"end": 43,
|
||||
"name": {
|
||||
"commentStart": 29,
|
||||
"end": 43,
|
||||
"name": "startProfileAt",
|
||||
"start": 29,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 29,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 29,
|
||||
"end": 49,
|
||||
"start": 29,
|
||||
@ -100,12 +132,20 @@ expression: actual
|
||||
}
|
||||
},
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 68,
|
||||
"end": 69,
|
||||
"name": {
|
||||
"commentStart": 68,
|
||||
"end": 69,
|
||||
"name": "l",
|
||||
"start": 68,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 68,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"end": 70,
|
||||
@ -116,12 +156,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 53,
|
||||
"end": 57,
|
||||
"name": {
|
||||
"commentStart": 53,
|
||||
"end": 57,
|
||||
"name": "line",
|
||||
"start": 53,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 53,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 53,
|
||||
"end": 71,
|
||||
"start": 53,
|
||||
|
@ -54,12 +54,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": "line",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 26,
|
||||
"start": 0,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": {
|
||||
"commentStart": 25,
|
||||
"end": 27,
|
||||
"name": "XY",
|
||||
"start": 25,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 25,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"commentStart": 11,
|
||||
"end": 24,
|
||||
"name": "startSketchOn",
|
||||
"start": 11,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 11,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 11,
|
||||
"end": 28,
|
||||
"start": 11,
|
||||
@ -86,12 +102,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 32,
|
||||
"end": 46,
|
||||
"name": {
|
||||
"commentStart": 32,
|
||||
"end": 46,
|
||||
"name": "startProfileAt",
|
||||
"start": 32,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 32,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 32,
|
||||
"end": 56,
|
||||
"start": 32,
|
||||
|
@ -31,21 +31,37 @@ expression: actual
|
||||
"value": "hello"
|
||||
},
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 16,
|
||||
"end": 27,
|
||||
"name": {
|
||||
"commentStart": 16,
|
||||
"end": 27,
|
||||
"name": "aIdentifier",
|
||||
"start": 16,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 16,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 3,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 3,
|
||||
"name": "log",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 28,
|
||||
"start": 0,
|
||||
|
@ -25,12 +25,20 @@ expression: actual
|
||||
}
|
||||
},
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 9,
|
||||
"end": 10,
|
||||
"name": {
|
||||
"commentStart": 9,
|
||||
"end": 10,
|
||||
"name": "l",
|
||||
"start": 9,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 9,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"end": 11,
|
||||
@ -47,12 +55,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": "line",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 15,
|
||||
"start": 0,
|
||||
|
@ -21,21 +21,37 @@ expression: actual
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 31,
|
||||
"end": 33,
|
||||
"name": {
|
||||
"commentStart": 31,
|
||||
"end": 33,
|
||||
"name": "XY",
|
||||
"start": 31,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 31,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 17,
|
||||
"end": 30,
|
||||
"name": {
|
||||
"commentStart": 17,
|
||||
"end": 30,
|
||||
"name": "startSketchOn",
|
||||
"start": 17,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 17,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 17,
|
||||
"end": 34,
|
||||
"start": 17,
|
||||
@ -111,12 +127,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 42,
|
||||
"end": 48,
|
||||
"name": {
|
||||
"commentStart": 42,
|
||||
"end": 48,
|
||||
"name": "circle",
|
||||
"start": 42,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 42,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 42,
|
||||
"end": 76,
|
||||
"start": 42,
|
||||
@ -150,12 +174,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 84,
|
||||
"end": 91,
|
||||
"name": {
|
||||
"commentStart": 84,
|
||||
"end": 91,
|
||||
"name": "extrude",
|
||||
"start": 84,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 84,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 84,
|
||||
"end": 104,
|
||||
"start": 84,
|
||||
|
@ -23,13 +23,21 @@ expression: actual
|
||||
"argument": {
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 36,
|
||||
"end": 41,
|
||||
"name": {
|
||||
"commentStart": 36,
|
||||
"end": 41,
|
||||
"name": "angle",
|
||||
"start": 36,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 36,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
{
|
||||
"commentStart": 43,
|
||||
"end": 46,
|
||||
@ -44,12 +52,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 28,
|
||||
"end": 35,
|
||||
"name": {
|
||||
"commentStart": 28,
|
||||
"end": 35,
|
||||
"name": "default",
|
||||
"start": 28,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 28,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 28,
|
||||
"end": 47,
|
||||
"start": 28,
|
||||
|
@ -59,12 +59,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 17,
|
||||
"end": 23,
|
||||
"name": {
|
||||
"commentStart": 17,
|
||||
"end": 23,
|
||||
"name": "legLen",
|
||||
"start": 17,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 17,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 17,
|
||||
"end": 29,
|
||||
"start": 17,
|
||||
@ -80,12 +88,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 8,
|
||||
"end": 11,
|
||||
"name": {
|
||||
"commentStart": 8,
|
||||
"end": 11,
|
||||
"name": "min",
|
||||
"start": 8,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 8,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 8,
|
||||
"end": 30,
|
||||
"start": 8,
|
||||
|
@ -31,12 +31,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 13,
|
||||
"end": 26,
|
||||
"name": {
|
||||
"commentStart": 13,
|
||||
"end": 26,
|
||||
"name": "startSketchOn",
|
||||
"start": 13,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 13,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 13,
|
||||
"end": 32,
|
||||
"start": 13,
|
||||
@ -54,12 +62,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 109,
|
||||
"end": 123,
|
||||
"name": {
|
||||
"commentStart": 109,
|
||||
"end": 123,
|
||||
"name": "startProfileAt",
|
||||
"start": 109,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 109,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 109,
|
||||
"end": 126,
|
||||
"start": 109,
|
||||
|
@ -34,21 +34,37 @@ expression: actual
|
||||
"cond": {
|
||||
"arguments": [
|
||||
{
|
||||
"abs_path": false,
|
||||
"commentStart": 51,
|
||||
"end": 57,
|
||||
"name": {
|
||||
"commentStart": 51,
|
||||
"end": 57,
|
||||
"name": "radius",
|
||||
"start": 51,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 51,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 46,
|
||||
"end": 50,
|
||||
"name": {
|
||||
"commentStart": 46,
|
||||
"end": 50,
|
||||
"name": "func",
|
||||
"start": 46,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 46,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 46,
|
||||
"end": 58,
|
||||
"start": 46,
|
||||
|
@ -66,12 +66,20 @@ expression: actual
|
||||
"start": 22,
|
||||
"type": "ObjectProperty",
|
||||
"value": {
|
||||
"abs_path": false,
|
||||
"commentStart": 22,
|
||||
"end": 23,
|
||||
"name": {
|
||||
"commentStart": 22,
|
||||
"end": 23,
|
||||
"name": "x",
|
||||
"start": 22,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 22,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -8,13 +8,21 @@ expression: actual
|
||||
"commentStart": 0,
|
||||
"end": 5,
|
||||
"expression": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 5,
|
||||
"name": "truee",
|
||||
"start": 0,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ExpressionStatement",
|
||||
"type": "ExpressionStatement"
|
||||
|
@ -47,12 +47,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 13,
|
||||
"end": 19,
|
||||
"name": {
|
||||
"commentStart": 13,
|
||||
"end": 19,
|
||||
"name": "legLen",
|
||||
"start": 13,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 13,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 13,
|
||||
"end": 25,
|
||||
"start": 13,
|
||||
@ -80,12 +88,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 8,
|
||||
"end": 11,
|
||||
"name": {
|
||||
"commentStart": 8,
|
||||
"end": 11,
|
||||
"name": "min",
|
||||
"start": 8,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 8,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 8,
|
||||
"end": 29,
|
||||
"start": 8,
|
||||
|
@ -73,12 +73,20 @@ expression: actual
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 17,
|
||||
"end": 23,
|
||||
"name": {
|
||||
"commentStart": 17,
|
||||
"end": 23,
|
||||
"name": "myFunc",
|
||||
"start": 17,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 17,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 17,
|
||||
"end": 30,
|
||||
"start": 17,
|
||||
|
@ -21,13 +21,21 @@ expression: actual
|
||||
"end": 21,
|
||||
"left": {
|
||||
"argument": {
|
||||
"abs_path": false,
|
||||
"commentStart": 5,
|
||||
"end": 9,
|
||||
"name": {
|
||||
"commentStart": 5,
|
||||
"end": 9,
|
||||
"name": "leg2",
|
||||
"start": 5,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 5,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 4,
|
||||
"end": 9,
|
||||
"operator": "-",
|
||||
@ -37,13 +45,21 @@ expression: actual
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 12,
|
||||
"end": 21,
|
||||
"name": {
|
||||
"commentStart": 12,
|
||||
"end": 21,
|
||||
"name": "thickness",
|
||||
"start": 12,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 12,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"start": 4,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
|
@ -21,13 +21,21 @@ expression: actual
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"abs_path": false,
|
||||
"commentStart": 30,
|
||||
"end": 32,
|
||||
"name": {
|
||||
"commentStart": 30,
|
||||
"end": 32,
|
||||
"name": "sg",
|
||||
"start": 30,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 30,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 23,
|
||||
"end": 32,
|
||||
"start": 23,
|
||||
@ -36,13 +44,21 @@ expression: actual
|
||||
},
|
||||
{
|
||||
"argument": {
|
||||
"abs_path": false,
|
||||
"commentStart": 48,
|
||||
"end": 50,
|
||||
"name": {
|
||||
"commentStart": 48,
|
||||
"end": 50,
|
||||
"name": "sg",
|
||||
"start": 48,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 48,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 41,
|
||||
"end": 50,
|
||||
"start": 41,
|
||||
|
@ -28,12 +28,20 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 14,
|
||||
"end": 15,
|
||||
"name": {
|
||||
"commentStart": 14,
|
||||
"end": 15,
|
||||
"name": "a",
|
||||
"start": 14,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 14,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -46,22 +54,38 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 21,
|
||||
"end": 22,
|
||||
"name": {
|
||||
"commentStart": 21,
|
||||
"end": 22,
|
||||
"name": "b",
|
||||
"start": 21,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 21,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 9,
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 9,
|
||||
"name": "foo",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 6,
|
||||
"end": 23,
|
||||
"start": 6,
|
||||
|
@ -42,22 +42,38 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 19,
|
||||
"end": 20,
|
||||
"name": {
|
||||
"commentStart": 19,
|
||||
"end": 20,
|
||||
"name": "x",
|
||||
"start": 19,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 19,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 11,
|
||||
"end": 12,
|
||||
"name": {
|
||||
"commentStart": 11,
|
||||
"end": 12,
|
||||
"name": "f",
|
||||
"start": 11,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 11,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 11,
|
||||
"end": 21,
|
||||
"start": 11,
|
||||
|
@ -28,12 +28,20 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 28,
|
||||
"end": 29,
|
||||
"name": {
|
||||
"commentStart": 28,
|
||||
"end": 29,
|
||||
"name": "x",
|
||||
"start": 28,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 28,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -46,12 +54,20 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 50,
|
||||
"end": 51,
|
||||
"name": {
|
||||
"commentStart": 50,
|
||||
"end": 51,
|
||||
"name": "x",
|
||||
"start": 50,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 50,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -64,22 +80,38 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 72,
|
||||
"end": 73,
|
||||
"name": {
|
||||
"commentStart": 72,
|
||||
"end": 73,
|
||||
"name": "x",
|
||||
"start": 72,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 72,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 7,
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 7,
|
||||
"name": "f",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 6,
|
||||
"end": 87,
|
||||
"start": 6,
|
||||
|
@ -28,12 +28,20 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 28,
|
||||
"end": 29,
|
||||
"name": {
|
||||
"commentStart": 28,
|
||||
"end": 29,
|
||||
"name": "x",
|
||||
"start": 28,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 28,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -46,22 +54,38 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 75,
|
||||
"end": 76,
|
||||
"name": {
|
||||
"commentStart": 75,
|
||||
"end": 76,
|
||||
"name": "x",
|
||||
"start": 75,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 75,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 7,
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 7,
|
||||
"name": "f",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 6,
|
||||
"end": 90,
|
||||
"nonCodeMeta": {
|
||||
|
@ -28,34 +28,58 @@ expression: actual
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"abs_path": false,
|
||||
"commentStart": 17,
|
||||
"end": 18,
|
||||
"name": {
|
||||
"commentStart": 17,
|
||||
"end": 18,
|
||||
"name": "z",
|
||||
"start": 17,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 17,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 9,
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 9,
|
||||
"name": "foo",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 6,
|
||||
"end": 19,
|
||||
"start": 6,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": {
|
||||
"abs_path": false,
|
||||
"commentStart": 10,
|
||||
"end": 11,
|
||||
"name": {
|
||||
"commentStart": 10,
|
||||
"end": 11,
|
||||
"name": "x",
|
||||
"start": 10,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 10,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
|