Skip to content

Commit

Permalink
Hoist wally types and fix type errors (#233)
Browse files Browse the repository at this point in the history
# Problem

Discovered when hoisting up types for Wally packages that there's
several type errors to resolve

# Solution

This PR adds `wally-package-types` and a new `bin/wally-install.sh`
script for installing packages and hoisting up types at the same time.

All of this is integrated into CI, and relevant analysis errors have
been patched

# Checklist

- [ ] Ran `./bin/test.sh` locally before merging
  • Loading branch information
vocksel authored Jan 2, 2024
1 parent 3611fbe commit cc6e6b7
Show file tree
Hide file tree
Showing 19 changed files with 115 additions and 51 deletions.
15 changes: 3 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,10 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install dependencies
run: wally install

- name: Download global Roblox types
shell: bash
run: curl -s -O https://raw.githubusercontent.com/JohnnyMorganz/luau-lsp/master/scripts/globalTypes.d.lua

- name: Generate sourcemap for LSP
shell: bash
run: rojo sourcemap tests.project.json -o sourcemap.json
run: ./bin/wally-install.sh

- name: Analyze
shell: bash
run: luau-lsp analyze --sourcemap=sourcemap.json --defs=globalTypes.d.lua --defs=testez.d.lua --ignore=**/_Index/** src/
- name: Run Luau analysis
run: ./bin/analyze.sh

scripts:
runs-on: ubuntu-latest
Expand Down
8 changes: 7 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Install packages",
"type": "shell",
"problemMatcher": [],
"command": "./bin/wally-install.sh"
},
{
"label": "Build (Development)",
"type": "shell",
Expand Down Expand Up @@ -50,4 +56,4 @@
"command": "npx moonwave dev"
}
]
}
}
3 changes: 3 additions & 0 deletions bin/analyze.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ curl -s -O https://raw.githubusercontent.com/JohnnyMorganz/luau-lsp/master/scrip
rojo sourcemap tests.project.json -o sourcemap.json

luau-lsp analyze --sourcemap=sourcemap.json --defs=globalTypes.d.lua --defs=testez.d.lua --ignore=**/_Index/** src/
exit_code=$?

rm globalTypes.d.lua

exit $exit_code
9 changes: 9 additions & 0 deletions bin/wally-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -e

wally install

rojo sourcemap tests.project.json --output sourcemap.json

wally-package-types --sourcemap sourcemap.json Packages/
1 change: 1 addition & 0 deletions foreman.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ tarmac = { source = "Roblox/tarmac", version = "0.7.0" }
wally = { source = "UpliftGames/wally", version = "0.3.2" }
moonwave-extractor = { source = "UpliftGames/moonwave", version = "1.0.0" }
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "1.x" }
wally-package-types = { source = "JohnnyMorganz/wally-package-types", version = "1.2.1" }
8 changes: 5 additions & 3 deletions src/Explorer/Component/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ local defaultProps = {
indent = 0,
}

type Props = typeof(defaultProps) & {
type Props = {
node: types.ComponentTreeNode,
filter: string?,
activeNode: types.ComponentTreeNode?,
onClick: ((types.ComponentTreeNode) -> ())?,
}

local function Component(props: Props)
props = Sift.Dictionary.merge(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local function Component(providedProps: Props)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local hasChildren = props.node.children and #props.node.children > 0

Expand Down
14 changes: 9 additions & 5 deletions src/Forms/Button.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ local function shift(color: Color3, percent: number): Color3
return Color3.fromHSV(h, s, math.clamp(v * (1 + percent), 0, 1))
end

type Style = "contain" | "stroke"

local defaultProps = {
style = "contain",
style = "contain" :: Style,
text = "Button",
}

type Props = typeof(defaultProps) & {
type Props = {
text: string,
style: "contain" | "stroke",
style: Style?,

anchorPoint: Vector2?,
position: UDim2?,
Expand All @@ -29,8 +31,10 @@ type Props = typeof(defaultProps) & {
onClick: (() -> ())?,
}

local function Button(props: Props)
props = Sift.Dictionary.join(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local function Button(providedProps: Props)
local props: InternalProps = Sift.Dictionary.join(defaultProps, providedProps)

local theme = useTheme()
local hover, setHover = React.useState(false)
Expand Down
8 changes: 5 additions & 3 deletions src/Forms/InputField.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ local defaultProps = {
autoFocus = false,
}

export type Props = typeof(defaultProps) & {
export type Props = {
layoutOrder: number?,
onSubmit: (text: string) -> (),
onFocus: (() -> ())?,
Expand All @@ -22,8 +22,10 @@ export type Props = typeof(defaultProps) & {
transform: ((newText: string, oldText: string) -> string)?,
}

local function InputField(props: Props)
props = Sift.Dictionary.merge(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local function InputField(providedProps: Props)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local ref = React.createRef()
local text, setText = React.useState("")
Expand Down
8 changes: 5 additions & 3 deletions src/Forms/Searchbar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ local defaultProps = {
size = UDim2.new(1, 0, 0, 36),
}

type Props = typeof(defaultProps) & {
export type Props = {
layoutOrder: number?,
onSearchChanged: ((value: string) -> ())?,
}

type InternalProps = Props & typeof(defaultProps)

local SEARCH_ICON_SIZE = 16 -- px

local function Searchbar(props: Props)
props = Sift.Dictionary.merge(defaultProps, props)
local function Searchbar(providedProps: Props)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local theme = useTheme()
local search, setSearch = React.useState("")
Expand Down
8 changes: 5 additions & 3 deletions src/Panels/DragHandle.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ local defaultProps = {
hoverIconY = "rbxasset://textures/StudioUIEditor/icon_resize4.png",
}

export type Props = typeof(defaultProps) & {
export type Props = {
handle: types.DragHandle,
onDrag: (delta: Vector2) -> (),
onDragEnd: (() -> ())?,
}

local function DragHandle(props: Props)
props = Sift.Dictionary.merge(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local function DragHandle(providedProps: Props)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local plugin = React.useContext(PluginContext.Context)
local isDragging, setIsDragging = React.useState(false)
Expand Down
8 changes: 5 additions & 3 deletions src/Panels/ResizablePanel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local defaultProps = {
maxSize = Vector2.new(math.huge, math.huge),
}

export type Props = typeof(defaultProps) & {
export type Props = {
initialSize: UDim2,
layoutOrder: number?,
dragHandles: { types.DragHandle }?,
Expand All @@ -21,8 +21,10 @@ export type Props = typeof(defaultProps) & {
children: any,
}

local function ResizablePanel(props: Props)
props = Sift.Dictionary.merge(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local function ResizablePanel(providedProps: Props)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local absoluteSize, setAbsoluteSize = React.useState(nil)

Expand Down
8 changes: 6 additions & 2 deletions src/Panels/Sidebar.story.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ return {
storybooks = {
internalStorybook,
},
selectStory = print,
selectStorybook = print,
selectStory = function(storyModule)
print(storyModule)
end,
selectStorybook = function(storybook)
print(storybook)
end,
}),
}
1 change: 1 addition & 0 deletions src/Plugin/PluginApp.story.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ return {
controls = {},
story = React.createElement(PluginApp, {
loader = ModuleLoader.new(),
plugin = plugin,
}),
}
3 changes: 2 additions & 1 deletion src/Storybook/StoryControls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ local Dropdown = require(flipbook.Forms.Dropdown)
local e = React.createElement

type Props = {
layoutOrder: number,
controls: { [string]: any },
setControl: (key: string, value: any) -> (),
layoutOrder: number?,
}

local function StoryControls(props: Props)
Expand Down Expand Up @@ -40,6 +40,7 @@ local function StoryControls(props: Props)
option = React.createElement(InputField, {
placeholder = value,
onTextChange = setControl,
onSubmit = setControl,
})
end

Expand Down
1 change: 1 addition & 0 deletions src/Storybook/StoryControls.story.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ return {
"Option 3",
},
},
setControl = function() end,
}),
}
2 changes: 1 addition & 1 deletion src/Storybook/StoryMeta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ local MAX_SUMMARY_SIZE = 600
local e = React.createElement

export type Props = {
layoutOrder: number,
story: types.Story,
layoutOrder: number?,
}

local function StoryMeta(props: Props)
Expand Down
8 changes: 5 additions & 3 deletions src/Storybook/StoryPreview.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ local defaultProps = {
zoom = 0,
}

type Props = typeof(defaultProps) & {
export type Props = {
layoutOrder: number,
story: types.Story,
ref: any,
controls: { [string]: any },
storyModule: ModuleScript,
}

local StoryPreview = React.forwardRef(function(props: Props, ref: any)
props = Sift.Dictionary.merge(defaultProps, props)
type InternalProps = Props & typeof(defaultProps)

local StoryPreview = React.forwardRef(function(providedProps: Props, ref: any)
local props: InternalProps = Sift.Dictionary.merge(defaultProps, providedProps)

local err, setErr = React.useState(nil)

Expand Down
20 changes: 15 additions & 5 deletions src/Storybook/loadStoryModule.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,23 @@ local function loadStoryModule(loader: any, module: ModuleScript, storybook: typ
local isValid, message = types.StoryMeta(result)

if isValid then
local extraProps = {}
if types.ReactStorybook(storybook) then
local reactStorybook = storybook :: types.ReactStorybook
extraProps = {
react = reactStorybook.react,
reactRoblox = reactStorybook.reactRoblox,
}
elseif types.RoactStorybook(storybook) then
local roactStorybook = storybook :: types.RoactStorybook
extraProps = {
roact = roactStorybook.roact,
}
end

story = Sift.Dictionary.merge({
name = module.Name,
}, {
react = storybook.react,
reactRoblox = storybook.reactRoblox,
roact = storybook.roact,
}, result)
}, extraProps, result)
else
return nil, Errors.Generic:format(module:GetFullName(), message)
end
Expand Down
33 changes: 27 additions & 6 deletions src/Storybook/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,9 @@ export type StoryProps = {
controls: Controls,
}

export type Storybook = {
export type StorybookMeta = {
storyRoots: { Instance },

name: string?,
roact: Roact?,
react: React?,
reactRoblox: ReactRoblox?,
}
types.Storybook = t.interface({
storyRoots = t.array(t.Instance),
Expand All @@ -58,8 +54,33 @@ types.Storybook = t.interface({
reactRoblox = t.optional(types.ReactRoblox),
})

export type RoactStorybook = StorybookMeta & {
roact: Roact,
}
types.RoactStorybook = t.union(
types.Storybook,
t.interface({
roact = t.optional(types.Roact),
})
)

export type ReactStorybook = StorybookMeta & {
react: React,
reactRoblox: ReactRoblox,
}
types.ReactStorybook = t.union(
types.Storybook,
t.interface({
react = t.optional(types.React),
reactRoblox = t.optional(types.ReactRoblox),
})
)

export type Storybook = RoactStorybook | ReactStorybook | StorybookMeta

export type StoryMeta = {
name: string,
story: any,
summary: string?,
controls: Controls?,
roact: Roact?,
Expand Down Expand Up @@ -90,6 +111,6 @@ export type FunctionalStory = StoryMeta & {
story: (target: GuiObject, props: StoryProps) -> (() -> ())?,
}

export type Story = FunctionalStory | RoactStory | ReactStory
export type Story = FunctionalStory | RoactStory | ReactStory | StoryMeta

return types

0 comments on commit cc6e6b7

Please sign in to comment.