Skip to content

Commit 1e5a54e

Browse files
authored
Fix a host of TypeScript issues (#110)
* Fixes #97 * Fixes #100 * Fixes #101 * Fixes #102 * Fixes #103 * clang-format
1 parent 1f29490 commit 1e5a54e

12 files changed

Lines changed: 1002 additions & 915 deletions

jswinrt/jswinrt/Settings.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ Settings::Settings(const CommandReader& commandReader) :
5959
std::filesystem::create_directories(OutputFolder);
6060
}
6161

62-
bool is_type_allowed(const Settings& settings, const TypeDef& typeDef, bool isClass)
62+
bool is_type_allowed(const Settings& settings, const TypeDef& typeDef)
6363
{
64+
auto isClass = winmd::reader::get_category(typeDef) == winmd::reader::category::class_type;
6465
if (!settings.Filter.Includes(typeDef))
6566
{
6667
return false;
@@ -105,7 +106,7 @@ bool is_namespace_allowed(const Settings& settings, const cache::namespace_membe
105106

106107
for (const auto& typeDef : members.classes)
107108
{
108-
if (is_type_allowed(settings, typeDef, true /*isClass*/))
109+
if (is_type_allowed(settings, typeDef))
109110
{
110111
return true;
111112
}

jswinrt/jswinrt/Settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ struct Settings
1717
const bool Verbose;
1818
};
1919

20-
bool is_type_allowed(const Settings& settings, const winmd::reader::TypeDef& typeDef, bool isClass = false);
20+
bool is_type_allowed(const Settings& settings, const winmd::reader::TypeDef& typeDef);
2121
bool is_namespace_allowed(const Settings& settings, const winmd::reader::cache::namespace_members& members);
2222
bool is_method_allowed(const Settings& settings, const winmd::reader::MethodDef& methodDef);

jswinrt/jswinrt/TypescriptWriter.h

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ class TypescriptWriter
3333

3434
void WriteTypeDefiniton(winmd::reader::TypeDef const& type, TextWriter& textWriter)
3535
{
36+
if (!is_type_allowed(settings, type))
37+
return;
38+
39+
// A couple other types are projected to other JS types
40+
if (type.TypeNamespace() == "Windows.Foundation"sv)
41+
{
42+
auto name = type.TypeName();
43+
if ((name == "DateTime"sv) || (name == "TimeSpan"sv) || (name == "HResult"sv))
44+
return;
45+
}
46+
3647
switch (get_category(type))
3748
{
3849
case winmd::reader::category::struct_type:
@@ -85,7 +96,8 @@ class TypescriptWriter
8596

8697
void WriteClassOrInterface(winmd::reader::TypeDef const& type, TextWriter& textWriter)
8798
{
88-
if (get_category(type) == winmd::reader::category::interface_type && exclusiveto_class(type))
99+
auto category = winmd::reader::get_category(type);
100+
if ((category == winmd::reader::category::interface_type) && exclusiveto_class(type))
89101
{
90102
return;
91103
}
@@ -111,13 +123,13 @@ class TypescriptWriter
111123
)");
112124
textWriter.WriteIndentedLine();
113125
}
114-
if (type.Flags().Abstract() && get_category(type) != winmd::reader::category::interface_type)
126+
if (type.Flags().Abstract() && (category != winmd::reader::category::interface_type))
115127
{
116128
textWriter.Write("abstract ");
117129
}
118130
},
119131
[&]() {
120-
switch (get_category(type))
132+
switch (category)
121133
{
122134
case winmd::reader::category::interface_type:
123135
textWriter.Write("interface");
@@ -181,8 +193,7 @@ class TypescriptWriter
181193
{
182194
return;
183195
}
184-
textWriter.Write(
185-
get_category(type) == winmd::reader::category::interface_type ? " extends " : " implements ");
196+
textWriter.Write((category == winmd::reader::category::interface_type) ? " extends " : " implements ");
186197
for (auto&& implementsTypeSem : filteredInterfaces)
187198
{
188199
WriteTypeSemantics(implementsTypeSem, type, textWriter, false, false);
@@ -196,7 +207,11 @@ class TypescriptWriter
196207
for (auto&& field : type.FieldList())
197208
{
198209
textWriter.WriteIndentedLine(
199-
"% %: ", [&]() { WriteAccess(field.Flags().Access(), textWriter); },
210+
"%%: ",
211+
[&]() {
212+
WriteAccess(
213+
field.Flags().Access(), textWriter, category != winmd::reader::category::class_type);
214+
},
200215
TextWriter::ToCamelCase(std::string(field.Name())));
201216
WriteTypeSemantics(jswinrt::typeparser::get_type_semantics(field.Signature().Type()), type,
202217
textWriter, field.Signature().Type().is_szarray(), false);
@@ -206,6 +221,8 @@ class TypescriptWriter
206221
for (auto&& prop : type.PropertyList())
207222
{
208223
textWriter.WriteIndentedLine();
224+
WriteAccess(prop.MethodSemantic().first.Method().Flags().Access(), textWriter,
225+
category != winmd::reader::category::class_type);
209226
if (prop.MethodSemantic().first.Method().Flags().Static())
210227
{
211228
textWriter.Write("static ");
@@ -222,41 +239,28 @@ class TypescriptWriter
222239
}
223240

224241
// Methods:
225-
std::map<std::string_view, winmd::reader::MethodDef> eventListeners;
242+
std::vector<winmd::reader::MethodDef> eventListeners;
226243
for (auto&& method : type.MethodList())
227244
{
228245
if (!is_method_allowed(settings, method))
229246
continue;
230-
if (method.SpecialName() &&
231-
(starts_with(method.Name(), "get_") || starts_with(method.Name(), "put_")))
232-
continue;
233-
if (method.SpecialName() &&
234-
(starts_with(method.Name(), "add_") || starts_with(method.Name(), "remove_")))
235-
{
236-
eventListeners[method.Name()] = method;
237-
}
238-
else
247+
else if (!method.SpecialName() || (method.Name() == ".ctor"sv))
239248
{
240249
textWriter.WriteIndentedLine();
241250
WriteMethod(method, type, textWriter);
242251
}
252+
else if (starts_with(method.Name(), "add_"))
253+
{
254+
eventListeners.push_back(method);
255+
}
256+
// NOTE: If there's an add there must be a remove and vice-versa
257+
// NOTE: Properties handled later
243258
}
244259

245260
// Event Listeners:
246-
for (auto const& [name, method] : eventListeners)
261+
for (auto&& method : eventListeners)
247262
{
248-
if (!is_method_allowed(settings, method))
249-
continue;
250-
textWriter.WriteIndentedLine();
251-
if (name._Starts_with("add_"))
252-
{
253-
WriteEventListener(method, type, textWriter, true);
254-
}
255-
else
256-
{
257-
auto addListenerName = "add_" + std::string(method.Name().substr(7));
258-
WriteEventListener(eventListeners[addListenerName], type, textWriter, false);
259-
}
263+
WriteEventListener(method, type, textWriter);
260264
}
261265

262266
WriteSpecialPropertiesAndMethods(textWriter, type);
@@ -349,29 +353,54 @@ class TypescriptWriter
349353
}
350354

351355
void WriteEventListener(winmd::reader::MethodDef const& addEventListener,
352-
winmd::reader::TypeDef const& containerType, TextWriter& textWriter, bool shouldCreateAddListener)
356+
winmd::reader::TypeDef const& containerType, TextWriter& textWriter)
353357
{
354-
textWriter.Write("%EventListener(type: \"%\", listener: %): void", shouldCreateAddListener ? "add" : "remove",
355-
TextWriter::ToCamelCase(TextWriter::ToLowerAllCase(std::string(addEventListener.Name().substr(4)))), [&]() {
356-
jswinrt::typeparser::method_signature methodSignature(addEventListener);
357-
for (auto&& [param, paramSignature] : methodSignature.params())
358-
{
359-
WriteTypeSemantics(jswinrt::typeparser::get_type_semantics(paramSignature->Type()), containerType,
360-
textWriter, paramSignature->Type().is_szarray(), false);
361-
}
362-
});
358+
std::string name{ addEventListener.Name().substr(4) }; // Remove 'add_'
359+
std::transform(
360+
name.begin(), name.end(), name.begin(), [](char ch) { return static_cast<char>(::tolower(ch)); });
361+
362+
auto isClass = winmd::reader::get_category(containerType) == winmd::reader::category::class_type;
363+
const char* accessType = addEventListener.Flags().Static() ? "static " : "";
364+
365+
textWriter.WriteIndentedLine();
366+
if (isClass)
367+
{
368+
WriteAccess(addEventListener.Flags().Access(), textWriter, false);
369+
}
370+
textWriter.Write(R"^-^(%addEventListener(type: "%", listener: %): void;)^-^", accessType, name, [&]() {
371+
jswinrt::typeparser::method_signature methodSignature(addEventListener);
372+
for (auto&& [param, paramSignature] : methodSignature.params())
373+
{
374+
WriteTypeSemantics(jswinrt::typeparser::get_type_semantics(paramSignature->Type()), containerType,
375+
textWriter, paramSignature->Type().is_szarray(), false);
376+
}
377+
});
378+
379+
textWriter.WriteIndentedLine();
380+
if (isClass)
381+
{
382+
WriteAccess(addEventListener.Flags().Access(), textWriter, false);
383+
}
384+
textWriter.Write(R"^-^(%removeEventListener(type: "%", listener: %): void;)^-^", accessType, name, [&]() {
385+
jswinrt::typeparser::method_signature methodSignature(addEventListener);
386+
for (auto&& [param, paramSignature] : methodSignature.params())
387+
{
388+
WriteTypeSemantics(jswinrt::typeparser::get_type_semantics(paramSignature->Type()), containerType,
389+
textWriter, paramSignature->Type().is_szarray(), false);
390+
}
391+
});
363392
}
364393

365394
void WriteMethod(winmd::reader::MethodDef const& method, winmd::reader::TypeDef const& containerType,
366395
TextWriter& textWriter, bool isAnonymousFunction = false)
367396
{
368397
jswinrt::typeparser::method_signature methodSignature(method);
369398
std::vector<std::pair<std::string_view, winmd::reader::TypeSig>> returnNameTypePairs;
399+
auto isClass = winmd::reader::get_category(containerType) == winmd::reader::category::class_type;
370400
textWriter.Write(
371-
"%%%%(%)%;"sv, [&]() { WriteAccess(method.Flags().Access(), textWriter); },
401+
"%%%%(%)%;"sv, [&]() { WriteAccess(method.Flags().Access(), textWriter, !isClass); },
372402
[&]() {
373-
if (method.Flags().Abstract() && !isAnonymousFunction &&
374-
get_category(containerType) == winmd::reader::category::class_type)
403+
if (method.Flags().Abstract() && !isAnonymousFunction && isClass)
375404
{
376405
textWriter.Write("abstract ");
377406
}
@@ -457,24 +486,38 @@ class TypescriptWriter
457486
if (std::holds_alternative<jswinrt::typeparser::type_definition>(typeSemantics))
458487
{
459488
winmd::reader::TypeDef typeDef = std::get<jswinrt::typeparser::type_definition>(typeSemantics);
460-
if (!IsTypeDefAllowed(typeDef))
489+
bool handled = false;
490+
if (!is_type_allowed(settings, typeDef))
461491
{
462492
textWriter.Write("any");
463-
return;
493+
handled = true;
464494
}
465-
if (typeDef.TypeNamespace() == "Windows.Foundation" && typeDef.TypeName() == "HResult")
495+
else if (typeDef.TypeNamespace() == "Windows.Foundation"sv)
466496
{
467-
textWriter.Write("number");
468-
return;
497+
auto name = typeDef.TypeName();
498+
if ((name == "HResult") || (name == "TimeSpan"sv))
499+
{
500+
textWriter.Write("number");
501+
handled = true;
502+
}
503+
else if (name == "IAsyncAction"sv)
504+
{
505+
textWriter.Write("Windows.Foundation.WinRTPromise<void, void>");
506+
handled = true;
507+
}
508+
else if (name == "DateTime"sv)
509+
{
510+
textWriter.Write("Date");
511+
handled = true;
512+
}
469513
}
470-
if (typeDef.TypeNamespace() == "Windows.Foundation" && typeDef.TypeName() == "IAsyncAction")
514+
if (!handled)
471515
{
472-
textWriter.Write("Windows.Foundation.WinRTPromise<void, void>");
473-
return;
516+
textWriter.Write("%.%", typeDef.TypeNamespace(), typeDef.TypeName());
474517
}
518+
475519
bool isStruct = get_category(typeDef) == winmd::reader::category::struct_type;
476-
textWriter.Write("%.%%%", typeDef.TypeNamespace(), typeDef.TypeName(), isArray ? "[]" : "",
477-
isNullable && !isArray && !isStruct ? " | null" : "");
520+
textWriter.Write("%%", isArray ? "[]" : "", isNullable && !isArray && !isStruct ? " | null" : "");
478521
}
479522
else if (std::holds_alternative<jswinrt::typeparser::fundamental_type>(typeSemantics))
480523
{
@@ -512,7 +555,7 @@ class TypescriptWriter
512555
else if (std::holds_alternative<jswinrt::typeparser::generic_type_instance>(typeSemantics))
513556
{
514557
auto generic_type_instance = std::get<jswinrt::typeparser::generic_type_instance>(typeSemantics);
515-
if (!IsTypeDefAllowed(generic_type_instance.generic_type))
558+
if (!is_type_allowed(settings, generic_type_instance.generic_type))
516559
{
517560
textWriter.Write("any");
518561
return;
@@ -631,11 +674,6 @@ class TypescriptWriter
631674
}
632675
}
633676

634-
bool IsTypeDefAllowed(winmd::reader::TypeDef const& type)
635-
{
636-
return is_type_allowed(settings, type, get_category(type) == winmd::reader::category::class_type);
637-
}
638-
639677
static bool IsGeneric(std::string_view name)
640678
{
641679
return name.find("`") != std::string::npos;

tests/RnWinRTTests/windows/WinRTTurboModule/WinRTTurboModule.vcxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
2525
<CppWinRTVerbosity>high</CppWinRTVerbosity>
2626
<CppWinRTParameters>-base</CppWinRTParameters>
27-
<JsWinRTParameters>-include Windows.Foundation -include TestComponent</JsWinRTParameters>
27+
<JsWinRTParameters>-include Windows.Foundation -include TestComponent -include Windows.Web.Http.HttpStatusCode</JsWinRTParameters>
2828
<JsWinRTVerbosity>high</JsWinRTVerbosity>
2929
</PropertyGroup>
3030
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

0 commit comments

Comments
 (0)