Adding Runtime Features
How to add a new class or feature to sharp-runtime following project conventions.
Before You Start
- Check
DOTNET_PORTING_PLAN.mdto see if the class is tracked and what its target status is - Check
TODO.mdfor classes explicitly listed as pending - Confirm the class is part of
System.*— sharp-runtime only targets the .NET System namespace - Consult the .NET reference docs to understand the expected API surface
Step 1: Create the Header
Create include/System/[Namespace]/ClassName.hpp:
// SPDX-License-Identifier: MIT
// Copyright (C) 2024 Robert Vokac
// Based on .NET Runtime (MIT License)
#pragma once
#include <System/Object.hpp>
#include <SharpRuntime/Prop.hpp>
namespace System {
// Or: namespace System::IO etc.
/**
* @brief One-line description.
* @status Partial
*/
class MyClass : public Object {
public:
MyClass();
DDATA(int, SomeProperty)
void SomeMethod(const std::string& arg);
GetTypeNameHPP();
};
} // namespace System
Step 2: Create the Implementation
Create src/System/[Namespace]/MyClass.cpp:
// SPDX-License-Identifier: MIT
// Copyright (C) 2024 Robert Vokac
// Based on .NET Runtime (MIT License)
#include <System/MyClass.hpp>
namespace System {
GetTypeNameCPP(MyClass, "System.MyClass")
IDATA(MyClass, int, SomeProperty)
MyClass::MyClass() : someProperty_(0) {}
void MyClass::SomeMethod(const std::string& arg) {
// implementation
}
} // namespace System
Auto-discovery by CMake
The CMakeLists.txt uses GLOB_RECURSE to discover all
src/*.cpp files automatically. You do not need to modify CMakeLists.txt to add
a new source file — just create it in the right location and rebuild.
Step 3: Write Tests
Create tests/System/MyClassTest.cpp:
// SPDX-License-Identifier: MIT
#include <gtest/gtest.h>
#include <System/MyClass.hpp>
using namespace System;
TEST(MyClassTest, ConstructorDefault) {
MyClass obj;
EXPECT_EQ(obj.getSomePropertyProperty(), 0);
}
TEST(MyClassTest, SomeMethod) {
MyClass obj;
obj.SomeMethod("test");
// assert expected state
}
TEST(MyClassTest, GetTypeName) {
MyClass obj;
EXPECT_EQ(obj.GetTypeName(), "System.MyClass");
}
Test count requirement
The project must maintain 3132+ passing tests. Your new class must have at least basic
constructor, method, and GetTypeName tests. Run ctest --output-on-failure
after adding tests to verify everything passes.
Step 4: Platform Guards (if needed)
If your implementation uses platform-specific APIs:
- Keep platform-specific
#includes in.cppfiles only - Use
#ifdef _WIN32/#elif defined(__EMSCRIPTEN__)/#elseguards - If a feature is POSIX-only, document it in the header with a Doxygen note
- Provide stub implementations for unsupported platforms rather than compilation errors
Step 5: Update Status
Update the @status Doxygen comment in the header file as the implementation progresses:
Todo— planned, not startedStub— header exists, empty/minimal implementationPartial— key functionality works, some methods missingImplemented— all planned methods doneVerified— fully tested against .NET behavior
Checklist
- SPDX header on every file
#pragma oncein headerGetTypeNameHPP()in class bodyGetTypeNameCPP()in .cpp- All properties use
DDATA/DGETTERmacros - No POSIX
#includes in .hpp files - Tests written and passing
- Zero new warnings after build
@statuscomment reflects actual state