Skip to content

Commit f121a03

Browse files
authored
Revise validation and quality assurance guidelines
1 parent 04badef commit f121a03

File tree

1 file changed

+144
-16
lines changed

1 file changed

+144
-16
lines changed

.github/copilot-instructions.md

Lines changed: 144 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -328,22 +328,150 @@ _total = this.WhenAnyValue(
328328
.ToProperty(this, nameof(Total));
329329
```
330330

331-
## 🎨 Code Style & Formatting
332-
333-
ReactiveUI enforces strict code style and formatting guidelines:
334-
335-
### EditorConfig & StyleCop Compliance
336-
- **EditorConfig**: The repository has a comprehensive `.editorconfig` file with detailed formatting rules
337-
- **StyleCop Analyzers**: Extensive StyleCop analyzer rules are configured with error-level enforcement
338-
- **Code Analysis**: Over 200 analyzer rules are configured for code quality and consistency
331+
## Validation and Quality Assurance
332+
333+
### Code Style and Analysis Enforcement
334+
- **EditorConfig Compliance**: Repository uses comprehensive `.editorconfig` with detailed rules for C# formatting, naming conventions, and code analysis
335+
- **StyleCop Analyzers**: Enforces consistent C# code style with `stylecop.analyzers`
336+
- **Roslynator Analyzers**: Additional code quality rules with `Roslynator.Analyzers`
337+
- **Analysis Level**: Set to `latest` with enhanced .NET analyzers enabled
338+
- **CRITICAL**: All code must comply with **ReactiveUI contribution guidelines**: https://www.reactiveui.net/contribute/index.html
339+
340+
### C# Style Guide
341+
**General Rule**: Follow "Visual Studio defaults" with the following specific requirements:
342+
343+
#### **Brace Style**
344+
- **Allman style braces**: Each brace begins on a new line
345+
- **Single line statement blocks**: Can go without braces but must be properly indented on its own line
346+
- **Exception**: A `using` statement is permitted to be nested within another `using` statement by starting on the following line at the same indentation level
347+
348+
#### **Indentation and Spacing**
349+
- **Four spaces** of indentation (no tabs)
350+
- **Avoid spurious free spaces**: For example, avoid `if (someVar == 0)...` where dots mark spurious spaces
351+
- **Avoid more than one empty line** at any time between members of a type
352+
- **Labels**: Indent one less than the current indentation (for `goto` statements)
353+
354+
#### **Field and Property Naming**
355+
- **Internal and private fields**: Use `_camelCase` prefix with `readonly` where possible
356+
- **Static fields**: `readonly` should come after `static` (e.g., `static readonly` not `readonly static`)
357+
- **Public fields**: Use PascalCasing with no prefix (use sparingly)
358+
- **Constants**: Use PascalCasing for all constant local variables and fields (except interop code)
359+
- **Fields placement**: Specify fields at the top within type declarations
360+
361+
#### **Visibility and Modifiers**
362+
- **Always specify visibility**: Even if it's the default (e.g., `private string _foo` not `string _foo`)
363+
- **Visibility first**: Should be the first modifier (e.g., `public abstract` not `abstract public`)
364+
- **Modifier order**: `public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async`
365+
366+
#### **Namespace and Using Statements**
367+
- **Namespace imports**: At the top of the file, outside of namespace declarations
368+
- **Sorting**: System namespaces alphabetically first, then third-party namespaces alphabetically
369+
- **Placement**: Use `using` directives outside namespace declarations
370+
371+
#### **Type Usage and Variables**
372+
- **Language keywords**: Use instead of BCL types (`int, string, float` instead of `Int32, String, Single`)
373+
- **var usage**: Encouraged when it makes sense (large return types, refactoring scenarios)
374+
- **this. avoidance**: Avoid `this.` unless absolutely necessary
375+
- **nameof(...)**: Use instead of string literals whenever possible and relevant
376+
377+
#### **Code Patterns and Features**
378+
- **Method groups**: Use where appropriate
379+
- **C# 7 pattern matching**: Use when possible
380+
- **Inline out variables**: Use C# 7 inline variable feature with `out` parameters
381+
- **Non-ASCII characters**: Use Unicode escape sequences (`\uXXXX`) instead of literal characters
382+
383+
#### **Documentation Requirements**
384+
- **XML comments**: All publicly exposed methods and properties must have .NET XML comments
385+
- **Protected methods**: Include XML comments for protected methods of public classes
386+
- **Documentation culture**: en-US as specified in `src/stylecop.json`
387+
388+
#### **File Style Precedence**
389+
- **Existing style**: If a file differs from these guidelines, the existing style in that file takes precedence
390+
- **Consistency**: Maintain consistency within individual files
391+
392+
#### **Example Code Structure**
393+
```csharp
394+
using System;
395+
using System.Collections;
396+
using System.Collections.Generic;
397+
using System.Collections.Specialized;
398+
using System.ComponentModel;
399+
using System.Diagnostics;
400+
using Microsoft.Win32;
401+
402+
namespace System.Collections.Generic
403+
{
404+
/// <summary>
405+
/// Observable implementation of LinkedList.
406+
/// </summary>
407+
/// <typeparam name="T">The type of elements in the list.</typeparam>
408+
public partial class ObservableLinkedList<T> : INotifyCollectionChanged, INotifyPropertyChanged
409+
{
410+
private ObservableLinkedListNode<T> _head;
411+
private int _count;
412+
413+
/// <summary>
414+
/// Initializes a new instance of the <see cref="ObservableLinkedList{T}"/> class.
415+
/// </summary>
416+
/// <param name="items">The items to initialize the list with.</param>
417+
public ObservableLinkedList(IEnumerable<T> items)
418+
{
419+
if (items == null)
420+
{
421+
throw new ArgumentNullException(nameof(items));
422+
}
339423

340-
### Key Style Requirements
341-
- **Indentation**: 4 spaces (configured in `.editorconfig`)
342-
- **Braces**: Allman style (opening braces on new lines)
343-
- **Field naming**: Private fields use `_camelCase` prefix, static fields use `s_` prefix
344-
- **Var usage**: Prefer `var` when type is apparent
345-
- **Documentation**: All public APIs require XML documentation
346-
- **Null checking**: Use modern C# null-conditional operators
424+
foreach (T item in items)
425+
{
426+
AddLast(item);
427+
}
428+
}
429+
430+
/// <summary>
431+
/// Occurs when the collection changes.
432+
/// </summary>
433+
public event NotifyCollectionChangedEventHandler CollectionChanged;
434+
435+
/// <summary>
436+
/// Gets the number of elements in the list.
437+
/// </summary>
438+
public int Count
439+
{
440+
get { return _count; }
441+
}
442+
443+
/// <summary>
444+
/// Adds a new node containing the specified value at the end of the list.
445+
/// </summary>
446+
/// <param name="value">The value to add.</param>
447+
/// <returns>The new node that was added.</returns>
448+
public ObservableLinkedListNode AddLast(T value)
449+
{
450+
var newNode = new LinkedListNode<T>(this, value);
451+
InsertNodeBefore(_head, newNode);
452+
return newNode;
453+
}
454+
455+
/// <summary>
456+
/// Raises the CollectionChanged event.
457+
/// </summary>
458+
/// <param name="e">The event arguments.</param>
459+
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
460+
{
461+
NotifyCollectionChangedEventHandler handler = CollectionChanged;
462+
if (handler != null)
463+
{
464+
handler(this, e);
465+
}
466+
}
467+
468+
private void InsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
469+
{
470+
// Implementation details...
471+
}
472+
}
473+
}
474+
```
347475

348476
### Official Style Guide
349477
Follow the comprehensive ReactiveUI style guide:
@@ -387,4 +515,4 @@ dotnet build src/ReactiveUI.sln -c Release -warnaserror
387515
3. Verify AOT compatibility
388516
4. Ensure no regression in existing tests
389517

390-
Remember: ReactiveUI emphasizes functional reactive programming patterns, immutability where possible, and clean separation of concerns through the MVVM pattern. When in doubt, prefer reactive streams over imperative code, and always consider the AOT implications of your changes.
518+
Remember: ReactiveUI emphasizes functional reactive programming patterns, immutability where possible, and clean separation of concerns through the MVVM pattern. When in doubt, prefer reactive streams over imperative code, and always consider the AOT implications of your changes.

0 commit comments

Comments
 (0)