cmeeren / flinter Goto Github PK
View Code? Open in Web Editor NEWA linter for F#
License: MIT License
A linter for F#
License: MIT License
Do we need try/with in visitors so that even if one node fails, the analyzer can continue to others?
This issue serves as notes for rule ideas.
use
async
CE via do!
instead of return!
, recursive task
CE, missing tail recursion (or is that not generally useful?))unit
values, string
applied to string argument, etc.)Quick-notes, to be elaborated/merged into the below:
let
/let!
instead of use
/use!
on IDisposable
and IAsyncDisposable
(for bang operators, depending on the CE, these may be wrapped in arbitrary container types like Async
or Task
)Foo<'a>
) except for option
, voption
, list
, []
, ref
(source: formatting guidelines)
Option.defaultWith (fun thisIsUnit -> ...)
)Option.Value
, List.Head
and similar?Sealed
and AbstractClass
on types with only static members?with
expression without the thrown exception containing the caught exception (loses stack trace and other information)sprintf
, failwithf
etc. (when not piped)Guidelines from the book "Code that fits in your head" by Mark Seemann
Limit number of "activated objects" in any given function (section 7.2.7 of the book)
Cyclomatic complexity (section 7.1.2 of the book)
Parse, don't validate (section section 7.2.5 of the book)
EmailAddress
type and use that everywhere else. All code that uses EmailAddress
knows that they have a valid email address, as opposed to if they had just worked with a plain string.bool
-returning function), and then returning the string (unmodified). Might be complicated.Guidelines from F# coding conventions
Prefer namespaces instead of modules at the top level
module Foo.Bar
as a namespaceUse classes to contain values that have side effects
unit
(also check in module-level values, recursively)let f = f' a b
if a
or b
(any part of them if multi-part) are mutable.DateTime.Now
etc.Do not use monadic error handling to replace exceptions
Result.Error
or a Choice
case with an exceptionError exn.Message
?_
and returning None
Strive to keep all helper functionality private
Helper
, Helpers
, Util
, Utils
, etc.?Explicitly annotate all parameter and return types in public functions
OutputType
is Exe
)Consider giving a meaningful name to your generic arguments
'a
, 'b
, 'T
, etc. Only if public, and only in libraries, not console apps (where OutputType
is Exe
)Consider naming generic type parameters with PascalCase
'a
, 'b'
, etc., since that is common in F#Consider structs for small types with high allocation rates
Avoid inheritance-based type hierarchies and implementation inheritance
Use object expressions to implement interfaces if you don't need a class
Guidelines from F# component design guidelines
Use XML docs for the entire public API surface (applicable for libraries)
Use namespaces or modules to contain your types and modules
Is this only relevant for single-file projects? For multi-file projects, the compiler enforces this, right?
Use interfaces to group related operations
Hide the representations of record and union types if the design of these types is likely to evolve
Avoid the use of implementation inheritance for extensibility
Use correct Async prefix/postfix for Async/Task overloads of sync methods
Carefully use type abbreviations)
Rules from the sections relevant only when intending consumption from other .NET languages (not 1st priority)
Stuff from .NET framework design guidelines
Naming guidelines - common capitalization mistakes
userName
(username seems to be a closed-form compound word)Attribute
suffix for types inheriting from System.Attribute
EventArgs
suffix for types inheriting from System.EventArgs
Enum
, Flag
, or Flags
Dictionary
suffix for types implementing IDictionary
Collection
suffix for types implementing IEnumerable
, ICollection
, or IList
Stream
suffix for types inheriting from System.IO.Stream
System.FlagsAttribute
System.FlagsAttribute
Get
has the same name as a method. This pattern typically indicates that the property should really be a method. (What about Set
?)Before
or After
left
and right
for binary operator overload parameter names if there is no meaning to the parameters.
value
for unary operator overload parameter names if there is no meaning to the parameters.
IEquatable<T>
on value types.System.FlagsAttribute
)
Int32
, Int64
, String
, Object
, or an enum.Event design (low priority?)
**Using standard exception types
Exception
(failwith
/failwithf
) or SystemException
; use a more specific exception
System.Exception
or System.SystemException
in framework code, unless you intend to rethrow.ApplicationException
.NullReferenceException
, AccessViolationException
, or IndexOutOfRangeException
. These exceptions are reserved and thrown by the execution engine and in most cases indicate a bug.StackOverflowException
StackOverflowException
.OutOfMemoryException
COMException,
ExecutionEngineException, and
SEHException`Officially documented best practices:
Check existing linter rules for ideas (note: Before implementation, they should be grounded in something more than just "implemented in another linter")
FSharpLint
return!
not do!
new
keyword?failwith
, raise
, nulArg
, invalidOp
being passed more than one argumentinvalidArg
being passed more than two argumentsfailwithf
being passed more arguments than contained in the format stringignore
over let _
_ as x
with x
(_, _)
with wildcard _
List.find
(but what it you know it will exist? Pointless to use pattern matching only to have the None
case be failwith "Unreachable code"
)reraise ()
instead of raise
inside a try ... with
block (not applicable inside a CE)this
identifier in classes/interfaces (is this covered by the F# style guide?)Various Roslyn analyzers
TODO: For all rules that work with accessibility modifiers, what if signatures files are used?
For testing, will this need to be specified in ProjectOptions together with --targetprofile:netstandard
? What about when actually running this as a tool?
Related: ionide/FSharp.Analyzers.SDK#68
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.