Compare commits

..

3 Commits

52 changed files with 9919 additions and 14370 deletions

View File

@ -10,7 +10,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

View File

@ -7,11 +7,14 @@ on:
- main
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'nightly-v[0-9]+.[0-9]+.[0-9]+'
schedule:
- cron: '0 4 * * *'
# Daily at 04:00 AM UTC
# Will checkout the last commit from the default branch (main as of 2023-10-04)
env:
IS_RELEASE: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
IS_NIGHTLY: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'nightly-v') }}
IS_RELEASE: ${{ github.ref_type == 'tag' }}
IS_NIGHTLY: ${{ github.event_name == 'schedule' }}
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@ -26,12 +29,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
@ -52,10 +52,7 @@ jobs:
- name: Set nightly version, product name, release notes, and icons
if: ${{ env.IS_NIGHTLY == 'true' }}
run: |
export VERSION=${GITHUB_REF_NAME#nightly-v}
yarn files:set-version
yarn files:flip-to-nightly
run: yarn files:flip-to-nightly
- name: Set release version
if: ${{ env.IS_RELEASE == 'true' }}
@ -126,24 +123,9 @@ jobs:
cp prepared-files/assets/icon.ico assets/icon.ico
cp prepared-files/assets/icon.png assets/icon.png
- name: Get exact Node.js version
run: echo "NODE_VERSION=$(node -v)" >> $GITHUB_ENV
shell: bash
- name: Clear hosted tool cache on Windows
if: ${{ contains(matrix.os, 'windows') }}
run: |
$nodeVersion = $env:NODE_VERSION.TrimStart('v')
Remove-Item -Force "C:\hostedtoolcache\windows\node\$nodeVersion\x64\corepack*"
npm i -g --force corepack
- run: corepack enable
- name: Sync node version and setup cache
uses: actions/setup-node@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- name: yarn install
# Windows is picky sometimes and fails on fetch. Step takes about ~30s
@ -288,7 +270,7 @@ jobs:
runs-on: ubuntu-22.04
permissions:
contents: write
if: ${{ github.ref_type == 'tag' }}
if: ${{ github.ref_type == 'tag' || github.event_name == 'schedule' }}
env:
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
VERSION: ${{ format('v{0}', needs.prepare-files.outputs.version) }}
@ -345,8 +327,8 @@ jobs:
env:
NOTES: ${{ needs.prepare-files.outputs.notes }}
PUB_DATE: ${{ github.event.repository.updated_at }}
WEBSITE_DIR: ${{ env.IS_NIGHTLY == 'true' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }}
URL_CODED_NAME: ${{ env.IS_NIGHTLY == 'true' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
WEBSITE_DIR: ${{ github.event_name == 'schedule' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }}
URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
run: |
RELEASE_DIR=https://${WEBSITE_DIR}
jq --null-input \
@ -429,3 +411,14 @@ jobs:
- name: Invalidate bucket cache on latest*.yml and last_download.json files
if: ${{ env.IS_NIGHTLY == 'true' }}
run: yarn files:invalidate-bucket:nightly
- name: Tag nightly commit
if: ${{ env.IS_NIGHTLY == 'true' }}
uses: actions/github-script@v7
with:
script: |
const { VERSION } = process.env
const { owner, repo } = context.repo
const { sha } = context
const ref = `refs/tags/nightly-${VERSION}`
github.rest.git.createRef({ owner, repo, sha, ref })

View File

@ -16,8 +16,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

View File

@ -54,16 +54,6 @@ jobs:
- uses: actions/checkout@v4
with:
token: ${{ steps.app-token.outputs.token }}
- name: Get exact Node.js version
run: echo "NODE_VERSION=$(node -v)" >> $GITHUB_ENV
shell: bash
- name: Clear hosted tool cache on Windows
if: ${{ contains(matrix.os, 'windows') }}
run: |
$nodeVersion = $env:NODE_VERSION.TrimStart('v')
Remove-Item -Force "C:\hostedtoolcache\windows\node\$nodeVersion\x64\corepack*"
npm i -g --force corepack
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

View File

@ -18,7 +18,6 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

View File

@ -16,8 +16,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

View File

@ -20,7 +20,6 @@ jobs:
runs-on: 'ubuntu-22.04'
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@ -33,7 +32,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@ -49,7 +47,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@ -70,7 +67,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@ -96,12 +92,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: taiki-e/install-action@2dbeb927f58939d3aa13bf06ba0c0a34b76b9bfb
with:
@ -126,12 +121,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: taiki-e/install-action@2dbeb927f58939d3aa13bf06ba0c0a34b76b9bfb
with:

View File

@ -1,41 +0,0 @@
name: tag-nightly
permissions:
contents: write
on:
schedule:
- cron: '0 4 * * *'
# Daily at 04:00 AM UTC
# Will checkout the last commit from the default branch (main as of 2023-10-04)
jobs:
tag-nightly:
runs-on: ubuntu-22.04
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
with:
token: ${{ steps.app-token.outputs.token }}
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- run: yarn install
- name: Push tag
run: |
VERSION_NO_V=$(date +'%-y.%-m.%-d')
TAG="nightly-v$VERSION_NO_V"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git tag $TAG
git push origin tag $TAG

11
.gitignore vendored
View File

@ -1,14 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# dependencies
/node_modules
/.pnp
@ -33,7 +24,7 @@ yarn-debug.log*
yarn-error.log*
.idea
.vscode
# .vscode
.helix
src/wasm-lib/.idea
src/wasm-lib/.vscode

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"rust-analyzer.linkedProjects": [
"src/wasm-lib/Cargo.toml"
]
}

View File

@ -1 +0,0 @@
nodeLinker: node-modules

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 145 KiB

1
exp Normal file
View File

@ -0,0 +1 @@
sketch001=startSketchOn('XZ')|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]|>angledLine([0,268.43],%,$rectangleSegmentA001)|>angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)|>angledLine([segAng(rectangleSegmentA001),-segLen(rectangleSegmentA001)],%,$yo)|>line(endAbsolute=[profileStartX(%),profileStartY(%)],tag=$seg02)|>close()extrude001=extrude(sketch001,length=100)|>chamfer(length=30,tags=[getOppositeEdge(seg01)],tag=$seg03)|>chamfer(length=30,tags=[seg01],tag=$seg04)|>chamfer(length=30,tags=[getNextAdjacentEdge(seg02)],tag=$seg05)|>chamfer(length=30,tags=[getNextAdjacentEdge(yo)],tag=$seg06)sketch004=startSketchOn(extrude001,seg05)profile003=startProfileAt([82.57,322.96],sketch004)|>angledLine([0,11.16],%,$rectangleSegmentA004)|>angledLine([segAng(rectangleSegmentA004)-90,103.07],%)|>angledLine([segAng(rectangleSegmentA004),-segLen(rectangleSegmentA004)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()sketch003=startSketchOn(extrude001,seg04)profile002=startProfileAt([-209.64,255.28],sketch003)|>angledLine([0,11.56],%,$rectangleSegmentA003)|>angledLine([segAng(rectangleSegmentA003)-90,106.84],%)|>angledLine([segAng(rectangleSegmentA003),-segLen(rectangleSegmentA003)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()sketch002=startSketchOn(extrude001,seg03)profile001=startProfileAt([205.96,254.59],sketch002)|>angledLine([0,11.39],%,$rectangleSegmentA002)|>angledLine([segAng(rectangleSegmentA002)-90,105.26],%)|>angledLine([segAng(rectangleSegmentA002),-segLen(rectangleSegmentA002)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()

1
got Normal file
View File

@ -0,0 +1 @@
sketch001=startSketchOn('XZ')|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]|>angledLine([0,268.43],%,$rectangleSegmentA001)|>angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)|>angledLine([segAng(rectangleSegmentA001),-segLen(rectangleSegmentA001)],%,$yo)|>line(endAbsolute=[profileStartX(%),profileStartY(%)],tag=$seg02)|>close()extrude001=extrude(sketch001,length=100)|>chamfer(length=30,tags=[getOppositeEdge(seg01)],tag=$seg03)|>chamfer(length=30,tags=[seg01],tag=$seg04)|>chamfer(length=30,tags=[getNextAdjacentEdge(seg02)],tag=$seg05)|>chamfer(length=30,tags=[getNextAdjacentEdge(yo)],tag=$seg06)sketch005=startSketchOn(extrude001,seg06)profile004=startProfileAt([-23.43,19.69],sketch005)|>angledLine([0,9.1],%,$rectangleSegmentA005)|>angledLine([segAng(rectangleSegmentA005)-90,84.07],%)|>angledLine([segAng(rectangleSegmentA005),-segLen(rectangleSegmentA005)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()sketch004=startSketchOn(extrude001,seg05)profile003=startProfileAt([82.57,322.96],sketch004)|>angledLine([0,11.16],%,$rectangleSegmentA004)|>angledLine([segAng(rectangleSegmentA004)-90,103.07],%)|>angledLine([segAng(rectangleSegmentA004),-segLen(rectangleSegmentA004)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()sketch003=startSketchOn(extrude001,seg04)profile002=startProfileAt([-209.64,255.28],sketch003)|>angledLine([0,11.56],%,$rectangleSegmentA003)|>angledLine([segAng(rectangleSegmentA003)-90,106.84],%)|>angledLine([segAng(rectangleSegmentA003),-segLen(rectangleSegmentA003)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()sketch002=startSketchOn(extrude001,seg03)profile001=startProfileAt([205.96,254.59],sketch002)|>angledLine([0,11.39],%,$rectangleSegmentA002)|>angledLine([segAng(rectangleSegmentA002)-90,105.26],%)|>angledLine([segAng(rectangleSegmentA002),-segLen(rectangleSegmentA002)],%)|>line(endAbsolute=[profileStartX(%),profileStartY(%)])|>close()

View File

@ -77,7 +77,7 @@
"start": "vite --port=3000 --host=0.0.0.0",
"start:prod": "vite preview --port=3000",
"serve": "vite serve --port=3000",
"build": "corepack enable && yarn set version stable && yarn install:rust && . $HOME/.cargo/env && yarn install:wasm-pack:sh && yarn build:wasm && vite build",
"build": "yarn install:rust && . $HOME/.cargo/env && yarn install:wasm-pack:sh && yarn build:wasm && vite build",
"build:local": "vite build",
"build:both": "vite build",
"build:both:local": "yarn build:wasm && vite build",
@ -91,11 +91,11 @@
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/next/manifest.json",
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/next/manifest.json",
"build:wasm-dev": "yarn wasm-prep && (cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
"build:wasm:nocopy": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings",
"build:wasm": "yarn build:wasm:nocopy && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
"build:wasm:windows": "yarn install:wasm-pack:cargo && yarn build:wasm:nocopy && ./scripts/copy-wasm.ps1 && yarn fmt",
"build:wasm:windows": "yarn install:wasm-pack:cargo && yarn build:wasm:nocopy && copy src\\wasm-lib\\pkg\\wasm_lib_bg.wasm public && yarn fmt",
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
"wasm-prep": "rimraf src/wasm-lib/pkg && mkdirp src/wasm-lib/pkg && rimraf src/wasm-lib/kcl/bindings",
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src",
@ -218,5 +218,5 @@
"ws": "^8.17.0",
"yarn": "^1.22.22"
},
"packageManager": "yarn@4.6.0"
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

View File

@ -1 +0,0 @@
copy src\wasm-lib\pkg\wasm_lib_bg.wasm public

View File

@ -1,8 +1,10 @@
#!/bin/bash
export VERSION=$(date +'%-y.%-m.%-d')
export COMMIT=$(git rev-parse --short HEAD)
# package.json
yarn files:set-version
PACKAGE=$(jq '.productName="Zoo Modeling App (Nightly)" | .name="zoo-modeling-app-nightly"' package.json --indent 2)
echo "$PACKAGE" > package.json
@ -12,7 +14,7 @@ yq -i '.appId = "dev.zoo.modeling-app-nightly"' electron-builder.yml
yq -i '.nsis.include = "./scripts/installer-nightly.nsh"' electron-builder.yml
# Release notes
echo "Nightly build (commit $COMMIT)" > release-notes.md
echo "Nightly build $VERSION (commit $COMMIT)" > release-notes.md
# icons
cp assets/icon-nightly.png assets/icon.png

View File

@ -24,7 +24,12 @@ import ModelingMachineProvider from 'components/ModelingMachineProvider'
import FileMachineProvider from 'components/FileMachineProvider'
import { MachineManagerProvider } from 'components/MachineManagerProvider'
import { PATHS } from 'lib/paths'
import { fileLoader, homeLoader, telemetryLoader } from 'lib/routeLoaders'
import {
fileLoader,
homeLoader,
onboardingRedirectLoader,
telemetryLoader,
} from 'lib/routeLoaders'
import LspProvider from 'components/LspProvider'
import { KclContextProvider } from 'lang/KclProvider'
import { ASK_TO_OPEN_QUERY_PARAM, BROWSER_PROJECT_NAME } from 'lib/constants'
@ -108,6 +113,11 @@ const router = createRouter([
{
id: PATHS.FILE + 'SETTINGS',
children: [
{
loader: onboardingRedirectLoader,
index: true,
element: <></>,
},
{
path: makeUrlPathRelative(PATHS.SETTINGS),
element: <Settings />,

View File

@ -130,8 +130,6 @@ export const FileMachineProvider = ({
navigateToFile: ({ context, event }) => {
if (event.type !== 'xstate.done.actor.create-and-open-file') return
if (event.output && 'name' in event.output) {
// TODO: Technically this is not the same as the FileTree Onclick even if they are in the same page
// What is "Open file?"
commandBarActor.send({ type: 'Close' })
navigate(
`..${PATHS.FILE}/${encodeURIComponent(

View File

@ -23,8 +23,6 @@ import { FileEntry } from 'lib/project'
import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher'
import { normalizeLineEndings } from 'lib/codeEditor'
import { reportRejection } from 'lib/trap'
import { useKclContext } from 'lang/KclProvider'
import { kclErrorsByFilename, KCLError } from 'lang/errors'
function getIndentationCSS(level: number) {
return `calc(1rem * ${level + 1})`
@ -160,7 +158,6 @@ const FileTreeItem = ({
level = 0,
treeSelection,
setTreeSelection,
runtimeErrors,
}: {
parentDir: FileEntry | undefined
project?: IndexLoaderData['project']
@ -180,7 +177,6 @@ const FileTreeItem = ({
level?: number
treeSelection: FileEntry | undefined
setTreeSelection: Dispatch<React.SetStateAction<FileEntry | undefined>>
runtimeErrors: Map<string, KCLError[]>
}) => {
const { send: fileSend, context: fileContext } = useFileContext()
const { onFileOpen, onFileClose } = useLspContext()
@ -190,8 +186,6 @@ const FileTreeItem = ({
const isFileOrDirHighlighted = treeSelection?.path === fileOrDir?.path
const itemRef = useRef(null)
const hasRuntimeError = runtimeErrors.has(fileOrDir.path)
// Since every file or directory gets its own FileTreeItem, we can do this.
// Because subtrees only render when they are opened, that means this
// only listens when they open. Because this acts like a useEffect, when
@ -298,7 +292,7 @@ const FileTreeItem = ({
>
{!isRenaming ? (
<button
className="relative flex gap-1 items-center py-0.5 rounded-none border-none p-0 m-0 text-sm w-full hover:!bg-transparent text-left !text-inherit"
className="flex gap-1 items-center py-0.5 rounded-none border-none p-0 m-0 text-sm w-full hover:!bg-transparent text-left !text-inherit"
style={{ paddingInlineStart: getIndentationCSS(level) }}
onClick={(e) => {
e.currentTarget.focus()
@ -306,21 +300,11 @@ const FileTreeItem = ({
}}
onKeyUp={handleKeyUp}
>
{hasRuntimeError && (
<p
className={
'absolute m-0 p-0 bottom-3 left-6 w-3 h-3 flex items-center justify-center text-[9px] font-semibold text-white bg-red-600 rounded-full border border-red-300 dark:border-red-800 z-50 hover:cursor-pointer hover:scale-[2] transition-transform duration-200'
}
title={`Click to view notifications`}
>
<span>x</span>
</p>
)}
<CustomIcon
name={fileOrDir.name?.endsWith(FILE_EXT) ? 'kcl' : 'file'}
className="inline-block w-3 text-current"
/>
<span className="pl-1">{fileOrDir.name}</span>
{fileOrDir.name}
</button>
) : (
<RenameForm
@ -430,7 +414,6 @@ const FileTreeItem = ({
key={level + '-' + child.path}
treeSelection={treeSelection}
setTreeSelection={setTreeSelection}
runtimeErrors={runtimeErrors}
/>
)
)}
@ -677,8 +660,6 @@ export const FileTreeInner = ({
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const { send: fileSend, context: fileContext } = useFileContext()
const { send: modelingSend } = useModelingContext()
const { errors } = useKclContext()
const runtimeErrors = kclErrorsByFilename(errors)
const [lastDirectoryClicked, setLastDirectoryClicked] = useState<
FileEntry | undefined
@ -788,7 +769,6 @@ export const FileTreeInner = ({
key={fileOrDir.path}
treeSelection={treeSelection}
setTreeSelection={setTreeSelection}
runtimeErrors={runtimeErrors}
/>
)
)}

View File

@ -18,7 +18,6 @@ import { editorManager } from 'lib/singletons'
import { ContextFrom } from 'xstate'
import { settingsMachine } from 'machines/settingsMachine'
import { FeatureTreePane } from './FeatureTreePane'
import { kclErrorsByFilename } from 'lang/errors'
export type SidebarType =
| 'code'
@ -31,10 +30,8 @@ export type SidebarType =
| 'variables'
export interface BadgeInfo {
value: (props: PaneCallbackProps) => boolean | number | string
value: (props: PaneCallbackProps) => boolean | number
onClick?: MouseEventHandler<any>
className?: string
title?: string
}
/**
@ -155,25 +152,6 @@ export const sidebarPanes: SidebarPane[] = [
},
keybinding: 'Shift + F',
hide: ({ platform }) => platform === 'web',
showBadge: {
value: (context) => {
// Only compute runtime errors! Compilation errors are not tracked here.
const errors = kclErrorsByFilename(context.kclContext.errors)
return errors.size > 0 ? 'x' : ''
},
onClick: (e) => {
e.preventDefault()
// TODO: When we have generic file open
// If badge is pressed
// Open the first error in the array of errors
// Then scroll to error
// Do you automatically open the project files
// editorManager.scrollToFirstErrorDiagnosticIfExists()
},
className:
'absolute m-0 p-0 bottom-4 left-4 w-3 h-3 flex items-center justify-center text-[9px] font-semibold text-white bg-red-600 rounded-full border border-red-300 dark:border-red-800 z-50 hover:cursor-pointer hover:scale-[2] transition-transform duration-200',
title: 'Project files have runtime errors',
},
},
{
id: 'variables',

View File

@ -27,10 +27,8 @@ interface ModelingSidebarProps {
}
interface BadgeInfoComputed {
value: number | boolean | string
value: number | boolean
onClick?: MouseEventHandler<any>
className?: string
title?: string
}
function getPlatformString(): 'web' | 'desktop' {
@ -118,8 +116,6 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
acc[pane.id] = {
value: pane.showBadge.value(paneCallbackProps),
onClick: pane.showBadge.onClick,
className: pane.showBadge.className,
title: pane.showBadge.title,
}
}
return acc
@ -129,7 +125,6 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
// Clear any hidden panes from the `openPanes` array
useEffect(() => {
const panesToReset: SidebarType[] = []
sidebarPanes.forEach((pane) => {
if (
pane.hide === true ||
@ -344,31 +339,22 @@ function ModelingPaneButton({
<p
id={`${paneConfig.id}-badge`}
className={
showBadge.className
? showBadge.className
: 'absolute m-0 p-0 bottom-4 left-4 w-3 h-3 flex items-center justify-center text-[10px] font-semibold text-white bg-primary hue-rotate-90 rounded-full border border-chalkboard-10 dark:border-chalkboard-80 z-50 hover:cursor-pointer hover:scale-[2] transition-transform duration-200'
'absolute m-0 p-0 bottom-4 left-4 w-3 h-3 flex items-center justify-center text-[10px] font-semibold text-white bg-primary hue-rotate-90 rounded-full border border-chalkboard-10 dark:border-chalkboard-80 z-50 hover:cursor-pointer hover:scale-[2] transition-transform duration-200'
}
onClick={showBadge.onClick}
title={
showBadge.title
? showBadge.title
: `Click to view ${showBadge.value} notification${
Number(showBadge.value) > 1 ? 's' : ''
}`
}
title={`Click to view ${showBadge.value} notification${
Number(showBadge.value) > 1 ? 's' : ''
}`}
>
<span className="sr-only">&nbsp;has&nbsp;</span>
{typeof showBadge.value === 'number' ||
typeof showBadge.value === 'string' ? (
{typeof showBadge.value === 'number' ? (
<span>{showBadge.value}</span>
) : (
<span className="sr-only">a</span>
)}
{typeof showBadge.value === 'number' && (
<span className="sr-only">
&nbsp;notification{Number(showBadge.value) > 1 ? 's' : ''}
</span>
)}
<span className="sr-only">
&nbsp;notification{Number(showBadge.value) > 1 ? 's' : ''}
</span>
</p>
)}
</div>

View File

@ -4,12 +4,11 @@ import {
useLocation,
useNavigate,
useRouteLoaderData,
redirect,
} from 'react-router-dom'
import { PATHS } from 'lib/paths'
import { markOnce } from 'lib/performance'
import { useAuthNavigation } from 'hooks/useAuthNavigation'
import { useAuthState, useSettings } from 'machines/appMachine'
import { useAuthState } from 'machines/appMachine'
import { IndexLoaderData } from 'lib/types'
import { getAppSettingsFilePath } from 'lib/desktop'
import { isDesktop } from 'lib/isDesktop'
@ -17,9 +16,6 @@ import { trap } from 'lib/trap'
import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher'
import { loadAndValidateSettings } from 'lib/settings/settingsUtils'
import { settingsActor } from 'machines/appMachine'
import makeUrlPathRelative from 'lib/makeUrlPathRelative'
import { OnboardingStatus } from 'wasm-lib/kcl/bindings/OnboardingStatus'
import { SnapshotFrom } from 'xstate'
export const RouteProviderContext = createContext({})
@ -33,7 +29,6 @@ export function RouteProvider({ children }: { children: ReactNode }) {
const navigation = useNavigation()
const navigate = useNavigate()
const location = useLocation()
const settings = useSettings()
const authState = useAuthState()
useEffect(() => {
@ -48,32 +43,6 @@ export function RouteProvider({ children }: { children: ReactNode }) {
markOnce('code/willLoadHome')
} else if (isFile) {
markOnce('code/willLoadFile')
/**
* TODO: Move to XState. This block has been moved from routerLoaders
* and is borrowing the `isFile` logic from the rest of this
* telemetry-focused `useEffect`. Once `appMachine` knows about
* the current route and navigation, this can be moved into settingsMachine
* to fire as soon as the user settings have been read.
*/
const onboardingStatus: OnboardingStatus =
settings.app.onboardingStatus.current || ''
// '' is the initial state, 'completed' and 'dismissed' are the final states
const needsToOnboard =
onboardingStatus.length === 0 ||
!(onboardingStatus === 'completed' || onboardingStatus === 'dismissed')
const shouldRedirectToOnboarding = isFile && needsToOnboard
if (
shouldRedirectToOnboarding &&
settingsActor.getSnapshot().matches('idle')
) {
navigate(
(first ? location.pathname : navigation.location?.pathname) +
PATHS.ONBOARDING.INDEX +
onboardingStatus.slice(1)
)
}
}
setFirstState(false)
}, [navigation])

View File

@ -293,13 +293,6 @@ export class KclManager {
return null
}
// GOTCHA:
// When we safeParse this is tied to execution because they clicked a new file to load
// Clear all previous errors and logs because they are old since they executed a new file
// If we decouple safeParse from execution we need to move this application logic.
this._kclErrorsCallBack([])
this._logsCallBack([])
this.addDiagnostics(complilationErrorsToDiagnostics(result.errors))
this.addDiagnostics(complilationErrorsToDiagnostics(result.warnings))
if (result.errors.length > 0) {

View File

@ -13,7 +13,6 @@ describe('test kclErrToDiagnostic', () => {
operations: [],
artifactCommands: [],
artifactGraph: defaultArtifactGraph(),
filenames: {},
},
{
name: '',
@ -24,7 +23,6 @@ describe('test kclErrToDiagnostic', () => {
operations: [],
artifactCommands: [],
artifactGraph: defaultArtifactGraph(),
filenames: {},
},
]
const diagnostics = kclErrorsToDiagnostics(errors)

View File

@ -1,7 +1,4 @@
import {
KclError,
KclError as RustKclError,
} from '../wasm-lib/kcl/bindings/KclError'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { CompilationError } from 'wasm-lib/kcl/bindings/CompilationError'
import { Diagnostic as CodeMirrorDiagnostic } from '@codemirror/lint'
import { posToOffset } from '@kittycad/codemirror-lsp-client'
@ -16,7 +13,6 @@ import {
SourceRange,
} from 'lang/wasm'
import { Operation } from 'wasm-lib/kcl/bindings/Operation'
import { ModulePath } from 'wasm-lib/kcl/bindings/ModulePath'
type ExtractKind<T> = T extends { kind: infer K } ? K : never
export class KCLError extends Error {
@ -26,7 +22,6 @@ export class KCLError extends Error {
operations: Operation[]
artifactCommands: ArtifactCommand[]
artifactGraph: ArtifactGraph
filenames: { [x: number]: ModulePath | undefined }
constructor(
kind: ExtractKind<RustKclError> | 'name',
@ -34,8 +29,7 @@ export class KCLError extends Error {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super()
this.kind = kind
@ -44,7 +38,6 @@ export class KCLError extends Error {
this.operations = operations
this.artifactCommands = artifactCommands
this.artifactGraph = artifactGraph
this.filenames = filenames
Object.setPrototypeOf(this, KCLError.prototype)
}
}
@ -55,8 +48,7 @@ export class KCLLexicalError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'lexical',
@ -64,8 +56,7 @@ export class KCLLexicalError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
}
@ -77,8 +68,7 @@ export class KCLInternalError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'internal',
@ -86,8 +76,7 @@ export class KCLInternalError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
}
@ -99,8 +88,7 @@ export class KCLSyntaxError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'syntax',
@ -108,8 +96,7 @@ export class KCLSyntaxError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
}
@ -121,8 +108,7 @@ export class KCLSemanticError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'semantic',
@ -130,8 +116,7 @@ export class KCLSemanticError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLSemanticError.prototype)
}
@ -143,18 +128,9 @@ export class KCLTypeError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'type',
msg,
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
)
super('type', msg, sourceRange, operations, artifactCommands, artifactGraph)
Object.setPrototypeOf(this, KCLTypeError.prototype)
}
}
@ -165,8 +141,7 @@ export class KCLUnimplementedError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'unimplemented',
@ -174,8 +149,7 @@ export class KCLUnimplementedError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLUnimplementedError.prototype)
}
@ -187,8 +161,7 @@ export class KCLUnexpectedError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'unexpected',
@ -196,8 +169,7 @@ export class KCLUnexpectedError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLUnexpectedError.prototype)
}
@ -209,8 +181,7 @@ export class KCLValueAlreadyDefined extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'name',
@ -218,8 +189,7 @@ export class KCLValueAlreadyDefined extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLValueAlreadyDefined.prototype)
}
@ -231,8 +201,7 @@ export class KCLUndefinedValueError extends KCLError {
sourceRange: SourceRange,
operations: Operation[],
artifactCommands: ArtifactCommand[],
artifactGraph: ArtifactGraph,
filenames: { [x: number]: ModulePath | undefined }
artifactGraph: ArtifactGraph
) {
super(
'name',
@ -240,8 +209,7 @@ export class KCLUndefinedValueError extends KCLError {
sourceRange,
operations,
artifactCommands,
artifactGraph,
filenames
artifactGraph
)
Object.setPrototypeOf(this, KCLUndefinedValueError.prototype)
}
@ -264,8 +232,7 @@ export function lspDiagnosticsToKclErrors(
[posToOffset(doc, range.start)!, posToOffset(doc, range.end)!, 0],
[],
[],
defaultArtifactGraph(),
{}
defaultArtifactGraph()
)
)
.sort((a, b) => {
@ -337,34 +304,3 @@ export function complilationErrorsToDiagnostics(
}
})
}
// Create an array of KCL Errors with a new formatting to
// easily map SourceRange of an error to the filename to display in the
// side bar UI. This is to indicate an error in an imported file, it isn't
// the specific code mirror error interface.
export function kclErrorsByFilename(
errors: KCLError[]
): Map<string, KCLError[]> {
const fileNameToError: Map<string, KCLError[]> = new Map()
errors.forEach((error: KCLError) => {
const filenames = error.filenames
const sourceRange: SourceRange = error.sourceRange
const fileIndex = sourceRange[2]
const modulePath: ModulePath | undefined = filenames[fileIndex]
if (modulePath) {
let stdOrLocalPath = modulePath.value
if (stdOrLocalPath) {
// Build up an array of errors per file name
const value = fileNameToError.get(stdOrLocalPath)
if (!value) {
fileNameToError.set(stdOrLocalPath, [error])
} else {
value.push(error)
fileNameToError.set(stdOrLocalPath, [error])
}
}
}
})
return fileNameToError
}

View File

@ -511,8 +511,7 @@ const theExtrude = startSketchOn('XY')
topLevelRange(129, 135),
[],
[],
defaultArtifactGraph(),
{}
defaultArtifactGraph()
)
)
})

View File

@ -60,7 +60,6 @@ import { MetaSettings } from 'wasm-lib/kcl/bindings/MetaSettings'
import { UnitAngle, UnitLength } from 'wasm-lib/kcl/bindings/ModelingCmd'
import { UnitLen } from 'wasm-lib/kcl/bindings/UnitLen'
import { UnitAngle as UnitAng } from 'wasm-lib/kcl/bindings/UnitAngle'
import { ModulePath } from 'wasm-lib/kcl/bindings/ModulePath'
export type { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
export type { ArtifactCommand } from 'wasm-lib/kcl/bindings/Artifact'
@ -267,8 +266,7 @@ export const parse = (code: string | Error): ParseResult | Error => {
firstSourceRange(parsed),
[],
[],
defaultArtifactGraph(),
{}
defaultArtifactGraph()
)
}
}
@ -298,7 +296,6 @@ export interface ExecState {
artifactCommands: ArtifactCommand[]
artifactGraph: ArtifactGraph
errors: CompilationError[]
filenames: { [x: number]: ModulePath | undefined }
}
/**
@ -313,7 +310,6 @@ export function emptyExecState(): ExecState {
artifactCommands: [],
artifactGraph: defaultArtifactGraph(),
errors: [],
filenames: [],
}
}
@ -340,7 +336,6 @@ function execStateFromRust(
artifactCommands: execOutcome.artifactCommands,
artifactGraph,
errors: execOutcome.errors,
filenames: execOutcome.filenames,
}
}
@ -352,7 +347,6 @@ function mockExecStateFromRust(execOutcome: RustExecOutcome): ExecState {
artifactCommands: execOutcome.artifactCommands,
artifactGraph: new Map<ArtifactId, Artifact>(),
errors: execOutcome.errors,
filenames: execOutcome.filenames,
}
}
@ -480,7 +474,7 @@ const jsAppSettings = async () => {
}
const errFromErrWithOutputs = (e: any): KCLError => {
console.log(e)
console.log('execute error', e)
const parsed: KclErrorWithOutputs = JSON.parse(e.toString())
return new KCLError(
parsed.error.kind,
@ -488,8 +482,7 @@ const errFromErrWithOutputs = (e: any): KCLError => {
firstSourceRange(parsed.error),
parsed.operations,
parsed.artifactCommands,
rustArtifactGraphToMap(parsed.artifactGraph),
parsed.filenames
rustArtifactGraphToMap(parsed.artifactGraph)
)
}
@ -555,8 +548,7 @@ export const modifyAstForSketch = async (
firstSourceRange(parsed),
[],
[],
defaultArtifactGraph(),
{}
defaultArtifactGraph()
)
return Promise.reject(kclError)

View File

@ -155,7 +155,7 @@ export interface components {
color?: string | null
/** @description The material that the filament is made of. */
material: components['schemas']['FilamentMaterial']
/** @description The name of the filament, this is likely specfic to the manufacturer. */
/** @description The name of the filament, this is likely specific to the manufacturer. */
name?: string | null
}
/** @description The material that the filament is made of. */

View File

@ -23,6 +23,30 @@ export const telemetryLoader: LoaderFunction = async ({
return null
}
// Redirect users to the appropriate onboarding page if they haven't completed it
export const onboardingRedirectLoader: ActionFunction = async (args) => {
const settings = getSettings()
const onboardingStatus: OnboardingStatus =
settings.app.onboardingStatus.current || ''
const notEnRouteToOnboarding = !args.request.url.includes(
PATHS.ONBOARDING.INDEX
)
// '' is the initial state, 'completed' and 'dismissed' are the final states
const hasValidOnboardingStatus =
onboardingStatus.length === 0 ||
!(onboardingStatus === 'completed' || onboardingStatus === 'dismissed')
const shouldRedirectToOnboarding =
notEnRouteToOnboarding && hasValidOnboardingStatus
if (shouldRedirectToOnboarding) {
return redirect(
makeUrlPathRelative(PATHS.ONBOARDING.INDEX) + onboardingStatus.slice(1)
)
}
return null
}
export const fileLoader: LoaderFunction = async (
routerData
): Promise<FileLoaderData | Response> => {

View File

@ -103,7 +103,3 @@ path = "tests/modify/main.rs"
#[patch.crates-io]
#kittycad-modeling-cmds = { path = "../../../modeling-api/modeling-cmds" }
#kittycad-modeling-session = { path = "../../../modeling-api/modeling-session" }
# Local development only. Placeholder to speed up development cycle
#[package.metadata.wasm-pack.profile.release]
#wasm-opt = false

View File

@ -2,12 +2,9 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
use indexmap::IndexMap;
use crate::{
execution::{ArtifactCommand, ArtifactGraph, Operation},
lsp::IntoDiagnostic,
modules::ModulePath,
source_range::SourceRange,
ModuleId,
};
@ -119,7 +116,6 @@ pub struct KclErrorWithOutputs {
pub operations: Vec<Operation>,
pub artifact_commands: Vec<ArtifactCommand>,
pub artifact_graph: ArtifactGraph,
pub filenames: IndexMap<ModuleId, ModulePath>,
}
impl KclErrorWithOutputs {
@ -128,14 +124,12 @@ impl KclErrorWithOutputs {
operations: Vec<Operation>,
artifact_commands: Vec<ArtifactCommand>,
artifact_graph: ArtifactGraph,
filenames: IndexMap<ModuleId, ModulePath>,
) -> Self {
Self {
error,
operations,
artifact_commands,
artifact_graph,
filenames,
}
}
pub fn no_outputs(error: KclError) -> Self {
@ -144,7 +138,6 @@ impl KclErrorWithOutputs {
operations: Default::default(),
artifact_commands: Default::default(),
artifact_graph: Default::default(),
filenames: Default::default(),
}
}
}

View File

@ -329,8 +329,6 @@ impl ExecutorContext {
}
let id = exec_state.next_module_id();
// Add file path string to global state even if it fails to import
exec_state.add_path_to_source_id(resolved_path.clone(), id);
let source = resolved_path.source(&self.fs, source_range).await?;
// TODO handle parsing errors properly
let parsed = crate::parsing::parse_str(&source, id).parse_errs_as_err()?;
@ -345,8 +343,6 @@ impl ExecutorContext {
let id = exec_state.next_module_id();
let path = resolved_path.expect_path();
// Add file path string to global state even if it fails to import
exec_state.add_path_to_source_id(resolved_path.clone(), id);
let format = super::import::format_from_annotations(attrs, path, source_range)?;
let geom = super::import::import_foreign(path, format, exec_state, self, source_range).await?;
exec_state.add_module(id, resolved_path, ModuleRepr::Foreign(geom));
@ -358,8 +354,6 @@ impl ExecutorContext {
}
let id = exec_state.next_module_id();
// Add file path string to global state even if it fails to import
exec_state.add_path_to_source_id(resolved_path.clone(), id);
let source = resolved_path.source(&self.fs, source_range).await?;
let parsed = crate::parsing::parse_str(&source, id).parse_errs_as_err().unwrap();
exec_state.add_module(id, resolved_path, ModuleRepr::Kcl(parsed, None));

View File

@ -23,7 +23,6 @@ use crate::{
cache::{CacheInformation, CacheResult},
},
fs::FileManager,
modules::{ModuleId, ModulePath},
parsing::ast::types::{Expr, ImportPath, Node, NodeRef, Program},
settings::types::UnitLength,
source_range::SourceRange,
@ -71,8 +70,6 @@ pub struct ExecOutcome {
pub artifact_graph: ArtifactGraph,
/// Non-fatal errors and warnings.
pub errors: Vec<CompilationError>,
/// File Names in module Id array index order
pub filenames: IndexMap<ModuleId, ModulePath>,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
@ -715,19 +712,11 @@ impl ExecutorContext {
.execute_and_build_graph(program, exec_state, preserve_mem)
.await
.map_err(|e| {
let module_id_to_module_path: IndexMap<ModuleId, ModulePath> = exec_state
.global
.path_to_source_id
.iter()
.map(|(k, v)| ((*v), k.clone()))
.collect();
KclErrorWithOutputs::new(
e,
exec_state.mod_local.operations.clone(),
exec_state.global.artifact_commands.clone(),
exec_state.global.artifact_graph.clone(),
module_id_to_module_path,
)
})?;

View File

@ -124,12 +124,6 @@ impl ExecState {
artifact_commands: self.global.artifact_commands,
artifact_graph: self.global.artifact_graph,
errors: self.global.errors,
filenames: self
.global
.path_to_source_id
.iter()
.map(|(k, v)| ((*v), k.clone()))
.collect(),
}
}
@ -147,7 +141,6 @@ impl ExecState {
artifact_commands: Default::default(),
artifact_graph: Default::default(),
errors: self.global.errors,
filenames: Default::default(),
}
}
@ -176,13 +169,11 @@ impl ExecState {
self.global.path_to_source_id.get(path).cloned()
}
pub(super) fn add_path_to_source_id(&mut self, path: ModulePath, id: ModuleId) {
debug_assert!(!self.global.path_to_source_id.contains_key(&path));
self.global.path_to_source_id.insert(path.clone(), id);
}
pub(super) fn add_module(&mut self, id: ModuleId, path: ModulePath, repr: ModuleRepr) {
debug_assert!(self.global.path_to_source_id.contains_key(&path));
debug_assert!(!self.global.path_to_source_id.contains_key(&path));
self.global.path_to_source_id.insert(path.clone(), id);
let module_info = ModuleInfo { id, repr, path };
self.global.module_infos.insert(id, module_info);
}
@ -234,15 +225,11 @@ impl GlobalState {
root_id,
ModuleInfo {
id: root_id,
path: ModulePath::Local {
value: root_path.clone(),
},
path: ModulePath::Local(root_path.clone()),
repr: ModuleRepr::Root,
},
);
global
.path_to_source_id
.insert(ModulePath::Local { value: root_path }, root_id);
global.path_to_source_id.insert(ModulePath::Local(root_path), root_id);
global
}
}

View File

@ -64,13 +64,13 @@ impl ModuleLoader {
}
pub(crate) fn enter_module(&mut self, path: &ModulePath) {
if let ModulePath::Local { value: ref path } = path {
if let ModulePath::Local(ref path) = path {
self.import_stack.push(path.clone());
}
}
pub(crate) fn leave_module(&mut self, path: &ModulePath) {
if let ModulePath::Local { value: ref path } = path {
if let ModulePath::Local(ref path) = path {
let popped = self.import_stack.pop().unwrap();
assert_eq!(path, &popped);
}
@ -119,32 +119,31 @@ pub enum ModuleRepr {
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, Hash, ts_rs::TS)]
#[serde(tag = "type")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, Hash)]
pub enum ModulePath {
Local { value: PathBuf },
Std { value: String },
Local(PathBuf),
Std(String),
}
impl ModulePath {
pub(crate) fn expect_path(&self) -> &PathBuf {
match self {
ModulePath::Local { value: p } => p,
ModulePath::Local(p) => p,
_ => unreachable!(),
}
}
pub(crate) fn std_path(&self) -> Option<String> {
match self {
ModulePath::Local { value: _ } => None,
ModulePath::Std { value: p } => Some(p.clone()),
ModulePath::Local(_) => None,
ModulePath::Std(p) => Some(p.clone()),
}
}
pub(crate) async fn source(&self, fs: &FileManager, source_range: SourceRange) -> Result<String, KclError> {
match self {
ModulePath::Local { value: p } => fs.read_to_string(p, source_range).await,
ModulePath::Std { value: name } => read_std(name)
ModulePath::Local(p) => fs.read_to_string(p, source_range).await,
ModulePath::Std(name) => read_std(name)
.ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
message: format!("Cannot find standard library module to import: std::{name}."),
@ -163,14 +162,14 @@ impl ModulePath {
} else {
std::path::PathBuf::from(path)
};
ModulePath::Local { value: resolved_path }
ModulePath::Local(resolved_path)
}
ImportPath::Std { path } => {
// For now we only support importing from singly-nested modules inside std.
assert_eq!(path.len(), 2);
assert_eq!(&path[0], "std");
ModulePath::Std { value: path[1].clone() }
ModulePath::Std(path[1].clone())
}
}
}
@ -179,8 +178,8 @@ impl ModulePath {
impl fmt::Display for ModulePath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ModulePath::Local { value: path } => path.display().fmt(f),
ModulePath::Std { value: s } => write!(f, "std::{s}"),
ModulePath::Local(path) => path.display().fmt(f),
ModulePath::Std(s) => write!(f, "std::{s}"),
}
}
}

View File

@ -1990,29 +1990,7 @@ mod helix_simple {
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME);
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[test]
fn unparse() {
super::unparse(TEST_NAME)
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod import_file_parse_error {
const TEST_NAME: &str = "import_file_parse_error";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME);
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.

View File

@ -1,284 +0,0 @@
---
source: kcl/src/simulation_tests.rs
description: Artifact commands import_file_parse_error.kcl
---
[
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "plane_set_color",
"plane_id": "[uuid]",
"color": {
"r": 0.7,
"g": 0.28,
"b": 0.28,
"a": 0.4
}
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "plane_set_color",
"plane_id": "[uuid]",
"color": {
"r": 0.28,
"g": 0.7,
"b": 0.28,
"a": 0.4
}
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "plane_set_color",
"plane_id": "[uuid]",
"color": {
"r": 0.28,
"g": 0.28,
"b": 0.7,
"a": 0.4
}
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": -1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 0.0,
"y": -1.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": -1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 100.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [
0,
0,
0
],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
}
]

View File

@ -1,6 +0,0 @@
---
source: kcl/src/simulation_tests.rs
description: Artifact graph flowchart import_file_parse_error.kcl
extension: md
snapshot_kind: binary
---

View File

@ -1,3 +0,0 @@
```mermaid
flowchart LR
```

View File

@ -1,39 +0,0 @@
---
source: kcl/src/simulation_tests.rs
description: Result of parsing import_file_parse_error.kcl
---
{
"Ok": {
"body": [
{
"end": 38,
"path": {
"type": "Kcl",
"filename": "parse-failure.kcl"
},
"selector": {
"type": "List",
"items": [
{
"alias": null,
"end": 13,
"name": {
"end": 13,
"name": "hotdog",
"start": 7,
"type": "Identifier"
},
"start": 7,
"type": "ImportItem"
}
]
},
"start": 0,
"type": "ImportStatement",
"type": "ImportStatement"
}
],
"end": 39,
"start": 0
}
}

View File

@ -1,11 +0,0 @@
---
source: kcl/src/simulation_tests.rs
description: Error from executing import_file_parse_error.kcl
---
KCL Syntax error
× syntax: Unexpected token: }
╭────
1 │ import hotdog from "parse-failure.kcl"
· ─
╰────

View File

@ -1 +0,0 @@
import hotdog from "parse-failure.kcl"

View File

@ -1,5 +0,0 @@
---
source: kcl/src/simulation_tests.rs
description: Operations executed import_file_parse_error.kcl
---
[]

View File

@ -1,3 +0,0 @@
export fn hotdog () {
return
}

23394
yarn.lock

File diff suppressed because it is too large Load Diff