From 094afb2cd98fa9ead82735174b99f15fb796e843 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 May 2015 11:09:31 -0700 Subject: [PATCH 01/11] Added single-file package declaration using multiple ambient modules --- src/compiler/commandLineParser.ts | 18 ++ src/compiler/declarationEmitter.ts | 155 ++++++++++++++---- .../diagnosticInformationMap.generated.ts | 6 +- src/compiler/diagnosticMessages.json | 18 +- src/compiler/emitter.ts | 13 +- src/compiler/program.ts | 33 ++++ src/compiler/types.ts | 3 + 7 files changed, 214 insertions(+), 32 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6a055aebf6a5a..1267d4ae0fec5 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -16,6 +16,24 @@ module ts { type: "boolean", description: Diagnostics.Generates_corresponding_d_ts_file, }, + { + name: "packageMain", + type: "string", + isFilePath: true, + experimental: true + }, + { + name: "packageName", + type: "string", + isFilePath: true, + experimental: true + }, + { + name: "packageDeclaration", + type: "string", + isFilePath: true, + experimental: true + }, { name: "diagnostics", type: "boolean", diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 5c705f1819045..c4dba203edaee 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -42,6 +42,8 @@ module ts { let compilerOptions = host.getCompilerOptions(); let languageVersion = compilerOptions.target || ScriptTarget.ES3; + let isPackage = (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) != undefined; + let packageMainFile: string; let write: (s: string) => void; let writeLine: () => void; let increaseIndent: () => void; @@ -63,6 +65,10 @@ module ts { // Collecting this separately because reference paths need to be first thing in the declaration file // and we could be collecting these paths from multiple files into single one with --out option let referencePathsOutput = ""; + + if (isPackage) { + packageMainFile = host.getCanonicalFileName(compilerOptions.packageMain); + } if (root) { // Emitting just a single file, so emit references in this file only @@ -83,9 +89,9 @@ module ts { } }); } - + emitSourceFile(root); - + // create asynchronous output for the importDeclarations if (moduleElementDeclarationEmitInfo.length) { let oldWriter = writer; @@ -104,11 +110,11 @@ module ts { else { // Emit references corresponding to this file let emittedReferencedFiles: SourceFile[] = []; - forEach(host.getSourceFiles(), sourceFile => { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { + for (let sourceFile of sortSourceFiles(host.getSourceFiles())) { + if (!isExternalModuleOrDeclarationFile(sourceFile) || (isPackage && isExternalModule(sourceFile))) { // Check what references need to be added if (!compilerOptions.noResolve) { - forEach(sourceFile.referencedFiles, fileReference => { + for (let fileReference of sourceFile.referencedFiles) { let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); // If the reference file is a declaration file or an external module, emit that reference @@ -117,15 +123,16 @@ module ts { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); - } - }); + } + } } + writeLine(); emitSourceFile(sourceFile); - } - }); + } + } } - + return { reportedDeclarationError, moduleElementDeclarationEmitInfo, @@ -133,6 +140,35 @@ module ts { referencePathsOutput, } + function sortSourceFiles(sourceFiles: SourceFile[]) { + if (isPackage) { + let indices = new Array(sourceFiles.length); + for (let i = 0; i < sourceFiles.length; ++i) indices[i] = i; + indices.sort((left, right) => { + let leftFile = sourceFiles[left]; + if (leftFile.fileName === packageMainFile) { + return -1; + } + + let rightFile = sourceFiles[right]; + if (rightFile.fileName === packageMainFile) { + return +1; + } + + return left - right; + }); + + let sorted = new Array(sourceFiles.length); + for (let i = 0; i < sourceFiles.length; ++i) { + sorted[i] = sourceFiles[indices[i]]; + } + + return sorted; + } + + return sourceFiles; + } + function hasInternalAnnotation(range: CommentRange) { let text = currentSourceFile.text; let comment = text.substring(range.pos, range.end); @@ -439,7 +475,29 @@ module ts { function emitSourceFile(node: SourceFile) { currentSourceFile = node; enclosingDeclaration = node; + + if (isPackage) { + // compute file name relative to main + let packageQualifiedModuleName: string; + if (packageMainFile === node.fileName) { + packageQualifiedModuleName = compilerOptions.packageName; + } + else { + let sourcePath = removeFileExtension(node.fileName); + packageQualifiedModuleName = getPackageQualifiedPath(host, sourcePath, "."); + } + write(`declare module "${packageQualifiedModuleName}" {`); + increaseIndent(); + writeLine(); + } + emitLines(node.statements); + + if (isPackage) { + decreaseIndent(); + writeLine(); + write("}"); + } } // Return a temp variable name to be used in `export default` statements. @@ -563,7 +621,7 @@ module ts { function emitModuleElementDeclarationFlags(node: Node) { // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent === currentSourceFile) { + if (node.parent === currentSourceFile && !isPackage) { // If the node is exported if (node.flags & NodeFlags.Export) { write("export "); @@ -686,7 +744,7 @@ module ts { // write each of these declarations asynchronously writeAsynchronousModuleElements(nodes); } - + function emitExportDeclaration(node: ExportDeclaration) { emitJsDocComments(node); write("export "); @@ -700,7 +758,21 @@ module ts { } if (node.moduleSpecifier) { write(" from "); - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + if (isPackage) { + let moduleNameText = (node.moduleSpecifier).text; + let searchPath = getDirectoryPath(currentSourceFile.fileName); + let searchName = normalizePath(combinePaths(searchPath, moduleNameText)); + if (host.getSourceFile(searchName + ".ts") || host.getSourceFile(searchName + ".d.ts")) { + let packageQualifiedPath = getPackageQualifiedPath(host, moduleNameText, searchPath); + write(`"${packageQualifiedPath}"`); + } + else { + writeTextOfNode(currentSourceFile, node.moduleSpecifier); + } + } + else { + writeTextOfNode(currentSourceFile, node.moduleSpecifier); + } } write(";"); writer.writeLine(); @@ -1560,7 +1632,46 @@ module ts { referencePathsOutput += "/// " + newLine; } } - + + function getPackageQualifiedPath(host: EmitHost, moduleName: string, basePath: string) { + let compilerOptions = host.getCompilerOptions(); + let modulePath = normalizePath(combinePaths(basePath, moduleName)); + let packageRelativePath = getRelativePathToDirectoryOrUrl( + getDirectoryPath(host.getCanonicalFileName(compilerOptions.packageMain)), + modulePath, + host.getCurrentDirectory(), + host.getCanonicalFileName, + false); + return `package://${compilerOptions.packageName}/${packageRelativePath}`; + } + + function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) { + let appliedSyncOutputPos = 0; + let declarationOutput = ""; + // apply asynchronous additions to the synchronous output + forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => { + if (aliasEmitInfo.asynchronousOutput) { + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); + declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); + appliedSyncOutputPos = aliasEmitInfo.outputPos; + } + }); + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); + return declarationOutput; + } + + /* @internal */ + export function writePackageDeclarationFile(dtsFilePath: string, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) { + let compilerOptions = host.getCompilerOptions(); + let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, dtsFilePath); + if (!emitDeclarationResult.reportedDeclarationError) { + let declarationOutput = emitDeclarationResult.referencePathsOutput + + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); + + writeFile(host, diagnostics, dtsFilePath, declarationOutput, compilerOptions.emitBOM); + } + } + /* @internal */ export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) { let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile); @@ -1569,22 +1680,8 @@ module ts { if (!emitDeclarationResult.reportedDeclarationError) { let declarationOutput = emitDeclarationResult.referencePathsOutput + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); - writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM); - } - function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) { - let appliedSyncOutputPos = 0; - let declarationOutput = ""; - // apply asynchronous additions to the synchronous output - forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => { - if (aliasEmitInfo.asynchronousOutput) { - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); - declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); - appliedSyncOutputPos = aliasEmitInfo.outputPos; - } - }); - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); - return declarationOutput; + writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM); } } } \ No newline at end of file diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 1f8edf8fee367..c6b34182e3351 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -453,11 +453,15 @@ module ts { Option_declaration_cannot_be_specified_with_option_separateCompilation: { code: 5044, category: DiagnosticCategory.Error, key: "Option 'declaration' cannot be specified with option 'separateCompilation'." }, Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation: { code: 5045, category: DiagnosticCategory.Error, key: "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'." }, Option_out_cannot_be_specified_with_option_separateCompilation: { code: 5046, category: DiagnosticCategory.Error, key: "Option 'out' cannot be specified with option 'separateCompilation'." }, - Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher." }, + Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher." }, Option_sourceMap_cannot_be_specified_with_option_inlineSourceMap: { code: 5048, category: DiagnosticCategory.Error, key: "Option 'sourceMap' cannot be specified with option 'inlineSourceMap'." }, Option_sourceRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5049, category: DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified with option 'inlineSourceMap'." }, Option_mapRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5050, category: DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified with option 'inlineSourceMap'." }, Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided: { code: 5051, category: DiagnosticCategory.Error, key: "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided." }, + Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0: { code: 5052, category: DiagnosticCategory.Error, key: "Options 'packageName', 'packageMain', and 'packageDeclaration' must all be specified with option '{0}'." }, + Option_declaration_must_be_specified_with_options_packageName_packageMain_and_packageDeclaration: { code: 5053, category: DiagnosticCategory.Error, key: "Option 'declaration' must be specified with options 'packageName', 'packageMain', and 'packageDeclaration'." }, + Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5054, category: DiagnosticCategory.Error, key: "Options 'packageName', 'packageMain', and 'packageDeclaration' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher." }, + Option_0_cannot_be_specified_with_option_separateCompilation: { code: 5055, category: DiagnosticCategory.Error, key: "Option '{0}' cannot be specified with option 'separateCompilation'." }, Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." }, Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." }, Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 42eae83e26946..838ddf57f284c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1801,7 +1801,7 @@ "category": "Error", "code": 5046 }, - "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher.": { + "Option 'separateCompilation' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher.": { "category": "Error", "code": 5047 }, @@ -1821,6 +1821,22 @@ "category": "Error", "code": 5051 }, + "Options 'packageName', 'packageMain', and 'packageDeclaration' must all be specified with option '{0}'.": { + "category": "Error", + "code": 5052 + }, + "Option 'declaration' must be specified with options 'packageName', 'packageMain', and 'packageDeclaration'.": { + "category": "Error", + "code": 5053 + }, + "Options 'packageName', 'packageMain', and 'packageDeclaration' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher.": { + "category": "Error", + "code": 5054 + }, + "Option '{0}' cannot be specified with option 'separateCompilation'.": { + "category": "Error", + "code": 5055 + }, "Concatenate and emit output to single file.": { "category": "Message", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6d5146a680172..e4e9391310240 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -65,6 +65,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { if (compilerOptions.out) { emitFile(compilerOptions.out); } + + if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { + writePackageDeclarationFile(compilerOptions.packageDeclaration, host, resolver, diagnostics); + } } else { // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service) @@ -6047,7 +6051,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitJavaScript(jsFilePath, sourceFile); if (compilerOptions.declaration) { - writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); + if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { + if (sourceFile.fileName === host.getCanonicalFileName(compilerOptions.packageMain)) { + writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); + } + } + else { + writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); + } } } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 3ebd8740faa86..b72bac505a0aa 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -540,6 +540,18 @@ module ts { if (options.out) { diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_out_cannot_be_specified_with_option_separateCompilation)); } + + if (options.packageName) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_separateCompilation, "packageName")); + } + + if (options.packageMain) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_separateCompilation, "packageMain")); + } + + if (options.packageDeclaration) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_separateCompilation, "packageDeclaration")); + } } if (options.inlineSourceMap) { @@ -571,6 +583,27 @@ module ts { } return; } + + if (options.packageMain || options.packageName || options.packageDeclaration) { + if (!options.packageMain) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageMain")); + return; + } + if (!options.packageName) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageName")); + return; + } + if (!options.packageDeclaration) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageDeclaration")); + return; + } + if (options.module === ModuleKind.None && options.target < ScriptTarget.ES6) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher)); + } + if (!options.declaration) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_declaration_must_be_specified_with_options_packageName_packageMain_and_packageDeclaration)); + } + } let languageVersion = options.target || ScriptTarget.ES3; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 86e680ca8b047..8052f2de200fb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1678,6 +1678,9 @@ module ts { watch?: boolean; separateCompilation?: boolean; emitDecoratorMetadata?: boolean; + packageMain?: string; + packageName?: string; + packageDeclaration?: string; /* @internal */ stripInternal?: boolean; [option: string]: string | number | boolean; } From 03b5cc36ce3b955b911830a11384a5e29c5c52c1 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 May 2015 17:48:13 -0700 Subject: [PATCH 02/11] Updated format for submodule urls in a package --- src/compiler/declarationEmitter.ts | 10 +++++-- src/compiler/program.ts | 47 ++++++++++++++++++++++++++++-- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 2 ++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index c4dba203edaee..2db9c9bc84fb7 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1632,17 +1632,21 @@ module ts { referencePathsOutput += "/// " + newLine; } } - + function getPackageQualifiedPath(host: EmitHost, moduleName: string, basePath: string) { let compilerOptions = host.getCompilerOptions(); let modulePath = normalizePath(combinePaths(basePath, moduleName)); let packageRelativePath = getRelativePathToDirectoryOrUrl( - getDirectoryPath(host.getCanonicalFileName(compilerOptions.packageMain)), + host.getPackagePath(), modulePath, host.getCurrentDirectory(), host.getCanonicalFileName, false); - return `package://${compilerOptions.packageName}/${packageRelativePath}`; + if (host.getCanonicalFileName(packageRelativePath + ".ts") === host.getCanonicalFileName(compilerOptions.packageMain) || + host.getCanonicalFileName(packageRelativePath + ".d.ts") === host.getCanonicalFileName(compilerOptions.packageMain)) { + return compilerOptions.packageName; + } + return combinePaths(compilerOptions.packageName, packageRelativePath); } function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b72bac505a0aa..cd4c07164be7a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -28,6 +28,25 @@ module ts { } return undefined; } + + export function findPackageFile(searchPath: string): string { + let fileName = "package.json"; + while (true) { + if (sys.fileExists(fileName)) { + return fileName; + } + + let parentPath = getDirectoryPath(searchPath); + if (parentPath === searchPath) { + break; + } + + searchPath = parentPath; + fileName = "../" + fileName; + } + + return undefined; + } export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { let currentDirectory: string; @@ -93,6 +112,24 @@ module ts { } } } + + function getCurrentDirectory(): string { + return currentDirectory || (currentDirectory = sys.getCurrentDirectory()); + } + + function getPackagePath(host?: EmitHost): string { + let searchPath = getCurrentDirectory(); + let packageFile = findPackageFile(searchPath); + if (packageFile) { + return getDirectoryPath(normalizePath(packageFile)); + } + + if (host) { + return host.getCommonSourceDirectory(); + } + + return searchPath; + } let newLine = options.newLine === NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed : @@ -103,7 +140,8 @@ module ts { getSourceFile, getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)), writeFile, - getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()), + getCurrentDirectory, + getPackagePath, useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine @@ -178,6 +216,7 @@ module ts { getTypeChecker, getDiagnosticsProducingTypeChecker, getCommonSourceDirectory: () => commonSourceDirectory, + getPackagePath: () => host.getPackagePath(), emit, getCurrentDirectory: () => host.getCurrentDirectory(), getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(), @@ -186,19 +225,21 @@ module ts { getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(), }; return program; - + function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { - return { + let emitHost: EmitHost = { getCanonicalFileName: fileName => host.getCanonicalFileName(fileName), getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, getCurrentDirectory: () => host.getCurrentDirectory(), + getPackagePath: () => host.getPackagePath(emitHost), getNewLine: () => host.getNewLine(), getSourceFile: program.getSourceFile, getSourceFiles: program.getSourceFiles, writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)), }; + return emitHost; } function getDiagnosticsProducingTypeChecker() { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8052f2de200fb..3652e246042b1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1881,6 +1881,7 @@ module ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; + /*@internal*/ getPackagePath(host?: EmitHost): string; } export interface TextSpan { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0bb0065d1b0a9..a3338d5ac4b0b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -35,8 +35,10 @@ module ts { getCommonSourceDirectory(): string; getCanonicalFileName(fileName: string): string; getNewLine(): string; + /*@internal*/ getPackagePath(): string; writeFile: WriteFileCallback; + } // Pool writers to avoid needing to allocate them for every symbol we write. From 57a81e6cf9ac136b85214a474d128066f02a06bc Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 May 2015 18:29:46 -0700 Subject: [PATCH 03/11] Updated services and harnesses and added a test --- src/harness/harness.ts | 49 +++++++++++++++---- src/harness/projectsRunner.ts | 3 +- src/services/services.ts | 4 +- .../cases/compiler/packageDeclarationEmit.ts | 13 +++++ 4 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 tests/cases/compiler/packageDeclarationEmit.ts diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 97d53a6b75e71..933376929db47 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -45,10 +45,10 @@ module Utils { export function getExecutionEnvironment() { if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { return ExecutionEnvironment.CScript; - } else if (typeof window !== "undefined") { + } else if (typeof window !== "undefined") { return ExecutionEnvironment.Browser; - } else { - return ExecutionEnvironment.Node; + } else { + return ExecutionEnvironment.Node; } } @@ -878,7 +878,8 @@ module Harness { writeFile, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: () => newLine + getNewLine: () => newLine, + getPackagePath: getCurrentDirectory }; } @@ -1048,6 +1049,18 @@ module Harness { case 'declaration': options.declaration = !!setting.value; break; + + case 'packagename': + options.packageName = setting.value; + break; + + case 'packagemain': + options.packageMain = setting.value; + break; + + case 'packagedeclaration': + options.packageDeclaration = setting.value; + break; case 'newline': if (setting.value.toLowerCase() === 'crlf') { @@ -1149,7 +1162,7 @@ module Harness { options?: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file currentDirectory?: string) { - if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) { + if (options.declaration && result.errors.length === 0 && (options.packageDeclaration ? result.declFilesCode.length !== 1 : result.declFilesCode.length !== result.files.length)) { throw new Error('There were no errors and declFiles generated did not match number of js files generated'); } @@ -1158,12 +1171,27 @@ module Harness { var declInputFiles: { unitName: string; content: string }[] = []; var declOtherFiles: { unitName: string; content: string }[] = []; var declResult: Harness.Compiler.CompilerResult; - - ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); - ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); + if (options.packageDeclaration) { + let file = ts.forEach(result.declFilesCode, declFile => declFile.fileName === options.packageDeclaration ? declFile : undefined); + declInputFiles.push({ unitName: file.fileName, content: file.code }); + ts.forEach(inputFiles, file => { + if (isDTS(file.unitName)) { + declInputFiles.push(file); + } + }); + ts.forEach(otherFiles, file => { + if (isDTS(file.unitName)) { + declOtherFiles.push(file); + } + }); + } + else { + ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); + ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); + } + this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) { declResult = compileResult; }, settingsCallback, options, currentDirectory); - return { declInputFiles, declOtherFiles, declResult }; } @@ -1510,7 +1538,8 @@ module Harness { "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal", "separatecompilation", "inlinesourcemap", "maproot", "sourceroot", - "inlinesources", "emitdecoratormetadata"]; + "inlinesources", "emitdecoratormetadata", "packagemain", "packagename", + "packagedeclaration"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 39221d55b2945..017cf22837808 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -189,7 +189,8 @@ class ProjectRunner extends RunnerBase { getCurrentDirectory, getCanonicalFileName: Harness.Compiler.getCanonicalFileName, useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, - getNewLine: () => ts.sys.newLine + getNewLine: () => ts.sys.newLine, + getPackagePath: getCurrentDirectory }; } } diff --git a/src/services/services.ts b/src/services/services.ts index ede6fb8ca7baa..90037d21922e4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1794,6 +1794,7 @@ module ts { useCaseSensitiveFileNames: () => false, getCanonicalFileName: fileName => fileName, getCurrentDirectory: () => "", + getPackagePath: () => "", getNewLine: () => (sys && sys.newLine) || "\r\n" }; @@ -2419,7 +2420,8 @@ module ts { getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n", getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, - getCurrentDirectory: () => host.getCurrentDirectory() + getCurrentDirectory: () => host.getCurrentDirectory(), + getPackagePath: (emitHost?: EmitHost) => (emitHost && emitHost.getCommonSourceDirectory()) || host.getCurrentDirectory() }); // Release any files we have acquired in the old program but are diff --git a/tests/cases/compiler/packageDeclarationEmit.ts b/tests/cases/compiler/packageDeclarationEmit.ts new file mode 100644 index 0000000000000..97b98044b1113 --- /dev/null +++ b/tests/cases/compiler/packageDeclarationEmit.ts @@ -0,0 +1,13 @@ +// @module: commonjs +// @target: es5 +// @declaration: true +// @packageName: app +// @packageMain: index.ts +// @packageDeclaration: app.d.ts + +// @filename: index.ts +export * from './ext'; + +// @filename: ext.ts +export function func(): void { +} \ No newline at end of file From 8a1c7c53452be478fc821ea2e7d953fe5280fabb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 May 2015 21:25:02 -0700 Subject: [PATCH 04/11] fixed harness to support packageDeclaration --- src/harness/harness.ts | 16 ++++------- .../reference/packageDeclarationEmit.js | 28 +++++++++++++++++++ .../reference/packageDeclarationEmit.symbols | 8 ++++++ .../reference/packageDeclarationEmit.types | 8 ++++++ ...ateCompilationUnspecifiedModule.errors.txt | 4 +-- 5 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/baselines/reference/packageDeclarationEmit.js create mode 100644 tests/baselines/reference/packageDeclarationEmit.symbols create mode 100644 tests/baselines/reference/packageDeclarationEmit.types diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 933376929db47..595370aee7ff6 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1173,17 +1173,11 @@ module Harness { var declResult: Harness.Compiler.CompilerResult; if (options.packageDeclaration) { let file = ts.forEach(result.declFilesCode, declFile => declFile.fileName === options.packageDeclaration ? declFile : undefined); - declInputFiles.push({ unitName: file.fileName, content: file.code }); - ts.forEach(inputFiles, file => { - if (isDTS(file.unitName)) { - declInputFiles.push(file); - } - }); - ts.forEach(otherFiles, file => { - if (isDTS(file.unitName)) { - declOtherFiles.push(file); - } - }); + if (file) { + declInputFiles.push({ unitName: file.fileName, content: file.code }); + } + ts.forEach(inputFiles, file => isDTS(file.unitName) && declInputFiles.push(file)); + ts.forEach(otherFiles, file => isDTS(file.unitName) && declOtherFiles.push(file)); } else { ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); diff --git a/tests/baselines/reference/packageDeclarationEmit.js b/tests/baselines/reference/packageDeclarationEmit.js new file mode 100644 index 0000000000000..9471cccd46179 --- /dev/null +++ b/tests/baselines/reference/packageDeclarationEmit.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/packageDeclarationEmit.ts] //// + +//// [index.ts] + +export * from './ext'; + +//// [ext.ts] +export function func(): void { +} + +//// [ext.js] +function func() { +} +exports.func = func; +//// [index.js] +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +__export(require('./ext')); + + +//// [app.d.ts] +declare module "app/tests/cases/compiler/ext" { + function func(): void; +} +declare module "app/tests/cases/compiler/index" { + export * from "app/tests/cases/compiler/ext"; +} \ No newline at end of file diff --git a/tests/baselines/reference/packageDeclarationEmit.symbols b/tests/baselines/reference/packageDeclarationEmit.symbols new file mode 100644 index 0000000000000..62f3d9f1c2fc8 --- /dev/null +++ b/tests/baselines/reference/packageDeclarationEmit.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/index.ts === + +No type information for this code.export * from './ext'; +No type information for this code. +No type information for this code.=== tests/cases/compiler/ext.ts === +export function func(): void { +>func : Symbol(func, Decl(ext.ts, 0, 0)) +} diff --git a/tests/baselines/reference/packageDeclarationEmit.types b/tests/baselines/reference/packageDeclarationEmit.types new file mode 100644 index 0000000000000..76b096bf90978 --- /dev/null +++ b/tests/baselines/reference/packageDeclarationEmit.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/index.ts === + +No type information for this code.export * from './ext'; +No type information for this code. +No type information for this code.=== tests/cases/compiler/ext.ts === +export function func(): void { +>func : () => void +} diff --git a/tests/baselines/reference/separateCompilationUnspecifiedModule.errors.txt b/tests/baselines/reference/separateCompilationUnspecifiedModule.errors.txt index ab0fd7ffe9d5d..a89dd011f1f33 100644 --- a/tests/baselines/reference/separateCompilationUnspecifiedModule.errors.txt +++ b/tests/baselines/reference/separateCompilationUnspecifiedModule.errors.txt @@ -1,6 +1,6 @@ -error TS5047: Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher. +error TS5047: Option 'separateCompilation' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher. -!!! error TS5047: Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher. +!!! error TS5047: Option 'separateCompilation' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher. ==== tests/cases/compiler/separateCompilationUnspecifiedModule.ts (0 errors) ==== export var x; \ No newline at end of file From 895a096ad554c9400963059ddb2018bf7a5d47c5 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 8 May 2015 17:37:27 -0700 Subject: [PATCH 05/11] Cleanup, bug fixes --- src/compiler/declarationEmitter.ts | 43 +++++++++---------- .../diagnosticInformationMap.generated.ts | 3 +- src/compiler/diagnosticMessages.json | 6 +-- src/compiler/emitter.ts | 17 ++++---- src/compiler/program.ts | 9 ++-- 5 files changed, 34 insertions(+), 44 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 2db9c9bc84fb7..19af5624ef2ee 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -37,12 +37,11 @@ module ts { return diagnostics; } - function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit { + function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile, isPackageDeclaration?: boolean): DeclarationEmit { let newLine = host.getNewLine(); let compilerOptions = host.getCompilerOptions(); let languageVersion = compilerOptions.target || ScriptTarget.ES3; - let isPackage = (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) != undefined; let packageMainFile: string; let write: (s: string) => void; let writeLine: () => void; @@ -66,8 +65,8 @@ module ts { // and we could be collecting these paths from multiple files into single one with --out option let referencePathsOutput = ""; - if (isPackage) { - packageMainFile = host.getCanonicalFileName(compilerOptions.packageMain); + if (isPackageDeclaration) { + packageMainFile = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageMain))); } if (root) { @@ -111,7 +110,7 @@ module ts { // Emit references corresponding to this file let emittedReferencedFiles: SourceFile[] = []; for (let sourceFile of sortSourceFiles(host.getSourceFiles())) { - if (!isExternalModuleOrDeclarationFile(sourceFile) || (isPackage && isExternalModule(sourceFile))) { + if (!isExternalModuleOrDeclarationFile(sourceFile) || (isPackageDeclaration && isExternalModule(sourceFile))) { // Check what references need to be added if (!compilerOptions.noResolve) { for (let fileReference of sourceFile.referencedFiles) { @@ -123,13 +122,13 @@ module ts { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); - } + } } } writeLine(); emitSourceFile(sourceFile); - } + } } } @@ -141,7 +140,7 @@ module ts { } function sortSourceFiles(sourceFiles: SourceFile[]) { - if (isPackage) { + if (isPackageDeclaration) { let indices = new Array(sourceFiles.length); for (let i = 0; i < sourceFiles.length; ++i) indices[i] = i; indices.sort((left, right) => { @@ -476,24 +475,20 @@ module ts { currentSourceFile = node; enclosingDeclaration = node; - if (isPackage) { + if (isPackageDeclaration && isExternalModule(node)) { // compute file name relative to main - let packageQualifiedModuleName: string; - if (packageMainFile === node.fileName) { - packageQualifiedModuleName = compilerOptions.packageName; - } - else { - let sourcePath = removeFileExtension(node.fileName); - packageQualifiedModuleName = getPackageQualifiedPath(host, sourcePath, "."); - } - write(`declare module "${packageQualifiedModuleName}" {`); + let sourcePath = removeFileExtension(node.fileName); + let packageQualifiedModuleName = getPackageQualifiedPath(host, sourcePath, "."); + write("declare module \""); + write(escapeString(packageQualifiedModuleName)); + write("\" {"); increaseIndent(); writeLine(); } emitLines(node.statements); - if (isPackage) { + if (isPackageDeclaration && isExternalModule(node)) { decreaseIndent(); writeLine(); write("}"); @@ -621,7 +616,7 @@ module ts { function emitModuleElementDeclarationFlags(node: Node) { // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent === currentSourceFile && !isPackage) { + if (node.parent === currentSourceFile && !(isPackageDeclaration && isExternalModule(currentSourceFile))) { // If the node is exported if (node.flags & NodeFlags.Export) { write("export "); @@ -758,13 +753,15 @@ module ts { } if (node.moduleSpecifier) { write(" from "); - if (isPackage) { + if (isPackageDeclaration) { let moduleNameText = (node.moduleSpecifier).text; let searchPath = getDirectoryPath(currentSourceFile.fileName); let searchName = normalizePath(combinePaths(searchPath, moduleNameText)); if (host.getSourceFile(searchName + ".ts") || host.getSourceFile(searchName + ".d.ts")) { let packageQualifiedPath = getPackageQualifiedPath(host, moduleNameText, searchPath); - write(`"${packageQualifiedPath}"`); + write("\""); + write(escapeString(packageQualifiedPath)); + write("\""); } else { writeTextOfNode(currentSourceFile, node.moduleSpecifier); @@ -1667,7 +1664,7 @@ module ts { /* @internal */ export function writePackageDeclarationFile(dtsFilePath: string, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) { let compilerOptions = host.getCompilerOptions(); - let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, dtsFilePath); + let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, dtsFilePath, /*root*/ undefined, /*isPackageDeclaration*/ true); if (!emitDeclarationResult.reportedDeclarationError) { let declarationOutput = emitDeclarationResult.referencePathsOutput + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index c6b34182e3351..2903902997cff 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -458,8 +458,7 @@ module ts { Option_sourceRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5049, category: DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified with option 'inlineSourceMap'." }, Option_mapRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5050, category: DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified with option 'inlineSourceMap'." }, Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided: { code: 5051, category: DiagnosticCategory.Error, key: "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided." }, - Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0: { code: 5052, category: DiagnosticCategory.Error, key: "Options 'packageName', 'packageMain', and 'packageDeclaration' must all be specified with option '{0}'." }, - Option_declaration_must_be_specified_with_options_packageName_packageMain_and_packageDeclaration: { code: 5053, category: DiagnosticCategory.Error, key: "Option 'declaration' must be specified with options 'packageName', 'packageMain', and 'packageDeclaration'." }, + Options_0_and_1_must_also_be_specified_with_option_2: { code: 5052, category: DiagnosticCategory.Error, key: "Options '{0}' and '{1}' must also be specified with option '{2}'." }, Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5054, category: DiagnosticCategory.Error, key: "Options 'packageName', 'packageMain', and 'packageDeclaration' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher." }, Option_0_cannot_be_specified_with_option_separateCompilation: { code: 5055, category: DiagnosticCategory.Error, key: "Option '{0}' cannot be specified with option 'separateCompilation'." }, Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 838ddf57f284c..903a4b1b17440 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1821,14 +1821,10 @@ "category": "Error", "code": 5051 }, - "Options 'packageName', 'packageMain', and 'packageDeclaration' must all be specified with option '{0}'.": { + "Options '{0}' and '{1}' must also be specified with option '{2}'.": { "category": "Error", "code": 5052 }, - "Option 'declaration' must be specified with options 'packageName', 'packageMain', and 'packageDeclaration'.": { - "category": "Error", - "code": 5053 - }, "Options 'packageName', 'packageMain', and 'packageDeclaration' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher.": { "category": "Error", "code": 5054 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e4e9391310240..27d97237dc65b 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -79,6 +79,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) { emitFile(compilerOptions.out); } + + if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { + let packageMainPath = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageMain))); + if (targetSourceFile.fileName === packageMainPath) { + let packageDeclarationPath = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageDeclaration))); + writePackageDeclarationFile(packageDeclarationPath, host, resolver, diagnostics); + } + } } // Sort and make the unique list of diagnostics @@ -6051,14 +6059,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitJavaScript(jsFilePath, sourceFile); if (compilerOptions.declaration) { - if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { - if (sourceFile.fileName === host.getCanonicalFileName(compilerOptions.packageMain)) { - writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); - } - } - else { - writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); - } + writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); } } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index cd4c07164be7a..40558a750bb9f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -627,23 +627,20 @@ module ts { if (options.packageMain || options.packageName || options.packageDeclaration) { if (!options.packageMain) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageMain")); + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageName", "packageDeclaration", "packageMain")); return; } if (!options.packageName) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageName")); + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageDeclaration", "packageMain", "packageName")); return; } if (!options.packageDeclaration) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_must_all_be_specified_with_option_0, "packageDeclaration")); + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageMain", "packageName", "packageDeclaration")); return; } if (options.module === ModuleKind.None && options.target < ScriptTarget.ES6) { diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher)); } - if (!options.declaration) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_declaration_must_be_specified_with_options_packageName_packageMain_and_packageDeclaration)); - } } let languageVersion = options.target || ScriptTarget.ES3; From 28438bfaa8da48648a7d7f765b49f837a1978b06 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sat, 9 May 2015 23:16:40 -0700 Subject: [PATCH 06/11] Updated test harness --- src/harness/harness.ts | 23 +++++++++++-------- .../cases/compiler/packageDeclarationEmit.ts | 1 - 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 595370aee7ff6..1d228e54a184d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1162,12 +1162,20 @@ module Harness { options?: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file currentDirectory?: string) { - if (options.declaration && result.errors.length === 0 && (options.packageDeclaration ? result.declFilesCode.length !== 1 : result.declFilesCode.length !== result.files.length)) { + let expectedDeclFileCount = 0; + if (options.declaration) { + expectedDeclFileCount += result.files.length; + } + if (options.packageDeclaration) { + expectedDeclFileCount++; + } + + if ((options.declaration || options.packageDeclaration) && result.errors.length === 0 && (result.declFilesCode.length !== expectedDeclFileCount)) { throw new Error('There were no errors and declFiles generated did not match number of js files generated'); } // if the .d.ts is non-empty, confirm it compiles correctly as well - if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) { + if ((options.declaration || options.packageDeclaration) && result.errors.length === 0 && result.declFilesCode.length > 0) { var declInputFiles: { unitName: string; content: string }[] = []; var declOtherFiles: { unitName: string; content: string }[] = []; var declResult: Harness.Compiler.CompilerResult; @@ -1176,13 +1184,10 @@ module Harness { if (file) { declInputFiles.push({ unitName: file.fileName, content: file.code }); } - ts.forEach(inputFiles, file => isDTS(file.unitName) && declInputFiles.push(file)); - ts.forEach(otherFiles, file => isDTS(file.unitName) && declOtherFiles.push(file)); - } - else { - ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); - ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); } + + ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); + ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) { declResult = compileResult; }, settingsCallback, options, currentDirectory); @@ -1193,7 +1198,7 @@ module Harness { if (isDTS(file.unitName)) { dtsFiles.push(file); } - else if (isTS(file.unitName)) { + else if (isTS(file.unitName) && options.declaration) { var declFile = findResultCodeFile(file.unitName); if (!findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); diff --git a/tests/cases/compiler/packageDeclarationEmit.ts b/tests/cases/compiler/packageDeclarationEmit.ts index 97b98044b1113..84942a1105217 100644 --- a/tests/cases/compiler/packageDeclarationEmit.ts +++ b/tests/cases/compiler/packageDeclarationEmit.ts @@ -1,6 +1,5 @@ // @module: commonjs // @target: es5 -// @declaration: true // @packageName: app // @packageMain: index.ts // @packageDeclaration: app.d.ts From 1f86bfa3416f62e71eb74eca00cf31a7b71f7f08 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 11 May 2015 15:04:17 -0700 Subject: [PATCH 07/11] Some cleanup and reorganization of code --- src/compiler/declarationEmitter.ts | 102 +++++++++++++++++--------- src/compiler/emitter.ts | 13 ++-- src/compiler/program.ts | 15 ++-- src/compiler/types.ts | 3 +- src/compiler/utilities.ts | 31 +++++++- src/harness/harness.ts | 2 +- src/harness/harnessLanguageService.ts | 1 + src/harness/projectsRunner.ts | 2 +- src/services/services.ts | 5 +- src/services/shims.ts | 9 +++ 10 files changed, 123 insertions(+), 60 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 19af5624ef2ee..74fe260da46cf 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -34,6 +34,15 @@ module ts { let diagnostics: Diagnostic[] = []; let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js"); emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile); + + let packageDeclaration = getPackageDeclaration(host); + let compilerOptions = host.getCompilerOptions(); + if (packageDeclaration) { + if (!targetSourceFile || isPackageMain(targetSourceFile, host)) { + writePackageDeclarationFile(packageDeclaration, host, resolver, diagnostics); + } + } + return diagnostics; } @@ -42,7 +51,6 @@ module ts { let compilerOptions = host.getCompilerOptions(); let languageVersion = compilerOptions.target || ScriptTarget.ES3; - let packageMainFile: string; let write: (s: string) => void; let writeLine: () => void; let increaseIndent: () => void; @@ -66,10 +74,30 @@ module ts { let referencePathsOutput = ""; if (isPackageDeclaration) { - packageMainFile = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageMain))); - } + // Emitting a package declaration, so emit all of the source declarations + let emittedReferencedFiles: SourceFile[] = []; + for (let sourceFile of sortSourceFiles(host.getSourceFiles())) { + if (!isDeclarationFile(sourceFile)) { + // Check what references need to be added + if (!compilerOptions.noResolve) { + for (let fileReference of sourceFile.referencedFiles) { + let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); - if (root) { + // If the reference file is a declaration file or an external module, emit that reference + if (referencedFile && (isDeclarationFile(referencedFile) && + !contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted + writeReferencePath(referencedFile); + emittedReferencedFiles.push(referencedFile); + } + } + } + + writeLine(); + emitSourceFile(sourceFile); + } + } + } + else if (root) { // Emitting just a single file, so emit references in this file only if (!compilerOptions.noResolve) { let addedGlobalFileReference = false; @@ -109,8 +137,8 @@ module ts { else { // Emit references corresponding to this file let emittedReferencedFiles: SourceFile[] = []; - for (let sourceFile of sortSourceFiles(host.getSourceFiles())) { - if (!isExternalModuleOrDeclarationFile(sourceFile) || (isPackageDeclaration && isExternalModule(sourceFile))) { + for (let sourceFile of host.getSourceFiles()) { + if (!isExternalModuleOrDeclarationFile(sourceFile)) { // Check what references need to be added if (!compilerOptions.noResolve) { for (let fileReference of sourceFile.referencedFiles) { @@ -140,32 +168,28 @@ module ts { } function sortSourceFiles(sourceFiles: SourceFile[]) { - if (isPackageDeclaration) { - let indices = new Array(sourceFiles.length); - for (let i = 0; i < sourceFiles.length; ++i) indices[i] = i; - indices.sort((left, right) => { - let leftFile = sourceFiles[left]; - if (leftFile.fileName === packageMainFile) { - return -1; - } - - let rightFile = sourceFiles[right]; - if (rightFile.fileName === packageMainFile) { - return +1; - } - - return left - right; - }); - - let sorted = new Array(sourceFiles.length); - for (let i = 0; i < sourceFiles.length; ++i) { - sorted[i] = sourceFiles[indices[i]]; - } - - return sorted; + let indices = new Array(sourceFiles.length); + for (let i = 0; i < sourceFiles.length; ++i) indices[i] = i; + indices.sort((left, right) => { + let leftFile = sourceFiles[left]; + if (isPackageMain(leftFile, host)) { + return -1; + } + + let rightFile = sourceFiles[right]; + if (isPackageMain(rightFile, host)) { + return +1; + } + + return left - right; + }); + + let sorted = new Array(sourceFiles.length); + for (let i = 0; i < sourceFiles.length; ++i) { + sorted[i] = sourceFiles[indices[i]]; } - return sourceFiles; + return sorted; } function hasInternalAnnotation(range: CommentRange) { @@ -1631,18 +1655,24 @@ module ts { } function getPackageQualifiedPath(host: EmitHost, moduleName: string, basePath: string) { - let compilerOptions = host.getCompilerOptions(); - let modulePath = normalizePath(combinePaths(basePath, moduleName)); + let packageRoot = getPackageDirectory(host); + let modulePath = combinePaths(basePath, moduleName); let packageRelativePath = getRelativePathToDirectoryOrUrl( - host.getPackagePath(), + packageRoot, modulePath, host.getCurrentDirectory(), host.getCanonicalFileName, false); - if (host.getCanonicalFileName(packageRelativePath + ".ts") === host.getCanonicalFileName(compilerOptions.packageMain) || - host.getCanonicalFileName(packageRelativePath + ".d.ts") === host.getCanonicalFileName(compilerOptions.packageMain)) { + + let compilerOptions = host.getCompilerOptions(); + let packageMain = getPackageMain(host); + let packageAbsolutePath = getNormalizedAbsolutePath(packageRelativePath, packageRoot); + + if (host.getSourceFile(packageAbsolutePath + ".ts") === packageMain || + host.getSourceFile(packageAbsolutePath + ".d.ts") === packageMain) { return compilerOptions.packageName; - } + } + return combinePaths(compilerOptions.packageName, packageRelativePath); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 27d97237dc65b..bb964703b3794 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -53,6 +53,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; let diagnostics: Diagnostic[] = []; let newLine = host.getNewLine(); + let packageDeclaration = getPackageDeclaration(host); if (targetSourceFile === undefined) { forEach(host.getSourceFiles(), sourceFile => { @@ -66,8 +67,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitFile(compilerOptions.out); } - if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { - writePackageDeclarationFile(compilerOptions.packageDeclaration, host, resolver, diagnostics); + if (packageDeclaration) { + writePackageDeclarationFile(packageDeclaration, host, resolver, diagnostics); } } else { @@ -80,12 +81,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitFile(compilerOptions.out); } - if (compilerOptions.packageMain && compilerOptions.packageName && compilerOptions.packageDeclaration) { - let packageMainPath = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageMain))); - if (targetSourceFile.fileName === packageMainPath) { - let packageDeclarationPath = host.getCanonicalFileName(normalizePath(combinePaths(host.getCurrentDirectory(), compilerOptions.packageDeclaration))); - writePackageDeclarationFile(packageDeclarationPath, host, resolver, diagnostics); - } + if (packageDeclaration && isPackageMain(targetSourceFile, host)) { + writePackageDeclarationFile(packageDeclaration, host, resolver, diagnostics); } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 40558a750bb9f..8077209d44cec 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -117,17 +117,13 @@ module ts { return currentDirectory || (currentDirectory = sys.getCurrentDirectory()); } - function getPackagePath(host?: EmitHost): string { + function getPackageDirectory(): string { let searchPath = getCurrentDirectory(); let packageFile = findPackageFile(searchPath); if (packageFile) { return getDirectoryPath(normalizePath(packageFile)); } - if (host) { - return host.getCommonSourceDirectory(); - } - return searchPath; } @@ -141,7 +137,7 @@ module ts { getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)), writeFile, getCurrentDirectory, - getPackagePath, + getPackageDirectory, useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine @@ -216,9 +212,9 @@ module ts { getTypeChecker, getDiagnosticsProducingTypeChecker, getCommonSourceDirectory: () => commonSourceDirectory, - getPackagePath: () => host.getPackagePath(), emit, getCurrentDirectory: () => host.getCurrentDirectory(), + getPackageDirectory: host.getPackageDirectory ? () => host.getPackageDirectory() : () => host.getCurrentDirectory(), getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(), getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(), getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(), @@ -227,19 +223,18 @@ module ts { return program; function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { - let emitHost: EmitHost = { + return { getCanonicalFileName: fileName => host.getCanonicalFileName(fileName), getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, getCurrentDirectory: () => host.getCurrentDirectory(), - getPackagePath: () => host.getPackagePath(emitHost), + getPackageDirectory: host.getPackageDirectory ? () => host.getPackageDirectory() : () => host.getCurrentDirectory(), getNewLine: () => host.getNewLine(), getSourceFile: program.getSourceFile, getSourceFiles: program.getSourceFiles, writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)), }; - return emitHost; } function getDiagnosticsProducingTypeChecker() { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3652e246042b1..ca6ebfc597c39 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1032,6 +1032,7 @@ module ts { getCompilerOptions(): CompilerOptions; getSourceFile(fileName: string): SourceFile; getCurrentDirectory(): string; + /*@internal*/ getPackageDirectory?(): string; } export interface ParseConfigHost { @@ -1881,7 +1882,7 @@ module ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - /*@internal*/ getPackagePath(host?: EmitHost): string; + /*@internal*/ getPackageDirectory(): string; } export interface TextSpan { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a3338d5ac4b0b..4ce15dd0208d1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -35,7 +35,6 @@ module ts { getCommonSourceDirectory(): string; getCanonicalFileName(fileName: string): string; getNewLine(): string; - /*@internal*/ getPackagePath(): string; writeFile: WriteFileCallback; @@ -1699,6 +1698,36 @@ module ts { export function getLocalSymbolForExportDefault(symbol: Symbol) { return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined; } + + export function getPackageDirectory(host: ScriptReferenceHost) { + return host.getPackageDirectory ? host.getPackageDirectory() : host.getCurrentDirectory(); + } + + export function getPackageDeclaration(host: ScriptReferenceHost) { + let options = host.getCompilerOptions(); + if (options.packageDeclaration) { + let packageDeclaration = getNormalizedAbsolutePath(options.packageDeclaration, getPackageDirectory(host)); + return removeFileExtension(packageDeclaration) + ".d.ts"; + } + + return undefined; + } + + export function getPackageMain(host: ScriptReferenceHost) { + let options = host.getCompilerOptions(); + if (options.packageMain) { + let packageMain = getNormalizedAbsolutePath(options.packageMain, getPackageDirectory(host)); + let packageFile = host.getSourceFile(packageMain); + return packageFile; + } + + return undefined; + } + + export function isPackageMain(node: SourceFile, host: ScriptReferenceHost) { + let packageMain = getPackageMain(host); + return node === packageMain; + } /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 595370aee7ff6..81aea06ab1a29 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -879,7 +879,7 @@ module Harness { getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getNewLine: () => newLine, - getPackagePath: getCurrentDirectory + getPackageDirectory: getCurrentDirectory }; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 0e0b8d829183d..5e5e8bb46049a 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -186,6 +186,7 @@ module Harness.LanguageService { var script = this.getScriptInfo(fileName); return script ? script.version.toString() : undefined; } + getPackageDirectory(): string { return ""; } log(s: string): void { } trace(s: string): void { } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 017cf22837808..a85676261f792 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -190,7 +190,7 @@ class ProjectRunner extends RunnerBase { getCanonicalFileName: Harness.Compiler.getCanonicalFileName, useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, getNewLine: () => ts.sys.newLine, - getPackagePath: getCurrentDirectory + getPackageDirectory: getCurrentDirectory }; } } diff --git a/src/services/services.ts b/src/services/services.ts index 90037d21922e4..83df575d049bb 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -956,6 +956,7 @@ module ts { getCancellationToken?(): CancellationToken; getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; + /*@internal*/ getPackageDirectory?(): string; log? (s: string): void; trace? (s: string): void; error? (s: string): void; @@ -1794,7 +1795,7 @@ module ts { useCaseSensitiveFileNames: () => false, getCanonicalFileName: fileName => fileName, getCurrentDirectory: () => "", - getPackagePath: () => "", + getPackageDirectory: () => "", getNewLine: () => (sys && sys.newLine) || "\r\n" }; @@ -2421,7 +2422,7 @@ module ts { getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => host.getCurrentDirectory(), - getPackagePath: (emitHost?: EmitHost) => (emitHost && emitHost.getCommonSourceDirectory()) || host.getCurrentDirectory() + getPackageDirectory: () => host.getPackageDirectory ? host.getPackageDirectory() : host.getCurrentDirectory() }); // Release any files we have acquired in the old program but are diff --git a/src/services/shims.ts b/src/services/shims.ts index dc19b8eb79bc0..9322061cf5364 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -55,6 +55,7 @@ module ts { getCurrentDirectory(): string; getDefaultLibFileName(options: string): string; getNewLine?(): string; + getPackageDirectory?(): string; } /** Public interface of the the of a config service shim instance.*/ @@ -310,6 +311,14 @@ module ts { public getCurrentDirectory(): string { return this.shimHost.getCurrentDirectory(); } + + public getPackageDirectory(): string { + if (this.shimHost.getPackageDirectory) { + return this.shimHost.getPackageDirectory(); + } + + return this.getCurrentDirectory(); + } public getDefaultLibFileName(options: CompilerOptions): string { // Wrap the API changes for 1.5 release. This try/catch From 073da995ccd146a82399c9a8c6ff25c22c6ad4ac Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 May 2015 13:26:43 -0700 Subject: [PATCH 08/11] Added support for package paths in ImportEqualsDeclaration emit --- src/compiler/declarationEmitter.ts | 46 ++++++++++++++++-------------- src/compiler/utilities.ts | 14 +++++---- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 74fe260da46cf..d51100d7b175b 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -684,7 +684,7 @@ module ts { } else { write("require("); - writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node)); + emitModuleSpecifier(getExternalModuleImportEqualsDeclarationExpression(node)); write(");"); } writer.writeLine(); @@ -741,10 +741,30 @@ module ts { } write(" from "); } - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitModuleSpecifier(node.moduleSpecifier); write(";"); writer.writeLine(); } + + function emitModuleSpecifier(node: Expression) { + if (isPackageDeclaration) { + let moduleNameText = (node).text; + let searchPath = getDirectoryPath(currentSourceFile.fileName); + let searchName = normalizePath(combinePaths(searchPath, moduleNameText)); + if (host.getSourceFile(searchName + ".ts") || host.getSourceFile(searchName + ".d.ts")) { + let packageQualifiedPath = getPackageQualifiedPath(host, moduleNameText, searchPath); + write("\""); + write(escapeString(packageQualifiedPath)); + write("\""); + } + else { + writeTextOfNode(currentSourceFile, node); + } + } + else { + writeTextOfNode(currentSourceFile, node); + } + } function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { if (node.propertyName) { @@ -777,23 +797,7 @@ module ts { } if (node.moduleSpecifier) { write(" from "); - if (isPackageDeclaration) { - let moduleNameText = (node.moduleSpecifier).text; - let searchPath = getDirectoryPath(currentSourceFile.fileName); - let searchName = normalizePath(combinePaths(searchPath, moduleNameText)); - if (host.getSourceFile(searchName + ".ts") || host.getSourceFile(searchName + ".d.ts")) { - let packageQualifiedPath = getPackageQualifiedPath(host, moduleNameText, searchPath); - write("\""); - write(escapeString(packageQualifiedPath)); - write("\""); - } - else { - writeTextOfNode(currentSourceFile, node.moduleSpecifier); - } - } - else { - writeTextOfNode(currentSourceFile, node.moduleSpecifier); - } + emitModuleSpecifier(node.moduleSpecifier); } write(";"); writer.writeLine(); @@ -1668,8 +1672,8 @@ module ts { let packageMain = getPackageMain(host); let packageAbsolutePath = getNormalizedAbsolutePath(packageRelativePath, packageRoot); - if (host.getSourceFile(packageAbsolutePath + ".ts") === packageMain || - host.getSourceFile(packageAbsolutePath + ".d.ts") === packageMain) { + if (packageAbsolutePath + ".ts" === packageMain || + packageAbsolutePath + ".d.ts" === packageMain) { return compilerOptions.packageName; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4ce15dd0208d1..4087a66bbd0e1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1700,7 +1700,12 @@ module ts { } export function getPackageDirectory(host: ScriptReferenceHost) { - return host.getPackageDirectory ? host.getPackageDirectory() : host.getCurrentDirectory(); + let searchPath = host.getCurrentDirectory(); + if (host.getPackageDirectory) { + return getNormalizedAbsolutePath(host.getPackageDirectory(), searchPath); + } + + return searchPath; } export function getPackageDeclaration(host: ScriptReferenceHost) { @@ -1717,16 +1722,15 @@ module ts { let options = host.getCompilerOptions(); if (options.packageMain) { let packageMain = getNormalizedAbsolutePath(options.packageMain, getPackageDirectory(host)); - let packageFile = host.getSourceFile(packageMain); - return packageFile; + return packageMain; } return undefined; } export function isPackageMain(node: SourceFile, host: ScriptReferenceHost) { - let packageMain = getPackageMain(host); - return node === packageMain; + let packageMain = getPackageMain(host); + return node.fileName === packageMain; } /** From 5f41f6828d2ee1e80deff3b05895f314a95cf842 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 May 2015 17:28:11 -0700 Subject: [PATCH 09/11] Cleaned up package parameters, added packageDir option, added path comparison function --- src/compiler/commandLineParser.ts | 20 ++++- src/compiler/core.ts | 38 ++++++++++ src/compiler/declarationEmitter.ts | 26 ++++--- .../diagnosticInformationMap.generated.ts | 6 ++ src/compiler/diagnosticMessages.json | 27 ++++++- src/compiler/emitter.ts | 5 +- src/compiler/program.ts | 73 +++++++++++-------- src/compiler/types.ts | 11 ++- src/compiler/utilities.ts | 40 +--------- src/harness/harness.ts | 9 ++- src/services/services.ts | 5 +- 11 files changed, 164 insertions(+), 96 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 1267d4ae0fec5..cacaaaca7fdb4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -20,19 +20,31 @@ module ts { name: "packageMain", type: "string", isFilePath: true, - experimental: true + experimental: true, + description: Diagnostics.Specifies_the_main_module_for_the_package, + paramType: Diagnostics.FILE }, { name: "packageName", type: "string", - isFilePath: true, - experimental: true + experimental: true, + description: Diagnostics.Specifies_the_name_of_the_package, + paramType: Diagnostics.NAME }, { name: "packageDeclaration", type: "string", isFilePath: true, - experimental: true + experimental: true, + description: Diagnostics.Specifies_the_output_path_for_the_package_declaration, + paramType: Diagnostics.LOCATION + }, + { + name: "packageDir", + type: "string", + isFilePath: true, + experimental: true, + description: Diagnostics.Specifies_the_root_directory_of_the_package }, { name: "diagnostics", diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9b987ba77c619..f07acaf00cb1f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -20,6 +20,12 @@ module ts { EqualTo = 0, GreaterThan = 1 } + + export const enum StringComparison { + Ordinal = 0, + IgnoreCase = 1, + CurrentCultureIgnoreCase = 2 + } export interface StringSet extends Map { } @@ -485,6 +491,38 @@ module ts { return normalized; } + + export function compareStrings(x: string, y: string, comparison?: StringComparison): Comparison { + if (x === y) return Comparison.EqualTo; + if (x === undefined) return Comparison.LessThan; + if (y === undefined) return Comparison.GreaterThan; + if (comparison === StringComparison.CurrentCultureIgnoreCase) { + x = x.toLocaleLowerCase(); + y = y.toLocaleLowerCase(); + } + else if (comparison === StringComparison.IgnoreCase) { + x = x.toLowerCase(); + y = y.toLowerCase(); + } + + return x === y ? Comparison.EqualTo : x < y ? Comparison.LessThan : Comparison.GreaterThan; + } + + export function comparePaths(path1: string, path2: string, currentDirectory: string, ignoreCase?: boolean): Comparison { + let pathComponents1 = getNormalizedPathComponents(path1, currentDirectory); + let pathComponents2 = getNormalizedPathComponents(path2, currentDirectory); + let sharedLength = Math.min(pathComponents1.length, pathComponents2.length); + for (let i = 0; i < sharedLength; i++) { + let component1 = pathComponents1[i]; + let component2 = pathComponents2[i]; + let result = compareStrings(component1, component2, ignoreCase ? StringComparison.IgnoreCase : StringComparison.Ordinal); + if (result !== Comparison.EqualTo) { + return result; + } + } + + return compareValues(pathComponents1.length, pathComponents2.length); + } export function normalizePath(path: string): string { path = normalizeSlashes(path); diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index d51100d7b175b..d3ae0ca48f7f2 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -35,10 +35,11 @@ module ts { let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js"); emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile); - let packageDeclaration = getPackageDeclaration(host); - let compilerOptions = host.getCompilerOptions(); + let packageDeclaration = host.getPackageDeclaration(); if (packageDeclaration) { - if (!targetSourceFile || isPackageMain(targetSourceFile, host)) { + let packageMain = host.getPackageMain(); + if (!targetSourceFile || + comparePaths(targetSourceFile.fileName, host.getPackageMain(), host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo) { writePackageDeclarationFile(packageDeclaration, host, resolver, diagnostics); } } @@ -67,6 +68,7 @@ module ts { let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = []; let asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]; + let packageMain = isPackageDeclaration ? host.getPackageMain() : undefined; // Contains the reference paths that needs to go in the declaration file. // Collecting this separately because reference paths need to be first thing in the declaration file @@ -170,14 +172,16 @@ module ts { function sortSourceFiles(sourceFiles: SourceFile[]) { let indices = new Array(sourceFiles.length); for (let i = 0; i < sourceFiles.length; ++i) indices[i] = i; + let currentDirectory = host.getCurrentDirectory(); + let ignoreCase = !host.useCaseSensitiveFileNames(); indices.sort((left, right) => { let leftFile = sourceFiles[left]; - if (isPackageMain(leftFile, host)) { + if (comparePaths(leftFile.fileName, packageMain, currentDirectory, ignoreCase) === Comparison.EqualTo) { return -1; } let rightFile = sourceFiles[right]; - if (isPackageMain(rightFile, host)) { + if (comparePaths(rightFile.fileName, packageMain, currentDirectory, ignoreCase) === Comparison.EqualTo) { return +1; } @@ -1659,21 +1663,23 @@ module ts { } function getPackageQualifiedPath(host: EmitHost, moduleName: string, basePath: string) { - let packageRoot = getPackageDirectory(host); + let currentDirectory = host.getCurrentDirectory(); + let ignoreCase = !host.useCaseSensitiveFileNames(); + let packageRoot = host.getPackageDirectory(); let modulePath = combinePaths(basePath, moduleName); let packageRelativePath = getRelativePathToDirectoryOrUrl( packageRoot, modulePath, - host.getCurrentDirectory(), + currentDirectory, host.getCanonicalFileName, false); let compilerOptions = host.getCompilerOptions(); - let packageMain = getPackageMain(host); + let packageMain = host.getPackageMain(); let packageAbsolutePath = getNormalizedAbsolutePath(packageRelativePath, packageRoot); - if (packageAbsolutePath + ".ts" === packageMain || - packageAbsolutePath + ".d.ts" === packageMain) { + if (comparePaths(packageAbsolutePath + ".ts", packageMain, currentDirectory, ignoreCase) === Comparison.EqualTo || + comparePaths(packageAbsolutePath + ".d.ts", packageMain, currentDirectory, ignoreCase) === Comparison.EqualTo) { return compilerOptions.packageName; } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 2903902997cff..8904d9cb73aa7 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -461,6 +461,7 @@ module ts { Options_0_and_1_must_also_be_specified_with_option_2: { code: 5052, category: DiagnosticCategory.Error, key: "Options '{0}' and '{1}' must also be specified with option '{2}'." }, Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5054, category: DiagnosticCategory.Error, key: "Options 'packageName', 'packageMain', and 'packageDeclaration' can only be used when either option 'module' is provided or option 'target' is 'ES6' or higher." }, Option_0_cannot_be_specified_with_option_separateCompilation: { code: 5055, category: DiagnosticCategory.Error, key: "Option '{0}' cannot be specified with option 'separateCompilation'." }, + Option_noEmit_cannot_be_specified_with_option_packageDeclaration: { code: 5056, category: DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'packageDeclaration'." }, Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." }, Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." }, Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." }, @@ -510,6 +511,11 @@ module ts { Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix: { code: 6060, category: DiagnosticCategory.Message, key: "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix)." }, NEWLINE: { code: 6061, category: DiagnosticCategory.Message, key: "NEWLINE" }, Argument_for_newLine_option_must_be_CRLF_or_LF: { code: 6062, category: DiagnosticCategory.Error, key: "Argument for '--newLine' option must be 'CRLF' or 'LF'." }, + Specifies_the_main_module_for_the_package: { code: 6100, category: DiagnosticCategory.Message, key: "Specifies the main module for the package" }, + Specifies_the_name_of_the_package: { code: 6101, category: DiagnosticCategory.Message, key: "Specifies the name of the package" }, + Specifies_the_output_path_for_the_package_declaration: { code: 6102, category: DiagnosticCategory.Message, key: "Specifies the output path for the package declaration" }, + Specifies_the_root_directory_of_the_package: { code: 6103, category: DiagnosticCategory.Message, key: "Specifies the root directory of the package" }, + NAME: { code: 6104, category: DiagnosticCategory.Message, key: "NAME" }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 903a4b1b17440..aa630913254a3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1817,7 +1817,7 @@ "category": "Error", "code": 5050 }, - "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.": { + "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.": { "category": "Error", "code": 5051 }, @@ -1833,6 +1833,10 @@ "category": "Error", "code": 5055 }, + "Option 'noEmit' cannot be specified with option 'packageDeclaration'.": { + "category": "Error", + "code": 5056 + }, "Concatenate and emit output to single file.": { "category": "Message", @@ -2030,7 +2034,26 @@ "category": "Error", "code": 6062 }, - + "Specifies the main module for the package": { + "category": "Message", + "code": 6100 + }, + "Specifies the name of the package": { + "category": "Message", + "code": 6101 + }, + "Specifies the output path for the package declaration": { + "category": "Message", + "code": 6102 + }, + "Specifies the root directory of the package": { + "category": "Message", + "code": 6103 + }, + "NAME": { + "category": "Message", + "code": 6104 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index bb964703b3794..58e8e1d454d14 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -53,7 +53,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; let diagnostics: Diagnostic[] = []; let newLine = host.getNewLine(); - let packageDeclaration = getPackageDeclaration(host); + let packageDeclaration = host.getPackageDeclaration(); if (targetSourceFile === undefined) { forEach(host.getSourceFiles(), sourceFile => { @@ -81,7 +81,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitFile(compilerOptions.out); } - if (packageDeclaration && isPackageMain(targetSourceFile, host)) { + if (packageDeclaration && + comparePaths(targetSourceFile.fileName, host.getPackageMain(), host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo) { writePackageDeclarationFile(packageDeclaration, host, resolver, diagnostics); } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8077209d44cec..d42482a10fb41 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -116,16 +116,6 @@ module ts { function getCurrentDirectory(): string { return currentDirectory || (currentDirectory = sys.getCurrentDirectory()); } - - function getPackageDirectory(): string { - let searchPath = getCurrentDirectory(); - let packageFile = findPackageFile(searchPath); - if (packageFile) { - return getDirectoryPath(normalizePath(packageFile)); - } - - return searchPath; - } let newLine = options.newLine === NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed : @@ -137,7 +127,6 @@ module ts { getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)), writeFile, getCurrentDirectory, - getPackageDirectory, useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine @@ -189,6 +178,9 @@ module ts { let commonSourceDirectory: string; let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; + let packageDirectory: string; + let packageMain: string; + let packageDeclaration: string; let start = new Date().getTime(); @@ -214,7 +206,7 @@ module ts { getCommonSourceDirectory: () => commonSourceDirectory, emit, getCurrentDirectory: () => host.getCurrentDirectory(), - getPackageDirectory: host.getPackageDirectory ? () => host.getPackageDirectory() : () => host.getCurrentDirectory(), + getPackageDirectory: () => packageDirectory, getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(), getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(), getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(), @@ -228,15 +220,18 @@ module ts { getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, getCurrentDirectory: () => host.getCurrentDirectory(), - getPackageDirectory: host.getPackageDirectory ? () => host.getPackageDirectory() : () => host.getCurrentDirectory(), + getPackageDirectory: () => packageDirectory, + getPackageMain: () => packageMain, + getPackageDeclaration: () => packageDeclaration, getNewLine: () => host.getNewLine(), + useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(), getSourceFile: program.getSourceFile, getSourceFiles: program.getSourceFiles, writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)), }; } - + function getDiagnosticsProducingTypeChecker() { return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true)); } @@ -620,24 +615,6 @@ module ts { return; } - if (options.packageMain || options.packageName || options.packageDeclaration) { - if (!options.packageMain) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageName", "packageDeclaration", "packageMain")); - return; - } - if (!options.packageName) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageDeclaration", "packageMain", "packageName")); - return; - } - if (!options.packageDeclaration) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageMain", "packageName", "packageDeclaration")); - return; - } - if (options.module === ModuleKind.None && options.target < ScriptTarget.ES6) { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher)); - } - } - let languageVersion = options.target || ScriptTarget.ES3; let firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined); @@ -687,6 +664,34 @@ module ts { } } + if (options.packageMain || options.packageName || options.packageDeclaration) { + if (!options.packageMain) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageName", "packageDeclaration", "packageMain")); + return; + } + if (!options.packageName) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageDeclaration", "packageMain", "packageName")); + return; + } + if (!options.packageDeclaration) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_0_and_1_must_also_be_specified_with_option_2, "packageMain", "packageName", "packageDeclaration")); + return; + } + if (options.module === ModuleKind.None && options.target < ScriptTarget.ES6) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Options_packageName_packageMain_and_packageDeclaration_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher)); + } + + if (options.packageDir) { + packageDirectory = getNormalizedAbsolutePath(options.packageDir, host.getCurrentDirectory()); + } + else { + packageDirectory = commonSourceDirectory ? commonSourceDirectory : host.getCurrentDirectory(); + } + + packageMain = getNormalizedAbsolutePath(options.packageMain, packageDirectory); + packageDeclaration = removeFileExtension(getNormalizedAbsolutePath(options.packageDeclaration, packageDirectory)) + ".d.ts"; + } + if (options.noEmit) { if (options.out || options.outDir) { diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir)); @@ -695,6 +700,10 @@ module ts { if (options.declaration) { diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration)); } + + if (options.packageDeclaration) { + diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_packageDeclaration)); + } } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca6ebfc597c39..9691515201ad7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1032,7 +1032,7 @@ module ts { getCompilerOptions(): CompilerOptions; getSourceFile(fileName: string): SourceFile; getCurrentDirectory(): string; - /*@internal*/ getPackageDirectory?(): string; + /*@internal*/ getPackageDirectory(): string; } export interface ParseConfigHost { @@ -1682,6 +1682,7 @@ module ts { packageMain?: string; packageName?: string; packageDeclaration?: string; + packageDir?: string; /* @internal */ stripInternal?: boolean; [option: string]: string | number | boolean; } @@ -1731,6 +1732,13 @@ module ts { error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type' experimental?: boolean; } + + /* @internal */ + export interface PackageFile { + name: string; + main: string; + typings: string; + } /* @internal */ export const enum CharacterCodes { @@ -1882,7 +1890,6 @@ module ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - /*@internal*/ getPackageDirectory(): string; } export interface TextSpan { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4087a66bbd0e1..854ebe5cf8e33 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -31,13 +31,13 @@ module ts { export interface EmitHost extends ScriptReferenceHost { getSourceFiles(): SourceFile[]; - getCommonSourceDirectory(): string; getCanonicalFileName(fileName: string): string; getNewLine(): string; - + useCaseSensitiveFileNames(): boolean; + getPackageMain(): string; + getPackageDeclaration(): string; writeFile: WriteFileCallback; - } // Pool writers to avoid needing to allocate them for every symbol we write. @@ -1698,40 +1698,6 @@ module ts { export function getLocalSymbolForExportDefault(symbol: Symbol) { return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined; } - - export function getPackageDirectory(host: ScriptReferenceHost) { - let searchPath = host.getCurrentDirectory(); - if (host.getPackageDirectory) { - return getNormalizedAbsolutePath(host.getPackageDirectory(), searchPath); - } - - return searchPath; - } - - export function getPackageDeclaration(host: ScriptReferenceHost) { - let options = host.getCompilerOptions(); - if (options.packageDeclaration) { - let packageDeclaration = getNormalizedAbsolutePath(options.packageDeclaration, getPackageDirectory(host)); - return removeFileExtension(packageDeclaration) + ".d.ts"; - } - - return undefined; - } - - export function getPackageMain(host: ScriptReferenceHost) { - let options = host.getCompilerOptions(); - if (options.packageMain) { - let packageMain = getNormalizedAbsolutePath(options.packageMain, getPackageDirectory(host)); - return packageMain; - } - - return undefined; - } - - export function isPackageMain(node: SourceFile, host: ScriptReferenceHost) { - let packageMain = getPackageMain(host); - return node.fileName === packageMain; - } /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 140ea50785b7d..3542d639642da 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -878,8 +878,7 @@ module Harness { writeFile, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: () => newLine, - getPackageDirectory: getCurrentDirectory + getNewLine: () => newLine }; } @@ -1061,6 +1060,10 @@ module Harness { case 'packagedeclaration': options.packageDeclaration = setting.value; break; + + case 'packagedir': + options.packageDir = setting.value; + break; case 'newline': if (setting.value.toLowerCase() === 'crlf') { @@ -1180,7 +1183,7 @@ module Harness { var declOtherFiles: { unitName: string; content: string }[] = []; var declResult: Harness.Compiler.CompilerResult; if (options.packageDeclaration) { - let file = ts.forEach(result.declFilesCode, declFile => declFile.fileName === options.packageDeclaration ? declFile : undefined); + let file = ts.forEach(result.declFilesCode, declFile => ts.comparePaths(declFile.fileName, options.packageDeclaration, result.currentDirectoryForProgram, true) === ts.Comparison.EqualTo ? declFile : undefined); if (file) { declInputFiles.push({ unitName: file.fileName, content: file.code }); } diff --git a/src/services/services.ts b/src/services/services.ts index 83df575d049bb..ede6fb8ca7baa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -956,7 +956,6 @@ module ts { getCancellationToken?(): CancellationToken; getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; - /*@internal*/ getPackageDirectory?(): string; log? (s: string): void; trace? (s: string): void; error? (s: string): void; @@ -1795,7 +1794,6 @@ module ts { useCaseSensitiveFileNames: () => false, getCanonicalFileName: fileName => fileName, getCurrentDirectory: () => "", - getPackageDirectory: () => "", getNewLine: () => (sys && sys.newLine) || "\r\n" }; @@ -2421,8 +2419,7 @@ module ts { getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n", getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, - getCurrentDirectory: () => host.getCurrentDirectory(), - getPackageDirectory: () => host.getPackageDirectory ? host.getPackageDirectory() : host.getCurrentDirectory() + getCurrentDirectory: () => host.getCurrentDirectory() }); // Release any files we have acquired in the old program but are From b001006b9df8ce0f77f44736f77cf9abf0ca32d1 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 May 2015 17:32:02 -0700 Subject: [PATCH 10/11] Added paramType for packageDir --- src/compiler/commandLineParser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cacaaaca7fdb4..4cc7bfe569035 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -44,7 +44,8 @@ module ts { type: "string", isFilePath: true, experimental: true, - description: Diagnostics.Specifies_the_root_directory_of_the_package + description: Diagnostics.Specifies_the_root_directory_of_the_package, + paramType: Diagnostics.DIRECTORY }, { name: "diagnostics", From 1ecd2e78459b7525a1bc6ac07de125224e3c625f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 May 2015 17:33:23 -0700 Subject: [PATCH 11/11] Additional compiler option cleanup --- src/compiler/commandLineParser.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 4cc7bfe569035..3788545e3be83 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -17,19 +17,19 @@ module ts { description: Diagnostics.Generates_corresponding_d_ts_file, }, { - name: "packageMain", + name: "packageName", type: "string", - isFilePath: true, experimental: true, - description: Diagnostics.Specifies_the_main_module_for_the_package, - paramType: Diagnostics.FILE + description: Diagnostics.Specifies_the_name_of_the_package, + paramType: Diagnostics.NAME }, { - name: "packageName", + name: "packageMain", type: "string", + isFilePath: true, experimental: true, - description: Diagnostics.Specifies_the_name_of_the_package, - paramType: Diagnostics.NAME + description: Diagnostics.Specifies_the_main_module_for_the_package, + paramType: Diagnostics.FILE }, { name: "packageDeclaration", @@ -37,7 +37,7 @@ module ts { isFilePath: true, experimental: true, description: Diagnostics.Specifies_the_output_path_for_the_package_declaration, - paramType: Diagnostics.LOCATION + paramType: Diagnostics.FILE }, { name: "packageDir",