Skip to content

Commit 5c4009a

Browse files
committed
Merge pull request #161 from Microsoft/privacyErrors
Report errors for usage of private types when generating declaration file
2 parents afeabe8 + e31aa9e commit 5c4009a

35 files changed

+5264
-265
lines changed

src/compiler/checker.ts

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ module ts {
677677
}
678678

679679
// If symbol is directly available by its name in the symbol table
680-
if (isAccessible(symbols[symbol.name])) {
680+
if (isAccessible(lookUp(symbols, symbol.name))) {
681681
return symbol;
682682
}
683683

@@ -700,7 +700,7 @@ module ts {
700700
var qualify = false;
701701
forEachSymbolTableInScope(enclosingDeclaration, symbolTable => {
702702
// If symbol of this name is not available in the symbol table we are ok
703-
if (!symbolTable[symbol.name]) {
703+
if (!hasProperty(symbolTable, symbol.name)) {
704704
// Continue to the next symbol table
705705
return false;
706706
}
@@ -725,6 +725,52 @@ module ts {
725725
return qualify;
726726
}
727727

728+
function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult {
729+
if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) {
730+
var initialSymbol = symbol;
731+
var meaningToLook = meaning;
732+
while (symbol) {
733+
// Symbol is accessible if it by itself is accessible
734+
var accessibleSymbol = getAccessibleSymbol(symbol, enclosingDeclaration, meaningToLook);
735+
if (accessibleSymbol) {
736+
if (forEach(accessibleSymbol.declarations, declaration => !isDeclarationVisible(declaration))) {
737+
return {
738+
accessibility: SymbolAccessibility.NotAccessible,
739+
errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
740+
errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, SymbolFlags.Namespace) : undefined
741+
};
742+
}
743+
return { accessibility: SymbolAccessibility.Accessible };
744+
}
745+
746+
// TODO(shkamat): Handle static method of class
747+
748+
// If we havent got the accessible symbol doesnt mean the symbol is actually inaccessible.
749+
// It could be qualified symbol and hence verify the path
750+
// eg:
751+
// module m {
752+
// export class c {
753+
// }
754+
// }
755+
// var x: typeof m.c
756+
// In the above example when we start with checking if typeof m.c symbol is accessible,
757+
// we are going to see if c can be accessed in scope directly.
758+
// But it cant, hence the accessible is going to be undefined, but that doesnt mean m.c is accessible
759+
// It is accessible if the parent m is accessible because then m.c can be accessed through qualification
760+
meaningToLook = SymbolFlags.Namespace;
761+
symbol = symbol.parent;
762+
}
763+
764+
// This is a local symbol that cannot be named
765+
return {
766+
accessibility: SymbolAccessibility.CannotBeNamed,
767+
errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
768+
};
769+
}
770+
771+
return { accessibility: SymbolAccessibility.Accessible };
772+
}
773+
728774
// Enclosing declaration is optional when we dont want to get qualified name in the enclosing declaration scope
729775
// Meaning needs to be specified if the enclosing declaration is given
730776
function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
@@ -760,10 +806,15 @@ module ts {
760806
return getSymbolName(symbol);
761807
}
762808

809+
function writeSymbolToTextWriter(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, writer: TextWriter) {
810+
writer.write(symbolToString(symbol, enclosingDeclaration, meaning));
811+
}
812+
763813
function createSingleLineTextWriter() {
764814
var result = "";
765815
return {
766816
write(s: string) { result += s; },
817+
writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { writeSymbolToTextWriter(symbol, enclosingDeclaration, meaning, this); },
767818
writeLine() { result += " "; },
768819
increaseIndent() { },
769820
decreaseIndent() { },
@@ -790,7 +841,7 @@ module ts {
790841
writeTypeReference(<TypeReference>type);
791842
}
792843
else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) {
793-
writer.write(symbolToString(type.symbol, enclosingDeclaration, SymbolFlags.Type));
844+
writer.writeSymbol(type.symbol, enclosingDeclaration, SymbolFlags.Type);
794845
}
795846
else if (type.flags & TypeFlags.Anonymous) {
796847
writeAnonymousType(<ObjectType>type, allowFunctionOrConstructorTypeLiteral);
@@ -812,7 +863,7 @@ module ts {
812863
writer.write("[]");
813864
}
814865
else {
815-
writer.write(symbolToString(type.target.symbol, enclosingDeclaration, SymbolFlags.Type));
866+
writer.writeSymbol(type.target.symbol, enclosingDeclaration, SymbolFlags.Type);
816867
writer.write("<");
817868
for (var i = 0; i < type.typeArguments.length; i++) {
818869
if (i > 0) {
@@ -846,7 +897,7 @@ module ts {
846897

847898
function writeTypeofSymbol(type: ObjectType) {
848899
writer.write("typeof ");
849-
writer.write(symbolToString(type.symbol, enclosingDeclaration, SymbolFlags.Value));
900+
writer.writeSymbol(type.symbol, enclosingDeclaration, SymbolFlags.Value);
850901
}
851902

852903
function writeLiteralType(type: ObjectType, allowFunctionOrConstructorTypeLiteral: boolean) {
@@ -902,7 +953,7 @@ module ts {
902953
if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfType(t).length) {
903954
var signatures = getSignaturesOfType(t, SignatureKind.Call);
904955
for (var j = 0; j < signatures.length; j++) {
905-
writer.write(symbolToString(p));
956+
writer.writeSymbol(p);
906957
if (isOptionalProperty(p)) {
907958
writer.write("?");
908959
}
@@ -912,7 +963,7 @@ module ts {
912963
}
913964
}
914965
else {
915-
writer.write(symbolToString(p));
966+
writer.writeSymbol(p);
916967
if (isOptionalProperty(p)) {
917968
writer.write("?");
918969
}
@@ -934,7 +985,7 @@ module ts {
934985
writer.write(", ");
935986
}
936987
var tp = signature.typeParameters[i];
937-
writer.write(symbolToString(tp.symbol));
988+
writer.writeSymbol(tp.symbol);
938989
var constraint = getConstraintOfTypeParameter(tp);
939990
if (constraint) {
940991
writer.write(" extends ");
@@ -952,7 +1003,7 @@ module ts {
9521003
if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) {
9531004
writer.write("...");
9541005
}
955-
writer.write(symbolToString(p));
1006+
writer.writeSymbol(p);
9561007
if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (<VariableDeclaration>p.valueDeclaration).initializer) {
9571008
writer.write("?");
9581009
}
@@ -6695,7 +6746,9 @@ module ts {
66956746
isDeclarationVisible: isDeclarationVisible,
66966747
isImplementationOfOverload: isImplementationOfOverload,
66976748
writeTypeAtLocation: writeTypeAtLocation,
6698-
writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration
6749+
writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration,
6750+
writeSymbol: writeSymbolToTextWriter,
6751+
isSymbolAccessible: isSymbolAccessible
66996752
};
67006753
checkProgram();
67016754
return emitFiles(resolver);

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,28 @@ module ts {
106106
An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." },
107107
An_export_assignment_cannot_have_modifiers: { code: 1120, category: DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." },
108108
Duplicate_identifier_0: { code: 2000, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
109+
Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 2018, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
110+
Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 2019, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
111+
Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 2020, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
112+
Extends_clause_of_exported_class_0_has_or_is_using_name_1_from_private_module_2: { code: 2021, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using name '{1}' from private module '{2}'." },
113+
Implements_clause_of_exported_class_0_has_or_is_using_name_1_from_private_module_2: { code: 2022, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using name '{1}' from private module '{2}'." },
114+
Extends_clause_of_exported_interface_0_has_or_is_using_name_1_from_private_module_2: { code: 2023, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using name '{1}' from private module '{2}'." },
115+
Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 2208, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
116+
Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 2209, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
117+
Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 2210, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
118+
Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 2211, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
119+
Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 2212, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
120+
Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 2213, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
121+
Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 2214, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
122+
Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 2215, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
123+
Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 2216, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
124+
Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 2217, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
125+
Type_parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 2218, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
126+
Type_parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 2219, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
127+
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 2220, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
128+
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 2221, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
129+
Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 2222, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
130+
Type_parameter_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 2223, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
109131
new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 2068, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
110132
Multiple_constructor_implementations_are_not_allowed: { code: 2070, category: DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
111133
A_class_may_only_implement_another_class_or_interface: { code: 2074, category: DiagnosticCategory.Error, key: "A class may only implement another class or interface." },

src/compiler/diagnosticMessages.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,94 @@
416416
"category": "Error",
417417
"code": 2000
418418
},
419+
"Extends clause of exported class '{0}' has or is using private name '{1}'.": {
420+
"category": "Error",
421+
"code": 2018
422+
},
423+
"Implements clause of exported class '{0}' has or is using private name '{1}'.": {
424+
"category": "Error",
425+
"code": 2019
426+
},
427+
"Extends clause of exported interface '{0}' has or is using private name '{1}'.": {
428+
"category": "Error",
429+
"code": 2020
430+
},
431+
"Extends clause of exported class '{0}' has or is using name '{1}' from private module '{2}'.": {
432+
"category": "Error",
433+
"code": 2021
434+
},
435+
"Implements clause of exported class '{0}' has or is using name '{1}' from private module '{2}'.": {
436+
"category": "Error",
437+
"code": 2022
438+
},
439+
"Extends clause of exported interface '{0}' has or is using name '{1}' from private module '{2}'.": {
440+
"category": "Error",
441+
"code": 2023
442+
},
443+
"Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'.": {
444+
"category": "Error",
445+
"code": 2208
446+
},
447+
"Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'.": {
448+
"category": "Error",
449+
"code": 2209
450+
},
451+
"Type parameter '{0}' of public static method from exported class has or is using private name '{1}'.": {
452+
"category": "Error",
453+
"code": 2210
454+
},
455+
"Type parameter '{0}' of public method from exported class has or is using private name '{1}'.": {
456+
"category": "Error",
457+
"code": 2211
458+
},
459+
"Type parameter '{0}' of method from exported interface has or is using private name '{1}'.": {
460+
"category": "Error",
461+
"code": 2212
462+
},
463+
"Type parameter '{0}' of exported function has or is using private name '{1}'.": {
464+
"category": "Error",
465+
"code": 2213
466+
},
467+
"Type parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'.": {
468+
"category": "Error",
469+
"code": 2214
470+
},
471+
"Type parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'.": {
472+
"category": "Error",
473+
"code": 2215
474+
},
475+
"Type parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'.": {
476+
"category": "Error",
477+
"code": 2216
478+
},
479+
"Type parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'.": {
480+
"category": "Error",
481+
"code": 2217
482+
},
483+
"Type parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'.": {
484+
"category": "Error",
485+
"code": 2218
486+
},
487+
"Type parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'.": {
488+
"category": "Error",
489+
"code": 2219
490+
},
491+
"Type parameter '{0}' of exported class has or is using private name '{1}'.": {
492+
"category": "Error",
493+
"code": 2220
494+
},
495+
"Type parameter '{0}' of exported interface has or is using private name '{1}'.": {
496+
"category": "Error",
497+
"code": 2221
498+
},
499+
"Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'.": {
500+
"category": "Error",
501+
"code": 2222
502+
},
503+
"Type parameter '{0}' of exported interface has or is using name '{1}' from private module '{2}'.": {
504+
"category": "Error",
505+
"code": 2223
506+
},
419507
"'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.": {
420508
"category": "Error",
421509
"code": 2068

0 commit comments

Comments
 (0)