Skip to content

Commit

Permalink
Merge branch 'master' into completionsJsxAttributeInitializer
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Hanson committed Jan 25, 2018
2 parents 8486bf2 + 0b7f6d5 commit caf23d6
Show file tree
Hide file tree
Showing 81 changed files with 1,403 additions and 296 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "2.7.0",
"version": "2.8.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
Expand Down
23 changes: 13 additions & 10 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2424,12 +2424,15 @@ namespace ts {
const visitedSymbolTables: SymbolTable[] = [];
return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);

function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] | undefined {
/**
* @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already)
*/
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean): Symbol[] | undefined {
if (!pushIfUnique(visitedSymbolTables, symbols)) {
return undefined;
}

const result = trySymbolTable(symbols);
const result = trySymbolTable(symbols, ignoreQualification);
visitedSymbolTables.pop();
return result;
}
Expand All @@ -2441,22 +2444,22 @@ namespace ts {
!!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
}

function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol) {
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) {
return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) &&
// if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
// and if symbolFromSymbolTable or alias resolution matches the symbol,
// check the symbol can be qualified, it is only then this symbol is accessible
!some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
canQualifySymbol(symbolFromSymbolTable, meaning);
(ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning));
}

function isUMDExportSymbol(symbol: Symbol) {
return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
}

function trySymbolTable(symbols: SymbolTable) {
function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined) {
// If symbol is directly available by its name in the symbol table
if (isAccessible(symbols.get(symbol.escapedName))) {
if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) {
return [symbol];
}

Expand All @@ -2469,14 +2472,14 @@ namespace ts {
&& (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration))) {

const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) {
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
return [symbolFromSymbolTable];
}

// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
// but only if the symbolFromSymbolTable can be qualified
const candidateTable = getExportsOfSymbol(resolvedImportedSymbol);
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable);
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true);
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
}
Expand Down Expand Up @@ -16717,7 +16720,7 @@ namespace ts {
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);

let typeArguments: ReadonlyArray<TypeNode>;
let typeArguments: NodeArray<TypeNode>;

if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
typeArguments = (<CallExpression>node).typeArguments;
Expand Down Expand Up @@ -16846,7 +16849,7 @@ namespace ts {
max = Math.max(max, length(sig.typeParameters));
}
const paramCount = min < max ? min + "-" + max : min;
diagnostics.add(createDiagnosticForNode(node, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
}
else if (args) {
let min = Number.POSITIVE_INFINITY;
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "2.7";
export const versionMajorMinor = "2.8";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0`;
}
Expand Down Expand Up @@ -340,6 +340,10 @@ namespace ts {
return false;
}

export function arraysEqual<T>(a: ReadonlyArray<T>, b: ReadonlyArray<T>, equalityComparer: EqualityComparer<T> = equateValues): boolean {
return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i]));
}

export function indexOfAnyCharCode(text: string, charCodes: ReadonlyArray<number>, start?: number): number {
for (let i = start || 0; i < text.length; i++) {
if (contains(charCodes, text.charCodeAt(i))) {
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,10 @@ namespace ts {

/* @internal */
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string): number {
Debug.assert(line >= 0 && line < lineStarts.length);
if (line < 0 || line >= lineStarts.length) {
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
}

const res = lineStarts[line] + character;
if (line < lineStarts.length - 1) {
Debug.assert(res < lineStarts[line + 1]);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/esnext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ namespace ts {
}

function visitLabeledStatement(node: LabeledStatement) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
if (enclosingFunctionFlags & FunctionFlags.Async) {
const statement = unwrapInnermostStatementOfLabel(node);
if (statement.kind === SyntaxKind.ForOfStatement && (<ForOfStatement>statement).awaitModifier) {
return visitForOfStatement(<ForOfStatement>statement, node);
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,11 @@ namespace ts {
return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2, arg3);
}

export function createDiagnosticForNodeArray(sourceFile: SourceFile, nodes: NodeArray<Node>, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
const start = skipTrivia(sourceFile.text, nodes.pos);
return createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2, arg3);
}

export function createDiagnosticForNodeInSourceFile(sourceFile: SourceFile, node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
const span = getErrorSpanForNode(sourceFile, node);
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2, arg3);
Expand Down
51 changes: 17 additions & 34 deletions src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace FourSlash {
ts.disableIncrementalParsing = false;

// Represents a parsed source file with metadata
export interface FourSlashFile {
interface FourSlashFile {
// The contents of the file (with markers, etc stripped out)
content: string;
fileName: string;
Expand All @@ -34,7 +34,7 @@ namespace FourSlash {
}

// Represents a set of parsed source files and options
export interface FourSlashData {
interface FourSlashData {
// Global options (name/value pairs)
globalOptions: Harness.TestCaseParser.CompilerSettings;

Expand All @@ -59,7 +59,7 @@ namespace FourSlash {
export interface Marker {
fileName: string;
position: number;
data?: any;
data?: {};
}

export interface Range {
Expand Down Expand Up @@ -89,21 +89,6 @@ namespace FourSlash {
end: number;
}

export import IndentStyle = ts.IndentStyle;

const entityMap = ts.createMapFromTemplate({
"&": "&amp;",
"\"": "&quot;",
"'": "&#39;",
"/": "&#47;",
"<": "&lt;",
">": "&gt;"
});

export function escapeXmlAttributeValue(s: string) {
return s.replace(/[&<>"'\/]/g, ch => entityMap.get(ch));
}

// Name of testcase metadata including ts.CompilerOptions properties that will be used by globalOptions
// To add additional option, add property into the testOptMetadataNames, refer the property in either globalMetadataNames or fileMetadataNames
// Add cases into convertGlobalOptionsToCompilationsSettings function for the compiler to acknowledge such option from meta data
Expand Down Expand Up @@ -1079,7 +1064,7 @@ namespace FourSlash {
for (const reference of expectedReferences) {
const { fileName, start, end } = reference;
if (reference.marker && reference.marker.data) {
const { isWriteAccess, isDefinition } = reference.marker.data;
const { isWriteAccess, isDefinition } = reference.marker.data as { isWriteAccess?: boolean, isDefinition?: boolean };
this.verifyReferencesWorker(actualReferences, fileName, start, end, isWriteAccess, isDefinition);
}
else {
Expand Down Expand Up @@ -1108,7 +1093,16 @@ namespace FourSlash {
}
const fullExpected = ts.map<FourSlashInterface.ReferenceGroup, ReferenceGroupJson>(parts, ({ definition, ranges }) => ({
definition: typeof definition === "string" ? definition : { ...definition, range: textSpanFromRange(definition.range) },
references: ranges.map(rangeToReferenceEntry),
references: ranges.map<ts.ReferenceEntry>(r => {
const { isWriteAccess = false, isDefinition = false, isInString } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true };
return {
isWriteAccess,
isDefinition,
fileName: r.fileName,
textSpan: textSpanFromRange(r),
...(isInString ? { isInString: true } : undefined),
};
}),
}));

for (const startRange of toArray(startRanges)) {
Expand All @@ -1122,15 +1116,6 @@ namespace FourSlash {
});
this.assertObjectsEqual(fullActual, fullExpected);
}

function rangeToReferenceEntry(r: Range): ts.ReferenceEntry {
const { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined };
const result: ts.ReferenceEntry = { fileName: r.fileName, textSpan: textSpanFromRange(r), isWriteAccess: !!isWriteAccess, isDefinition: !!isDefinition };
if (isInString !== undefined) {
result.isInString = isInString;
}
return result;
}
}

public verifyNoReferences(markerNameOrRange?: string | Range) {
Expand Down Expand Up @@ -2587,12 +2572,10 @@ Actual: ${stringify(fullActual)}`);
actualTextArray.push(text);
scriptInfo.updateContent(originalContent);
}
const sortedExpectedArray = expectedTextArray.sort();
const sortedActualArray = actualTextArray.sort();
if (sortedExpectedArray.length !== sortedActualArray.length) {
this.raiseError(`Expected ${sortedExpectedArray.length} import fixes, got ${sortedActualArray.length}`);
if (expectedTextArray.length !== actualTextArray.length) {
this.raiseError(`Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}`);
}
ts.zipWith(sortedExpectedArray, sortedActualArray, (expected, actual, index) => {
ts.zipWith(expectedTextArray, actualTextArray, (expected, actual, index) => {
if (expected !== actual) {
this.raiseError(`Import fix at index ${index} doesn't match.\n${showTextDiff(expected, actual)}`);
}
Expand Down
7 changes: 7 additions & 0 deletions src/harness/unittests/extractConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,13 @@ let i: I = [#|{ a: 1 }|];
const myObj: { member(x: number, y: string): void } = {
member: [#|(x, y) => x + y|],
}
`);

testExtractConstant("extractConstant_CaseClauseExpression", `
switch (1) {
case [#|1|]:
break;
}
`);
});

Expand Down
52 changes: 52 additions & 0 deletions src/harness/unittests/extractRanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,58 @@ switch (x) {
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

testExtractRangeFailed("extractRangeFailed14",
`
switch(1) {
case [#|1:
break;|]
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

testExtractRangeFailed("extractRangeFailed15",
`
switch(1) {
case [#|1:
break|];
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

// Documentation only - it would be nice if the result were [$|1|]
testExtractRangeFailed("extractRangeFailed16",
`
switch(1) {
[#|case 1|]:
break;
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

// Documentation only - it would be nice if the result were [$|1|]
testExtractRangeFailed("extractRangeFailed17",
`
switch(1) {
[#|case 1:|]
break;
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

testExtractRangeFailed("extractRangeFailed18",
`[#|{ 1;|] }`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);

testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]);
});
}
39 changes: 39 additions & 0 deletions src/harness/unittests/tsserverProjectSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2846,6 +2846,45 @@ namespace ts.projectSystem {
const options = project.getCompilerOptions();
assert.equal(options.outDir, "C:/a/b", "");
});

it("dynamic file without external project", () => {
const file: FileOrFolder = {
path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js",
content: "var x = 10;"
};
const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
const projectService = createProjectService(host);
projectService.setCompilerOptionsForInferredProjects({
module: ModuleKind.CommonJS,
allowJs: true,
allowSyntheticDefaultImports: true,
allowNonTsExtensions: true
});
projectService.openClientFile(file.path, "var x = 10;");

projectService.checkNumberOfProjects({ inferredProjects: 1 });
const project = projectService.inferredProjects[0];
checkProjectRootFiles(project, [file.path]);
checkProjectActualFiles(project, [file.path, libFile.path]);

assert.strictEqual(projectService.getDefaultProjectForFile(server.toNormalizedPath(file.path), /*ensureProject*/ true), project);
const indexOfX = file.content.indexOf("x");
assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), {
kind: ScriptElementKind.variableElement,
kindModifiers: "",
textSpan: { start: indexOfX, length: 1 },
displayParts: [
{ text: "var", kind: "keyword" },
{ text: " ", kind: "space" },
{ text: "x", kind: "localName" },
{ text: ":", kind: "punctuation" },
{ text: " ", kind: "space" },
{ text: "number", kind: "keyword" }
],
documentation: [],
tags: []
});
});
});

describe("tsserverProjectSystem Proper errors", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<Cmt Name="ManifestData" />
<Cmt Name="Mnemonic" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
<Cmt Name="UIType" />
<Cmt Name="UTSData" />
<Cmt Name="UTSUI" />
Expand Down
Loading

0 comments on commit caf23d6

Please sign in to comment.