Thank you for your interest in contributing to Eagle. This document describes the coding conventions, rules, and procedures that all contributions must follow. Pull requests that do not conform to these rules will be rejected.
All contributions must be dedicated to the public domain or signed over to the project administrator via a signed copyright release. By submitting a pull request you acknowledge this requirement.
This repository uses the CLA Assistant to automate contributor license management. When you open a pull request:
- The CLA Assistant bot will post a comment with a link to the CLA.
- Read the CLA and choose Option A (public domain dedication) or Option B (copyright assignment).
- Post the following comment on the pull request to sign: "I have read the CLA Document and I hereby sign the CLA"
- The
cla-checkstatus will update automatically once your signature is recorded.
Your signature is stored in the repository and applies to all future contributions -- you only need to sign once.
All C# source code and Eagle script lines must be "soft" broken at the 79-character mark, or at the limit used by the surrounding code.
Certain legacy files have longer line lengths; always make sure to match the convention already in use in the file you are modifying.
Use of System.Core, System.Linq, LINQ query syntax, and related
extension methods is forbidden throughout the codebase.
Adding NuGet packages, assembly references, or other external
dependencies is forbidden unless explicitly approved by the project
administrator. If an approved dependency is added, there must be
fallback behavior at both compile-time (via #if) and runtime. All
applicable MSBuild project files must be kept updated with the
necessary conditionals.
In general, backward compatibility for script constructs must be maintained at all times. Additionally, compatibility with the Tcl 8.4 language specification is required. Exceptions may be made; however, they will require approval by the project administrator.
All C# source code must compile and build successfully against the
.NET Framework 2.0 RTM (or later) using its shipped C# compiler.
Any use of newer language features or APIs must be wrapped in
preprocessor directives (e.g., #if NET_40, #if NET_STANDARD_21).
These features must be optional and the surrounding behavior must
degrade gracefully when they are not present.
All new code that is capable of throwing exceptions must handle them in such a way that they will not cause an unhandled exception for the process. For native interop via P/Invoke (which must only be used for optional features), this generally means catching all exceptions and logging them via the existing tracing infrastructure.
- All new functionality must have accompanying tests.
- All bug fixes must have a regression test.
All major new or changed functionality must be documented in the change
log file (ChangeLog) following its existing conventions.
Coding agents (AI assistants, copilots, etc.) may be used; however, the resulting code must still follow every rule in this document and must be easy for a human to understand and review.
Any algorithms and/or code that are not immediately obvious to a junior engineer must have explanatory block comments formatted according to the existing conventions:
//
// NOTE: Explanation of what this code does and why.
//Other recognized comment prefixes include HACK:, TODO:, WARNING:,
BUGBUG:, and FIXME:.
All new commands, sub-commands, and options must be evaluated for their impact on safe interpreters:
-
If the parent command is already marked unsafe, adding sub-commands is relatively straightforward, but the implications must still be documented.
-
If the parent command is safe, any new sub-commands must not violate the safety guarantees. This includes disclosure of information that is not already available within a safe interpreter context.
-
Any new options to commands or sub-commands that are allowed in a safe interpreter must be marked as unsafe (via
CommandFlags) until they have been vetted by the project administrator.
All new classes and structs must have an [ObjectId("...")] attribute
with a freshly generated GUID value. Other attributes may be required
as well, depending on the subsystem of the file being added.
All new public and internal types must document their thread-safety
guarantees. Shared mutable state must be protected with appropriate
synchronization. Follow the existing patterns in the codebase (e.g.,
lock on a dedicated syncRoot object). If there is a possibility
of deadlock, the TryLock pattern must be used.
Every C# type and member -- public, internal, and private alike (classes, structs, interfaces, enums, delegates, fields, constants, properties, methods, operators, constructors, and events) -- must carry an XML documentation comment. This applies to all new code without exception; a contribution that adds an undocumented type or member will be rejected.
- The documentation comment is one contiguous run of
///lines placed above the member's attributes (and above any#if-guarded attribute block); a preprocessor directive must never appear inside a documentation comment. - Each tag is on its own line. Every parameter has a
<param>(including parameters that are conditionally compiled out); every non-void member has a<returns>; every generic type or method has a<typeparam>. - Reference types and members with
<see cref="..." />and parameters with<paramref name="..." />. Never use<see langword=...>, and nevercrefa parameter. - Members inside
#if DEAD_CODE(or other compiled-out) blocks are documented too -- such code is intentionally preserved and may be revived, so its contract must remain described.
When you modify an existing member, you must update its XML documentation comment so it continues to match the code whenever your change affects the behavior, parameters, return value, exceptions, or any other part of the contract the comment describes. A documentation comment that no longer matches the code it describes is treated as a defect.
For the full conventions, placement rules, and worked examples, see
"Comprehensive XML Documentation" (convention 25) -- together with
the related conventions 18 through 27 -- in architecture_patterns.md
in the documentation repository (this will
redirect).
The Eagle documentation repository (this will redirect) must be kept up-to-date with changes in this repository. If your pull request adds, changes, or removes any user-facing functionality (commands, sub-commands, options, configuration, APIs, etc.), a corresponding pull request to the documentation repository is required and must be linked in your PR description.
Do not leave dead code, commented-out blocks, or any unused using
statements in your contribution. Remove anything that is not actively
used.
Every C# file must begin with the standard copyright header:
/*
* FileName.cs --
*
* Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: $
*/- 4 spaces per indentation level. No tabs.
- Allman style braces for namespace and class declarations (opening brace on its own line).
- Same-line braces for method bodies, control structures, and property accessors.
- One blank line between methods.
- Trailing spaces are forbidden.
- Section separators use a line of slashes:
///////////////////////////////////////////////////////////////////////
| Element | Convention | Example |
|---|---|---|
| Namespace | PascalCase | Eagle._Commands |
| Class / Struct | PascalCase | ObjectIdAttribute |
| Interface | IPascalCase | IExecute |
| Public method | PascalCase | Execute() |
| Public property | PascalCase | SubCommands |
| Private field | camelCase | defaultSubSubCommands |
| Local variable | camelCase | localResult |
| Parameter | camelCase | interpreter |
| Constant | PascalCase | DefaultNoCase |
| Enum member | PascalCase | CommandFlags.Safe |
- System namespaces first, then Eagle namespaces, then other namespaces, and finally type alises, etc.
- Alphabetical order within each group.
- Conditional
usingdirectives wrapped in#ifwhen needed:#if NET_STANDARD_21 using Index = Eagle._Constants.Index; #endif
Use #region / #endregion blocks to organize code within classes.
Follow the existing ordering:
- Private Constants
- Private Static Data
- Private Data
- Public Data
- Constructors
- Interface implementation members (grouped by interface)
- IDisposable pattern members
Use inline comments to indicate parameter direction when the intent is not obvious:
private void Initialize(
ref EnsembleDictionary subCommands /* in, out */
)Other recognized inline annotations include /* throw */, /* EXEMPT */,
and /* TRANSACTIONAL */.
- Use existing symbols:
DEBUG,PATCHLEVEL,NET_STANDARD_21,NET_40,THROW_ON_DISPOSED,SHELL, etc. - New symbols must be documented and added to all relevant MSBuild project files.
- All
#if-guarded code must compile cleanly with and without the symbol defined.
Every Eagle script file must begin with the standard copyright header:
###############################################################################
#
# filename.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
#
# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################- 2 spaces per indentation level. No tabs.
- Same-line brace style (opening brace on the same line as the
statement):
if {$condition} then { # body } else { # alternative }
- Use
thenwithifstatements for clarity. - Closing brace on its own line at the same indentation level as the opening statement.
} else {and} elseif {on the same line as the closing brace.
| Element | Convention | Example |
|---|---|---|
| Procedure | camelCase | getTclReserved |
| Local variable | camelCase | savedFlags |
| Global variable | snake_case | tcl_platform |
| Environment var | UPPER_CASE | EAGLE_TEST_TEMP |
- Use
#for all comments. - Block comments use the pattern:
# # NOTE: Explanation of what this code does. #
- Recognized prefixes:
NOTE:,HACK:,TODO:,WARNING:,MONO:,BUGBUG:. - Comments are indented to match the surrounding code block.
- Prefer curly braces
{}for literal strings and bodies (no substitution, better performance). - Use double quotes
""only when variable or command substitution is required.
Use a line of hash marks between procedures and between test cases:
###############################################################################- Test files begin with
source [file join ... prologue.eagle]to load the test framework. - Tests use the
runTestwrapper:runTest {test testname-1.1 {description} -setup { # setup } -body { # test body } -cleanup { # cleanup } -constraints {constraint} -result {expected}} - Test names follow the pattern
category-major.minorwith sequential numbering. - Use
-constraintsto gate tests on platform, feature, or configuration. - Use
unset -nocomplainin cleanup blocks.
Any pull request that modifies Eagle scripts in the repository must be tagged with "scripts" so the project administrator knows those files need to be re-signed for use with the Harpy / Badge plugins.
If any core script library (Eagle1.0) or test package library
(Test1.0) scripts are modified, the associated embedded resource file
must be rebuilt:
Eagle1.0-Library/Resources/library.resourcesTest1.0-Library/Resources/packages.resources
Before submitting a pull request, verify that:
- Code compiles against .NET Framework 2.0 RTM (no newer APIs
without
#ifguards). - Code compiles against .NET Standard 2.1 / .NET 10.0.
- No LINQ usage anywhere in the change.
- No new dependencies added without prior approval.
- All new classes and structs have
[ObjectId("...")]with a new GUID. - All new types and members have conforming XML documentation comments, and any modified members' doc comments were updated to reflect behavioral changes.
- All exceptions are caught and handled appropriately.
- All safe interpreter implications have been considered for any new commands, sub-commands, or options.
- Line length does not exceed the file's convention (79 or 100/104 columns).
- New functionality has tests.
- Bug fixes have regression tests.
- The
ChangeLoghas been updated. - If Eagle scripts were modified, the PR is tagged "scripts".
- If
Eagle1.0orTest1.0library scripts were modified, the embedded resource files have been rebuilt. - All CI checks pass on both Linux and macOS.
- If user-facing functionality was added or changed, a corresponding PR to the documentation repository (this will redirect) has been opened and linked.