-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ben's Proposal #3
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 4 | ||
end_of_line = lf | ||
charset = utf-8 | ||
insert_final_newline = true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.js |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
{ | ||
"root": true, | ||
"parser": "@typescript-eslint/parser", | ||
"extends": [ | ||
"eslint:recommended", | ||
"plugin:@typescript-eslint/recommended" | ||
], | ||
"parserOptions": { | ||
"ecmaVersion": 2017, | ||
"sourceType": "module" | ||
}, | ||
"plugins": [ | ||
"@typescript-eslint", | ||
"header" | ||
], | ||
"ignorePatterns": [ | ||
"**/{node_modules,lib,bin}" | ||
], | ||
"rules": { | ||
// List of [ESLint rules](https://eslint.org/docs/rules/) | ||
"arrow-parens": ["off", "as-needed"], // do not force arrow function parentheses | ||
"constructor-super": "error", // checks the correct use of super() in sub-classes | ||
"dot-notation": "error", // obj.a instead of obj['a'] when possible | ||
"eqeqeq": "error", // ban '==', don't use 'smart' option! | ||
"guard-for-in": "error", // needs obj.hasOwnProperty(key) checks | ||
"new-parens": "error", // new Error() instead of new Error | ||
"no-bitwise": "error", // bitwise operators &, | can be confused with &&, || | ||
"no-caller": "error", // ECMAScript deprecated arguments.caller and arguments.callee | ||
"no-cond-assign": "error", // assignments if (a = '1') are error-prone | ||
"no-debugger": "error", // disallow debugger; statements | ||
"no-eval": "error", // eval is considered unsafe | ||
"no-inner-declarations": "off", // we need to have 'namespace' functions when using TS 'export =' | ||
"no-labels": "error", // GOTO is only used in BASIC ;) | ||
"no-multiple-empty-lines": ["error", {"max": 1}], // two or more empty lines need to be fused to one | ||
"no-new-wrappers": "error", // there is no reason to wrap primitve values | ||
"no-throw-literal": "error", // only throw Error but no objects {} | ||
"no-trailing-spaces": "error", // trim end of lines | ||
"no-unsafe-finally": "error", // safe try/catch/finally behavior | ||
"no-var": "error", // use const and let instead of var | ||
"space-before-function-paren": ["error", { // space in function decl: f() vs async () => {} | ||
"anonymous": "never", | ||
"asyncArrow": "always", | ||
"named": "never" | ||
}], | ||
"semi": [2, "always"], // Always use semicolons at end of statement | ||
"quotes": [2, "single", { "avoidEscape": true }], // Prefer single quotes | ||
"use-isnan": "error", // isNaN(i) Number.isNaN(i) instead of i === NaN | ||
"header/header": [ // Use MIT/Generated file header | ||
2, | ||
"block", | ||
{ "pattern": "MIT License|DO NOT EDIT MANUALLY!" } | ||
], | ||
// List of [@typescript-eslint rules](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules) | ||
"@typescript-eslint/adjacent-overload-signatures": "error", // grouping same method names | ||
"@typescript-eslint/array-type": ["error", { // string[] instead of Array<string> | ||
"default": "array-simple" | ||
}], | ||
"@typescript-eslint/ban-types": "error", // bans types like String in favor of string | ||
"@typescript-eslint/no-inferrable-types": "off", // don't blame decls like "index: number = 0", esp. in api signatures! | ||
"@typescript-eslint/indent": "error", // consistent indentation | ||
"@typescript-eslint/no-explicit-any": "error", // don't use :any type | ||
"@typescript-eslint/no-misused-new": "error", // no constructors for interfaces or new for classes | ||
"@typescript-eslint/no-namespace": "off", // disallow the use of custom TypeScript modules and namespaces | ||
"@typescript-eslint/no-non-null-assertion": "off", // allow ! operator | ||
"@typescript-eslint/no-parameter-properties": "error", // no property definitions in class constructors | ||
"@typescript-eslint/no-unused-vars": ["error", { // disallow Unused Variables | ||
"argsIgnorePattern": "^_" | ||
}], | ||
"@typescript-eslint/no-var-requires": "error", // use import instead of require | ||
"@typescript-eslint/prefer-for-of": "error", // prefer for-of loop over arrays | ||
"@typescript-eslint/prefer-namespace-keyword": "error", // prefer namespace over module in TypeScript | ||
"@typescript-eslint/triple-slash-reference": "error", // ban /// <reference />, prefer imports | ||
"@typescript-eslint/type-annotation-spacing": "error" // consistent space around colon ':' | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"name": "typir-workspace", | ||
"private": true, | ||
"engineStrict": true, | ||
"engines": { | ||
"npm": ">= 7.7.0" | ||
}, | ||
"scripts": { | ||
"clean": "shx rm -rf packages/**/lib packages/**/out packages/**/*.tsbuildinfo", | ||
"build": "tsc -b tsconfig.build.json", | ||
"watch": "tsc -b tsconfig.build.json -w", | ||
"build:clean": "npm run clean && npm run build", | ||
"lint": "npm run lint --workspaces", | ||
"test": "vitest", | ||
"test-ui": "vitest --ui", | ||
"coverage": "vitest run --coverage" | ||
}, | ||
"author": "TypeFox GmbH", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@types/node": "~16.18.11", | ||
"@types/vscode": "~1.67.0", | ||
"@typescript-eslint/eslint-plugin": "^5.51.0", | ||
"@typescript-eslint/parser": "^5.51.0", | ||
"@vitest/coverage-c8": "~0.28.4", | ||
"@vitest/ui": "~0.28.4", | ||
"concurrently": "^7.6.0", | ||
"eslint": "^8.33.0", | ||
"eslint-plugin-header": "^3.1.1", | ||
"editorconfig": "~1.0.2", | ||
"shx": "^0.3.4", | ||
"typescript": "~4.9.5", | ||
"vitest": "~0.28.4" | ||
}, | ||
"workspaces": [ | ||
"packages/*", | ||
"examples/*" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "typir", | ||
"version": "0.0.1", | ||
"description": "General purpose type checking library", | ||
"homepage": "https://langium.org", | ||
"engines": { | ||
"node": ">=14.0.0" | ||
}, | ||
"keywords": [ | ||
"typesystem", | ||
"typescript" | ||
], | ||
"license": "MIT", | ||
"files": [ | ||
"lib", | ||
"src" | ||
], | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"scripts": { | ||
"clean": "shx rm -rf lib coverage", | ||
"build": "tsc", | ||
"watch": "tsc --watch", | ||
"lint": "eslint src test --ext .ts", | ||
"publish:next": "npm --no-git-tag-version version \"$(semver $npm_package_version -i minor)-next.$(git rev-parse --short HEAD)\" && npm publish --tag next", | ||
"publish:latest": "npm publish --tag latest" | ||
}, | ||
"volta": { | ||
"node": "16.19.0", | ||
"npm": "8.19.3" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/langium/langium", | ||
"directory": "packages/langium" | ||
}, | ||
"bugs": "https://github.com/langium/langium/issues", | ||
"author": { | ||
"name": "TypeFox", | ||
"url": "https://www.typefox.io" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Type } from "./base"; | ||
|
||
export interface AssignabilityResult { | ||
/** | ||
* The failure of this result. If `undefined`, the assignability check succeeded. | ||
*/ | ||
readonly failure?: AssignabilityFailure; | ||
} | ||
|
||
export interface AssignabilityFailure { | ||
from: string; | ||
to: string; | ||
nested?: AssignabilityFailure; | ||
} | ||
|
||
export type AssignabilityCallback<From extends Type<unknown>, To extends Type<unknown> = From> = (types: { from: From, to: To }) => AssignabilityResult; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import type { TypeSystem } from "./type-system"; | ||
import { Disposable } from "./utils"; | ||
|
||
export interface Type<T> { | ||
readonly literal?: T; | ||
readonly members: Iterable<TypeMember<T>>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it really make sense to have |
||
/** | ||
* A reference to the original type system that produced this type | ||
*/ | ||
readonly typeSystem: TypeSystem<T>; | ||
} | ||
|
||
export interface TypeMember<T> { | ||
name?: string; | ||
literal?: T; | ||
optional: boolean; | ||
type: Type<T>; | ||
} | ||
|
||
export interface MemberCollection<T> extends Iterable<TypeMember<T>> { | ||
push(...member: TypeMember<T>[]): Disposable; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { MemberCollection, Type, TypeMember } from "./base"; | ||
import { TypeParameter } from "./type-parameter"; | ||
|
||
export interface FunctionType<T> extends Type<T> { | ||
readonly name?: string; | ||
readonly members: MemberCollection<T>; | ||
readonly typeParameters: TypeParameter<T>[]; | ||
readonly typeArguments: Type<T>[]; | ||
applyTypeArguments(args: Type<T>[]): FunctionType<T>; | ||
readonly parameters: FunctionParameter<T>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I am lost: What are members in contrast to parameters? (What about |
||
readonly returnType: Type<T>[]; | ||
} | ||
|
||
export interface FunctionTypeOptions<T> { | ||
name?: string; | ||
literal?: T; | ||
members?: TypeMember<T>[]; | ||
typeParameters?: TypeParameter<T>[]; | ||
parameters?: FunctionParameter<T>[]; | ||
returnType?: Type<T>[]; | ||
} | ||
|
||
export interface FunctionParameter<T> { | ||
readonly name?: string | ||
readonly literal?: T; | ||
readonly type: Type<T>; | ||
readonly optional: boolean; | ||
readonly spread: boolean; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Type } from "./base"; | ||
|
||
export interface Indexer<T> extends Type<T> { | ||
readonly: boolean; | ||
writeonly: boolean; | ||
parameters: IndexerParameter<T>[]; | ||
} | ||
|
||
export interface IndexerParameter<T> { | ||
readonly name?: string | ||
readonly literal?: T; | ||
readonly type: Type<T>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { PrimitiveType } from "./primitive"; | ||
|
||
export const Primitive = Symbol('Primitive'); | ||
|
||
export function isPrimitiveType<T>(type: unknown): type is PrimitiveType<T> { | ||
return isType(type, Primitive); | ||
} | ||
|
||
function isType(type: unknown, symbol: symbol): boolean { | ||
if (typeof type !== 'object' || !type) { | ||
return false; | ||
} | ||
const value = type as { '_type': symbol }; | ||
return value._type === symbol; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { AssignabilityCallback } from "./assignablity"; | ||
import { MemberCollection, Type, TypeMember } from "./base"; | ||
import { Disposable } from "./utils"; | ||
|
||
export interface PrimitiveType<T> extends Type<T> { | ||
readonly name: string | ||
readonly members: MemberCollection<T>; | ||
constant(options: PrimitiveTypeConstantOptions<T>): PrimitiveTypeConstant<T> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In which scenario do we need constants for primitives? Why don't we have constants/instances for types of other kinds like functions? |
||
assignable(to: PrimitiveType<T>): Disposable; | ||
assignable(callback: AssignabilityCallback<PrimitiveType<T>>): Disposable; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't we have |
||
} | ||
|
||
export interface PrimitiveTypeConstant<T> extends Type<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did I understand correctly, that PrimitiveTypeConstant is an instance/element of the set defined by a PrimitiveType? |
||
type: PrimitiveType<T> | ||
value: unknown; | ||
} | ||
|
||
export interface PrimitiveTypeConstantOptions<T> { | ||
value: unknown; | ||
literal?: T; | ||
} | ||
|
||
export type PrimitiveTypeOptions<T> = string | { | ||
name: string | ||
members: TypeMember<T>[] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Type } from "./base"; | ||
|
||
export interface TupleType<T> extends Type<T> { | ||
types: Type<T>[]; | ||
/** | ||
* Indicates that the last type in this tuple is spread. | ||
*/ | ||
spread: boolean; | ||
} | ||
|
||
export interface TupleTypeOptions<T> { | ||
literal?: T; | ||
types: Type<T>[]; | ||
spread?: boolean; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { AssignabilityCallback } from "./assignablity"; | ||
import { MemberCollection, Type, TypeMember } from "./base"; | ||
import { TypeParameter } from "./type-parameter"; | ||
import type { TypeSystem } from "./type-system"; | ||
import { Disposable } from "./utils"; | ||
|
||
export interface TypeCategory<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is a type category? Could you add some comments? |
||
readonly name: string; | ||
readonly typeSystem: TypeSystem<T>; | ||
create(options: TypeCategoryInstanceOptions<T>): TypeCategoryInstance<T>; | ||
assignable(to: TypeCategory<T>, callback: AssignabilityCallback<TypeCategoryInstance<T>>): Disposable; | ||
castable(to: TypeCategory<T>, callback: AssignabilityCallback<TypeCategoryInstance<T>>): Disposable; | ||
} | ||
|
||
export interface TypeCategoryInstance<T> extends Type<T>, Disposable { | ||
readonly name?: string; | ||
readonly category: TypeCategory<T>; | ||
readonly members: MemberCollection<T>; | ||
readonly super: TypeCategoryInstance<T>[]; | ||
readonly typeParameters: TypeParameter<T>[]; | ||
readonly typeArguments: Type<T>[]; | ||
applyTypeArguments(args: Type<T>[]): TypeCategoryInstance<T>; | ||
assignable(callback: AssignabilityCallback<Type<T>>): Disposable; | ||
castable(callback: AssignabilityCallback<Type<T>>): Disposable; | ||
} | ||
|
||
export interface TypeCategoryOptions { | ||
name: string | ||
} | ||
|
||
export interface TypeCategoryInstanceOptions<T> { | ||
name?: string | ||
literal?: T | ||
parameters?: TypeParameter<T>[]; | ||
members?: TypeMember<T>[]; | ||
typeParameters: TypeParameter<T>[]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Type } from "./base"; | ||
import { TypeParameter } from "./type-parameter"; | ||
|
||
export interface TypeFunction<T> extends Type<T> { | ||
readonly name: string; | ||
readonly parameters: TypeParameter<T>[]; | ||
readonly type: Type<T>; | ||
applyArguments(args: Type<T>[]): Type<T>; | ||
} | ||
|
||
export interface TypeFunctionOptions<T> { | ||
readonly name: string; | ||
readonly literal?: T; | ||
readonly parameters?: TypeParameter<T>[]; | ||
readonly type: Type<T>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Type } from "./base"; | ||
|
||
export interface TypeIntersection<T> extends Type<T> { | ||
types: Type<T>[]; | ||
} | ||
|
||
export interface TypeIntersectionOptions<T> { | ||
literal?: T; | ||
types: Type<T>[]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is
T
and theliteral
? WouldAstNode
be a value forT
in the context of Langium? If a type likestring
is the type for multiple literals, do I have multiple Type instances representingstring
, one for each literal?