Skip to content

Commit e87fc2d

Browse files
Copilotanupriya13
andcommitted
Fix API extraction to generate correct method signatures from spec files instead of generic multiply method
Co-authored-by: anupriya13 <54227869+anupriya13@users.noreply.github.com>
1 parent 532da2f commit e87fc2d

1 file changed

Lines changed: 95 additions & 30 deletions

File tree

packages/@react-native-windows/cli/src/commands/moduleWindowsSetup/moduleWindowsSetup.ts

Lines changed: 95 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ interface MethodSignature {
4242

4343
export class ModuleWindowsSetup {
4444
private actualModuleName?: string;
45+
private discoveredSpecFiles: string[] = [];
4546
public root: string;
4647
public options: ModuleWindowsSetupOptions;
4748

@@ -179,6 +180,8 @@ export class ModuleWindowsSetup {
179180
this.verboseMessage(
180181
`Found valid spec file(s): ${validSpecFiles.join(', ')}`,
181182
);
183+
// Store the discovered spec files for later use
184+
this.discoveredSpecFiles = validSpecFiles;
182185
// Extract the actual module name from the existing spec file
183186
await this.extractModuleNameFromExistingSpec(validSpecFiles[0]);
184187
}
@@ -702,28 +705,53 @@ export default TurboModuleRegistry.getEnforcing<Spec>('${moduleName}');
702705
const methods = await this.parseSpecFileForMethods(specName);
703706

704707
// Generate header file with parsed methods
705-
const headerContent = this.generateHeaderStub(specName, methods);
706-
if (!(await fs.exists(headerPath))) {
707-
await fs.writeFile(headerPath, headerContent);
708-
this.verboseMessage(`Generated header stub: ${headerPath}`);
709-
}
708+
const headerContent = await this.generateHeaderStub(specName, methods);
709+
// Always write the header file to ensure it has the correct methods from the spec
710+
await fs.writeFile(headerPath, headerContent);
711+
this.verboseMessage(`Generated header stub: ${headerPath} with ${methods.length} methods`);
710712

711713
// Generate cpp file with parsed methods
712-
const cppContent = this.generateCppStub(specName, methods);
713-
if (!(await fs.exists(cppPath))) {
714-
await fs.writeFile(cppPath, cppContent);
715-
this.verboseMessage(`Generated cpp stub: ${cppPath}`);
716-
}
714+
const cppContent = await this.generateCppStub(specName, methods);
715+
// Always write the cpp file to ensure it has the correct methods from the spec
716+
await fs.writeFile(cppPath, cppContent);
717+
this.verboseMessage(`Generated cpp stub: ${cppPath} with ${methods.length} methods`);
717718
}
718719
}
719720

720721
private async parseSpecFileForMethods(
721722
moduleName: string,
722723
): Promise<MethodSignature[]> {
723724
try {
724-
// Find the spec file
725-
const specPattern = `**/Native${moduleName}.[jt]s`;
726-
const specFiles = glob.sync(specPattern, {cwd: this.root});
725+
// First, try to use the previously discovered spec files
726+
let specFiles = this.discoveredSpecFiles;
727+
728+
// If no discovered spec files, try to find them again with broader patterns
729+
if (specFiles.length === 0) {
730+
this.verboseMessage(`Searching for spec files for module: ${moduleName}`);
731+
732+
// Try multiple patterns to find the spec file
733+
const patterns = [
734+
`**/Native${moduleName}.[jt]s`,
735+
`**/Native*${moduleName}*.[jt]s`,
736+
`**/Native*.[jt]s`,
737+
`src/**/Native*.[jt]s`,
738+
`lib/**/Native*.[jt]s`,
739+
];
740+
741+
for (const pattern of patterns) {
742+
const matches = glob.sync(pattern, {
743+
cwd: this.root,
744+
ignore: ['**/node_modules/**', '**/build/**', '**/dist/**'],
745+
});
746+
if (matches.length > 0) {
747+
specFiles = await this.filterValidSpecFiles(matches);
748+
if (specFiles.length > 0) {
749+
this.verboseMessage(`Found spec files with pattern "${pattern}": ${specFiles.join(', ')}`);
750+
break;
751+
}
752+
}
753+
}
754+
}
727755

728756
if (specFiles.length === 0) {
729757
this.verboseMessage(
@@ -732,12 +760,14 @@ export default TurboModuleRegistry.getEnforcing<Spec>('${moduleName}');
732760
return [];
733761
}
734762

763+
// Use the first valid spec file
735764
const specPath = path.join(this.root, specFiles[0]);
765+
this.verboseMessage(`Reading spec file: ${specPath}`);
736766
const specContent = await fs.readFile(specPath, 'utf8');
737767

738768
// Parse method signatures from the Spec interface
739769
const methods = this.extractMethodsFromSpecInterface(specContent);
740-
this.verboseMessage(`Extracted ${methods.length} methods from spec file`);
770+
this.verboseMessage(`Extracted ${methods.length} methods from spec file: ${methods.map(m => m.name).join(', ')}`);
741771
return methods;
742772
} catch (error) {
743773
this.verboseMessage(
@@ -808,10 +838,28 @@ export default TurboModuleRegistry.getEnforcing<Spec>('${moduleName}');
808838
});
809839
}
810840

811-
private generateHeaderStub(
841+
private async getNamespaceInfo(): Promise<{namespace: string, codegenNamespace: string}> {
842+
try {
843+
const packageJsonPath = path.join(this.root, 'package.json');
844+
const pkgJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
845+
const actualModuleName = this.getActualModuleName(pkgJson.name || 'SampleModule');
846+
847+
// Create reasonable namespace from package name
848+
const namespace = this.getModuleName(pkgJson.name || 'SampleModule');
849+
const codegenNamespace = `${namespace}Codegen`;
850+
851+
return { namespace, codegenNamespace };
852+
} catch (error) {
853+
// Fallback
854+
return { namespace: 'ReactNativeWebview', codegenNamespace: 'ReactNativeWebviewCodegen' };
855+
}
856+
}
857+
858+
private async generateHeaderStub(
812859
moduleName: string,
813860
methods: MethodSignature[],
814-
): string {
861+
): Promise<string> {
862+
const {namespace, codegenNamespace} = await this.getNamespaceInfo();
815863
const methodDeclarations = methods
816864
.map(method => {
817865
const cppParams = method.parameters
@@ -844,29 +892,43 @@ export default TurboModuleRegistry.getEnforcing<Spec>('${moduleName}');
844892

845893
return `#pragma once
846894
847-
#include <${moduleName}Spec.g.h>
848-
#include <NativeModules.h>
895+
#include "pch.h"
896+
#include "resource.h"
897+
898+
#if __has_include("codegen/Native${moduleName}DataTypes.g.h")
899+
#include "codegen/Native${moduleName}DataTypes.g.h"
900+
#endif
901+
#include "codegen/Native${moduleName}Spec.g.h"
902+
903+
#include "NativeModules.h"
904+
905+
namespace winrt::${namespace}
906+
{
849907
850-
namespace ${moduleName}Specs {
908+
// See https://microsoft.github.io/react-native-windows/docs/native-platform for help writing native modules
851909
852910
REACT_MODULE(${moduleName})
853-
struct ${moduleName} {
854-
using ModuleSpec = ${moduleName}Spec;
855-
911+
struct ${moduleName}
912+
{
913+
using ModuleSpec = ${codegenNamespace}::${moduleName}Spec;
914+
856915
REACT_INIT(Initialize)
857916
void Initialize(React::ReactContext const &reactContext) noexcept;
858-
917+
859918
${defaultMethods}
919+
920+
private:
921+
React::ReactContext m_context;
860922
};
861923
862-
} // namespace ${moduleName}Specs
863-
`;
924+
} // namespace winrt::${namespace}`;
864925
}
865926

866-
private generateCppStub(
927+
private async generateCppStub(
867928
moduleName: string,
868929
methods: MethodSignature[],
869-
): string {
930+
): Promise<string> {
931+
const {namespace} = await this.getNamespaceInfo();
870932
const methodImplementations = methods
871933
.map(method => {
872934
const cppParams = method.parameters
@@ -912,15 +974,15 @@ ${defaultMethods}
912974

913975
return `#include "${moduleName}.h"
914976
915-
namespace ${moduleName}Specs {
977+
namespace winrt::${namespace} {
916978
917979
void ${moduleName}::Initialize(React::ReactContext const &reactContext) noexcept {
918-
// TODO: Initialize your module
980+
m_context = reactContext;
919981
}
920982
921983
${defaultImplementations}
922984
923-
} // namespace ${moduleName}Specs
985+
} // namespace winrt::${namespace}
924986
`;
925987
}
926988

@@ -933,6 +995,9 @@ ${defaultImplementations}
933995
any: 'React::JSValue',
934996
'any[]': 'React::JSValueArray',
935997
void: 'void',
998+
Double: 'double', // React Native codegen type
999+
Int32: 'int32_t', // React Native codegen type
1000+
Float: 'float', // React Native codegen type
9361001
};
9371002

9381003
// Handle array types

0 commit comments

Comments
 (0)