2017-04-28 00:46:07 +02:00
|
|
|
///<reference path="fourslash.ts" />
|
|
|
|
|
|
|
|
////abstract class B {
|
2017-05-01 20:45:18 +02:00
|
|
|
//// private privateMethod() { }
|
|
|
|
//// protected protectedMethod() { };
|
|
|
|
//// static staticMethod() { }
|
2017-04-28 00:46:07 +02:00
|
|
|
//// abstract getValue(): number;
|
|
|
|
//// /*abstractClass*/
|
|
|
|
////}
|
|
|
|
////class C extends B {
|
|
|
|
//// /*classThatIsEmptyAndExtendingAnotherClass*/
|
|
|
|
////}
|
|
|
|
////class D extends B {
|
|
|
|
//// /*classThatHasAlreadyImplementedAnotherClassMethod*/
|
|
|
|
//// getValue() {
|
|
|
|
//// return 10;
|
|
|
|
//// }
|
|
|
|
//// /*classThatHasAlreadyImplementedAnotherClassMethodAfterMethod*/
|
|
|
|
////}
|
2017-05-11 22:59:06 +02:00
|
|
|
////class D1 extends B {
|
|
|
|
//// /*classThatHasDifferentMethodThanBase*/
|
|
|
|
//// getValue1() {
|
|
|
|
//// return 10;
|
|
|
|
//// }
|
|
|
|
//// /*classThatHasDifferentMethodThanBaseAfterMethod*/
|
|
|
|
////}
|
|
|
|
////class D2 extends B {
|
|
|
|
//// /*classThatHasAlreadyImplementedAnotherClassProtectedMethod*/
|
|
|
|
//// protectedMethod() {
|
|
|
|
//// }
|
|
|
|
//// /*classThatHasDifferentMethodThanBaseAfterProtectedMethod*/
|
|
|
|
////}
|
2017-05-11 22:59:06 +02:00
|
|
|
////class D3 extends D1 {
|
|
|
|
//// /*classThatExtendsClassExtendingAnotherClass*/
|
|
|
|
////}
|
|
|
|
////class D4 extends D1 {
|
|
|
|
//// static /*classThatExtendsClassExtendingAnotherClassAndTypesStatic*/
|
|
|
|
////}
|
|
|
|
////class D5 extends D2 {
|
|
|
|
//// /*classThatExtendsClassExtendingAnotherClassWithOverridingMember*/
|
|
|
|
////}
|
|
|
|
////class D6 extends D2 {
|
|
|
|
//// static /*classThatExtendsClassExtendingAnotherClassWithOverridingMemberAndTypesStatic*/
|
|
|
|
////}
|
2017-04-28 00:46:07 +02:00
|
|
|
////class E {
|
|
|
|
//// /*classThatDoesNotExtendAnotherClass*/
|
|
|
|
////}
|
|
|
|
////class F extends B {
|
|
|
|
//// public /*classThatHasWrittenPublicKeyword*/
|
|
|
|
////}
|
2017-05-05 02:44:34 +02:00
|
|
|
////class F2 extends B {
|
|
|
|
//// private /*classThatHasWrittenPrivateKeyword*/
|
|
|
|
////}
|
2017-04-28 00:46:07 +02:00
|
|
|
////class G extends B {
|
|
|
|
//// static /*classElementContainingStatic*/
|
|
|
|
////}
|
2017-05-05 02:44:34 +02:00
|
|
|
////class G2 extends B {
|
|
|
|
//// private static /*classElementContainingPrivateStatic*/
|
|
|
|
////}
|
2017-04-28 00:46:07 +02:00
|
|
|
////class H extends B {
|
|
|
|
//// prop/*classThatStartedWritingIdentifier*/
|
|
|
|
////}
|
2017-05-05 02:44:34 +02:00
|
|
|
//////Class for location verification
|
2017-04-28 00:46:07 +02:00
|
|
|
////class I extends B {
|
|
|
|
//// prop0: number
|
|
|
|
//// /*propDeclarationWithoutSemicolon*/
|
|
|
|
//// prop: number;
|
|
|
|
//// /*propDeclarationWithSemicolon*/
|
|
|
|
//// prop1 = 10;
|
|
|
|
//// /*propAssignmentWithSemicolon*/
|
|
|
|
//// prop2 = 10
|
|
|
|
//// /*propAssignmentWithoutSemicolon*/
|
|
|
|
//// method(): number
|
|
|
|
//// /*methodSignatureWithoutSemicolon*/
|
|
|
|
//// method2(): number;
|
|
|
|
//// /*methodSignatureWithSemicolon*/
|
|
|
|
//// method3() {
|
|
|
|
//// /*InsideMethod*/
|
|
|
|
//// }
|
|
|
|
//// /*methodImplementation*/
|
|
|
|
//// get c()
|
|
|
|
//// /*accessorSignatureWithoutSemicolon*/
|
|
|
|
//// set c()
|
|
|
|
//// {
|
|
|
|
//// }
|
|
|
|
//// /*accessorSignatureImplementation*/
|
|
|
|
////}
|
|
|
|
////class J extends B {
|
|
|
|
//// get /*classThatHasWrittenGetKeyword*/
|
|
|
|
////}
|
|
|
|
////class K extends B {
|
|
|
|
//// set /*classThatHasWrittenSetKeyword*/
|
|
|
|
////}
|
|
|
|
////class J extends B {
|
|
|
|
//// get identi/*classThatStartedWritingIdentifierOfGetAccessor*/
|
|
|
|
////}
|
|
|
|
////class K extends B {
|
|
|
|
//// set identi/*classThatStartedWritingIdentifierOfSetAccessor*/
|
|
|
|
////}
|
|
|
|
////class L extends B {
|
|
|
|
//// public identi/*classThatStartedWritingIdentifierAfterModifier*/
|
|
|
|
////}
|
2017-05-05 02:44:34 +02:00
|
|
|
////class L2 extends B {
|
|
|
|
//// private identi/*classThatStartedWritingIdentifierAfterPrivateModifier*/
|
|
|
|
////}
|
|
|
|
////class M extends B {
|
2017-04-28 00:46:07 +02:00
|
|
|
//// static identi/*classThatStartedWritingIdentifierAfterStaticModifier*/
|
|
|
|
////}
|
2017-05-05 02:44:34 +02:00
|
|
|
////class M extends B {
|
|
|
|
//// private static identi/*classThatStartedWritingIdentifierAfterPrivateStaticModifier*/
|
|
|
|
////}
|
2017-05-11 20:42:36 +02:00
|
|
|
////class N extends B {
|
|
|
|
//// async /*classThatHasWrittenAsyncKeyword*/
|
|
|
|
////}
|
2017-06-05 23:54:14 +02:00
|
|
|
////class O extends B {
|
|
|
|
//// constructor(public a) {
|
|
|
|
//// },
|
|
|
|
//// /*classElementAfterConstructorSeparatedByComma*/
|
|
|
|
////}
|
2017-04-28 00:46:07 +02:00
|
|
|
|
2017-05-01 20:45:18 +02:00
|
|
|
const allowedKeywordCount = verify.allowedClassElementKeywords.length;
|
2017-05-05 02:44:34 +02:00
|
|
|
type CompletionInfo = [string, string];
|
|
|
|
type CompletionInfoVerifier = { validMembers: CompletionInfo[], invalidMembers: CompletionInfo[] };
|
|
|
|
|
|
|
|
function verifyClassElementLocations({ validMembers, invalidMembers }: CompletionInfoVerifier, classElementCompletionLocations: string[]) {
|
|
|
|
for (const marker of classElementCompletionLocations) {
|
|
|
|
goTo.marker(marker);
|
|
|
|
verifyCompletionInfo(validMembers, verify);
|
|
|
|
verifyCompletionInfo(invalidMembers, verify.not);
|
|
|
|
verify.completionListContainsClassElementKeywords();
|
|
|
|
verify.completionListCount(allowedKeywordCount + validMembers.length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function verifyCompletionInfo(memberInfo: CompletionInfo[], verify: FourSlashInterface.verifyNegatable) {
|
|
|
|
for (const [symbol, text] of memberInfo) {
|
|
|
|
verify.completionListContains(symbol, text, /*documentation*/ undefined, "method");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const allMembersOfBase: CompletionInfo[] = [
|
|
|
|
["getValue", "(method) B.getValue(): number"],
|
|
|
|
["protectedMethod", "(method) B.protectedMethod(): void"],
|
|
|
|
["privateMethod", "(method) B.privateMethod(): void"],
|
|
|
|
["staticMethod", "(method) B.staticMethod(): void"]
|
|
|
|
];
|
2017-05-11 22:59:06 +02:00
|
|
|
const publicCompletionInfoOfD1: CompletionInfo[] = [
|
|
|
|
["getValue1", "(method) D1.getValue1(): number"]
|
|
|
|
];
|
|
|
|
const publicCompletionInfoOfD2: CompletionInfo[] = [
|
|
|
|
["protectedMethod", "(method) D2.protectedMethod(): void"]
|
|
|
|
];
|
2017-05-05 02:44:34 +02:00
|
|
|
function filterCompletionInfo(fn: (a: CompletionInfo) => boolean): CompletionInfoVerifier {
|
|
|
|
const validMembers: CompletionInfo[] = [];
|
|
|
|
const invalidMembers: CompletionInfo[] = [];
|
|
|
|
for (const member of allMembersOfBase) {
|
|
|
|
if (fn(member)) {
|
|
|
|
validMembers.push(member);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
invalidMembers.push(member);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return { validMembers, invalidMembers };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const instanceMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "getValue" || a === "protectedMethod");
|
|
|
|
const staticMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "staticMethod");
|
2017-05-11 22:59:06 +02:00
|
|
|
const instanceWithoutProtectedMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "getValue");
|
|
|
|
const instanceWithoutPublicMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "protectedMethod");
|
2017-05-05 02:44:34 +02:00
|
|
|
|
2017-05-11 22:59:06 +02:00
|
|
|
const instanceMemberInfoD1: CompletionInfoVerifier = {
|
|
|
|
validMembers: instanceMemberInfo.validMembers.concat(publicCompletionInfoOfD1),
|
|
|
|
invalidMembers: instanceMemberInfo.invalidMembers
|
|
|
|
};
|
|
|
|
const instanceMemberInfoD2: CompletionInfoVerifier = {
|
|
|
|
validMembers: instanceWithoutProtectedMemberInfo.validMembers.concat(publicCompletionInfoOfD2),
|
|
|
|
invalidMembers: instanceWithoutProtectedMemberInfo.invalidMembers
|
|
|
|
};
|
|
|
|
const staticMemberInfoDn: CompletionInfoVerifier = {
|
|
|
|
validMembers: staticMemberInfo.validMembers,
|
|
|
|
invalidMembers: staticMemberInfo.invalidMembers.concat(publicCompletionInfoOfD1, publicCompletionInfoOfD2)
|
|
|
|
};
|
|
|
|
|
2017-05-05 02:44:34 +02:00
|
|
|
// Not a class element declaration location
|
2017-04-28 00:46:07 +02:00
|
|
|
const nonClassElementMarkers = [
|
|
|
|
"InsideMethod"
|
|
|
|
];
|
|
|
|
for (const marker of nonClassElementMarkers) {
|
|
|
|
goTo.marker(marker);
|
2017-05-05 02:44:34 +02:00
|
|
|
verifyCompletionInfo(allMembersOfBase, verify.not);
|
2017-04-28 00:46:07 +02:00
|
|
|
verify.not.completionListIsEmpty();
|
|
|
|
}
|
|
|
|
|
2017-05-05 02:44:34 +02:00
|
|
|
// Only keywords allowed at this position since they dont extend the class or are private
|
2017-04-28 00:46:07 +02:00
|
|
|
const onlyClassElementKeywordLocations = [
|
|
|
|
"abstractClass",
|
2017-05-05 02:44:34 +02:00
|
|
|
"classThatDoesNotExtendAnotherClass",
|
|
|
|
"classThatHasWrittenPrivateKeyword",
|
|
|
|
"classElementContainingPrivateStatic",
|
|
|
|
"classThatStartedWritingIdentifierAfterPrivateModifier",
|
|
|
|
"classThatStartedWritingIdentifierAfterPrivateStaticModifier"
|
2017-04-28 00:46:07 +02:00
|
|
|
];
|
2017-05-05 02:44:34 +02:00
|
|
|
verifyClassElementLocations({ validMembers: [], invalidMembers: allMembersOfBase }, onlyClassElementKeywordLocations);
|
2017-04-28 00:46:07 +02:00
|
|
|
|
2017-05-05 02:44:34 +02:00
|
|
|
// Instance base members and class member keywords allowed
|
|
|
|
const classInstanceElementLocations = [
|
2017-04-28 00:46:07 +02:00
|
|
|
"classThatIsEmptyAndExtendingAnotherClass",
|
2017-05-11 22:59:06 +02:00
|
|
|
"classThatHasDifferentMethodThanBase",
|
|
|
|
"classThatHasDifferentMethodThanBaseAfterMethod",
|
2017-05-01 20:45:18 +02:00
|
|
|
"classThatHasWrittenPublicKeyword",
|
2017-04-28 00:46:07 +02:00
|
|
|
"classThatStartedWritingIdentifier",
|
|
|
|
"propDeclarationWithoutSemicolon",
|
|
|
|
"propDeclarationWithSemicolon",
|
|
|
|
"propAssignmentWithSemicolon",
|
|
|
|
"propAssignmentWithoutSemicolon",
|
|
|
|
"methodSignatureWithoutSemicolon",
|
|
|
|
"methodSignatureWithSemicolon",
|
|
|
|
"methodImplementation",
|
|
|
|
"accessorSignatureWithoutSemicolon",
|
|
|
|
"accessorSignatureImplementation",
|
2017-05-01 20:45:18 +02:00
|
|
|
"classThatHasWrittenGetKeyword",
|
|
|
|
"classThatHasWrittenSetKeyword",
|
|
|
|
"classThatStartedWritingIdentifierOfGetAccessor",
|
|
|
|
"classThatStartedWritingIdentifierOfSetAccessor",
|
|
|
|
"classThatStartedWritingIdentifierAfterModifier",
|
2017-06-05 23:54:14 +02:00
|
|
|
"classThatHasWrittenAsyncKeyword",
|
|
|
|
"classElementAfterConstructorSeparatedByComma"
|
2017-05-01 20:45:18 +02:00
|
|
|
];
|
2017-05-05 02:44:34 +02:00
|
|
|
verifyClassElementLocations(instanceMemberInfo, classInstanceElementLocations);
|
2017-05-01 20:45:18 +02:00
|
|
|
|
2017-05-05 02:44:34 +02:00
|
|
|
// Static Base members and class member keywords allowed
|
|
|
|
const staticClassLocations = [
|
|
|
|
"classElementContainingStatic",
|
|
|
|
"classThatStartedWritingIdentifierAfterStaticModifier"
|
2017-04-28 00:46:07 +02:00
|
|
|
];
|
2017-05-11 22:59:06 +02:00
|
|
|
verifyClassElementLocations(staticMemberInfo, staticClassLocations);
|
|
|
|
|
|
|
|
const classInstanceElementWithoutPublicMethodLocations = [
|
|
|
|
"classThatHasAlreadyImplementedAnotherClassMethod",
|
|
|
|
"classThatHasAlreadyImplementedAnotherClassMethodAfterMethod",
|
|
|
|
];
|
|
|
|
verifyClassElementLocations(instanceWithoutPublicMemberInfo, classInstanceElementWithoutPublicMethodLocations);
|
|
|
|
|
|
|
|
const classInstanceElementWithoutProtectedMethodLocations = [
|
|
|
|
"classThatHasAlreadyImplementedAnotherClassProtectedMethod",
|
|
|
|
"classThatHasDifferentMethodThanBaseAfterProtectedMethod",
|
|
|
|
];
|
2017-05-11 22:59:06 +02:00
|
|
|
verifyClassElementLocations(instanceWithoutProtectedMemberInfo, classInstanceElementWithoutProtectedMethodLocations);
|
|
|
|
|
|
|
|
// instance memebers in D1 and base class are shown
|
|
|
|
verifyClassElementLocations(instanceMemberInfoD1, ["classThatExtendsClassExtendingAnotherClass"]);
|
|
|
|
|
|
|
|
// instance memebers in D2 and base class are shown
|
|
|
|
verifyClassElementLocations(instanceMemberInfoD2, ["classThatExtendsClassExtendingAnotherClassWithOverridingMember"]);
|
|
|
|
|
|
|
|
// static base members and class member keywords allowed
|
|
|
|
verifyClassElementLocations(staticMemberInfoDn, [
|
|
|
|
"classThatExtendsClassExtendingAnotherClassAndTypesStatic",
|
|
|
|
"classThatExtendsClassExtendingAnotherClassWithOverridingMemberAndTypesStatic"
|
|
|
|
]);
|