Skip to content

Commit

Permalink
feat: json encoded annotations
Browse files Browse the repository at this point in the history
feat: support companion extensions on interface and type

fix: overly permissive isCompanionReference

fix: call extensions

feat: import json extension definitions from package.json
  • Loading branch information
0x706b committed Oct 24, 2022
1 parent 6bc9bb8 commit 2137cb0
Show file tree
Hide file tree
Showing 16 changed files with 420 additions and 89 deletions.
20 changes: 20 additions & 0 deletions effect/packages/package1/src/companions-everywhere.ts
@@ -0,0 +1,20 @@
/**
* @tsplus type companions-everwhere/A
* @tsplus companion companions-everywhere/AOps
*/
export type A = {}

/**
* @tsplus static companions-everywhere/AOps get
*/
export const get: A = {}

/**
* @tsplus static companions-everywhere/AOps __call
*/
export const callA = (): A => ({})

class X {}

new X()
X
51 changes: 51 additions & 0 deletions effect/packages/package2/fp-ts__core.json
@@ -0,0 +1,51 @@
{
"@fp-ts/core/Async": [
{
"definitionName": "Async",
"definitionKind": "interface",
"extensions": [
{
"kind": "type",
"typeName": "fp-ts/Async"
},
{
"kind": "companion",
"typeName": "fp-ts/AsyncOps"
}
]
},
{
"definitionName": "fromSync",
"definitionKind": "const",
"extensions": [
{
"kind": "static",
"typeName": "fp-ts/AsyncOps",
"name": "fromSync"
}
]
},
{
"definitionName": "delay",
"definitionKind": "const",
"extensions": [
{
"kind": "pipeable",
"typeName": "fp-ts/Async",
"name": "delay"
}
]
},
{
"definitionName": "map",
"definitionKind": "const",
"extensions": [
{
"kind": "pipeable",
"typeName": "fp-ts/Async",
"name": "map"
}
]
}
]
}
1 change: 1 addition & 0 deletions effect/packages/package2/package.json
Expand Up @@ -5,6 +5,7 @@
"build:esm": "node ../../../built/local/tsc.js -p ./tsconfig.json"
},
"dependencies": {
"@fp-ts/core": "0.0.2",
"@tsplus-test/package1": "*"
}
}
4 changes: 4 additions & 0 deletions effect/packages/package2/src/external-definitions.ts
@@ -0,0 +1,4 @@
import { Async } from '@fp-ts/core/Async'

Async.fromSync(() => console.log("Fluent in fp-ts!")).delay(1)

2 changes: 1 addition & 1 deletion effect/packages/package2/src/globals2.ts
@@ -1,3 +1,3 @@
Effect.succeed(() => 1)

Maybe.just("A")
Maybe.just("A")
3 changes: 2 additions & 1 deletion effect/packages/package2/src/prelude.ts
Expand Up @@ -6,4 +6,5 @@ import { Effect, T, chain, chainPipeable } from "@tsplus-test/package1/prelude"
/**
* @tsplus global
*/
import { Maybe, Just } from "@tsplus-test/package1/prelude/definition/Maybe"
import { Maybe, Just } from "@tsplus-test/package1/prelude/definition/Maybe"

5 changes: 4 additions & 1 deletion effect/packages/package2/tsconfig.json
Expand Up @@ -6,7 +6,10 @@
"declarationDir": "build/dts",
"tsPlusConfig": "../../tsplus.config.json",
"noUnusedLocals": true,
"noUnusedParameters": true
"noUnusedParameters": true,
"tsPlusTypes": [
"./fp-ts__core.json"
]
},
"include": ["src/**/*.ts"]
}
142 changes: 96 additions & 46 deletions src/compiler/checker.ts
Expand Up @@ -826,7 +826,7 @@ namespace ts {
getIndexAccessExpressionCache: () => indexAccessExpressionCache,
isTsPlusMacroCall,
isTsPlusMacroGetter,
isClassCompanionReference,
isCompanionReference,
collectTsPlusFluentTags,
hasExportedPlusTags: (declaration) => {
return collectTsPlusFluentTags(declaration).length > 0 ||
Expand Down Expand Up @@ -1196,7 +1196,7 @@ namespace ts {
const copy: ESMap<string, Symbol> = new Map();
const copyFluent: ESMap<string, Set<TsPlusFluentExtension>> = new Map();
symbols.forEach((target) => {
if (typeSymbolCache.has(target) && !isClassCompanionReference(selfNode)) {
if (typeSymbolCache.has(target) && !isCompanionReference(selfNode)) {
typeSymbolCache.get(target)!.forEach((typeSymbol) => {
const _static = staticCache.get(typeSymbol);
if (_static) {
Expand Down Expand Up @@ -1238,7 +1238,7 @@ namespace ts {
}
});
}
if (companionSymbolCache.has(target) && isClassCompanionReference(selfNode)) {
if (companionSymbolCache.has(target) && isCompanionReference(selfNode)) {
companionSymbolCache.get(target)!.forEach((typeSymbol) => {
const _static = staticCache.get(typeSymbol);
if (_static) {
Expand Down Expand Up @@ -2783,6 +2783,31 @@ namespace ts {
result = undefined;
}
}
// TSPLUS EXTENSION START
else {
if (originalLocation && originalLocation.parent && (isPropertyAccessExpression(originalLocation.parent) || isCallExpression(originalLocation.parent))) {
const symbol = location.locals.get(name)
if (symbol) {
if (companionSymbolCache.has(symbol)) {
result = symbol;
break loop;
}
if (symbol.exportSymbol && companionSymbolCache.has(symbol.exportSymbol)) {
result = symbol.exportSymbol;
break loop;
}
if (symbol.declarations && symbol.declarations[0] && isImportSpecifier(symbol.declarations[0])) {
const originalSymbol = getTargetOfImportSpecifier(symbol.declarations[0], false);
if (originalSymbol && companionSymbolCache.has(originalSymbol)) {
result = originalSymbol;
symbol.isReferenced = SymbolFlags.Value;
break loop;
}
}
}
}
}
// TSPLUS EXTENSION END
}
withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation);
switch (location.kind) {
Expand Down Expand Up @@ -3030,7 +3055,10 @@ namespace ts {
const globalImport = tsPlusGlobalImportCache.get(name as string);
if (globalImport) {
const targetSymbol = getTargetOfImportSpecifier(globalImport.importSpecifier, false);
if (targetSymbol && targetSymbol.flags & meaning) {
if (targetSymbol &&
((targetSymbol.flags & meaning) ||
companionSymbolCache.has(targetSymbol) && (isPropertyAccessExpression(originalLocation.parent) || isCallExpression(originalLocation.parent)))
) {
const withoutGlobals = resolveNameHelper(
originalLocation,
name,
Expand Down Expand Up @@ -5795,7 +5823,7 @@ namespace ts {
}

// TSPLUS EXTENSION START
function isClassCompanionReference(node: Expression | QualifiedName): boolean {
function isCompanionReference(node: Expression | QualifiedName): boolean {
let type: Type | undefined

const symbol = getSymbolAtLocation(node);
Expand All @@ -5809,8 +5837,8 @@ namespace ts {
if (!type) {
return false
}

return !!(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class);
return !!(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class)
|| (!!symbol?.declarations?.[0] && (isInterfaceDeclaration(symbol.declarations[0]) || isTypeAliasDeclaration(symbol.declarations[0])))
}
// TSPLUS EXTENSION END

Expand Down Expand Up @@ -11023,6 +11051,13 @@ namespace ts {
if (symbol.flags & SymbolFlags.Alias) {
return getTypeOfAlias(symbol);
}
if ((symbol.flags & SymbolFlags.Interface) || (symbol.flags & SymbolFlags.TypeAlias)) {
if (companionSymbolCache.has(symbol)) {
if (symbol.declarations?.[0]) {
return getTypeOfNode(symbol.declarations[0])
}
}
}
return errorType;
}

Expand Down Expand Up @@ -30605,14 +30640,13 @@ namespace ts {
if (nodeLinks.tsPlusResolvedType) {
return nodeLinks.tsPlusResolvedType;
}
if (isClassCompanionReference(_left)) {
const staticExt = getStaticCompanionExtension(leftType, right.escapedText.toString());
if (staticExt) {
nodeLinks.tsPlusStaticExtension = staticExt;
nodeLinks.tsPlusResolvedType = staticExt.type
return staticExt.type;
if (isCompanionReference(_left)) {
const companionExt = getStaticCompanionExtension(leftType, right.escapedText.toString());
if (companionExt) {
nodeLinks.tsPlusStaticExtension = companionExt;
nodeLinks.tsPlusResolvedType = companionExt.type
return companionExt.type;
}
return;
}
const fluentExtType = getFluentExtension(leftType, right.escapedText.toString());
if (fluentExtType && isCallExpression(node.parent) && node.parent.expression === node) {
Expand Down Expand Up @@ -32881,37 +32915,32 @@ namespace ts {

// TSPLUS EXTENSION START
if (callSignatures.length === 0) {
if (isClassCompanionReference(node.expression)) {
const callExtension = getStaticCompanionExtension(apparentType, "__call");

if (callExtension) {
callSignatures = Array.from(getSignaturesOfType(getTypeOfSymbol(callExtension.patched), SignatureKind.Call));
callCache.set(node.expression, callExtension);
getNodeLinks(node).tsPlusCallExtension = callExtension;
}
let callExtension: TsPlusStaticFunctionExtension | undefined
if (isCompanionReference(node.expression)) {
callExtension = getStaticCompanionExtension(apparentType, "__call");
}
if (!callExtension) {
callExtension = getStaticExtension(apparentType, "__call");
}
if (callExtension) {
callSignatures = Array.from(getSignaturesOfType(getTypeOfSymbol(callExtension.patched), SignatureKind.Call));
callCache.set(node.expression, callExtension);
getNodeLinks(node).tsPlusCallExtension = callExtension;
}
else {
const callExtension = getStaticExtension(apparentType, "__call");

if (callExtension) {
callSignatures = Array.from(getSignaturesOfType(getTypeOfSymbol(callExtension.patched), SignatureKind.Call));
callCache.set(node.expression, callExtension);
getNodeLinks(node).tsPlusCallExtension = callExtension;
} else {
const callFluentExtensions = getFluentExtension(apparentType, "__call");
if (callFluentExtensions) {
callSignatures = Array.from(getSignaturesOfType(callFluentExtensions, SignatureKind.Call).map((s) => {
const sig = createTsPlusSignature(
(s as TsPlusSignature).tsPlusOriginal,
(s as TsPlusSignature).tsPlusExportName,
(s as TsPlusSignature).tsPlusFile
);
sig.tsPlusDeclaration = (s as TsPlusSignature).tsPlusDeclaration;
sig.tsPlusPipeable = (s as TsPlusSignature).tsPlusPipeable;
return sig;
}));
getNodeLinks(node).isFluentCall = true;
}
const callFluentExtensions = getFluentExtension(apparentType, "__call");
if (callFluentExtensions) {
callSignatures = Array.from(getSignaturesOfType(callFluentExtensions, SignatureKind.Call).map((s) => {
const sig = createTsPlusSignature(
(s as TsPlusSignature).tsPlusOriginal,
(s as TsPlusSignature).tsPlusExportName,
(s as TsPlusSignature).tsPlusFile
);
sig.tsPlusDeclaration = (s as TsPlusSignature).tsPlusDeclaration;
sig.tsPlusPipeable = (s as TsPlusSignature).tsPlusPipeable;
return sig;
}));
getNodeLinks(node).isFluentCall = true;
}
}
}
Expand Down Expand Up @@ -45185,6 +45214,21 @@ namespace ts {
symbols.set(id, symbol);
}
}
if (companionSymbolCache.has(symbol)) {
const id = symbol.escapedName;
if (!symbols.has(id)) {
symbols.set(id, symbol);
}
}
if (symbol.declarations && symbol.declarations[0] && isImportSpecifier(symbol.declarations[0])) {
const originalSymbol = getTargetOfImportSpecifier(symbol.declarations[0], false);
if (originalSymbol && companionSymbolCache.has(originalSymbol)) {
const id = symbol.escapedName;
if (!symbols.has(id)) {
symbols.set(id, symbol);
}
}
}
}

function copySymbols(source: SymbolTable, meaning: SymbolFlags): void {
Expand Down Expand Up @@ -46764,7 +46808,7 @@ namespace ts {
return [];
}
function collectTsPlusCompanionTags(declaration: Declaration) {
if (isClassDeclaration(declaration)) {
if (isClassDeclaration(declaration) || isInterfaceDeclaration(declaration) || isTypeAliasDeclaration(declaration)) {
return declaration.tsPlusCompanionTags || [];
}
return [];
Expand Down Expand Up @@ -47368,15 +47412,21 @@ namespace ts {
function getTsPlusSourceFileCache(tag: string) {
return tsPlusFiles.has(tag) ? tsPlusFiles.get(tag)! : (tsPlusFiles.set(tag, new Set()), tsPlusFiles.get(tag)!);
}
function cacheTsPlusCompanion(declaration: ClassDeclaration): void {
const type = getTypeOfNode(declaration);
function cacheTsPlusCompanion(declaration: ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration): void {
const tags = collectTsPlusCompanionTags(declaration);
const type = getTypeOfNode(declaration)
if (type.symbol) {
for (const companionTag of tags) {
getTsPlusSourceFileCache(companionTag).add(getSourceFileOfNode(declaration));
addToCompanionSymbolCache(type.symbol, companionTag);
}
}
if (type.aliasSymbol) {
for (const companionTag of tags) {
getTsPlusSourceFileCache(companionTag).add(getSourceFileOfNode(declaration));
addToCompanionSymbolCache(type.aliasSymbol, companionTag);
}
}
}
function cacheTsPlusStaticVariable(file: SourceFile, declaration: VariableDeclarationWithIdentifier | ClassDeclarationWithIdentifier) {
const staticTags = collectTsPlusStaticTags(declaration);
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/commandLineParser.ts
Expand Up @@ -208,7 +208,15 @@ namespace ts {
},
{
name: "tsPlusConfig",
type: "string"
type: "string",
},
{
name: "tsPlusTypes",
type: "list",
element: {
name: "tsPlusTypes",
type: "string"
},
},
{
name: "transformers",
Expand Down

0 comments on commit 2137cb0

Please sign in to comment.