Basic transformer functionality
This commit is contained in:
@@ -1,15 +1,21 @@
|
||||
ISC License
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020, Fireboltofdeath
|
||||
Copyright (c) 2025 evilbocchi
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,38 +1,99 @@
|
||||
# rbxts-transformer-services
|
||||
This is a [demo transformer](#template) that converts @rbxts/services imports into plain GetService calls for increased legibility.
|
||||
# rbxts-transformer-instances
|
||||
|
||||
## Example
|
||||
```ts
|
||||
// input.ts
|
||||
import { Players, ServerScriptService } from "@rbxts/services";
|
||||
Enable the use of instance constructors in roblox-ts, reducing boilerplate by letting you use familiar class-like syntax.
|
||||
|
||||
print(Players.LocalPlayer);
|
||||
print(ServerScriptService.GetChildren().size());
|
||||
## Overview
|
||||
|
||||
This transformer automatically converts constructor-style instance creation (`new Frame()`) into the standard Roblox `Instance.new("Frame")` pattern at compile time.
|
||||
|
||||
## Features
|
||||
|
||||
- ✨ Cleaner syntax for creating instances
|
||||
- 🔍 Full TypeScript type safety
|
||||
- ⚡ Zero runtime overhead (transforms at compile-time)
|
||||
- 🔄 Supports all creatable Roblox instance types
|
||||
- 📦 Easy to install and use
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install rbxts-transformer-instances
|
||||
```
|
||||
|
||||
### Configure in your tsconfig.json
|
||||
|
||||
Add the transformer to your `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
...
|
||||
"plugins": [
|
||||
{
|
||||
"transform": "rbxts-transformer-instances",
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": [..., "node_modules/rbxts-transformer-instances"]
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```ts
|
||||
// Instead of this:
|
||||
const part = new Instance("Part");
|
||||
part.Material = Enum.Material.Neon;
|
||||
part.Position = new Vector3(0, 10, 0);
|
||||
|
||||
// You can write this:
|
||||
const part = new Part();
|
||||
part.Material = Enum.Material.Neon;
|
||||
part.Position = new Vector3(0, 10, 0);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Input (TypeScript):
|
||||
|
||||
```ts
|
||||
// Creating a basic UI
|
||||
const screenGui = new ScreenGui();
|
||||
screenGui.Parent = game.GetService("Players").LocalPlayer!.WaitForChild("PlayerGui");
|
||||
|
||||
const frame = new Frame();
|
||||
frame.Size = new UDim2(0, 200, 0, 200);
|
||||
frame.Position = new UDim2(0.5, -100, 0.5, -100);
|
||||
frame.BackgroundColor3 = Color3.fromRGB(45, 45, 45);
|
||||
frame.Parent = screenGui;
|
||||
|
||||
const textLabel = new TextLabel();
|
||||
textLabel.Size = new UDim2(1, 0, 0, 50);
|
||||
textLabel.Text = "Hello, World!";
|
||||
textLabel.Parent = frame;
|
||||
```
|
||||
|
||||
### Output (Lua):
|
||||
|
||||
```lua
|
||||
-- output.lua
|
||||
local Players = game:GetService("Players")
|
||||
local ServerScriptService = game:GetService("ServerScriptService")
|
||||
print(Players.LocalPlayer)
|
||||
print(#ServerScriptService:GetChildren())
|
||||
-- Creates standard Instance.new calls
|
||||
local screenGui = Instance.new("ScreenGui")
|
||||
screenGui.Parent = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui")
|
||||
|
||||
local frame = Instance.new("Frame")
|
||||
frame.Size = UDim2.new(0, 200, 0, 200)
|
||||
frame.Position = UDim2.new(0.5, -100, 0.5, -100)
|
||||
frame.BackgroundColor3 = Color3.fromRGB(45, 45, 45)
|
||||
frame.Parent = screenGui
|
||||
|
||||
local textLabel = Instance.new("TextLabel")
|
||||
textLabel.Size = UDim2.new(1, 0, 0, 50)
|
||||
textLabel.Text = "Hello, World!"
|
||||
textLabel.Parent = frame
|
||||
```
|
||||
|
||||
# Template
|
||||
This transformer is intended to be used as a template for those who are interested in creating their own transformers in roblox-ts.
|
||||
## License
|
||||
|
||||
A necessary resource for those starting out with transformers is [ts-ast-viewer](https://ts-ast-viewer.com/). It shows you the result of AST, relevant properties, symbol information, type information and it automatically generates factory code for nodes. For example, you can see the code this transformer generates [here](https://ts-ast-viewer.com/#code/MYewdgzgLgBACgGwIYE8CmAnCMC8MDmSAtmgHQDiaUAypgG4CWwaAFAESKqYRsCUANACgYImAHUQGANYQADkma4CxMpRr0mrNhIxQZ85nwDcQA).
|
||||
|
||||
I'd also recommend downloading the [TypeScript repo](https://github.com/microsoft/TypeScript) locally as it's extremely helpful when you're using undocumented (the majority of the compiler API), internal or uncommon APIs.
|
||||
|
||||
Transformers mutate the TypeScript [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) by replacing parts of the AST with new nodes. Transformers are also able to utilize symbol and type information giving you access to TypeScript's advanced control flow analysis.
|
||||
|
||||
## Other Transformers
|
||||
|
||||
Here's a list of transformers if you want to see how they handle working with parts of the TypeScript compiler api not shown here (e.g symbols or types).
|
||||
|
||||
- [rbxts-transform-debug](https://github.com/roblox-aurora/rbxts-transform-debug) by [@roblox-aurora](https://github.com/roblox-aurora)
|
||||
- [rbxts-transform-env](https://github.com/roblox-aurora/rbxts-transform-env) by [@roblox-aurora](https://github.com/roblox-aurora)
|
||||
- [Flamework](https://github.com/rbxts-flamework/transformer) by [@rbxts-flamework](https://github.com/rbxts-flamework)
|
||||
|
||||
One other source you may goto for learning about transformers is actually [roblox-ts](https://github.com/roblox-ts/roblox-ts/tree/master/src/TSTransformer) itself. This generates a Luau AST instead of a TS AST but it may still be a useful resource for learning about the compiler api.
|
||||
MIT
|
||||
Vendored
+308
@@ -0,0 +1,308 @@
|
||||
/// <reference no-default-lib="true"/>
|
||||
/// <reference types="@rbxts/types" />
|
||||
|
||||
/**
|
||||
* Add constructors to all Roblox CreatableInstances
|
||||
* This adds `new ClassName()` constructors for all Roblox instance types
|
||||
* that can be created with Instance.new()
|
||||
*
|
||||
* The transformer will convert these to `new Instance("ClassName")`
|
||||
*/
|
||||
type CreatableInstancesWithConstructors = {
|
||||
[K in keyof CreatableInstances]: {
|
||||
new (...args: any[]): CreatableInstances[K];
|
||||
}
|
||||
}
|
||||
|
||||
declare const CreatableInstancesWithConstructors: CreatableInstancesWithConstructors;
|
||||
|
||||
declare const Accessory: CreatableInstancesWithConstructors["Accessory"];
|
||||
declare const AccessoryDescription: CreatableInstancesWithConstructors["AccessoryDescription"];
|
||||
declare const Accoutrement: CreatableInstancesWithConstructors["Accoutrement"];
|
||||
declare const Actor: CreatableInstancesWithConstructors["Actor"];
|
||||
declare const AdGui: CreatableInstancesWithConstructors["AdGui"];
|
||||
declare const AdPortal: CreatableInstancesWithConstructors["AdPortal"];
|
||||
declare const AirController: CreatableInstancesWithConstructors["AirController"];
|
||||
declare const AlignOrientation: CreatableInstancesWithConstructors["AlignOrientation"];
|
||||
declare const AlignPosition: CreatableInstancesWithConstructors["AlignPosition"];
|
||||
declare const AngularVelocity: CreatableInstancesWithConstructors["AngularVelocity"];
|
||||
declare const Animation: CreatableInstancesWithConstructors["Animation"];
|
||||
declare const AnimationConstraint: CreatableInstancesWithConstructors["AnimationConstraint"];
|
||||
declare const AnimationController: CreatableInstancesWithConstructors["AnimationController"];
|
||||
declare const AnimationRigData: CreatableInstancesWithConstructors["AnimationRigData"];
|
||||
declare const Animator: CreatableInstancesWithConstructors["Animator"];
|
||||
declare const Annotation: CreatableInstancesWithConstructors["Annotation"];
|
||||
declare const ArcHandles: CreatableInstancesWithConstructors["ArcHandles"];
|
||||
declare const Atmosphere: CreatableInstancesWithConstructors["Atmosphere"];
|
||||
declare const AtmosphereSensor: CreatableInstancesWithConstructors["AtmosphereSensor"];
|
||||
declare const Attachment: CreatableInstancesWithConstructors["Attachment"];
|
||||
declare const AudioAnalyzer: CreatableInstancesWithConstructors["AudioAnalyzer"];
|
||||
declare const AudioChannelMixer: CreatableInstancesWithConstructors["AudioChannelMixer"];
|
||||
declare const AudioChannelSplitter: CreatableInstancesWithConstructors["AudioChannelSplitter"];
|
||||
declare const AudioChorus: CreatableInstancesWithConstructors["AudioChorus"];
|
||||
declare const AudioCompressor: CreatableInstancesWithConstructors["AudioCompressor"];
|
||||
declare const AudioDeviceInput: CreatableInstancesWithConstructors["AudioDeviceInput"];
|
||||
declare const AudioDeviceOutput: CreatableInstancesWithConstructors["AudioDeviceOutput"];
|
||||
declare const AudioDistortion: CreatableInstancesWithConstructors["AudioDistortion"];
|
||||
declare const AudioEcho: CreatableInstancesWithConstructors["AudioEcho"];
|
||||
declare const AudioEmitter: CreatableInstancesWithConstructors["AudioEmitter"];
|
||||
declare const AudioEqualizer: CreatableInstancesWithConstructors["AudioEqualizer"];
|
||||
declare const AudioFader: CreatableInstancesWithConstructors["AudioFader"];
|
||||
declare const AudioFilter: CreatableInstancesWithConstructors["AudioFilter"];
|
||||
declare const AudioFlanger: CreatableInstancesWithConstructors["AudioFlanger"];
|
||||
declare const AudioLimiter: CreatableInstancesWithConstructors["AudioLimiter"];
|
||||
declare const AudioListener: CreatableInstancesWithConstructors["AudioListener"];
|
||||
declare const AudioPitchShifter: CreatableInstancesWithConstructors["AudioPitchShifter"];
|
||||
declare const AudioPlayer: CreatableInstancesWithConstructors["AudioPlayer"];
|
||||
declare const AudioReverb: CreatableInstancesWithConstructors["AudioReverb"];
|
||||
declare const AudioSearchParams: CreatableInstancesWithConstructors["AudioSearchParams"];
|
||||
declare const AudioTextToSpeech: CreatableInstancesWithConstructors["AudioTextToSpeech"];
|
||||
declare const AuroraScript: CreatableInstancesWithConstructors["AuroraScript"];
|
||||
declare const Backpack: CreatableInstancesWithConstructors["Backpack"];
|
||||
declare const BallSocketConstraint: CreatableInstancesWithConstructors["BallSocketConstraint"];
|
||||
declare const Beam: CreatableInstancesWithConstructors["Beam"];
|
||||
declare const BillboardGui: CreatableInstancesWithConstructors["BillboardGui"];
|
||||
declare const BindableEvent: CreatableInstancesWithConstructors["BindableEvent"];
|
||||
declare const BindableFunction: CreatableInstancesWithConstructors["BindableFunction"];
|
||||
declare const BlockMesh: CreatableInstancesWithConstructors["BlockMesh"];
|
||||
declare const BloomEffect: CreatableInstancesWithConstructors["BloomEffect"];
|
||||
declare const BlurEffect: CreatableInstancesWithConstructors["BlurEffect"];
|
||||
declare const BodyAngularVelocity: CreatableInstancesWithConstructors["BodyAngularVelocity"];
|
||||
declare const BodyColors: CreatableInstancesWithConstructors["BodyColors"];
|
||||
declare const BodyForce: CreatableInstancesWithConstructors["BodyForce"];
|
||||
declare const BodyGyro: CreatableInstancesWithConstructors["BodyGyro"];
|
||||
declare const BodyPartDescription: CreatableInstancesWithConstructors["BodyPartDescription"];
|
||||
declare const BodyPosition: CreatableInstancesWithConstructors["BodyPosition"];
|
||||
declare const BodyThrust: CreatableInstancesWithConstructors["BodyThrust"];
|
||||
declare const BodyVelocity: CreatableInstancesWithConstructors["BodyVelocity"];
|
||||
declare const Bone: CreatableInstancesWithConstructors["Bone"];
|
||||
declare const BoolValue: CreatableInstancesWithConstructors["BoolValue"];
|
||||
declare const BoxHandleAdornment: CreatableInstancesWithConstructors["BoxHandleAdornment"];
|
||||
declare const Breakpoint: CreatableInstancesWithConstructors["Breakpoint"];
|
||||
declare const BrickColorValue: CreatableInstancesWithConstructors["BrickColorValue"];
|
||||
declare const BubbleChatMessageProperties: CreatableInstancesWithConstructors["BubbleChatMessageProperties"];
|
||||
declare const BuoyancySensor: CreatableInstancesWithConstructors["BuoyancySensor"];
|
||||
declare const CFrameValue: CreatableInstancesWithConstructors["CFrameValue"];
|
||||
declare const Camera: CreatableInstancesWithConstructors["Camera"];
|
||||
declare const CanvasGroup: CreatableInstancesWithConstructors["CanvasGroup"];
|
||||
declare const CharacterMesh: CreatableInstancesWithConstructors["CharacterMesh"];
|
||||
declare const ChorusSoundEffect: CreatableInstancesWithConstructors["ChorusSoundEffect"];
|
||||
declare const ClickDetector: CreatableInstancesWithConstructors["ClickDetector"];
|
||||
declare const ClimbController: CreatableInstancesWithConstructors["ClimbController"];
|
||||
declare const Clouds: CreatableInstancesWithConstructors["Clouds"];
|
||||
declare const Color3Value: CreatableInstancesWithConstructors["Color3Value"];
|
||||
declare const ColorCorrectionEffect: CreatableInstancesWithConstructors["ColorCorrectionEffect"];
|
||||
declare const ColorGradingEffect: CreatableInstancesWithConstructors["ColorGradingEffect"];
|
||||
declare const CompressorSoundEffect: CreatableInstancesWithConstructors["CompressorSoundEffect"];
|
||||
declare const ConeHandleAdornment: CreatableInstancesWithConstructors["ConeHandleAdornment"];
|
||||
declare const Configuration: CreatableInstancesWithConstructors["Configuration"];
|
||||
declare const ControllerManager: CreatableInstancesWithConstructors["ControllerManager"];
|
||||
declare const ControllerPartSensor: CreatableInstancesWithConstructors["ControllerPartSensor"];
|
||||
declare const CornerWedgePart: CreatableInstancesWithConstructors["CornerWedgePart"];
|
||||
declare const CurveAnimation: CreatableInstancesWithConstructors["CurveAnimation"];
|
||||
declare const CustomLog: CreatableInstancesWithConstructors["CustomLog"];
|
||||
declare const CylinderHandleAdornment: CreatableInstancesWithConstructors["CylinderHandleAdornment"];
|
||||
declare const CylinderMesh: CreatableInstancesWithConstructors["CylinderMesh"];
|
||||
declare const CylindricalConstraint: CreatableInstancesWithConstructors["CylindricalConstraint"];
|
||||
declare const DataStoreGetOptions: CreatableInstancesWithConstructors["DataStoreGetOptions"];
|
||||
declare const DataStoreIncrementOptions: CreatableInstancesWithConstructors["DataStoreIncrementOptions"];
|
||||
declare const DataStoreOptions: CreatableInstancesWithConstructors["DataStoreOptions"];
|
||||
declare const DataStoreSetOptions: CreatableInstancesWithConstructors["DataStoreSetOptions"];
|
||||
declare const Decal: CreatableInstancesWithConstructors["Decal"];
|
||||
declare const DepthOfFieldEffect: CreatableInstancesWithConstructors["DepthOfFieldEffect"];
|
||||
declare const Dialog: CreatableInstancesWithConstructors["Dialog"];
|
||||
declare const DialogChoice: CreatableInstancesWithConstructors["DialogChoice"];
|
||||
declare const DistortionSoundEffect: CreatableInstancesWithConstructors["DistortionSoundEffect"];
|
||||
declare const DoubleConstrainedValue: CreatableInstancesWithConstructors["DoubleConstrainedValue"];
|
||||
declare const DragDetector: CreatableInstancesWithConstructors["DragDetector"];
|
||||
declare const Dragger: CreatableInstancesWithConstructors["Dragger"];
|
||||
declare const EchoSoundEffect: CreatableInstancesWithConstructors["EchoSoundEffect"];
|
||||
declare const EqualizerSoundEffect: CreatableInstancesWithConstructors["EqualizerSoundEffect"];
|
||||
declare const EulerRotationCurve: CreatableInstancesWithConstructors["EulerRotationCurve"];
|
||||
declare const ExperienceInviteOptions: CreatableInstancesWithConstructors["ExperienceInviteOptions"];
|
||||
declare const ExplorerFilter: CreatableInstancesWithConstructors["ExplorerFilter"];
|
||||
declare const Explosion: CreatableInstancesWithConstructors["Explosion"];
|
||||
declare const FaceControls: CreatableInstancesWithConstructors["FaceControls"];
|
||||
declare const FileMesh: CreatableInstancesWithConstructors["FileMesh"];
|
||||
declare const Fire: CreatableInstancesWithConstructors["Fire"];
|
||||
declare const FlangeSoundEffect: CreatableInstancesWithConstructors["FlangeSoundEffect"];
|
||||
declare const FloatCurve: CreatableInstancesWithConstructors["FloatCurve"];
|
||||
declare const FloorWire: CreatableInstancesWithConstructors["FloorWire"];
|
||||
declare const FluidForceSensor: CreatableInstancesWithConstructors["FluidForceSensor"];
|
||||
declare const Folder: CreatableInstancesWithConstructors["Folder"];
|
||||
declare const ForceField: CreatableInstancesWithConstructors["ForceField"];
|
||||
declare const Frame: CreatableInstancesWithConstructors["Frame"];
|
||||
declare const GetTextBoundsParams: CreatableInstancesWithConstructors["GetTextBoundsParams"];
|
||||
declare const Glue: CreatableInstancesWithConstructors["Glue"];
|
||||
declare const GroundController: CreatableInstancesWithConstructors["GroundController"];
|
||||
declare const Handles: CreatableInstancesWithConstructors["Handles"];
|
||||
declare const HapticEffect: CreatableInstancesWithConstructors["HapticEffect"];
|
||||
declare const Hat: CreatableInstancesWithConstructors["Hat"];
|
||||
declare const HiddenSurfaceRemovalAsset: CreatableInstancesWithConstructors["HiddenSurfaceRemovalAsset"];
|
||||
declare const Highlight: CreatableInstancesWithConstructors["Highlight"];
|
||||
declare const HingeConstraint: CreatableInstancesWithConstructors["HingeConstraint"];
|
||||
declare const Hole: CreatableInstancesWithConstructors["Hole"];
|
||||
declare const Humanoid: CreatableInstancesWithConstructors["Humanoid"];
|
||||
declare const HumanoidController: CreatableInstancesWithConstructors["HumanoidController"];
|
||||
declare const HumanoidDescription: CreatableInstancesWithConstructors["HumanoidDescription"];
|
||||
declare const HumanoidRigDescription: CreatableInstancesWithConstructors["HumanoidRigDescription"];
|
||||
declare const IKControl: CreatableInstancesWithConstructors["IKControl"];
|
||||
declare const ImageButton: CreatableInstancesWithConstructors["ImageButton"];
|
||||
declare const ImageHandleAdornment: CreatableInstancesWithConstructors["ImageHandleAdornment"];
|
||||
declare const ImageLabel: CreatableInstancesWithConstructors["ImageLabel"];
|
||||
declare const InputAction: CreatableInstancesWithConstructors["InputAction"];
|
||||
declare const InputBinding: CreatableInstancesWithConstructors["InputBinding"];
|
||||
declare const InputContext: CreatableInstancesWithConstructors["InputContext"];
|
||||
declare const IntConstrainedValue: CreatableInstancesWithConstructors["IntConstrainedValue"];
|
||||
declare const IntValue: CreatableInstancesWithConstructors["IntValue"];
|
||||
declare const InternalSyncItem: CreatableInstancesWithConstructors["InternalSyncItem"];
|
||||
declare const IntersectOperation: CreatableInstancesWithConstructors["IntersectOperation"];
|
||||
declare const Keyframe: CreatableInstancesWithConstructors["Keyframe"];
|
||||
declare const KeyframeMarker: CreatableInstancesWithConstructors["KeyframeMarker"];
|
||||
declare const KeyframeSequence: CreatableInstancesWithConstructors["KeyframeSequence"];
|
||||
declare const LineForce: CreatableInstancesWithConstructors["LineForce"];
|
||||
declare const LineHandleAdornment: CreatableInstancesWithConstructors["LineHandleAdornment"];
|
||||
declare const LinearVelocity: CreatableInstancesWithConstructors["LinearVelocity"];
|
||||
declare const LocalScript: CreatableInstancesWithConstructors["LocalScript"];
|
||||
declare const LocalizationTable: CreatableInstancesWithConstructors["LocalizationTable"];
|
||||
declare const ManualGlue: CreatableInstancesWithConstructors["ManualGlue"];
|
||||
declare const ManualWeld: CreatableInstancesWithConstructors["ManualWeld"];
|
||||
declare const MarkerCurve: CreatableInstancesWithConstructors["MarkerCurve"];
|
||||
declare const MaterialVariant: CreatableInstancesWithConstructors["MaterialVariant"];
|
||||
declare const MeshPart: CreatableInstancesWithConstructors["MeshPart"];
|
||||
declare const Model: CreatableInstancesWithConstructors["Model"];
|
||||
declare const ModuleScript: CreatableInstancesWithConstructors["ModuleScript"];
|
||||
declare const Motor: CreatableInstancesWithConstructors["Motor"];
|
||||
declare const Motor6D: CreatableInstancesWithConstructors["Motor6D"];
|
||||
declare const MotorFeature: CreatableInstancesWithConstructors["MotorFeature"];
|
||||
declare const NegateOperation: CreatableInstancesWithConstructors["NegateOperation"];
|
||||
declare const NoCollisionConstraint: CreatableInstancesWithConstructors["NoCollisionConstraint"];
|
||||
declare const Noise: CreatableInstancesWithConstructors["Noise"];
|
||||
declare const NumberPose: CreatableInstancesWithConstructors["NumberPose"];
|
||||
declare const NumberValue: CreatableInstancesWithConstructors["NumberValue"];
|
||||
declare const ObjectValue: CreatableInstancesWithConstructors["ObjectValue"];
|
||||
declare const OperationGraph: CreatableInstancesWithConstructors["OperationGraph"];
|
||||
declare const Pants: CreatableInstancesWithConstructors["Pants"];
|
||||
declare const Part: CreatableInstancesWithConstructors["Part"];
|
||||
declare const PartOperation: CreatableInstancesWithConstructors["PartOperation"];
|
||||
declare const ParticleEmitter: CreatableInstancesWithConstructors["ParticleEmitter"];
|
||||
declare const Path2D: CreatableInstancesWithConstructors["Path2D"];
|
||||
declare const PathfindingLink: CreatableInstancesWithConstructors["PathfindingLink"];
|
||||
declare const PathfindingModifier: CreatableInstancesWithConstructors["PathfindingModifier"];
|
||||
declare const PitchShiftSoundEffect: CreatableInstancesWithConstructors["PitchShiftSoundEffect"];
|
||||
declare const Plane: CreatableInstancesWithConstructors["Plane"];
|
||||
declare const PlaneConstraint: CreatableInstancesWithConstructors["PlaneConstraint"];
|
||||
declare const PluginCapabilities: CreatableInstancesWithConstructors["PluginCapabilities"];
|
||||
declare const PointLight: CreatableInstancesWithConstructors["PointLight"];
|
||||
declare const Pose: CreatableInstancesWithConstructors["Pose"];
|
||||
declare const PrismaticConstraint: CreatableInstancesWithConstructors["PrismaticConstraint"];
|
||||
declare const ProximityPrompt: CreatableInstancesWithConstructors["ProximityPrompt"];
|
||||
declare const RTAnimationTracker: CreatableInstancesWithConstructors["RTAnimationTracker"];
|
||||
declare const RayValue: CreatableInstancesWithConstructors["RayValue"];
|
||||
declare const RelativeGui: CreatableInstancesWithConstructors["RelativeGui"];
|
||||
declare const RemoteEvent: CreatableInstancesWithConstructors["RemoteEvent"];
|
||||
declare const RemoteFunction: CreatableInstancesWithConstructors["RemoteFunction"];
|
||||
declare const ReverbSoundEffect: CreatableInstancesWithConstructors["ReverbSoundEffect"];
|
||||
declare const RigidConstraint: CreatableInstancesWithConstructors["RigidConstraint"];
|
||||
declare const RocketPropulsion: CreatableInstancesWithConstructors["RocketPropulsion"];
|
||||
declare const RodConstraint: CreatableInstancesWithConstructors["RodConstraint"];
|
||||
declare const RopeConstraint: CreatableInstancesWithConstructors["RopeConstraint"];
|
||||
declare const Rotate: CreatableInstancesWithConstructors["Rotate"];
|
||||
declare const RotateP: CreatableInstancesWithConstructors["RotateP"];
|
||||
declare const RotateV: CreatableInstancesWithConstructors["RotateV"];
|
||||
declare const RotationCurve: CreatableInstancesWithConstructors["RotationCurve"];
|
||||
declare const ScreenGui: CreatableInstancesWithConstructors["ScreenGui"];
|
||||
declare const Script: CreatableInstancesWithConstructors["Script"];
|
||||
declare const ScrollingFrame: CreatableInstancesWithConstructors["ScrollingFrame"];
|
||||
declare const Seat: CreatableInstancesWithConstructors["Seat"];
|
||||
declare const SelectionBox: CreatableInstancesWithConstructors["SelectionBox"];
|
||||
declare const SelectionPartLasso: CreatableInstancesWithConstructors["SelectionPartLasso"];
|
||||
declare const SelectionPointLasso: CreatableInstancesWithConstructors["SelectionPointLasso"];
|
||||
declare const SelectionSphere: CreatableInstancesWithConstructors["SelectionSphere"];
|
||||
declare const Shirt: CreatableInstancesWithConstructors["Shirt"];
|
||||
declare const ShirtGraphic: CreatableInstancesWithConstructors["ShirtGraphic"];
|
||||
declare const SkateboardController: CreatableInstancesWithConstructors["SkateboardController"];
|
||||
declare const SkateboardPlatform: CreatableInstancesWithConstructors["SkateboardPlatform"];
|
||||
declare const Sky: CreatableInstancesWithConstructors["Sky"];
|
||||
declare const Smoke: CreatableInstancesWithConstructors["Smoke"];
|
||||
declare const Snap: CreatableInstancesWithConstructors["Snap"];
|
||||
declare const Sound: CreatableInstancesWithConstructors["Sound"];
|
||||
declare const SoundGroup: CreatableInstancesWithConstructors["SoundGroup"];
|
||||
declare const Sparkles: CreatableInstancesWithConstructors["Sparkles"];
|
||||
declare const SpawnLocation: CreatableInstancesWithConstructors["SpawnLocation"];
|
||||
declare const SpecialMesh: CreatableInstancesWithConstructors["SpecialMesh"];
|
||||
declare const SphereHandleAdornment: CreatableInstancesWithConstructors["SphereHandleAdornment"];
|
||||
declare const SpotLight: CreatableInstancesWithConstructors["SpotLight"];
|
||||
declare const SpringConstraint: CreatableInstancesWithConstructors["SpringConstraint"];
|
||||
declare const StarterGear: CreatableInstancesWithConstructors["StarterGear"];
|
||||
declare const StringValue: CreatableInstancesWithConstructors["StringValue"];
|
||||
declare const StudioAttachment: CreatableInstancesWithConstructors["StudioAttachment"];
|
||||
declare const StudioCallout: CreatableInstancesWithConstructors["StudioCallout"];
|
||||
declare const StyleDerive: CreatableInstancesWithConstructors["StyleDerive"];
|
||||
declare const StyleLink: CreatableInstancesWithConstructors["StyleLink"];
|
||||
declare const StyleRule: CreatableInstancesWithConstructors["StyleRule"];
|
||||
declare const StyleSheet: CreatableInstancesWithConstructors["StyleSheet"];
|
||||
declare const SunRaysEffect: CreatableInstancesWithConstructors["SunRaysEffect"];
|
||||
declare const SurfaceAppearance: CreatableInstancesWithConstructors["SurfaceAppearance"];
|
||||
declare const SurfaceGui: CreatableInstancesWithConstructors["SurfaceGui"];
|
||||
declare const SurfaceLight: CreatableInstancesWithConstructors["SurfaceLight"];
|
||||
declare const SurfaceSelection: CreatableInstancesWithConstructors["SurfaceSelection"];
|
||||
declare const SwimController: CreatableInstancesWithConstructors["SwimController"];
|
||||
declare const Team: CreatableInstancesWithConstructors["Team"];
|
||||
declare const TeleportOptions: CreatableInstancesWithConstructors["TeleportOptions"];
|
||||
declare const TerrainDetail: CreatableInstancesWithConstructors["TerrainDetail"];
|
||||
declare const TerrainRegion: CreatableInstancesWithConstructors["TerrainRegion"];
|
||||
declare const TextBox: CreatableInstancesWithConstructors["TextBox"];
|
||||
declare const TextButton: CreatableInstancesWithConstructors["TextButton"];
|
||||
declare const TextChannel: CreatableInstancesWithConstructors["TextChannel"];
|
||||
declare const TextChatCommand: CreatableInstancesWithConstructors["TextChatCommand"];
|
||||
declare const TextChatMessageProperties: CreatableInstancesWithConstructors["TextChatMessageProperties"];
|
||||
declare const TextLabel: CreatableInstancesWithConstructors["TextLabel"];
|
||||
declare const Texture: CreatableInstancesWithConstructors["Texture"];
|
||||
declare const Tool: CreatableInstancesWithConstructors["Tool"];
|
||||
declare const Torque: CreatableInstancesWithConstructors["Torque"];
|
||||
declare const TorsionSpringConstraint: CreatableInstancesWithConstructors["TorsionSpringConstraint"];
|
||||
declare const TrackerStreamAnimation: CreatableInstancesWithConstructors["TrackerStreamAnimation"];
|
||||
declare const Trail: CreatableInstancesWithConstructors["Trail"];
|
||||
declare const TremoloSoundEffect: CreatableInstancesWithConstructors["TremoloSoundEffect"];
|
||||
declare const TrussPart: CreatableInstancesWithConstructors["TrussPart"];
|
||||
declare const UIAspectRatioConstraint: CreatableInstancesWithConstructors["UIAspectRatioConstraint"];
|
||||
declare const UICorner: CreatableInstancesWithConstructors["UICorner"];
|
||||
declare const UIDragDetector: CreatableInstancesWithConstructors["UIDragDetector"];
|
||||
declare const UIFlexItem: CreatableInstancesWithConstructors["UIFlexItem"];
|
||||
declare const UIGradient: CreatableInstancesWithConstructors["UIGradient"];
|
||||
declare const UIGridLayout: CreatableInstancesWithConstructors["UIGridLayout"];
|
||||
declare const UIListLayout: CreatableInstancesWithConstructors["UIListLayout"];
|
||||
declare const UIPadding: CreatableInstancesWithConstructors["UIPadding"];
|
||||
declare const UIPageLayout: CreatableInstancesWithConstructors["UIPageLayout"];
|
||||
declare const UIScale: CreatableInstancesWithConstructors["UIScale"];
|
||||
declare const UISizeConstraint: CreatableInstancesWithConstructors["UISizeConstraint"];
|
||||
declare const UIStroke: CreatableInstancesWithConstructors["UIStroke"];
|
||||
declare const UITableLayout: CreatableInstancesWithConstructors["UITableLayout"];
|
||||
declare const UITextSizeConstraint: CreatableInstancesWithConstructors["UITextSizeConstraint"];
|
||||
declare const UnionOperation: CreatableInstancesWithConstructors["UnionOperation"];
|
||||
declare const UniversalConstraint: CreatableInstancesWithConstructors["UniversalConstraint"];
|
||||
declare const UnreliableRemoteEvent: CreatableInstancesWithConstructors["UnreliableRemoteEvent"];
|
||||
declare const Vector3Curve: CreatableInstancesWithConstructors["Vector3Curve"];
|
||||
declare const Vector3Value: CreatableInstancesWithConstructors["Vector3Value"];
|
||||
declare const VectorForce: CreatableInstancesWithConstructors["VectorForce"];
|
||||
declare const VehicleController: CreatableInstancesWithConstructors["VehicleController"];
|
||||
declare const VehicleSeat: CreatableInstancesWithConstructors["VehicleSeat"];
|
||||
declare const VelocityMotor: CreatableInstancesWithConstructors["VelocityMotor"];
|
||||
declare const VideoDeviceInput: CreatableInstancesWithConstructors["VideoDeviceInput"];
|
||||
declare const VideoDisplay: CreatableInstancesWithConstructors["VideoDisplay"];
|
||||
declare const VideoFrame: CreatableInstancesWithConstructors["VideoFrame"];
|
||||
declare const VideoPlayer: CreatableInstancesWithConstructors["VideoPlayer"];
|
||||
declare const ViewportFrame: CreatableInstancesWithConstructors["ViewportFrame"];
|
||||
declare const VisualizationMode: CreatableInstancesWithConstructors["VisualizationMode"];
|
||||
declare const VisualizationModeCategory: CreatableInstancesWithConstructors["VisualizationModeCategory"];
|
||||
declare const WedgePart: CreatableInstancesWithConstructors["WedgePart"];
|
||||
declare const Weld: CreatableInstancesWithConstructors["Weld"];
|
||||
declare const WeldConstraint: CreatableInstancesWithConstructors["WeldConstraint"];
|
||||
declare const Wire: CreatableInstancesWithConstructors["Wire"];
|
||||
declare const WireframeHandleAdornment: CreatableInstancesWithConstructors["WireframeHandleAdornment"];
|
||||
declare const WorkspaceAnnotation: CreatableInstancesWithConstructors["WorkspaceAnnotation"];
|
||||
declare const WorldModel: CreatableInstancesWithConstructors["WorldModel"];
|
||||
declare const WrapDeformer: CreatableInstancesWithConstructors["WrapDeformer"];
|
||||
declare const WrapLayer: CreatableInstancesWithConstructors["WrapLayer"];
|
||||
declare const WrapTarget: CreatableInstancesWithConstructors["WrapTarget"];
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/test/**/*.test.ts'],
|
||||
moduleFileExtensions: ['ts', 'js'],
|
||||
};
|
||||
Generated
+7074
-1236
File diff suppressed because it is too large
Load Diff
+26
-19
@@ -1,33 +1,40 @@
|
||||
{
|
||||
"name": "rbxts-transformer-services",
|
||||
"version": "1.1.1",
|
||||
"description": "A transformer that converts @rbxts/services imports into plain GetService calls.",
|
||||
"name": "rbxts-transformer-instances",
|
||||
"version": "1.0.0",
|
||||
"description": "Enable the use of instance constructors, reducing boilerplate.",
|
||||
"main": "out/index.js",
|
||||
"author": "Fireboltofdeath <fireboltofpublic@gmail.com> (https://github.com/Fireboltofdeath)",
|
||||
"license": "ISC",
|
||||
"author": "evilbocchi",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FireTS/rbxts-transformer-services.git"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.2.2"
|
||||
"url": "https://github.com/evilbocchi/rbxts-transformer-instances.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "npm run build",
|
||||
"prepare": "npm run generate-declarations && npm run build",
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w"
|
||||
"watch": "tsc -w",
|
||||
"test": "jest",
|
||||
"generate-declarations": "node scripts/generate-declarations.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rbxts/types": "^1.0.845",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^18.18.6",
|
||||
"@types/ts-expose-internals": "npm:ts-expose-internals@5.2.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.9.1",
|
||||
"@typescript-eslint/parser": "^4.9.1",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-prettier": "^7.0.0",
|
||||
"eslint-plugin-prettier": "^3.2.0",
|
||||
"prettier": "^2.2.1"
|
||||
"@typescript-eslint/eslint-plugin": "^8.5.0",
|
||||
"@typescript-eslint/parser": "^8.5.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.3.1"
|
||||
},
|
||||
"files": [
|
||||
"out"
|
||||
]
|
||||
"out",
|
||||
"index.d.ts"
|
||||
],
|
||||
"types": "index.d.ts"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Script to generate declaration statements for all creatable Roblox instances
|
||||
* This will produce declarations in the format:
|
||||
* declare const INSTANCENAME: CreatableInstancesWithConstructors["INSTANCENAME"]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
/**
|
||||
* Get all creatable instance class names by examining the @rbxts/types package
|
||||
*/
|
||||
function getCreatableInstanceNames() {
|
||||
try {
|
||||
// Find the location of @rbxts/types in node_modules
|
||||
let typesPath;
|
||||
try {
|
||||
// Try to find the path to @rbxts/types
|
||||
typesPath = path.dirname(require.resolve('@rbxts/types/package.json'));
|
||||
} catch (e) {
|
||||
console.error('Could not find @rbxts/types. Make sure it is installed.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Read the CreatableInstances interface definition file
|
||||
// This could be in a few different locations depending on the package structure
|
||||
let instancesFile;
|
||||
const possiblePaths = [
|
||||
path.join(typesPath, 'include', 'generated', 'None.d.ts'),
|
||||
path.join(typesPath, 'types', 'generated', 'None.d.ts'),
|
||||
path.join(typesPath, 'generated', 'None.d.ts')
|
||||
];
|
||||
|
||||
for (const filePath of possiblePaths) {
|
||||
if (fs.existsSync(filePath)) {
|
||||
instancesFile = filePath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!instancesFile) {
|
||||
throw new Error('Could not find None.d.ts file in @rbxts/types');
|
||||
}
|
||||
|
||||
// Read the file content
|
||||
const content = fs.readFileSync(instancesFile, 'utf-8');
|
||||
|
||||
// Extract interface names that appear in CreatableInstances
|
||||
// This regex might need adjustment depending on the exact format
|
||||
const creatableInstancesRegex = /interface CreatableInstances \{([\s\S]*?)\}/;
|
||||
const creatablesMatch = content.match(creatableInstancesRegex);
|
||||
|
||||
if (!creatablesMatch || !creatablesMatch[1]) {
|
||||
throw new Error('Could not find CreatableInstances interface in the types file');
|
||||
}
|
||||
|
||||
// Extract class names by looking for patterns like "ClassName: ClassName;"
|
||||
const classNameRegex = /([A-Za-z0-9_]+)\s*:\s*([A-Za-z0-9_]+);/g;
|
||||
const classNames = [];
|
||||
let match;
|
||||
|
||||
while ((match = classNameRegex.exec(creatablesMatch[1])) !== null) {
|
||||
classNames.push(match[1]);
|
||||
}
|
||||
|
||||
return classNames.sort();
|
||||
} catch (error) {
|
||||
console.error('Error extracting instance names:', error);
|
||||
|
||||
// Fallback to a predefined list of common instances
|
||||
console.log('Falling back to predefined list of common instances...');
|
||||
return [
|
||||
"Accessory", "Accoutrement", "Animation", "Attachment", "BillboardGui",
|
||||
"BindableEvent", "BindableFunction", "BlockMesh", "BodyAngularVelocity",
|
||||
"BodyForce", "BodyGyro", "BodyPosition", "BodyThrust", "BodyVelocity",
|
||||
"BoolValue", "BrickColorValue", "Camera", "CFrameValue", "ClickDetector",
|
||||
"Clothing", "Color3Value", "ColorCorrectionEffect", "Configuration",
|
||||
"CornerWedgePart", "Decal", "Dialog", "DialogChoice", "DoubleConstrainedValue",
|
||||
"Explosion", "Folder", "ForceField", "Frame", "GuiButton", "GuiObject",
|
||||
"Highlight", "Humanoid", "HumanoidDescription", "ImageButton", "ImageLabel",
|
||||
"IntConstrainedValue", "IntValue", "LocalScript", "MeshPart", "Model",
|
||||
"ModuleScript", "Motor", "Motor6D", "NumberValue", "ObjectValue", "Part",
|
||||
"ParticleEmitter", "ProximityPrompt", "RayValue", "RemoteEvent", "RemoteFunction",
|
||||
"ScreenGui", "Script", "ScrollingFrame", "Seat", "Sky", "Sound", "SpecialMesh",
|
||||
"SpotLight", "StringValue", "SurfaceGui", "TextBox", "TextButton",
|
||||
"TextLabel", "Texture", "Tool", "TouchTransmitter", "Trail", "TrussPart",
|
||||
"UIAspectRatioConstraint", "UICorner", "UIGradient", "UIGridLayout",
|
||||
"UIListLayout", "UIPadding", "UIPageLayout", "UIScale", "UIStroke",
|
||||
"UITableLayout", "UITextSizeConstraint", "UnionOperation", "Vector3Value",
|
||||
"VectorForce", "VideoFrame", "WedgePart", "Weld"
|
||||
].sort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the declarations file content
|
||||
* @param {string[]} classNames List of creatable instance class names
|
||||
* @returns {string} The content for the declarations file
|
||||
*/
|
||||
function generateDeclarations(classNames) {
|
||||
// Header part
|
||||
let content = `/// <reference no-default-lib="true"/>
|
||||
/// <reference types="@rbxts/types" />
|
||||
|
||||
/**
|
||||
* Add constructors to all Roblox CreatableInstances
|
||||
* This adds \`new ClassName()\` constructors for all Roblox instance types
|
||||
* that can be created with Instance.new()
|
||||
*
|
||||
* The transformer will convert these to \`new Instance("ClassName")\`
|
||||
*/
|
||||
type CreatableInstancesWithConstructors = {
|
||||
[K in keyof CreatableInstances]: {
|
||||
new (...args: any[]): CreatableInstances[K];
|
||||
}
|
||||
}
|
||||
|
||||
declare const CreatableInstancesWithConstructors: CreatableInstancesWithConstructors;
|
||||
|
||||
`;
|
||||
|
||||
// Add declarations for each class
|
||||
for (const className of classNames) {
|
||||
content += `declare const ${className}: CreatableInstancesWithConstructors["${className}"];\n`;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
function main() {
|
||||
const classNames = getCreatableInstanceNames();
|
||||
console.log(`Found ${classNames.length} creatable instance types`);
|
||||
|
||||
const declarationsContent = generateDeclarations(classNames);
|
||||
const outputPath = path.join(__dirname, '..', 'index.d.ts');
|
||||
|
||||
// Write to file
|
||||
fs.writeFileSync(outputPath, declarationsContent, 'utf-8');
|
||||
console.log(`Successfully generated declarations in ${outputPath}`);
|
||||
|
||||
console.log('Example declarations:');
|
||||
const examples = classNames.slice(0, 5);
|
||||
for (const className of examples) {
|
||||
console.log(`declare const ${className}: CreatableInstancesWithConstructors["${className}"];`);
|
||||
}
|
||||
console.log(`...and ${classNames.length - 5} more`);
|
||||
}
|
||||
|
||||
// Run the script
|
||||
main();
|
||||
+39
-69
@@ -31,87 +31,57 @@ export class TransformContext {
|
||||
}
|
||||
}
|
||||
|
||||
function visitImportDeclaration(context: TransformContext, node: ts.ImportDeclaration) {
|
||||
function visitExpression(context: TransformContext, node: ts.Expression): ts.Expression {
|
||||
// Check for new expressions (new Part())
|
||||
if (ts.isNewExpression(node)) {
|
||||
const { expression, arguments: args } = node;
|
||||
|
||||
// Check if it's a simple identifier (e.g., Part, not Something.Part)
|
||||
if (ts.isIdentifier(expression)) {
|
||||
const className = expression.text;
|
||||
|
||||
// Check if it's an Instance-derived class (assuming basic Roblox classes for now)
|
||||
const instanceClasses = [
|
||||
"Part", "Model", "Folder", "Script", "LocalScript", "ModuleScript",
|
||||
"Frame", "TextLabel", "TextButton", "ImageLabel", "ImageButton",
|
||||
"Sound", "Animation", "BoolValue", "StringValue", "NumberValue",
|
||||
// Add more Roblox classes as needed
|
||||
];
|
||||
|
||||
if (instanceClasses.includes(className)) {
|
||||
const { factory } = context;
|
||||
|
||||
const path = node.moduleSpecifier;
|
||||
const clause = node.importClause;
|
||||
if (!clause) return node;
|
||||
if (!ts.isStringLiteral(path)) return node;
|
||||
if (path.text !== "@rbxts/services") return node;
|
||||
|
||||
const namedBindings = clause.namedBindings;
|
||||
if (!namedBindings) return node;
|
||||
if (!ts.isNamedImports(namedBindings)) return node;
|
||||
|
||||
return [
|
||||
// We replace the import declaration instead of stripping it to prevent
|
||||
// issues with isolated modules.
|
||||
factory.updateImportDeclaration(
|
||||
node,
|
||||
// Create new Instance("ClassName") expression
|
||||
return factory.createNewExpression(
|
||||
factory.createIdentifier("Instance"),
|
||||
undefined,
|
||||
factory.createImportClause(false, undefined, factory.createNamedImports([])),
|
||||
node.moduleSpecifier,
|
||||
undefined,
|
||||
),
|
||||
|
||||
// Creates a multi-variable statement as shown below.
|
||||
//
|
||||
// const Players = game.GetService("Players"),
|
||||
// Workspace = game.GetService("Workspace");
|
||||
factory.createVariableStatement(
|
||||
undefined,
|
||||
factory.createVariableDeclarationList(
|
||||
namedBindings.elements.map((specifier) => {
|
||||
const serviceName = specifier.propertyName ? specifier.propertyName.text : specifier.name.text;
|
||||
const variableName = specifier.name;
|
||||
|
||||
return factory.createVariableDeclaration(
|
||||
variableName,
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createCallExpression(
|
||||
factory.createPropertyAccessExpression(factory.createIdentifier("game"), "GetService"),
|
||||
undefined,
|
||||
[factory.createStringLiteral(serviceName)],
|
||||
),
|
||||
[
|
||||
factory.createStringLiteral(className),
|
||||
...(args || [])
|
||||
]
|
||||
);
|
||||
}),
|
||||
ts.NodeFlags.Const,
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
function visitStatement(context: TransformContext, node: ts.Statement): ts.Statement | ts.Statement[] {
|
||||
// This is used to transform statements.
|
||||
// TypeScript allows you to return multiple statements here.
|
||||
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
// We have encountered an import declaration,
|
||||
// so we should transform it using a separate function.
|
||||
|
||||
return visitImportDeclaration(context, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return context.transform(node);
|
||||
}
|
||||
|
||||
function visitExpression(context: TransformContext, node: ts.Expression): ts.Expression {
|
||||
// This can be used to transform expressions
|
||||
// For example, a call expression for macros.
|
||||
|
||||
// For other expressions, continue traversing
|
||||
return context.transform(node);
|
||||
}
|
||||
|
||||
function visitNode(context: TransformContext, node: ts.Node): ts.Node | ts.Node[] {
|
||||
if (ts.isStatement(node)) {
|
||||
return visitStatement(context, node);
|
||||
} else if (ts.isExpression(node)) {
|
||||
if (ts.isExpression(node)) {
|
||||
return visitExpression(context, node);
|
||||
}
|
||||
|
||||
// We encountered a node that we don't handle above,
|
||||
// but we should keep iterating the AST in case we find something we want to transform.
|
||||
// Continue traversing the AST
|
||||
return context.transform(node);
|
||||
}
|
||||
|
||||
export default function(program: ts.Program, config: TransformerConfig = { _: undefined }) {
|
||||
return (context: ts.TransformationContext) => {
|
||||
const transformContext = new TransformContext(program, context, config);
|
||||
return (file: ts.SourceFile) => {
|
||||
return ts.visitNode(file, (node) => visitNode(transformContext, node));
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/// <reference path="index.d.ts" />
|
||||
|
||||
type hi = CreatableInstancesWithConstructors;
|
||||
new Frame()
|
||||
|
||||
new Part().Name = "hi";
|
||||
@@ -0,0 +1,64 @@
|
||||
import * as ts from 'typescript';
|
||||
import transformer from '../src/transformer';
|
||||
|
||||
function transpile(source: string): string {
|
||||
const program = ts.createProgram([], {});
|
||||
const result = ts.transpileModule(source, {
|
||||
compilerOptions: {
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
},
|
||||
transformers: {
|
||||
before: [transformer(program) as ts.TransformerFactory<ts.SourceFile>]
|
||||
}
|
||||
});
|
||||
|
||||
return result.outputText;
|
||||
}
|
||||
|
||||
describe('rbxts-transformer-instances', () => {
|
||||
test('transforms new Part() to new Instance("Part")', () => {
|
||||
const source = `const part = new Part();`;
|
||||
const result = transpile(source);
|
||||
|
||||
expect(result).toContain('const part = new Instance("Part")');
|
||||
});
|
||||
|
||||
test('transforms new instances with arguments', () => {
|
||||
const source = `const model = new Model("MyModel");`;
|
||||
const result = transpile(source);
|
||||
|
||||
expect(result).toContain('const model = new Instance("Model", "MyModel")');
|
||||
});
|
||||
|
||||
test('preserves non-instance constructors', () => {
|
||||
const source = `const obj = new CustomClass();`;
|
||||
const result = transpile(source);
|
||||
|
||||
expect(result).toContain('const obj = new CustomClass()');
|
||||
});
|
||||
|
||||
test('handles multiple constructors in the same file', () => {
|
||||
const source = `
|
||||
const part = new Part();
|
||||
const obj = new CustomClass();
|
||||
const folder = new Folder("MyFolder");
|
||||
`;
|
||||
const result = transpile(source);
|
||||
|
||||
expect(result).toContain('const part = new Instance("Part")');
|
||||
expect(result).toContain('const obj = new CustomClass()');
|
||||
expect(result).toContain('const folder = new Instance("Folder", "MyFolder")');
|
||||
});
|
||||
|
||||
test('transforms instances in complex expressions', () => {
|
||||
const source = `
|
||||
function createParts() {
|
||||
return [new Part(), new Part(), new Model("MyModel")];
|
||||
}
|
||||
`;
|
||||
const result = transpile(source);
|
||||
|
||||
expect(result).toContain('return [new Instance("Part"), new Instance("Part"), new Instance("Model", "MyModel")]');
|
||||
});
|
||||
});
|
||||
+17
-6
@@ -1,16 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"downlevelIteration": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleDetection": "force",
|
||||
"strict": true,
|
||||
"target": "ES5",
|
||||
"lib": [
|
||||
"ES2015",
|
||||
"DOM"
|
||||
],
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
"esModuleInterop": true,
|
||||
|
||||
"rootDir": "src",
|
||||
"outDir": "out",
|
||||
"baseUrl": "src",
|
||||
"tsBuildInfoFile": "out/tsconfig.tsbuildinfo",
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["src/**/*", "index.d.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user