mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'tsconfigMixedContentSupportRedux' into tsconfigMixedContentSupport
This commit is contained in:
@@ -827,7 +827,7 @@ namespace ts {
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = [], mixedContentFileExtensions: string[] = []): ParsedCommandLine {
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = [], fileExtensionMap: FileExtensionMap = {}): ParsedCommandLine {
|
||||
const errors: Diagnostic[] = [];
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName);
|
||||
@@ -964,7 +964,7 @@ namespace ts {
|
||||
includeSpecs = ["**/*"];
|
||||
}
|
||||
|
||||
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, mixedContentFileExtensions);
|
||||
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, fileExtensionMap);
|
||||
|
||||
if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
|
||||
errors.push(
|
||||
@@ -1166,7 +1166,7 @@ namespace ts {
|
||||
* @param host The host used to resolve files and directories.
|
||||
* @param errors An array for diagnostic reporting.
|
||||
*/
|
||||
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], mixedContentFileExtensions: string[]): ExpandResult {
|
||||
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], fileExtensionMap: FileExtensionMap): ExpandResult {
|
||||
basePath = normalizePath(basePath);
|
||||
|
||||
// The exclude spec list is converted into a regular expression, which allows us to quickly
|
||||
@@ -1200,7 +1200,7 @@ namespace ts {
|
||||
|
||||
// Rather than requery this for each file and filespec, we query the supported extensions
|
||||
// once and store it on the expansion context.
|
||||
const supportedExtensions = getSupportedExtensions(options, mixedContentFileExtensions);
|
||||
const supportedExtensions = getSupportedExtensions(options, fileExtensionMap);
|
||||
|
||||
// Literal files are always included verbatim. An "include" or "exclude" specification cannot
|
||||
// remove a literal file.
|
||||
|
||||
+12
-4
@@ -1942,8 +1942,16 @@ namespace ts {
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions, mixedContentFileExtensions?: string[]): string[] {
|
||||
return options && options.allowJs ? concatenate(allSupportedExtensions, mixedContentFileExtensions) : supportedTypeScriptExtensions;
|
||||
export function getSupportedExtensions(options?: CompilerOptions, fileExtensionMap?: FileExtensionMap): string[] {
|
||||
let typeScriptHostExtensions: string[] = [];
|
||||
let allHostExtensions: string[] = [];
|
||||
if (fileExtensionMap) {
|
||||
allHostExtensions = concatenate(concatenate(fileExtensionMap.javaScript, fileExtensionMap.typeScript), fileExtensionMap.mixedContent);
|
||||
typeScriptHostExtensions = fileExtensionMap.typeScript;
|
||||
}
|
||||
const allTypeScriptExtensions = concatenate(supportedTypeScriptExtensions, typeScriptHostExtensions);
|
||||
const allExtensions = concatenate(allSupportedExtensions, allHostExtensions);
|
||||
return options && options.allowJs ? allExtensions : allTypeScriptExtensions;
|
||||
}
|
||||
|
||||
export function hasJavaScriptFileExtension(fileName: string) {
|
||||
@@ -1954,10 +1962,10 @@ namespace ts {
|
||||
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, mixedContentFileExtensions?: string[]) {
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, fileExtensionMap?: FileExtensionMap) {
|
||||
if (!fileName) { return false; }
|
||||
|
||||
for (const extension of getSupportedExtensions(compilerOptions, mixedContentFileExtensions)) {
|
||||
for (const extension of getSupportedExtensions(compilerOptions, fileExtensionMap)) {
|
||||
if (fileExtensionIs(fileName, extension)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace ts {
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, mixedContentFileExtensions?: string[]): Program {
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, fileExtensionMap?: FileExtensionMap): Program {
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
let commonSourceDirectory: string;
|
||||
@@ -320,7 +320,7 @@ namespace ts {
|
||||
let skipDefaultLib = options.noLib;
|
||||
const programDiagnostics = createDiagnosticCollection();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const supportedExtensions = getSupportedExtensions(options, mixedContentFileExtensions);
|
||||
const supportedExtensions = getSupportedExtensions(options, fileExtensionMap);
|
||||
|
||||
// Map storing if there is emit blocking diagnostics for given input
|
||||
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
|
||||
|
||||
@@ -3075,6 +3075,12 @@ namespace ts {
|
||||
ThisProperty
|
||||
}
|
||||
|
||||
export interface FileExtensionMap {
|
||||
javaScript?: string[];
|
||||
typeScript?: string[];
|
||||
mixedContent?: string[];
|
||||
}
|
||||
|
||||
export interface DiagnosticMessage {
|
||||
key: string;
|
||||
category: DiagnosticCategory;
|
||||
|
||||
@@ -1464,7 +1464,7 @@ namespace ts.projectSystem {
|
||||
checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
|
||||
|
||||
// Specify .html extension as mixed content
|
||||
const configureHostRequest = makeSessionRequest<protocol.ConfigureRequestArguments>(CommandNames.Configure, { mixedContentFileExtensions: [".html"] });
|
||||
const configureHostRequest = makeSessionRequest<protocol.ConfigureRequestArguments>(CommandNames.Configure, { fileExtensionMap: { mixedContent: [".html"] } });
|
||||
session.executeCommand(configureHostRequest).response;
|
||||
|
||||
// HTML file still not included in the project as it is closed
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace ts.server {
|
||||
export interface HostConfiguration {
|
||||
formatCodeOptions: FormatCodeSettings;
|
||||
hostInfo: string;
|
||||
mixedContentFileExtensions?: string[];
|
||||
fileExtensionMap?: FileExtensionMap;
|
||||
}
|
||||
|
||||
interface ConfigFileConversionResult {
|
||||
@@ -133,13 +133,13 @@ namespace ts.server {
|
||||
interface FilePropertyReader<T> {
|
||||
getFileName(f: T): string;
|
||||
getScriptKind(f: T): ScriptKind;
|
||||
hasMixedContent(f: T, mixedContentFileExtensions: string[]): boolean;
|
||||
hasMixedContent(f: T, mixedContentExtensions: string[]): boolean;
|
||||
}
|
||||
|
||||
const fileNamePropertyReader: FilePropertyReader<string> = {
|
||||
getFileName: x => x,
|
||||
getScriptKind: _ => undefined,
|
||||
hasMixedContent: (fileName, mixedContentFileExtensions) => forEach(mixedContentFileExtensions, extension => fileExtensionIs(fileName, extension))
|
||||
hasMixedContent: (fileName, mixedContentExtensions) => forEach(mixedContentExtensions, extension => fileExtensionIs(fileName, extension))
|
||||
};
|
||||
|
||||
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
|
||||
@@ -284,7 +284,7 @@ namespace ts.server {
|
||||
this.hostConfiguration = {
|
||||
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
|
||||
hostInfo: "Unknown host",
|
||||
mixedContentFileExtensions: []
|
||||
fileExtensionMap: {}
|
||||
};
|
||||
|
||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
|
||||
@@ -488,7 +488,7 @@ namespace ts.server {
|
||||
// If a change was made inside "folder/file", node will trigger the callback twice:
|
||||
// one with the fileName being "folder/file", and the other one with "folder".
|
||||
// We don't respond to the second one.
|
||||
if (fileName && !ts.isSupportedSourceFileName(fileName, project.getCompilerOptions(), this.hostConfiguration.mixedContentFileExtensions)) {
|
||||
if (fileName && !ts.isSupportedSourceFileName(fileName, project.getCompilerOptions(), this.hostConfiguration.fileExtensionMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -810,7 +810,7 @@ namespace ts.server {
|
||||
/*existingOptions*/ {},
|
||||
configFilename,
|
||||
/*resolutionStack*/ [],
|
||||
this.hostConfiguration.mixedContentFileExtensions);
|
||||
this.hostConfiguration.fileExtensionMap);
|
||||
|
||||
if (parsedCommandLine.errors.length) {
|
||||
errors = concatenate(errors, parsedCommandLine.errors);
|
||||
@@ -914,7 +914,7 @@ namespace ts.server {
|
||||
for (const f of files) {
|
||||
const rootFilename = propertyReader.getFileName(f);
|
||||
const scriptKind = propertyReader.getScriptKind(f);
|
||||
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.mixedContentFileExtensions);
|
||||
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.fileExtensionMap.mixedContent);
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFilename), /*openedByClient*/ clientFileName == rootFilename, /*fileContent*/ undefined, scriptKind, hasMixedContent);
|
||||
project.addRoot(info);
|
||||
@@ -960,7 +960,7 @@ namespace ts.server {
|
||||
rootFilesChanged = true;
|
||||
if (!scriptInfo) {
|
||||
const scriptKind = propertyReader.getScriptKind(f);
|
||||
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.mixedContentFileExtensions);
|
||||
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.fileExtensionMap.mixedContent);
|
||||
scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent);
|
||||
}
|
||||
}
|
||||
@@ -1144,9 +1144,9 @@ namespace ts.server {
|
||||
mergeMaps(this.hostConfiguration.formatCodeOptions, convertFormatOptions(args.formatOptions));
|
||||
this.logger.info("Format host information updated");
|
||||
}
|
||||
if (args.mixedContentFileExtensions) {
|
||||
this.hostConfiguration.mixedContentFileExtensions = args.mixedContentFileExtensions;
|
||||
this.logger.info("Host mixed content file extensions updated");
|
||||
if (args.fileExtensionMap) {
|
||||
this.hostConfiguration.fileExtensionMap = args.fileExtensionMap;
|
||||
this.logger.info("Host file extension mappings updated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace ts.server {
|
||||
export class LSHost implements ts.LanguageServiceHost, ModuleResolutionHost {
|
||||
private compilationSettings: ts.CompilerOptions;
|
||||
private mixedContentFileExtensions: string[];
|
||||
private fileExtensionMap: FileExtensionMap;
|
||||
private readonly resolvedModuleNames = createFileMap<Map<ResolvedModuleWithFailedLookupLocations>>();
|
||||
private readonly resolvedTypeReferenceDirectives = createFileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
|
||||
private readonly getCanonicalFileName: (fileName: string) => string;
|
||||
@@ -144,8 +144,8 @@ namespace ts.server {
|
||||
return this.compilationSettings;
|
||||
}
|
||||
|
||||
getMixedContentFileExtensions() {
|
||||
return this.mixedContentFileExtensions;
|
||||
getFileExtensionMap() {
|
||||
return this.fileExtensionMap;
|
||||
}
|
||||
|
||||
useCaseSensitiveFileNames() {
|
||||
@@ -237,8 +237,8 @@ namespace ts.server {
|
||||
this.compilationSettings = opt;
|
||||
}
|
||||
|
||||
setMixedContentFileExtensions(mixedContentFileExtensions: string[]) {
|
||||
this.mixedContentFileExtensions = mixedContentFileExtensions || [];
|
||||
setFileExtensionMap(fileExtensionMap: FileExtensionMap) {
|
||||
this.fileExtensionMap = fileExtensionMap || {};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +254,7 @@ namespace ts.server {
|
||||
|
||||
this.lsHost = new LSHost(this.projectService.host, this, this.projectService.cancellationToken);
|
||||
this.lsHost.setCompilationSettings(this.compilerOptions);
|
||||
this.lsHost.setMixedContentFileExtensions(this.projectService.hostConfiguration.mixedContentFileExtensions);
|
||||
this.lsHost.setFileExtensionMap(this.projectService.hostConfiguration.fileExtensionMap);
|
||||
|
||||
this.languageService = ts.createLanguageService(this.lsHost, this.documentRegistry);
|
||||
this.noSemanticFeaturesLanguageService = createNoSemanticFeaturesWrapper(this.languageService);
|
||||
|
||||
@@ -992,9 +992,9 @@ namespace ts.server.protocol {
|
||||
formatOptions?: FormatCodeSettings;
|
||||
|
||||
/**
|
||||
* List of host's supported mixed content file extensions
|
||||
* The host's supported file extension mappings
|
||||
*/
|
||||
mixedContentFileExtensions?: string[];
|
||||
fileExtensionMap?: FileExtensionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -271,14 +271,14 @@ namespace ts.Completions {
|
||||
const span = getDirectoryFragmentTextSpan((<StringLiteral>node).text, node.getStart() + 1);
|
||||
let entries: CompletionEntry[];
|
||||
if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) {
|
||||
const mixedContentFileExtensions = host.getMixedContentFileExtensions ? host.getMixedContentFileExtensions() : [];
|
||||
const fileExtensionMap = host.getFileExtensionMap ? host.getFileExtensionMap() : {};
|
||||
if (compilerOptions.rootDirs) {
|
||||
entries = getCompletionEntriesForDirectoryFragmentWithRootDirs(
|
||||
compilerOptions.rootDirs, literalValue, scriptDirectory, getSupportedExtensions(compilerOptions, mixedContentFileExtensions), /*includeExtensions*/false, span, scriptPath);
|
||||
compilerOptions.rootDirs, literalValue, scriptDirectory, getSupportedExtensions(compilerOptions, fileExtensionMap), /*includeExtensions*/false, span, scriptPath);
|
||||
}
|
||||
else {
|
||||
entries = getCompletionEntriesForDirectoryFragment(
|
||||
literalValue, scriptDirectory, getSupportedExtensions(compilerOptions, mixedContentFileExtensions), /*includeExtensions*/false, span, scriptPath);
|
||||
literalValue, scriptDirectory, getSupportedExtensions(compilerOptions, fileExtensionMap), /*includeExtensions*/false, span, scriptPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -412,8 +412,8 @@ namespace ts.Completions {
|
||||
let result: CompletionEntry[];
|
||||
|
||||
if (baseUrl) {
|
||||
const mixedContentFileExtensions = host.getMixedContentFileExtensions ? host.getMixedContentFileExtensions() : [];
|
||||
const fileExtensions = getSupportedExtensions(compilerOptions, mixedContentFileExtensions);
|
||||
const fileExtensionMap = host.getFileExtensionMap ? host.getFileExtensionMap() : {};
|
||||
const fileExtensions = getSupportedExtensions(compilerOptions, fileExtensionMap);
|
||||
const projectDir = compilerOptions.project || host.getCurrentDirectory();
|
||||
const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl);
|
||||
result = getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span);
|
||||
@@ -590,8 +590,8 @@ namespace ts.Completions {
|
||||
if (kind === "path") {
|
||||
// Give completions for a relative path
|
||||
const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length);
|
||||
const mixedContentFileExtensions = host.getMixedContentFileExtensions ? host.getMixedContentFileExtensions() : [];
|
||||
completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions, mixedContentFileExtensions), /*includeExtensions*/true, span, sourceFile.path);
|
||||
const fileExtensionMap = host.getFileExtensionMap ? host.getFileExtensionMap() : {};
|
||||
completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions, fileExtensionMap), /*includeExtensions*/true, span, sourceFile.path);
|
||||
}
|
||||
else {
|
||||
// Give completions based on the typings available
|
||||
|
||||
@@ -757,7 +757,7 @@ namespace ts {
|
||||
class HostCache {
|
||||
private fileNameToEntry: FileMap<HostFileInformation>;
|
||||
private _compilationSettings: CompilerOptions;
|
||||
private _mixedContentFileExtensions: string[];
|
||||
private _fileExtensionMap: FileExtensionMap;
|
||||
private currentDirectory: string;
|
||||
|
||||
constructor(private host: LanguageServiceHost, private getCanonicalFileName: (fileName: string) => string) {
|
||||
@@ -774,15 +774,15 @@ namespace ts {
|
||||
// store the compilation settings
|
||||
this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
|
||||
|
||||
this._mixedContentFileExtensions = host.getMixedContentFileExtensions ? host.getMixedContentFileExtensions() : [];
|
||||
this._fileExtensionMap = host.getFileExtensionMap ? host.getFileExtensionMap() : {};
|
||||
}
|
||||
|
||||
public compilationSettings() {
|
||||
return this._compilationSettings;
|
||||
}
|
||||
|
||||
public mixedContentFileExtensions() {
|
||||
return this._mixedContentFileExtensions;
|
||||
public fileExtensionMap() {
|
||||
return this._fileExtensionMap;
|
||||
}
|
||||
|
||||
private createEntry(fileName: string, path: Path) {
|
||||
@@ -1107,7 +1107,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
|
||||
const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program, hostCache.mixedContentFileExtensions());
|
||||
const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program, hostCache.fileExtensionMap());
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
// not part of the new program.
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace ts {
|
||||
//
|
||||
export interface LanguageServiceHost {
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
getMixedContentFileExtensions?(): string[];
|
||||
getFileExtensionMap?(): FileExtensionMap;
|
||||
getNewLine?(): string;
|
||||
getProjectVersion?(): string;
|
||||
getScriptFileNames(): string[];
|
||||
|
||||
Reference in New Issue
Block a user