mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into allow-booleans-in-spreads
This commit is contained in:
+15
-1
@@ -14793,7 +14793,7 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
if (findAncestor(node, node => node.kind === SyntaxKind.PropertyDeclaration ? true : isExpression(node) ? false : "quit") &&
|
||||
if (isInPropertyInitializer(node) &&
|
||||
!isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)
|
||||
&& !isPropertyDeclaredInAncestorClass(prop)) {
|
||||
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeLeadingUnderscores(right.escapedText));
|
||||
@@ -14806,6 +14806,20 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isInPropertyInitializer(node: Node): boolean {
|
||||
return !!findAncestor(node, node => {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return true;
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
// We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`.
|
||||
return false;
|
||||
default:
|
||||
return isPartOfExpression(node) ? false : "quit";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass.
|
||||
* In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration.
|
||||
|
||||
+46
-47
@@ -22,10 +22,6 @@
|
||||
namespace FourSlash {
|
||||
ts.disableIncrementalParsing = false;
|
||||
|
||||
function normalizeNewLines(s: string) {
|
||||
return s.replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
// Represents a parsed source file with metadata
|
||||
export interface FourSlashFile {
|
||||
// The contents of the file (with markers, etc stripped out)
|
||||
@@ -364,7 +360,7 @@ namespace FourSlash {
|
||||
baseIndentSize: 0,
|
||||
indentSize: 4,
|
||||
tabSize: 4,
|
||||
newLineCharacter: Harness.IO.newLine(),
|
||||
newLineCharacter: "\n",
|
||||
convertTabsToSpaces: true,
|
||||
indentStyle: ts.IndentStyle.Smart,
|
||||
insertSpaceAfterCommaDelimiter: true,
|
||||
@@ -1603,7 +1599,7 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public printCurrentFileState(makeWhitespaceVisible: boolean, makeCaretVisible: boolean) {
|
||||
public printCurrentFileState(showWhitespace: boolean, makeCaretVisible: boolean) {
|
||||
for (const file of this.testData.files) {
|
||||
const active = (this.activeFile === file);
|
||||
Harness.IO.log(`=== Script (${file.fileName}) ${(active ? "(active, cursor at |)" : "")} ===`);
|
||||
@@ -1611,8 +1607,8 @@ namespace FourSlash {
|
||||
if (active) {
|
||||
content = content.substr(0, this.currentCaretPosition) + (makeCaretVisible ? "|" : "") + content.substr(this.currentCaretPosition);
|
||||
}
|
||||
if (makeWhitespaceVisible) {
|
||||
content = TestState.makeWhitespaceVisible(content);
|
||||
if (showWhitespace) {
|
||||
content = makeWhitespaceVisible(content);
|
||||
}
|
||||
Harness.IO.log(content);
|
||||
}
|
||||
@@ -2128,10 +2124,8 @@ namespace FourSlash {
|
||||
|
||||
public verifyCurrentFileContent(text: string) {
|
||||
const actual = this.getFileContent(this.activeFile.fileName);
|
||||
if (normalizeNewLines(actual) !== normalizeNewLines(text)) {
|
||||
throw new Error("verifyCurrentFileContent\n" +
|
||||
"\tExpected: \"" + TestState.makeWhitespaceVisible(text) + "\"\n" +
|
||||
"\t Actual: \"" + TestState.makeWhitespaceVisible(actual) + "\"");
|
||||
if (actual !== text) {
|
||||
throw new Error(`verifyCurrentFileContent failed:\n${showTextDiff(text, actual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2305,11 +2299,11 @@ namespace FourSlash {
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
const result = includeWhiteSpace
|
||||
? normalizeNewLines(actualText) === normalizeNewLines(expectedText)
|
||||
? actualText === expectedText
|
||||
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText);
|
||||
|
||||
if (!result) {
|
||||
this.raiseError(`Actual text doesn't match expected text. Actual:\n'${actualText}'\nExpected:\n'${expectedText}'`);
|
||||
this.raiseError(`Actual range text doesn't match expected text.\n${showTextDiff(expectedText, actualText)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2403,15 +2397,19 @@ namespace FourSlash {
|
||||
const originalContent = scriptInfo.content;
|
||||
for (const codeFix of codeFixes) {
|
||||
this.applyEdits(codeFix.changes[0].fileName, codeFix.changes[0].textChanges, /*isFormattingEdit*/ false);
|
||||
actualTextArray.push(this.normalizeNewlines(this.rangeText(ranges[0])));
|
||||
let text = this.rangeText(ranges[0]);
|
||||
// TODO:GH#18445 (remove this line to see errors in many `importNameCodeFix` tests)
|
||||
text = text.replace(/\r\n/g, "\n");
|
||||
actualTextArray.push(text);
|
||||
scriptInfo.updateContent(originalContent);
|
||||
}
|
||||
const sortedExpectedArray = ts.map(expectedTextArray, str => this.normalizeNewlines(str)).sort();
|
||||
const sortedExpectedArray = expectedTextArray.sort();
|
||||
const sortedActualArray = actualTextArray.sort();
|
||||
if (!ts.arrayIsEqualTo(sortedExpectedArray, sortedActualArray)) {
|
||||
this.raiseError(
|
||||
`Actual text array doesn't match expected text array. \nActual: \n'${sortedActualArray.join("\n\n")}'\n---\nExpected: \n'${sortedExpectedArray.join("\n\n")}'`);
|
||||
}
|
||||
ts.zipWith(sortedExpectedArray, sortedActualArray, (expected, actual, index) => {
|
||||
if (expected !== actual) {
|
||||
this.raiseError(`Import fix at index ${index} doesn't match.\n${showTextDiff(expected, actual)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined) {
|
||||
@@ -2431,7 +2429,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
if (actual.newText !== expected.newText) {
|
||||
this.raiseError(`${name} failed - expected insertion:\n"${this.clarifyNewlines(expected.newText)}"\nactual insertion:\n"${this.clarifyNewlines(actual.newText)}"`);
|
||||
this.raiseError(`${name} failed for expected insertion.\n${showTextDiff(expected.newText, actual.newText)}`);
|
||||
}
|
||||
|
||||
if (actual.caretOffset !== expected.caretOffset) {
|
||||
@@ -2440,17 +2438,6 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private clarifyNewlines(str: string) {
|
||||
return str.replace(/\r?\n/g, lineEnding => {
|
||||
const representation = lineEnding === "\r\n" ? "CRLF" : "LF";
|
||||
return "# - " + representation + lineEnding;
|
||||
});
|
||||
}
|
||||
|
||||
private normalizeNewlines(str: string) {
|
||||
return str.replace(/\r?\n/g, "\n");
|
||||
}
|
||||
|
||||
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
|
||||
|
||||
const openBraceMap = ts.createMapFromTemplate<ts.CharacterCodes>({
|
||||
@@ -2878,8 +2865,8 @@ namespace FourSlash {
|
||||
}
|
||||
const actualContent = this.getFileContent(this.activeFile.fileName);
|
||||
|
||||
if (this.normalizeNewlines(actualContent) !== this.normalizeNewlines(expectedContent)) {
|
||||
this.raiseError(`verifyFileAfterApplyingRefactors failed: expected:\n${expectedContent}\nactual:\n${actualContent}`);
|
||||
if (actualContent !== expectedContent) {
|
||||
this.raiseError(`verifyFileAfterApplyingRefactors failed:\n${showTextDiff(expectedContent, actualContent)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3014,10 +3001,6 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private static makeWhitespaceVisible(text: string) {
|
||||
return text.replace(/ /g, "\u00B7").replace(/\r/g, "\u00B6").replace(/\n/g, "\u2193\n").replace(/\t/g, "\u2192\ ");
|
||||
}
|
||||
|
||||
public setCancelled(numberOfCalls: number): void {
|
||||
this.cancellationToken.setCancelled(numberOfCalls);
|
||||
}
|
||||
@@ -3319,12 +3302,7 @@ ${code}
|
||||
let column = 1;
|
||||
|
||||
const flush = (lastSafeCharIndex: number) => {
|
||||
if (lastSafeCharIndex === undefined) {
|
||||
output = output + content.substr(lastNormalCharPosition);
|
||||
}
|
||||
else {
|
||||
output = output + content.substr(lastNormalCharPosition, lastSafeCharIndex - lastNormalCharPosition);
|
||||
}
|
||||
output = output + content.substr(lastNormalCharPosition, lastSafeCharIndex === undefined ? undefined : lastSafeCharIndex - lastNormalCharPosition);
|
||||
};
|
||||
|
||||
if (content.length > 0) {
|
||||
@@ -3511,6 +3489,27 @@ ${code}
|
||||
function toArray<T>(x: T | T[]): T[] {
|
||||
return ts.isArray(x) ? x : [x];
|
||||
}
|
||||
|
||||
function makeWhitespaceVisible(text: string) {
|
||||
return text.replace(/ /g, "\u00B7").replace(/\r/g, "\u00B6").replace(/\n/g, "\u2193\n").replace(/\t/g, "\u2192\ ");
|
||||
}
|
||||
|
||||
function showTextDiff(expected: string, actual: string): string {
|
||||
// Only show whitespace if the difference is whitespace-only.
|
||||
if (differOnlyByWhitespace(expected, actual)) {
|
||||
expected = makeWhitespaceVisible(expected);
|
||||
actual = makeWhitespaceVisible(actual);
|
||||
}
|
||||
return `Expected:\n${expected}\nActual:${actual}`;
|
||||
}
|
||||
|
||||
function differOnlyByWhitespace(a: string, b: string) {
|
||||
return stripWhitespace(a) === stripWhitespace(b);
|
||||
}
|
||||
|
||||
function stripWhitespace(s: string): string {
|
||||
return s.replace(/\s/g, "");
|
||||
}
|
||||
}
|
||||
|
||||
namespace FourSlashInterface {
|
||||
@@ -4143,15 +4142,15 @@ namespace FourSlashInterface {
|
||||
}
|
||||
|
||||
public printCurrentFileState() {
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/ false, /*makeCaretVisible*/ true);
|
||||
this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ true);
|
||||
}
|
||||
|
||||
public printCurrentFileStateWithWhitespace() {
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/ true, /*makeCaretVisible*/ true);
|
||||
this.state.printCurrentFileState(/*showWhitespace*/ true, /*makeCaretVisible*/ true);
|
||||
}
|
||||
|
||||
public printCurrentFileStateWithoutCaret() {
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/ false, /*makeCaretVisible*/ false);
|
||||
this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ false);
|
||||
}
|
||||
|
||||
public printCurrentQuickInfo() {
|
||||
|
||||
@@ -500,7 +500,8 @@ namespace Harness {
|
||||
export let IO: IO;
|
||||
|
||||
// harness always uses one kind of new line
|
||||
const harnessNewLine = "\r\n";
|
||||
// But note that `parseTestData` in `fourslash.ts` uses "\n"
|
||||
export const harnessNewLine = "\r\n";
|
||||
|
||||
// Root for file paths that are stored in a virtual file system
|
||||
export const virtualFileSystemRoot = "/";
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getNewLine(): string {
|
||||
return "\r\n";
|
||||
return harnessNewLine;
|
||||
}
|
||||
|
||||
public getFilenames(): string[] {
|
||||
|
||||
@@ -216,8 +216,8 @@ if (taskConfigsFolder) {
|
||||
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
const config = workerConfigs[i];
|
||||
// use last worker to run unit tests
|
||||
config.runUnitTests = i === workerCount - 1;
|
||||
// use last worker to run unit tests if we're not just running a single specific runner
|
||||
config.runUnitTests = runners.length !== 1 && i === workerCount - 1;
|
||||
Harness.IO.writeFile(ts.combinePaths(taskConfigsFolder, `task-config${i}.json`), JSON.stringify(workerConfigs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class RWCRunner extends RunnerBase {
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
// Read in and evaluate the test list
|
||||
const testList = this.enumerateTestFiles();
|
||||
const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles();
|
||||
for (let i = 0; i < testList.length; i++) {
|
||||
this.runTest(testList[i]);
|
||||
}
|
||||
|
||||
@@ -404,6 +404,12 @@ function test(x: number) {
|
||||
"Cannot extract range containing conditional break or continue statements."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed9",
|
||||
`var x = ([#||]1 + 2);`,
|
||||
[
|
||||
"Statement or expression expected."
|
||||
]);
|
||||
|
||||
testExtractMethod("extractMethod1",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
@@ -709,6 +715,57 @@ function M3() { }`);
|
||||
}
|
||||
M3() { }
|
||||
constructor() { }
|
||||
}`);
|
||||
// Shorthand property names
|
||||
testExtractMethod("extractMethod29",
|
||||
`interface UnaryExpression {
|
||||
kind: "Unary";
|
||||
operator: string;
|
||||
operand: any;
|
||||
}
|
||||
|
||||
function parseUnaryExpression(operator: string): UnaryExpression {
|
||||
[#|return {
|
||||
kind: "Unary",
|
||||
operator,
|
||||
operand: parsePrimaryExpression(),
|
||||
};|]
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): any {
|
||||
throw "Not implemented";
|
||||
}`);
|
||||
// Type parameter as declared type
|
||||
testExtractMethod("extractMethod30",
|
||||
`function F<T>() {
|
||||
[#|let t: T;|]
|
||||
}`);
|
||||
// Return in nested function
|
||||
testExtractMethod("extractMethod31",
|
||||
`namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
var f: () => number;
|
||||
[#|f = function (): number {
|
||||
return value;
|
||||
}|]
|
||||
}
|
||||
}`);
|
||||
// Return in nested class
|
||||
testExtractMethod("extractMethod32",
|
||||
`namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
[#|var c = class {
|
||||
M() {
|
||||
return value;
|
||||
}
|
||||
}|]
|
||||
}
|
||||
}`);
|
||||
});
|
||||
|
||||
|
||||
@@ -573,7 +573,7 @@ namespace ts.server {
|
||||
|
||||
getEditsForRefactor(
|
||||
fileName: string,
|
||||
_formatOptions: FormatCodeSettings,
|
||||
formatOptions: FormatCodeSettings,
|
||||
positionOrRange: number | TextRange,
|
||||
refactorName: string,
|
||||
actionName: string): RefactorEditInfo {
|
||||
@@ -581,6 +581,7 @@ namespace ts.server {
|
||||
const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetEditsForRefactorRequestArgs;
|
||||
args.refactor = refactorName;
|
||||
args.action = actionName;
|
||||
args.formatOptions = formatOptions;
|
||||
|
||||
const request = this.processRequest<protocol.GetEditsForRefactorRequest>(CommandNames.GetEditsForRefactor, args);
|
||||
const response = this.processResponse<protocol.GetEditsForRefactorResponse>(request);
|
||||
|
||||
@@ -494,6 +494,7 @@ namespace ts.server.protocol {
|
||||
refactor: string;
|
||||
/* The 'name' property from the refactoring action */
|
||||
action: string;
|
||||
formatOptions: FormatCodeSettings,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1488,7 +1488,7 @@ namespace ts.server {
|
||||
|
||||
const result = project.getLanguageService().getEditsForRefactor(
|
||||
file,
|
||||
this.projectService.getFormatCodeOptions(),
|
||||
convertFormatOptions(args.formatOptions),
|
||||
position || textRange,
|
||||
args.refactor,
|
||||
args.action
|
||||
|
||||
@@ -149,6 +149,11 @@ namespace ts.refactor.extractMethod {
|
||||
// exported only for tests
|
||||
export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan): RangeToExtract {
|
||||
const length = span.length || 0;
|
||||
|
||||
if (length === 0) {
|
||||
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] };
|
||||
}
|
||||
|
||||
// Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
|
||||
// This may fail (e.g. you select two statements in the root of a source file)
|
||||
let start = getParentNodeInSpan(getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span);
|
||||
@@ -855,6 +860,7 @@ namespace ts.refactor.extractMethod {
|
||||
return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
let returnValueProperty: string;
|
||||
let ignoreReturns = false;
|
||||
const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(<Expression>body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (writes || substitutions.size) {
|
||||
@@ -877,7 +883,7 @@ namespace ts.refactor.extractMethod {
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
if (node.kind === SyntaxKind.ReturnStatement && writes) {
|
||||
if (!ignoreReturns && node.kind === SyntaxKind.ReturnStatement && writes) {
|
||||
const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWrites(writes);
|
||||
if ((<ReturnStatement>node).expression) {
|
||||
if (!returnValueProperty) {
|
||||
@@ -893,8 +899,12 @@ namespace ts.refactor.extractMethod {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const oldIgnoreReturns = ignoreReturns;
|
||||
ignoreReturns = ignoreReturns || isFunctionLike(node) || isClassLike(node);
|
||||
const substitution = substitutions.get(getNodeId(node).toString());
|
||||
return substitution || visitEachChild(node, visitor, nullTransformationContext);
|
||||
const result = substitution || visitEachChild(node, visitor, nullTransformationContext);
|
||||
ignoreReturns = oldIgnoreReturns;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1161,7 +1171,11 @@ namespace ts.refactor.extractMethod {
|
||||
}
|
||||
|
||||
function recordUsagebySymbol(identifier: Identifier, usage: Usage, isTypeName: boolean) {
|
||||
const symbol = checker.getSymbolAtLocation(identifier);
|
||||
// If the identifier is both a property name and its value, we're only interested in its value
|
||||
// (since the name is a declaration and will be included in the extracted range).
|
||||
const symbol = identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier
|
||||
? checker.getShorthandAssignmentValueSymbol(identifier.parent)
|
||||
: checker.getSymbolAtLocation(identifier);
|
||||
if (!symbol) {
|
||||
// cannot find symbol - do nothing
|
||||
return undefined;
|
||||
@@ -1218,7 +1232,11 @@ namespace ts.refactor.extractMethod {
|
||||
substitutionsPerScope[i].set(symbolId, substitution);
|
||||
}
|
||||
else if (isTypeName) {
|
||||
errorsPerScope[i].push(createDiagnosticForNode(identifier, Messages.TypeWillNotBeVisibleInTheNewScope));
|
||||
// If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument
|
||||
// so there's no problem.
|
||||
if (!(symbol.flags & SymbolFlags.TypeParameter)) {
|
||||
errorsPerScope[i].push(createDiagnosticForNode(identifier, Messages.TypeWillNotBeVisibleInTheNewScope));
|
||||
}
|
||||
}
|
||||
else {
|
||||
usagesPerScope[i].usages.set(identifier.text as string, { usage, symbol, node: identifier });
|
||||
|
||||
@@ -2019,7 +2019,7 @@ namespace ts {
|
||||
startPosition,
|
||||
endPosition,
|
||||
program: getProgram(),
|
||||
newLineCharacter: host.getNewLine(),
|
||||
newLineCharacter: formatOptions ? formatOptions.newLineCharacter : host.getNewLine(),
|
||||
rulesProvider: getRuleProvider(formatOptions),
|
||||
cancellationToken
|
||||
};
|
||||
|
||||
@@ -184,16 +184,12 @@ namespace ts.textChanges {
|
||||
return s;
|
||||
}
|
||||
|
||||
function getNewlineKind(context: { newLineCharacter: string }) {
|
||||
return context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed;
|
||||
}
|
||||
|
||||
export class ChangeTracker {
|
||||
private changes: Change[] = [];
|
||||
private readonly newLineCharacter: string;
|
||||
|
||||
public static fromContext(context: RefactorContext | CodeFixContext) {
|
||||
return new ChangeTracker(getNewlineKind(context), context.rulesProvider);
|
||||
return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.rulesProvider);
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// ==ORIGINAL==
|
||||
interface UnaryExpression {
|
||||
kind: "Unary";
|
||||
operator: string;
|
||||
operand: any;
|
||||
}
|
||||
|
||||
function parseUnaryExpression(operator: string): UnaryExpression {
|
||||
return {
|
||||
kind: "Unary",
|
||||
operator,
|
||||
operand: parsePrimaryExpression(),
|
||||
};
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): any {
|
||||
throw "Not implemented";
|
||||
}
|
||||
// ==SCOPE::inner function in function 'parseUnaryExpression'==
|
||||
interface UnaryExpression {
|
||||
kind: "Unary";
|
||||
operator: string;
|
||||
operand: any;
|
||||
}
|
||||
|
||||
function parseUnaryExpression(operator: string): UnaryExpression {
|
||||
return /*RENAME*/newFunction();
|
||||
|
||||
function newFunction() {
|
||||
return {
|
||||
kind: "Unary",
|
||||
operator,
|
||||
operand: parsePrimaryExpression(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): any {
|
||||
throw "Not implemented";
|
||||
}
|
||||
// ==SCOPE::function in global scope==
|
||||
interface UnaryExpression {
|
||||
kind: "Unary";
|
||||
operator: string;
|
||||
operand: any;
|
||||
}
|
||||
|
||||
function parseUnaryExpression(operator: string): UnaryExpression {
|
||||
return /*RENAME*/newFunction(operator);
|
||||
}
|
||||
|
||||
function newFunction(operator: string) {
|
||||
return {
|
||||
kind: "Unary",
|
||||
operator,
|
||||
operand: parsePrimaryExpression(),
|
||||
};
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): any {
|
||||
throw "Not implemented";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// ==ORIGINAL==
|
||||
function F<T>() {
|
||||
let t: T;
|
||||
}
|
||||
// ==SCOPE::inner function in function 'F'==
|
||||
function F<T>() {
|
||||
/*RENAME*/newFunction();
|
||||
|
||||
function newFunction() {
|
||||
let t: T;
|
||||
}
|
||||
}
|
||||
// ==SCOPE::function in global scope==
|
||||
function F<T>() {
|
||||
/*RENAME*/newFunction<T>();
|
||||
}
|
||||
function newFunction<T>() {
|
||||
let t: T;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// ==ORIGINAL==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
var f: () => number;
|
||||
f = function (): number {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==SCOPE::function in namespace 'N'==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
var f: () => number;
|
||||
f = /*RENAME*/newFunction(f);
|
||||
}
|
||||
|
||||
function newFunction(f: () => number) {
|
||||
f = function(): number {
|
||||
return value;
|
||||
};
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// ==SCOPE::function in global scope==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
var f: () => number;
|
||||
f = /*RENAME*/newFunction(f);
|
||||
}
|
||||
}
|
||||
function newFunction(f: () => number) {
|
||||
f = function(): number {
|
||||
return N.value;
|
||||
};
|
||||
return f;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// ==ORIGINAL==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
var c = class {
|
||||
M() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==SCOPE::function in namespace 'N'==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
/*RENAME*/newFunction();
|
||||
}
|
||||
|
||||
function newFunction() {
|
||||
var c = class {
|
||||
M() {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// ==SCOPE::function in global scope==
|
||||
namespace N {
|
||||
|
||||
export const value = 1;
|
||||
|
||||
() => {
|
||||
/*RENAME*/newFunction();
|
||||
}
|
||||
}
|
||||
function newFunction() {
|
||||
var c = class {
|
||||
M() {
|
||||
return N.value;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,27): error TS2448: Block-scoped variable 'b' used before its declaration.
|
||||
|
||||
|
||||
==== tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts (1 errors) ====
|
||||
export class C {
|
||||
public a = { b: this.b };
|
||||
~
|
||||
!!! error TS2448: Block-scoped variable 'b' used before its declaration.
|
||||
private b = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//// [useBeforeDeclaration_propertyAssignment.ts]
|
||||
export class C {
|
||||
public a = { b: this.b };
|
||||
private b = 0;
|
||||
}
|
||||
|
||||
|
||||
//// [useBeforeDeclaration_propertyAssignment.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
this.a = { b: this.b };
|
||||
this.b = 0;
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
@@ -0,0 +1,4 @@
|
||||
export class C {
|
||||
public a = { b: this.b };
|
||||
private b = 0;
|
||||
}
|
||||
@@ -17,5 +17,4 @@ verify.currentFileContentIs(`class C {
|
||||
()=>{ this.foo === 10 };
|
||||
}
|
||||
}
|
||||
C.foo = undefined;
|
||||
`);
|
||||
C.foo = undefined;` + "\r\n"); // TODO: GH#18445
|
||||
|
||||
@@ -13,5 +13,4 @@ verify.getAndApplyCodeFix(/*errorCode*/ undefined, /*index*/ 2)
|
||||
verify.currentFileContentIs(`class C {
|
||||
static p = ()=>{ this.foo === 10 };
|
||||
}
|
||||
C.foo = undefined;
|
||||
`);
|
||||
C.foo = undefined;` + "\r\n"); // TODO: GH#18445
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
//// super();
|
||||
//// |]}
|
||||
////}
|
||||
// TODO: GH#18445
|
||||
verify.rangeAfterCodeFix(`
|
||||
super();
|
||||
super();\r
|
||||
this.a = 12;
|
||||
`, /*includeWhiteSpace*/ true);
|
||||
`, /*includeWhiteSpace*/ true);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//// constructor() {[|
|
||||
//// |]}
|
||||
////}
|
||||
// TODO: GH#18445
|
||||
verify.rangeAfterCodeFix(`
|
||||
super();
|
||||
super();\r
|
||||
`, /*includeWhitespace*/ true);
|
||||
|
||||
@@ -19,7 +19,7 @@ edit.applyRefactor({
|
||||
`function foo() {
|
||||
var i = 10;
|
||||
var __return: any;
|
||||
({ __return, i } = n/*RENAME*/ewFunction(i));
|
||||
({ __return, i } = /*RENAME*/newFunction(i));
|
||||
return __return;
|
||||
}
|
||||
function newFunction(i) {
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
////}
|
||||
|
||||
format.document();
|
||||
verify.currentFileContentIs("class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
||||||| merged common ancestors\r\n\
|
||||
v = 3;\r\n\
|
||||
=======\r\n\
|
||||
v = 2;\r\n\
|
||||
>>>>>>> Branch - a\r\n\
|
||||
}");
|
||||
verify.currentFileContentIs(`class C {
|
||||
<<<<<<< HEAD
|
||||
v = 1;
|
||||
||||||| merged common ancestors
|
||||
v = 3;
|
||||
=======
|
||||
v = 2;
|
||||
>>>>>>> Branch - a
|
||||
}`);
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
////}
|
||||
|
||||
format.document();
|
||||
verify.currentFileContentIs("class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
=======\r\n\
|
||||
v = 2;\r\n\
|
||||
>>>>>>> Branch - a\r\n\
|
||||
}");
|
||||
verify.currentFileContentIs(`class C {
|
||||
<<<<<<< HEAD
|
||||
v = 1;
|
||||
=======
|
||||
v = 2;
|
||||
>>>>>>> Branch - a
|
||||
}`);
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
////x;|]
|
||||
|
||||
goTo.file("/b.ts");
|
||||
verify.rangeAfterCodeFix(`import { x } from "./a";
|
||||
|
||||
// TODO:GH#18445
|
||||
verify.rangeAfterCodeFix(`import { x } from "./a";\r
|
||||
\r
|
||||
export { x } from "./a";
|
||||
x;`, /*includeWhiteSpace*/ true);
|
||||
|
||||
Reference in New Issue
Block a user