Skip to content

Commit

Permalink
feat: process assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
skarab42 committed Jul 10, 2022
1 parent 7618b52 commit a7af573
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 26 deletions.
4 changes: 4 additions & 0 deletions src/plugin/assert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as tsd from './tsd';
import * as tssert from './tssert';

export const assert = new Map(Object.entries({ tsd, tssert }));
36 changes: 36 additions & 0 deletions src/plugin/assert/tsd/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type ts from 'byots';
import type { Assertion } from '../../types';
import type { Compiler } from '../../../typescript/types';
import { createAssertionDiagnostic } from '../../diagnostics';

export function expectType(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectNotType(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectAssignable(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectNotAssignable(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectError(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectDeprecated(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function expectNotDeprecated(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function printType(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}
16 changes: 16 additions & 0 deletions src/plugin/assert/tssert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type ts from 'byots';
import type { Assertion } from '../../types';
import type { Compiler } from '../../../typescript/types';
import { createAssertionDiagnostic } from '../../diagnostics';

export function expectType(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function assignableTo(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}

export function notAssignableTo(assertion: Assertion, compiler: Compiler): ts.Diagnostic | undefined {
return createAssertionDiagnostic('Not yet implemented.', compiler.sourceFile, assertion.node.getStart());
}
11 changes: 11 additions & 0 deletions src/plugin/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,14 @@ throw (() => {
})()
`;
}

export function createAssertionDiagnostic(message: string, file: ts.SourceFile, start: number): ts.Diagnostic {
return {
category: ts.DiagnosticCategory.Error,
code: -42,
file,
start,
length: undefined,
messageText: message,
};
}
39 changes: 25 additions & 14 deletions src/plugin/transform.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import ts from 'byots';
import { assert } from './assert';
import MagicString from 'magic-string';
import type { TransformResult } from 'vite';
import { reportDiagnostics } from './diagnostics';
import type { Compiler } from '../typescript/types';
import { API_PROPERTY_KEY } from '../common/internal';
import { createCompiler } from '../typescript/compiler';
import type { Assertion, TransformSettings } from './types';
import { createError, ErrorCode } from '../common/error';
import type { APIName, Assertion, TransformSettings } from './types';

export function transform({ code, fileName, report, typescript }: TransformSettings): TransformResult {
const compiler = createCompiler({ config: typescript.config, fileName });
Expand Down Expand Up @@ -39,19 +41,15 @@ function getAssertions(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker):
const expressionType = typeChecker.getTypeAtLocation(expression);
const assertionProperty = expressionType.getProperty(API_PROPERTY_KEY);

if (!assertionProperty) {
return;
}

const assertionPropertyType = typeChecker.getTypeOfSymbolAtLocation(assertionProperty, expression);
const assertionPropertyValue = typeChecker.typeToString(assertionPropertyType).slice(1, -1);
const [apiName, functionName] = assertionPropertyValue.split(':');
if (assertionProperty) {
const assertionPropertyType = typeChecker.getTypeOfSymbolAtLocation(assertionProperty, expression);
const assertionPropertyValue = typeChecker.typeToString(assertionPropertyType).slice(1, -1);
const [apiName, functionName] = assertionPropertyValue.split(':');

if (!apiName || !functionName) {
return;
if (apiName && functionName) {
assertions.push({ apiName: apiName as APIName, functionName, node });
}
}

assertions.push({ apiName, functionName, node });
}

node.forEachChild(visit);
Expand All @@ -65,8 +63,21 @@ function getAssertions(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker):
function processAssertions(assertions: Assertion[], compiler: Compiler): ts.Diagnostic[] {
const diagnostics: ts.Diagnostic[] = [];

// eslint-disable-next-line no-console
console.log({ assertions, compiler });
assertions.forEach((assertion) => {
const api = assert.get(assertion.apiName);

if (!api) {
throw createError(ErrorCode.UNEXPECTED_ERROR, {
message: `The ${assertion.apiName} API could not be loaded.`,
});
}

const diagnostic = api[assertion.functionName as keyof typeof api](assertion, compiler);

if (diagnostic) {
diagnostics.push(diagnostic);
}
});

return diagnostics;
}
4 changes: 3 additions & 1 deletion src/plugin/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ export interface ErrorObject {
column: number;
}

export type APIName = 'tsd' | 'tssert';

export interface Assertion {
apiName: string;
apiName: APIName;
functionName: string;
node: ts.Node;
}
12 changes: 8 additions & 4 deletions test/tsd.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
// // expect("life").toBe(42);
// });
// });
import { expectType, expectType as assertType } from '../src/api/tsd';

import { test } from 'vitest';
import * as tsd from '../src/api/tsd';
import { expectType, expectType as assertType } from '../src/api/tsd';

expectType<string>('hello');
assertType<string>('hello');
tsd.expectType<string>('hello');
test('test-1', () => {
expectType<string>('hello');
assertType<string>('hello');
tsd.expectType<string>('hello');
});
17 changes: 10 additions & 7 deletions test/tssert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
// });
// });

import { expectType, expectType as assertType } from '../src/api/tssert';
import { test } from 'vitest';
import * as tssert from '../src/api/tssert';
import { expectType, expectType as assertType } from '../src/api/tssert';

expectType<string>('hello');
assertType<string>('hello');
tssert.expectType<string>('hello');
test('test-1', () => {
expectType<string>('hello');
assertType<string>('hello');
tssert.expectType<string>('hello');

expectType<string>().assignableTo('hello');
expectType<number>().not.assignableTo('hello');
tssert.expectType<number>().not.assignableTo('hello');
expectType<string>().assignableTo('hello');
expectType<number>().not.assignableTo('hello');
tssert.expectType<number>().not.assignableTo('hello');
});

0 comments on commit a7af573

Please sign in to comment.