mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add support for transpiling per-file jsx pragmas (#21218)
* Add support for per-file jsx pragmas * Add error for using jsx factory pragma with fragments * More tests, use different regex class for pragma capture * Unify all pragma parsing machinery
This commit is contained in:
+24
-6
@@ -299,7 +299,7 @@ namespace ts {
|
||||
resolveName(name, location, meaning, excludeGlobals) {
|
||||
return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals);
|
||||
},
|
||||
getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()),
|
||||
getJsxNamespace: n => unescapeLeadingUnderscores(getJsxNamespace(n)),
|
||||
getAccessibleSymbolChain,
|
||||
getTypePredicateOfSignature,
|
||||
resolveExternalModuleSymbol,
|
||||
@@ -765,7 +765,23 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getJsxNamespace(): __String {
|
||||
function getJsxNamespace(location: Node | undefined): __String {
|
||||
if (location) {
|
||||
const file = getSourceFileOfNode(location);
|
||||
if (file) {
|
||||
if (file.localJsxNamespace) {
|
||||
return file.localJsxNamespace;
|
||||
}
|
||||
const jsxPragma = file.pragmas.get("jsx");
|
||||
if (jsxPragma) {
|
||||
const chosenpragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma;
|
||||
file.localJsxFactory = parseIsolatedEntityName(chosenpragma.arguments.factory, languageVersion);
|
||||
if (file.localJsxFactory) {
|
||||
return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_jsxNamespace) {
|
||||
_jsxNamespace = "React" as __String;
|
||||
if (compilerOptions.jsxFactory) {
|
||||
@@ -15082,8 +15098,10 @@ namespace ts {
|
||||
function checkJsxFragment(node: JsxFragment, checkMode: CheckMode): Type {
|
||||
checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment, checkMode);
|
||||
|
||||
if (compilerOptions.jsx === JsxEmit.React && compilerOptions.jsxFactory) {
|
||||
error(node, Diagnostics.JSX_fragment_is_not_supported_when_using_jsxFactory);
|
||||
if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || getSourceFileOfNode(node).pragmas.has("jsx"))) {
|
||||
error(node, compilerOptions.jsxFactory
|
||||
? Diagnostics.JSX_fragment_is_not_supported_when_using_jsxFactory
|
||||
: Diagnostics.JSX_fragment_is_not_supported_when_using_an_inline_JSX_factory_pragma);
|
||||
}
|
||||
|
||||
return getJsxGlobalElementType() || anyType;
|
||||
@@ -15709,7 +15727,7 @@ namespace ts {
|
||||
// The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import.
|
||||
// And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error.
|
||||
const reactRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
|
||||
const reactNamespace = getJsxNamespace();
|
||||
const reactNamespace = getJsxNamespace(node);
|
||||
const reactLocation = isNodeOpeningLikeElement ? (<JsxOpeningLikeElement>node).tagName : node;
|
||||
const reactSym = resolveName(reactLocation, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace, /*isUse*/ true);
|
||||
if (reactSym) {
|
||||
@@ -25556,7 +25574,7 @@ namespace ts {
|
||||
return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late);
|
||||
},
|
||||
writeLiteralConstValue,
|
||||
getJsxFactoryEntity: () => _jsxFactoryEntity
|
||||
getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity
|
||||
};
|
||||
|
||||
// defined here to avoid outer scope pollution
|
||||
|
||||
@@ -3788,6 +3788,10 @@
|
||||
"category": "Error",
|
||||
"code": 17016
|
||||
},
|
||||
"JSX fragment is not supported when using an inline JSX factory pragma": {
|
||||
"category": "Error",
|
||||
"code": 17017
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -2375,6 +2375,9 @@ namespace ts {
|
||||
if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
|
||||
if (node.imports !== undefined) updated.imports = node.imports;
|
||||
if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations;
|
||||
if (node.pragmas !== undefined) updated.pragmas = node.pragmas;
|
||||
if (node.localJsxFactory !== undefined) updated.localJsxFactory = node.localJsxFactory;
|
||||
if (node.localJsxNamespace !== undefined) updated.localJsxNamespace = node.localJsxNamespace;
|
||||
return updateNode(updated, node);
|
||||
}
|
||||
|
||||
|
||||
+228
-89
@@ -769,7 +769,9 @@ namespace ts {
|
||||
|
||||
// Prime the scanner.
|
||||
nextToken();
|
||||
processReferenceComments(sourceFile);
|
||||
// A member of ReadonlyArray<T> isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future
|
||||
processCommentPragmas(sourceFile as {} as PragmaContext, sourceText);
|
||||
processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic);
|
||||
|
||||
sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement);
|
||||
Debug.assert(token() === SyntaxKind.EndOfFileToken);
|
||||
@@ -787,6 +789,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
return sourceFile;
|
||||
|
||||
function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) {
|
||||
parseDiagnostics.push(createFileDiagnostic(sourceFile, pos, end, diagnostic));
|
||||
}
|
||||
}
|
||||
|
||||
function addJSDocComment<T extends HasJSDoc>(node: T): T {
|
||||
@@ -6084,94 +6090,6 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function processReferenceComments(sourceFile: SourceFile): void {
|
||||
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
|
||||
const referencedFiles: FileReference[] = [];
|
||||
const typeReferenceDirectives: FileReference[] = [];
|
||||
const amdDependencies: { path: string; name: string }[] = [];
|
||||
let amdModuleName: string;
|
||||
let checkJsDirective: CheckJsDirective = undefined;
|
||||
|
||||
// Keep scanning all the leading trivia in the file until we get to something that
|
||||
// isn't trivia. Any single line comment will be analyzed to see if it is a
|
||||
// reference comment.
|
||||
while (true) {
|
||||
const kind = triviaScanner.scan();
|
||||
if (kind !== SyntaxKind.SingleLineCommentTrivia) {
|
||||
if (isTrivia(kind)) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const range = {
|
||||
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
|
||||
pos: triviaScanner.getTokenPos(),
|
||||
end: triviaScanner.getTextPos(),
|
||||
};
|
||||
|
||||
const comment = sourceText.substring(range.pos, range.end);
|
||||
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
|
||||
if (referencePathMatchResult) {
|
||||
const fileReference = referencePathMatchResult.fileReference;
|
||||
sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
|
||||
const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
|
||||
if (fileReference) {
|
||||
if (referencePathMatchResult.isTypeReferenceDirective) {
|
||||
typeReferenceDirectives.push(fileReference);
|
||||
}
|
||||
else {
|
||||
referencedFiles.push(fileReference);
|
||||
}
|
||||
}
|
||||
if (diagnosticMessage) {
|
||||
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
|
||||
const amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
|
||||
if (amdModuleNameMatchResult) {
|
||||
if (amdModuleName) {
|
||||
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
|
||||
}
|
||||
amdModuleName = amdModuleNameMatchResult[2];
|
||||
}
|
||||
|
||||
const amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
|
||||
const pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
|
||||
const nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
|
||||
const amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
|
||||
if (amdDependencyMatchResult) {
|
||||
const pathMatchResult = pathRegex.exec(comment);
|
||||
const nameMatchResult = nameRegex.exec(comment);
|
||||
if (pathMatchResult) {
|
||||
const amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
|
||||
amdDependencies.push(amdDependency);
|
||||
}
|
||||
}
|
||||
|
||||
const checkJsDirectiveRegEx = /^\/\/\/?\s*(@ts-check|@ts-nocheck)\s*$/gim;
|
||||
const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment);
|
||||
if (checkJsDirectiveMatchResult) {
|
||||
checkJsDirective = {
|
||||
enabled: equateStringsCaseInsensitive(checkJsDirectiveMatchResult[1], "@ts-check"),
|
||||
end: range.end,
|
||||
pos: range.pos
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceFile.referencedFiles = referencedFiles;
|
||||
sourceFile.typeReferenceDirectives = typeReferenceDirectives;
|
||||
sourceFile.amdDependencies = amdDependencies;
|
||||
sourceFile.moduleName = amdModuleName;
|
||||
sourceFile.checkJsDirective = checkJsDirective;
|
||||
}
|
||||
|
||||
function setExternalModuleIndicator(sourceFile: SourceFile) {
|
||||
sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
|
||||
hasModifier(node, ModifierFlags.Export)
|
||||
@@ -7552,4 +7470,225 @@ namespace ts {
|
||||
function isDeclarationFileName(fileName: string): boolean {
|
||||
return fileExtensionIs(fileName, Extension.Dts);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface PragmaContext {
|
||||
languageVersion: ScriptTarget;
|
||||
pragmas?: PragmaMap;
|
||||
checkJsDirective?: CheckJsDirective;
|
||||
referencedFiles: FileReference[];
|
||||
typeReferenceDirectives: FileReference[];
|
||||
amdDependencies: AmdDependency[];
|
||||
hasNoDefaultLib?: boolean;
|
||||
moduleName?: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
|
||||
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
|
||||
const pragmas: PragmaPsuedoMapEntry[] = [];
|
||||
|
||||
// Keep scanning all the leading trivia in the file until we get to something that
|
||||
// isn't trivia. Any single line comment will be analyzed to see if it is a
|
||||
// reference comment.
|
||||
while (true) {
|
||||
const kind = triviaScanner.scan();
|
||||
if (!isTrivia(kind)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const range = {
|
||||
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
|
||||
pos: triviaScanner.getTokenPos(),
|
||||
end: triviaScanner.getTextPos(),
|
||||
};
|
||||
|
||||
const comment = sourceText.substring(range.pos, range.end);
|
||||
extractPragmas(pragmas, range, comment);
|
||||
}
|
||||
|
||||
context.pragmas = createMap() as PragmaMap;
|
||||
for (const pragma of pragmas) {
|
||||
if (context.pragmas.has(pragma.name)) {
|
||||
const currentValue = context.pragmas.get(pragma.name);
|
||||
if (currentValue instanceof Array) {
|
||||
currentValue.push(pragma.args);
|
||||
}
|
||||
else {
|
||||
context.pragmas.set(pragma.name, [currentValue, pragma.args]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
context.pragmas.set(pragma.name, pragma.args);
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
|
||||
|
||||
/*@internal*/
|
||||
export function processPragmasIntoFields(context: PragmaContext, reportDiagnostic: PragmaDiagnosticReporter): void {
|
||||
context.checkJsDirective = undefined;
|
||||
context.referencedFiles = [];
|
||||
context.typeReferenceDirectives = [];
|
||||
context.amdDependencies = [];
|
||||
context.hasNoDefaultLib = false;
|
||||
context.pragmas.forEach((entryOrList, key) => {
|
||||
// TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to
|
||||
// key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :(
|
||||
switch (key) {
|
||||
case "reference": {
|
||||
const referencedFiles = context.referencedFiles;
|
||||
const typeReferenceDirectives = context.typeReferenceDirectives;
|
||||
forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => {
|
||||
if (arg.arguments["no-default-lib"]) {
|
||||
context.hasNoDefaultLib = true;
|
||||
}
|
||||
else if (arg.arguments.types) {
|
||||
typeReferenceDirectives.push({ pos: arg.arguments.types.pos, end: arg.arguments.types.end, fileName: arg.arguments.types.value });
|
||||
}
|
||||
else if (arg.arguments.path) {
|
||||
referencedFiles.push({ pos: arg.arguments.path.pos, end: arg.arguments.path.end, fileName: arg.arguments.path.value });
|
||||
}
|
||||
else {
|
||||
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "amd-dependency": {
|
||||
context.amdDependencies = map(
|
||||
toArray(entryOrList),
|
||||
({ arguments: { name, path } }: PragmaPsuedoMap["amd-dependency"]) => ({ name, path })
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "amd-module": {
|
||||
if (entryOrList instanceof Array) {
|
||||
for (const entry of entryOrList) {
|
||||
if (context.moduleName) {
|
||||
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
|
||||
reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
|
||||
}
|
||||
context.moduleName = (entry as PragmaPsuedoMap["amd-module"]).arguments.name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"]).arguments.name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ts-nocheck":
|
||||
case "ts-check": {
|
||||
// _last_ of either nocheck or check in a file is the "winner"
|
||||
forEach(toArray(entryOrList), entry => {
|
||||
if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
|
||||
context.checkJsDirective = {
|
||||
enabled: key === "ts-check",
|
||||
end: entry.range.end,
|
||||
pos: entry.range.pos
|
||||
};
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "jsx": return; // Accessed directly
|
||||
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const namedArgRegExCache = createMap<RegExp>();
|
||||
function getNamedArgRegEx(name: string) {
|
||||
if (namedArgRegExCache.has(name)) {
|
||||
return namedArgRegExCache.get(name);
|
||||
}
|
||||
const result = new RegExp(`(\\s${name}\\s*=\\s*)('|")(.+?)\\2`, "im");
|
||||
namedArgRegExCache.set(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
|
||||
const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
|
||||
function extractPragmas(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, text: string) {
|
||||
const tripleSlash = tripleSlashXMLCommentStartRegEx.exec(text);
|
||||
if (tripleSlash) {
|
||||
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
|
||||
const pragma = commentPragmas[name] as PragmaDefinition;
|
||||
if (!pragma || !(pragma.kind & PragmaKindFlags.TripleSlashXML)) {
|
||||
return;
|
||||
}
|
||||
if (pragma.args) {
|
||||
const argument: {[index: string]: string | {value: string, pos: number, end: number}} = {};
|
||||
for (const arg of pragma.args) {
|
||||
const matcher = getNamedArgRegEx(arg.name);
|
||||
const matchResult = matcher.exec(text);
|
||||
if (!matchResult && !arg.optional) {
|
||||
return; // Missing required argument, don't parse
|
||||
}
|
||||
else if (matchResult) {
|
||||
if (arg.captureSpan) {
|
||||
const startPos = range.pos + matchResult.index + matchResult[1].length + matchResult[2].length;
|
||||
argument[arg.name] = {
|
||||
value: matchResult[3],
|
||||
pos: startPos,
|
||||
end: startPos + matchResult[3].length
|
||||
};
|
||||
}
|
||||
else {
|
||||
argument[arg.name] = matchResult[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
|
||||
}
|
||||
else {
|
||||
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPsuedoMapEntry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const singleLine = singleLinePragmaRegEx.exec(text);
|
||||
if (singleLine) {
|
||||
return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
|
||||
}
|
||||
|
||||
const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
|
||||
let multiLineMatch: RegExpExecArray;
|
||||
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
|
||||
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
|
||||
}
|
||||
}
|
||||
|
||||
function addPragmaForMatch(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
|
||||
if (!match) return;
|
||||
const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
|
||||
const pragma = commentPragmas[name] as PragmaDefinition;
|
||||
if (!pragma || !(pragma.kind & kind)) {
|
||||
return;
|
||||
}
|
||||
const args = match[2]; // Split on spaces and match up positionally with definition
|
||||
const argument = getNamedPragmaArguments(pragma, args);
|
||||
if (argument === "fail") return; // Missing required argument, fail to parse it
|
||||
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" {
|
||||
if (!text) return {};
|
||||
if (!pragma.args) return {};
|
||||
const args = text.split(/\s+/);
|
||||
const argMap: {[index: string]: string} = {};
|
||||
for (let i = 0; i < pragma.args.length; i++) {
|
||||
const argument = pragma.args[i];
|
||||
if (!args[i] && !argument.optional) {
|
||||
return "fail";
|
||||
}
|
||||
if (argument.captureSpan) {
|
||||
return Debug.fail("Capture spans not yet implemented for non-xml pragmas");
|
||||
}
|
||||
argMap[argument.name] = args[i];
|
||||
}
|
||||
return argMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const element = createExpressionForJsxElement(
|
||||
context.getEmitResolver().getJsxFactoryEntity(),
|
||||
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
|
||||
compilerOptions.reactNamespace,
|
||||
tagName,
|
||||
objectProperties,
|
||||
@@ -140,7 +140,7 @@ namespace ts {
|
||||
|
||||
function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
|
||||
const element = createExpressionForJsxFragment(
|
||||
context.getEmitResolver().getJsxFactoryEntity(),
|
||||
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
|
||||
compilerOptions.reactNamespace,
|
||||
mapDefined(children, transformJsxChildToExpression),
|
||||
node,
|
||||
|
||||
+128
-2
@@ -2568,6 +2568,9 @@ namespace ts {
|
||||
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
|
||||
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
|
||||
/* @internal */ version: string;
|
||||
/* @internal */ pragmas: PragmaMap;
|
||||
/* @internal */ localJsxNamespace?: __String;
|
||||
/* @internal */ localJsxFactory?: EntityName;
|
||||
}
|
||||
|
||||
export interface Bundle extends Node {
|
||||
@@ -2934,7 +2937,7 @@ namespace ts {
|
||||
/* @internal */ isArrayLikeType(type: Type): boolean;
|
||||
/* @internal */ getAllPossiblePropertiesOfTypes(type: ReadonlyArray<Type>): Symbol[];
|
||||
/* @internal */ resolveName(name: string, location: Node, meaning: SymbolFlags, excludeGlobals: boolean): Symbol | undefined;
|
||||
/* @internal */ getJsxNamespace(): string;
|
||||
/* @internal */ getJsxNamespace(location?: Node): string;
|
||||
|
||||
/**
|
||||
* Note that this will return undefined in the following case:
|
||||
@@ -3208,7 +3211,7 @@ namespace ts {
|
||||
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
|
||||
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
|
||||
writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter): void;
|
||||
getJsxFactoryEntity(): EntityName;
|
||||
getJsxFactoryEntity(location?: Node): EntityName;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
@@ -5127,4 +5130,127 @@ namespace ts {
|
||||
Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,
|
||||
IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets,
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum PragmaKindFlags {
|
||||
None = 0,
|
||||
/**
|
||||
* Triple slash comment of the form
|
||||
* /// <pragma-name argname="value" />
|
||||
*/
|
||||
TripleSlashXML = 1 << 0,
|
||||
/**
|
||||
* Single line comment of the form
|
||||
* // @pragma-name argval1 argval2
|
||||
* or
|
||||
* /// @pragma-name argval1 argval2
|
||||
*/
|
||||
SingleLine = 1 << 1,
|
||||
/**
|
||||
* Multiline non-jsdoc pragma of the form
|
||||
* /* @pragma-name argval1 argval2 * /
|
||||
*/
|
||||
MultiLine = 1 << 2,
|
||||
All = TripleSlashXML | SingleLine | MultiLine,
|
||||
Default = All,
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
interface PragmaArgumentSpecification<TName extends string> {
|
||||
name: TName; // Determines the name of the key in the resulting parsed type, type parameter to cause literal type inference
|
||||
optional?: boolean;
|
||||
captureSpan?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface PragmaDefinition<T1 extends string = string, T2 extends string = string, T3 extends string = string> {
|
||||
args?: [PragmaArgumentSpecification<T1>] | [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>] | [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>];
|
||||
// If not present, defaults to PragmaKindFlags.Default
|
||||
kind?: PragmaKindFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function only exists to cause exact types to be inferred for all the literals within `commentPragmas`
|
||||
*/
|
||||
/* @internal */
|
||||
function _contextuallyTypePragmas<T extends {[name: string]: PragmaDefinition<K1, K2, K3>}, K1 extends string, K2 extends string, K3 extends string>(args: T): T {
|
||||
return args;
|
||||
}
|
||||
|
||||
// While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't
|
||||
// fancy effectively defining it twice, once in value-space and once in type-space
|
||||
/* @internal */
|
||||
export const commentPragmas = _contextuallyTypePragmas({
|
||||
"reference": {
|
||||
args: [
|
||||
{ name: "types", optional: true, captureSpan: true },
|
||||
{ name: "path", optional: true, captureSpan: true },
|
||||
{ name: "no-default-lib", optional: true }
|
||||
],
|
||||
kind: PragmaKindFlags.TripleSlashXML
|
||||
},
|
||||
"amd-dependency": {
|
||||
args: [{ name: "path" }, { name: "name", optional: true }],
|
||||
kind: PragmaKindFlags.TripleSlashXML
|
||||
},
|
||||
"amd-module": {
|
||||
args: [{ name: "name" }],
|
||||
kind: PragmaKindFlags.TripleSlashXML
|
||||
},
|
||||
"ts-check": {
|
||||
kind: PragmaKindFlags.SingleLine
|
||||
},
|
||||
"ts-nocheck": {
|
||||
kind: PragmaKindFlags.SingleLine
|
||||
},
|
||||
"jsx": {
|
||||
args: [{ name: "factory" }],
|
||||
kind: PragmaKindFlags.MultiLine
|
||||
},
|
||||
});
|
||||
|
||||
/* @internal */
|
||||
type PragmaArgTypeMaybeCapture<TDesc> = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string;
|
||||
|
||||
/* @internal */
|
||||
type PragmaArgTypeOptional<TDesc, TName extends string> =
|
||||
TDesc extends {optional: true}
|
||||
? {[K in TName]?: PragmaArgTypeMaybeCapture<TDesc>}
|
||||
: {[K in TName]: PragmaArgTypeMaybeCapture<TDesc>};
|
||||
|
||||
/**
|
||||
* Maps a pragma definition into the desired shape for its arguments object
|
||||
* Maybe the below is a good argument for types being iterable on struture in some way.
|
||||
*/
|
||||
/* @internal */
|
||||
type PragmaArgumentType<T extends PragmaDefinition> =
|
||||
T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3>
|
||||
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2>
|
||||
: T extends { args: [PragmaArgumentSpecification<infer TName>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName>
|
||||
: object;
|
||||
// The above fallback to `object` when there's no args to allow `{}` (as intended), but not the number 2, for example
|
||||
// TODO: Swap to `undefined` for a cleaner API once strictNullChecks is enabled
|
||||
|
||||
type ConcretePragmaSpecs = typeof commentPragmas;
|
||||
|
||||
/* @internal */
|
||||
export type PragmaPsuedoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
|
||||
|
||||
/* @internal */
|
||||
export type PragmaPsuedoMapEntry = {[K in keyof PragmaPsuedoMap]: {name: K, args: PragmaPsuedoMap[K]}}[keyof PragmaPsuedoMap];
|
||||
|
||||
/**
|
||||
* A strongly-typed es6 map of pragma entries, the values of which are either a single argument
|
||||
* value (if only one was found), or an array of multiple argument values if the pragma is present
|
||||
* in multiple places
|
||||
*/
|
||||
/* @internal */
|
||||
export interface PragmaMap extends Map<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]> {
|
||||
set<TKey extends keyof PragmaPsuedoMap>(key: TKey, value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]): this;
|
||||
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
|
||||
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1989,40 +1989,6 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
|
||||
const simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
|
||||
const isNoDefaultLibRegEx = new RegExp(defaultLibReferenceRegEx.source, "gim");
|
||||
if (simpleReferenceRegEx.test(comment)) {
|
||||
if (isNoDefaultLibRegEx.test(comment)) {
|
||||
return { isNoDefaultLib: true };
|
||||
}
|
||||
else {
|
||||
const refMatchResult = fullTripleSlashReferencePathRegEx.exec(comment);
|
||||
const refLibResult = !refMatchResult && fullTripleSlashReferenceTypeReferenceDirectiveRegEx.exec(comment);
|
||||
const match = refMatchResult || refLibResult;
|
||||
if (match) {
|
||||
const pos = commentRange.pos + match[1].length + match[2].length;
|
||||
return {
|
||||
fileReference: {
|
||||
pos,
|
||||
end: pos + match[3].length,
|
||||
fileName: match[3]
|
||||
},
|
||||
isNoDefaultLib: false,
|
||||
isTypeReferenceDirective: !!refLibResult
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
|
||||
isNoDefaultLib: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isKeyword(token: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
|
||||
}
|
||||
|
||||
@@ -663,7 +663,7 @@ namespace ts.codefix {
|
||||
const parent = token.parent;
|
||||
const isNodeOpeningLikeElement = isJsxOpeningLikeElement(parent);
|
||||
if ((isJsxOpeningLikeElement && (<JsxOpeningLikeElement>parent).tagName === token) || parent.kind === SyntaxKind.JsxOpeningFragment) {
|
||||
umdSymbol = checker.resolveName(checker.getJsxNamespace(),
|
||||
umdSymbol = checker.resolveName(checker.getJsxNamespace(parent),
|
||||
isNodeOpeningLikeElement ? (<JsxOpeningLikeElement>parent).tagName : parent, SymbolFlags.Value, /*excludeGlobals*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-25
@@ -1,10 +1,17 @@
|
||||
namespace ts {
|
||||
export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo {
|
||||
const referencedFiles: FileReference[] = [];
|
||||
const typeReferenceDirectives: FileReference[] = [];
|
||||
const pragmaContext: PragmaContext = {
|
||||
languageVersion: ScriptTarget.ES5, // controls weather the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia
|
||||
pragmas: undefined,
|
||||
checkJsDirective: undefined,
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
amdDependencies: [],
|
||||
hasNoDefaultLib: undefined,
|
||||
moduleName: undefined
|
||||
};
|
||||
const importedFiles: FileReference[] = [];
|
||||
let ambientExternalModules: { ref: FileReference, depth: number }[];
|
||||
let isNoDefaultLib = false;
|
||||
let braceNesting = 0;
|
||||
// assume that text represent an external module if it contains at least one top level import/export
|
||||
// ambient modules that are found inside external modules are interpreted as module augmentations
|
||||
@@ -21,25 +28,6 @@ namespace ts {
|
||||
return token;
|
||||
}
|
||||
|
||||
function processTripleSlashDirectives(): void {
|
||||
const commentRanges = getLeadingCommentRanges(sourceText, 0);
|
||||
forEach(commentRanges, commentRange => {
|
||||
const comment = sourceText.substring(commentRange.pos, commentRange.end);
|
||||
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange);
|
||||
if (referencePathMatchResult) {
|
||||
isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
|
||||
const fileReference = referencePathMatchResult.fileReference;
|
||||
if (fileReference) {
|
||||
const collection = referencePathMatchResult.isTypeReferenceDirective
|
||||
? typeReferenceDirectives
|
||||
: referencedFiles;
|
||||
|
||||
collection.push(fileReference);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getFileReference() {
|
||||
const fileName = scanner.getTokenValue();
|
||||
const pos = scanner.getTokenPos();
|
||||
@@ -328,7 +316,8 @@ namespace ts {
|
||||
if (readImportFiles) {
|
||||
processImports();
|
||||
}
|
||||
processTripleSlashDirectives();
|
||||
processCommentPragmas(pragmaContext, sourceText);
|
||||
processPragmasIntoFields(pragmaContext, noop);
|
||||
if (externalModule) {
|
||||
// for external modules module all nested ambient modules are augmentations
|
||||
if (ambientExternalModules) {
|
||||
@@ -337,7 +326,7 @@ namespace ts {
|
||||
importedFiles.push(decl.ref);
|
||||
}
|
||||
}
|
||||
return { referencedFiles, typeReferenceDirectives, importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined };
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined };
|
||||
}
|
||||
else {
|
||||
// for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0
|
||||
@@ -355,7 +344,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return { referencedFiles, typeReferenceDirectives, importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames };
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,6 +651,9 @@ namespace ts {
|
||||
public ambientModuleNames: string[];
|
||||
public checkJsDirective: CheckJsDirective | undefined;
|
||||
public possiblyContainDynamicImport: boolean;
|
||||
public pragmas: PragmaMap;
|
||||
public localJsxFactory: EntityName;
|
||||
public localJsxNamespace: __String;
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
super(kind, pos, end);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarations.tsx] ////
|
||||
|
||||
//// [renderer.d.ts]
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export function otherdom(): void;
|
||||
export function createElement(): void;
|
||||
export { dom as default };
|
||||
//// [otherreacty.tsx]
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
<h></h>
|
||||
//// [other.tsx]
|
||||
/** @jsx h */
|
||||
import { dom as h } from "./renderer"
|
||||
export const prerendered = <h></h>;
|
||||
//// [othernoalias.tsx]
|
||||
/** @jsx otherdom */
|
||||
import { otherdom } from "./renderer"
|
||||
export const prerendered2 = <h></h>;
|
||||
//// [reacty.tsx]
|
||||
import React from "./renderer"
|
||||
export const prerendered3 = <h></h>;
|
||||
|
||||
//// [index.tsx]
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer"
|
||||
<h></h>
|
||||
export * from "./other";
|
||||
export * from "./othernoalias";
|
||||
export * from "./reacty";
|
||||
|
||||
|
||||
//// [otherreacty.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx React.createElement */
|
||||
var React = require("./renderer");
|
||||
React.createElement("h", null);
|
||||
//// [other.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx h */
|
||||
var renderer_1 = require("./renderer");
|
||||
exports.prerendered = renderer_1.dom("h", null);
|
||||
//// [othernoalias.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx otherdom */
|
||||
var renderer_1 = require("./renderer");
|
||||
exports.prerendered2 = renderer_1.otherdom("h", null);
|
||||
//// [reacty.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var renderer_1 = require("./renderer");
|
||||
exports.prerendered3 = renderer_1["default"].createElement("h", null);
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
exports.__esModule = true;
|
||||
/** @jsx dom */
|
||||
var renderer_1 = require("./renderer");
|
||||
renderer_1.dom("h", null);
|
||||
__export(require("./other"));
|
||||
__export(require("./othernoalias"));
|
||||
__export(require("./reacty"));
|
||||
@@ -0,0 +1,80 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(renderer.d.ts, 0, 0))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(renderer.d.ts, 0, 16))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
[e: string]: any;
|
||||
>e : Symbol(e, Decl(renderer.d.ts, 3, 13))
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : Symbol(dom, Decl(renderer.d.ts, 6, 1))
|
||||
|
||||
export function otherdom(): void;
|
||||
>otherdom : Symbol(otherdom, Decl(renderer.d.ts, 7, 28))
|
||||
|
||||
export function createElement(): void;
|
||||
>createElement : Symbol(createElement, Decl(renderer.d.ts, 8, 33))
|
||||
|
||||
export { dom as default };
|
||||
>dom : Symbol(default, Decl(renderer.d.ts, 10, 8))
|
||||
>default : Symbol(default, Decl(renderer.d.ts, 10, 8))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/otherreacty.tsx ===
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
>React : Symbol(React, Decl(otherreacty.tsx, 1, 6))
|
||||
|
||||
<h></h>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/other.tsx ===
|
||||
/** @jsx h */
|
||||
import { dom as h } from "./renderer"
|
||||
>dom : Symbol(h, Decl(other.tsx, 1, 8))
|
||||
>h : Symbol(h, Decl(other.tsx, 1, 8))
|
||||
|
||||
export const prerendered = <h></h>;
|
||||
>prerendered : Symbol(prerendered, Decl(other.tsx, 2, 12))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/othernoalias.tsx ===
|
||||
/** @jsx otherdom */
|
||||
import { otherdom } from "./renderer"
|
||||
>otherdom : Symbol(otherdom, Decl(othernoalias.tsx, 1, 8))
|
||||
|
||||
export const prerendered2 = <h></h>;
|
||||
>prerendered2 : Symbol(prerendered2, Decl(othernoalias.tsx, 2, 12))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
import React from "./renderer"
|
||||
>React : Symbol(React, Decl(reacty.tsx, 0, 6))
|
||||
|
||||
export const prerendered3 = <h></h>;
|
||||
>prerendered3 : Symbol(prerendered3, Decl(reacty.tsx, 1, 12))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer"
|
||||
>dom : Symbol(dom, Decl(index.tsx, 1, 8))
|
||||
|
||||
<h></h>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
export * from "./other";
|
||||
export * from "./othernoalias";
|
||||
export * from "./reacty";
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
>JSX : any
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : IntrinsicElements
|
||||
|
||||
[e: string]: any;
|
||||
>e : string
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : () => void
|
||||
|
||||
export function otherdom(): void;
|
||||
>otherdom : () => void
|
||||
|
||||
export function createElement(): void;
|
||||
>createElement : () => void
|
||||
|
||||
export { dom as default };
|
||||
>dom : () => void
|
||||
>default : () => void
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/otherreacty.tsx ===
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
>React : typeof React
|
||||
|
||||
<h></h>
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/other.tsx ===
|
||||
/** @jsx h */
|
||||
import { dom as h } from "./renderer"
|
||||
>dom : () => void
|
||||
>h : () => void
|
||||
|
||||
export const prerendered = <h></h>;
|
||||
>prerendered : any
|
||||
><h></h> : any
|
||||
>h : () => void
|
||||
>h : () => void
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/othernoalias.tsx ===
|
||||
/** @jsx otherdom */
|
||||
import { otherdom } from "./renderer"
|
||||
>otherdom : () => void
|
||||
|
||||
export const prerendered2 = <h></h>;
|
||||
>prerendered2 : any
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
import React from "./renderer"
|
||||
>React : () => void
|
||||
|
||||
export const prerendered3 = <h></h>;
|
||||
>prerendered3 : any
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer"
|
||||
>dom : () => void
|
||||
|
||||
<h></h>
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
export * from "./other";
|
||||
export * from "./othernoalias";
|
||||
export * from "./reacty";
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryOverridesCompilerOption.tsx] ////
|
||||
|
||||
//// [renderer.d.ts]
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export { dom as p };
|
||||
//// [reacty.tsx]
|
||||
/** @jsx dom */
|
||||
import {dom} from "./renderer";
|
||||
<h></h>
|
||||
//// [index.tsx]
|
||||
import { p } from "./renderer";
|
||||
<h></h>
|
||||
|
||||
|
||||
//// [reacty.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx dom */
|
||||
var renderer_1 = require("./renderer");
|
||||
renderer_1.dom("h", null);
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var renderer_1 = require("./renderer");
|
||||
renderer_1.p("h", null);
|
||||
@@ -0,0 +1,39 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(renderer.d.ts, 0, 0))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(renderer.d.ts, 0, 16))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
[e: string]: any;
|
||||
>e : Symbol(e, Decl(renderer.d.ts, 3, 13))
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : Symbol(dom, Decl(renderer.d.ts, 6, 1))
|
||||
|
||||
export { dom as p };
|
||||
>dom : Symbol(p, Decl(renderer.d.ts, 8, 8))
|
||||
>p : Symbol(p, Decl(renderer.d.ts, 8, 8))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
/** @jsx dom */
|
||||
import {dom} from "./renderer";
|
||||
>dom : Symbol(dom, Decl(reacty.tsx, 1, 8))
|
||||
|
||||
<h></h>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
import { p } from "./renderer";
|
||||
>p : Symbol(p, Decl(index.tsx, 0, 8))
|
||||
|
||||
<h></h>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
>JSX : any
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : IntrinsicElements
|
||||
|
||||
[e: string]: any;
|
||||
>e : string
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : () => void
|
||||
|
||||
export { dom as p };
|
||||
>dom : () => void
|
||||
>p : () => void
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
/** @jsx dom */
|
||||
import {dom} from "./renderer";
|
||||
>dom : () => void
|
||||
|
||||
<h></h>
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
import { p } from "./renderer";
|
||||
>p : () => void
|
||||
|
||||
<h></h>
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
tests/cases/conformance/jsx/inline/index.tsx(3,1): error TS17017: JSX fragment is not supported when using an inline JSX factory pragma
|
||||
tests/cases/conformance/jsx/inline/reacty.tsx(3,1): error TS17017: JSX fragment is not supported when using an inline JSX factory pragma
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export function createElement(): void;
|
||||
==== tests/cases/conformance/jsx/inline/reacty.tsx (1 errors) ====
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
<><h></h></>
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS17017: JSX fragment is not supported when using an inline JSX factory pragma
|
||||
==== tests/cases/conformance/jsx/inline/index.tsx (1 errors) ====
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer";
|
||||
<><h></h></>
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS17017: JSX fragment is not supported when using an inline JSX factory pragma
|
||||
@@ -0,0 +1,35 @@
|
||||
//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryWithFragmentIsError.tsx] ////
|
||||
|
||||
//// [renderer.d.ts]
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export function createElement(): void;
|
||||
//// [reacty.tsx]
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
<><h></h></>
|
||||
//// [index.tsx]
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer";
|
||||
<><h></h></>
|
||||
|
||||
//// [reacty.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx React.createElement */
|
||||
var React = require("./renderer");
|
||||
React.createElement(React.Fragment, null,
|
||||
React.createElement("h", null));
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
/** @jsx dom */
|
||||
var renderer_1 = require("./renderer");
|
||||
renderer_1.dom(React.Fragment, null,
|
||||
renderer_1.dom("h", null));
|
||||
@@ -0,0 +1,39 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(renderer.d.ts, 0, 0))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(renderer.d.ts, 0, 16))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
[e: string]: any;
|
||||
>e : Symbol(e, Decl(renderer.d.ts, 3, 13))
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : Symbol(dom, Decl(renderer.d.ts, 6, 1))
|
||||
|
||||
export function createElement(): void;
|
||||
>createElement : Symbol(createElement, Decl(renderer.d.ts, 7, 28))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
>React : Symbol(React, Decl(reacty.tsx, 1, 6))
|
||||
|
||||
<><h></h></>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer";
|
||||
>dom : Symbol(dom, Decl(index.tsx, 1, 8))
|
||||
|
||||
<><h></h></>
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
>JSX : any
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : IntrinsicElements
|
||||
|
||||
[e: string]: any;
|
||||
>e : string
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
>dom : () => void
|
||||
|
||||
export function createElement(): void;
|
||||
>createElement : () => void
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/reacty.tsx ===
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
>React : typeof React
|
||||
|
||||
<><h></h></>
|
||||
><><h></h></> : any
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
=== tests/cases/conformance/jsx/inline/index.tsx ===
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer";
|
||||
>dom : () => void
|
||||
|
||||
<><h></h></>
|
||||
><><h></h></> : any
|
||||
><h></h> : any
|
||||
>h : any
|
||||
>h : any
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// @jsx: react
|
||||
// @filename: renderer.d.ts
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export function otherdom(): void;
|
||||
export function createElement(): void;
|
||||
export { dom as default };
|
||||
// @filename: otherreacty.tsx
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
<h></h>
|
||||
// @filename: other.tsx
|
||||
/** @jsx h */
|
||||
import { dom as h } from "./renderer"
|
||||
export const prerendered = <h></h>;
|
||||
// @filename: othernoalias.tsx
|
||||
/** @jsx otherdom */
|
||||
import { otherdom } from "./renderer"
|
||||
export const prerendered2 = <h></h>;
|
||||
// @filename: reacty.tsx
|
||||
import React from "./renderer"
|
||||
export const prerendered3 = <h></h>;
|
||||
|
||||
// @filename: index.tsx
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer"
|
||||
<h></h>
|
||||
export * from "./other";
|
||||
export * from "./othernoalias";
|
||||
export * from "./reacty";
|
||||
@@ -0,0 +1,19 @@
|
||||
// @jsx: react
|
||||
// @jsxFactory: p
|
||||
// @filename: renderer.d.ts
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export { dom as p };
|
||||
// @filename: reacty.tsx
|
||||
/** @jsx dom */
|
||||
import {dom} from "./renderer";
|
||||
<h></h>
|
||||
// @filename: index.tsx
|
||||
import { p } from "./renderer";
|
||||
<h></h>
|
||||
@@ -0,0 +1,19 @@
|
||||
// @jsx: react
|
||||
// @filename: renderer.d.ts
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[e: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function dom(): void;
|
||||
export function createElement(): void;
|
||||
// @filename: reacty.tsx
|
||||
/** @jsx React.createElement */
|
||||
import * as React from "./renderer";
|
||||
<><h></h></>
|
||||
// @filename: index.tsx
|
||||
/** @jsx dom */
|
||||
import { dom } from "./renderer";
|
||||
<><h></h></>
|
||||
Reference in New Issue
Block a user