Resolve first identifier of the jsxFactory as part of type check

This commit is contained in:
Sheetal Nandi
2016-11-09 13:15:13 -08:00
parent f7bac98948
commit 06affa6672
10 changed files with 548 additions and 119 deletions

View File

@@ -335,6 +335,7 @@ namespace ts {
});
let jsxElementType: Type;
let _jsxNamespace: string;
/** Things we lazy load from the JSX namespace */
const jsxTypes = createMap<Type>();
const JsxNames = {
@@ -372,6 +373,22 @@ namespace ts {
return checker;
function getJsxNamespace(): string {
if (_jsxNamespace === undefined) {
_jsxNamespace = "React";
if (compilerOptions.jsxFactory) {
const jsxEntity = host.getJsxFactoryEntity();
if (jsxEntity) {
_jsxNamespace = getFirstIdentifier(jsxEntity).text;
}
}
else if (compilerOptions.reactNamespace) {
_jsxNamespace = compilerOptions.reactNamespace;
}
}
return _jsxNamespace;
}
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
// Ensure we have all the type information in place for this file so that all the
// emitter questions of this resolver will return the right information.
@@ -11337,10 +11354,10 @@ namespace ts {
function checkJsxOpeningLikeElement(node: JsxOpeningLikeElement) {
checkGrammarJsxElement(node);
checkJsxPreconditions(node);
// The reactNamespace symbol should be marked as 'used' so we don't incorrectly elide its import. And if there
// is no reactNamespace symbol in scope when targeting React emit, we should issue an error.
// 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 = compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
const reactNamespace = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React";
const reactNamespace = getJsxNamespace();
const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace);
if (reactSym) {
// Mark local symbol as referenced here because it might not have been marked

View File

@@ -329,6 +329,9 @@ namespace ts {
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
// ReactNamespace and jsxFactory information
let jsxFactoryEntity: EntityName;
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModuleFull[];
if (host.resolveModuleNames) {
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile).map(resolved => {
@@ -421,7 +424,8 @@ namespace ts {
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
isSourceFileFromExternalLibrary,
dropDiagnosticsProducingTypeChecker
dropDiagnosticsProducingTypeChecker,
getJsxFactoryEntity: () => jsxFactoryEntity
};
verifyCompilerOptions();
@@ -1674,7 +1678,8 @@ namespace ts {
if (options.reactNamespace) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"));
}
if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
jsxFactoryEntity = parseIsolatedEntityName(options.jsxFactory, languageVersion);
if (!jsxFactoryEntity) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory));
}
}

View File

@@ -2177,6 +2177,7 @@ namespace ts {
getTypeChecker(): TypeChecker;
/* @internal */ getCommonSourceDirectory(): string;
/* @internal */ getJsxFactoryEntity(): EntityName;
// For testing purposes only. Should not be used by any other consumers (including the
// language service).
@@ -2250,6 +2251,7 @@ namespace ts {
/* @internal */
export interface TypeCheckerHost {
getCompilerOptions(): CompilerOptions;
getJsxFactoryEntity(): EntityName;
getSourceFiles(): SourceFile[];
getSourceFile(fileName: string): SourceFile;