Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use fantomas for formatting #80

Merged
merged 3 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {}
"tools": {
"fantomas": {
"version": "6.2.0",
"commands": [
"fantomas"
]
}
}
}
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*.{fs,fsi,fsx}]
end_of_line = lf
fsharp_keep_max_number_of_blank_lines = 1
fsharp_multi_line_lambda_closing_newline = true
fsharp_alternative_long_member_definitions = true
fsharp_align_function_signature_to_indentation = true
fsharp_experimental_keep_indent_in_branch = true
fsharp_bar_before_discriminated_union_declaration = true
fsharp_multiline_bracket_style = aligned
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# Automatically normalize line endings
* text=auto

# Always use lf for F# files
*.fs text eol=lf
*.fsx text eol=lf
*.fsi text eol=lf
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
- name: Restore tools
run: dotnet tool restore

- name: Check format
run: dotnet fantomas . --check

- name: Restore dependencies
run: dotnet restore --locked-mode

Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ in order to craft an excellent pull request:
[interactive rebase](https://help.github.com/articles/about-git-rebase/)
feature to tidy up your commits before making them public.

5. Make sure all the tests are still passing.
5. Ensure the code is formatted and the sample still works.

```bash
dotnet tool restore
dotnet fake build
dotnet fantomas .
dotnet build -c Release
dotnet run --project src/FSharp.Analyzers.Cli/FSharp.Analyzers.Cli.fsproj -- --project ./samples/OptionAnalyzer/OptionAnalyzer.fsproj --analyzers-path ./samples/OptionAnalyzer/bin/Release --verbose
Comment on lines +126 to +128
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, this is what frustrates me about not having a build script. "Remember to do all these steps we gotta keep in sync with our CI yml that we're totally gonna remember to keep in sync"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can give it a try. cc @baronfel

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nojaf floated this to me the other day - I'm ok with it, but lacking FSX script caching makes me sad. I'd prefer generally to push data/tasks into MSBuild targets as much as possible because that doesn't require any additional tooling. I understand that not everyone feels the same, however.

```

6. Push your topic branch up to your fork:
Expand Down
159 changes: 78 additions & 81 deletions samples/OptionAnalyzer/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,134 +6,131 @@ open FSharp.Compiler.Symbols
open FSharp.Compiler.Symbols.FSharpExprPatterns
open FSharp.Compiler.Text

let rec visitExpr memberCallHandler (e:FSharpExpr) =
let rec visitExpr memberCallHandler (e: FSharpExpr) =
match e with
| AddressOf(lvalueExpr) ->
visitExpr memberCallHandler lvalueExpr
| AddressOf(lvalueExpr) -> visitExpr memberCallHandler lvalueExpr
| AddressSet(lvalueExpr, rvalueExpr) ->
visitExpr memberCallHandler lvalueExpr; visitExpr memberCallHandler rvalueExpr
visitExpr memberCallHandler lvalueExpr
visitExpr memberCallHandler rvalueExpr
| Application(funcExpr, typeArgs, argExprs) ->
visitExpr memberCallHandler funcExpr; visitExprs memberCallHandler argExprs
visitExpr memberCallHandler funcExpr
visitExprs memberCallHandler argExprs
| Call(objExprOpt, memberOrFunc, typeArgs1, typeArgs2, argExprs) ->
memberCallHandler e.Range memberOrFunc
visitObjArg memberCallHandler objExprOpt; visitExprs memberCallHandler argExprs
| Coerce(targetType, inpExpr) ->
visitExpr memberCallHandler inpExpr
| FastIntegerForLoop(startExpr, limitExpr, consumeExpr, isUp, debugPointAtFor, debugPointAtInOrTo) ->
visitExpr memberCallHandler startExpr; visitExpr memberCallHandler limitExpr; visitExpr memberCallHandler consumeExpr
| ILAsm(asmCode, typeArgs, argExprs) ->
visitExprs memberCallHandler argExprs
| ILFieldGet (objExprOpt, fieldType, fieldName) ->
visitObjArg memberCallHandler objExprOpt
| ILFieldSet (objExprOpt, fieldType, fieldName, valueExpr) ->
visitObjArg memberCallHandler objExprOpt
| IfThenElse (guardExpr, thenExpr, elseExpr) ->
visitExpr memberCallHandler guardExpr; visitExpr memberCallHandler thenExpr; visitExpr memberCallHandler elseExpr
| Lambda(lambdaVar, bodyExpr) ->
visitExpr memberCallHandler bodyExpr
visitExprs memberCallHandler argExprs
| Coerce(targetType, inpExpr) -> visitExpr memberCallHandler inpExpr
| FastIntegerForLoop(startExpr, limitExpr, consumeExpr, isUp, debugPointAtFor, debugPointAtInOrTo) ->
visitExpr memberCallHandler startExpr
visitExpr memberCallHandler limitExpr
visitExpr memberCallHandler consumeExpr
| ILAsm(asmCode, typeArgs, argExprs) -> visitExprs memberCallHandler argExprs
| ILFieldGet(objExprOpt, fieldType, fieldName) -> visitObjArg memberCallHandler objExprOpt
| ILFieldSet(objExprOpt, fieldType, fieldName, valueExpr) -> visitObjArg memberCallHandler objExprOpt
| IfThenElse(guardExpr, thenExpr, elseExpr) ->
visitExpr memberCallHandler guardExpr
visitExpr memberCallHandler thenExpr
visitExpr memberCallHandler elseExpr
| Lambda(lambdaVar, bodyExpr) -> visitExpr memberCallHandler bodyExpr
| Let((bindingVar, bindingExpr, debugPointAtBinding), bodyExpr) ->
visitExpr memberCallHandler bindingExpr; visitExpr memberCallHandler bodyExpr
visitExpr memberCallHandler bindingExpr
visitExpr memberCallHandler bodyExpr
| LetRec(recursiveBindings, bodyExpr) ->
let recursiveBindings' = recursiveBindings |> List.map (fun (mfv, expr, dp) -> (mfv, expr))
List.iter (snd >> visitExpr memberCallHandler) recursiveBindings'; visitExpr memberCallHandler bodyExpr
| NewArray(arrayType, argExprs) ->
visitExprs memberCallHandler argExprs
| NewDelegate(delegateType, delegateBodyExpr) ->
visitExpr memberCallHandler delegateBodyExpr
| NewObject(objType, typeArgs, argExprs) ->
visitExprs memberCallHandler argExprs
| NewRecord(recordType, argExprs) ->
visitExprs memberCallHandler argExprs
| NewTuple(tupleType, argExprs) ->
visitExprs memberCallHandler argExprs
| NewUnionCase(unionType, unionCase, argExprs) ->
visitExprs memberCallHandler argExprs
| Quote(quotedExpr) ->
visitExpr memberCallHandler quotedExpr
| FSharpFieldGet(objExprOpt, recordOrClassType, fieldInfo) ->
visitObjArg memberCallHandler objExprOpt
let recursiveBindings' =
recursiveBindings |> List.map (fun (mfv, expr, dp) -> (mfv, expr))

List.iter (snd >> visitExpr memberCallHandler) recursiveBindings'
visitExpr memberCallHandler bodyExpr
| NewArray(arrayType, argExprs) -> visitExprs memberCallHandler argExprs
| NewDelegate(delegateType, delegateBodyExpr) -> visitExpr memberCallHandler delegateBodyExpr
| NewObject(objType, typeArgs, argExprs) -> visitExprs memberCallHandler argExprs
| NewRecord(recordType, argExprs) -> visitExprs memberCallHandler argExprs
| NewTuple(tupleType, argExprs) -> visitExprs memberCallHandler argExprs
| NewUnionCase(unionType, unionCase, argExprs) -> visitExprs memberCallHandler argExprs
| Quote(quotedExpr) -> visitExpr memberCallHandler quotedExpr
| FSharpFieldGet(objExprOpt, recordOrClassType, fieldInfo) -> visitObjArg memberCallHandler objExprOpt
| FSharpFieldSet(objExprOpt, recordOrClassType, fieldInfo, argExpr) ->
visitObjArg memberCallHandler objExprOpt; visitExpr memberCallHandler argExpr
visitObjArg memberCallHandler objExprOpt
visitExpr memberCallHandler argExpr
| Sequential(firstExpr, secondExpr) ->
visitExpr memberCallHandler firstExpr; visitExpr memberCallHandler secondExpr
visitExpr memberCallHandler firstExpr
visitExpr memberCallHandler secondExpr
| TryFinally(bodyExpr, finalizeExpr, debugPointAtTry, debugPointAtFinally) ->
visitExpr memberCallHandler bodyExpr; visitExpr memberCallHandler finalizeExpr
visitExpr memberCallHandler bodyExpr
visitExpr memberCallHandler finalizeExpr
| TryWith(bodyExpr, _, _, catchVar, catchExpr, debugPointAtTry, debugPointAtWith) ->
visitExpr memberCallHandler bodyExpr; visitExpr memberCallHandler catchExpr
| TupleGet(tupleType, tupleElemIndex, tupleExpr) ->
visitExpr memberCallHandler tupleExpr
| DecisionTree(decisionExpr, decisionTargets) ->
visitExpr memberCallHandler decisionExpr; List.iter (snd >> visitExpr memberCallHandler) decisionTargets
| DecisionTreeSuccess (decisionTargetIdx, decisionTargetExprs) ->
visitExprs memberCallHandler decisionTargetExprs
| TypeLambda(genericParam, bodyExpr) ->
visitExpr memberCallHandler bodyExpr
| TypeTest(ty, inpExpr) ->
visitExpr memberCallHandler inpExpr
visitExpr memberCallHandler catchExpr
| TupleGet(tupleType, tupleElemIndex, tupleExpr) -> visitExpr memberCallHandler tupleExpr
| DecisionTree(decisionExpr, decisionTargets) ->
visitExpr memberCallHandler decisionExpr
List.iter (snd >> visitExpr memberCallHandler) decisionTargets
| DecisionTreeSuccess(decisionTargetIdx, decisionTargetExprs) -> visitExprs memberCallHandler decisionTargetExprs
| TypeLambda(genericParam, bodyExpr) -> visitExpr memberCallHandler bodyExpr
| TypeTest(ty, inpExpr) -> visitExpr memberCallHandler inpExpr
| UnionCaseSet(unionExpr, unionType, unionCase, unionCaseField, valueExpr) ->
visitExpr memberCallHandler unionExpr; visitExpr memberCallHandler valueExpr
| UnionCaseGet(unionExpr, unionType, unionCase, unionCaseField) ->
visitExpr memberCallHandler unionExpr
| UnionCaseTest(unionExpr, unionType, unionCase) ->
visitExpr memberCallHandler unionExpr
| UnionCaseTag(unionExpr, unionType) ->
visitExpr memberCallHandler unionExpr
visitExpr memberCallHandler valueExpr
| UnionCaseGet(unionExpr, unionType, unionCase, unionCaseField) -> visitExpr memberCallHandler unionExpr
| UnionCaseTest(unionExpr, unionType, unionCase) -> visitExpr memberCallHandler unionExpr
| UnionCaseTag(unionExpr, unionType) -> visitExpr memberCallHandler unionExpr
| ObjectExpr(objType, baseCallExpr, overrides, interfaceImplementations) ->
visitExpr memberCallHandler baseCallExpr
List.iter (visitObjMember memberCallHandler) overrides
List.iter (snd >> List.iter (visitObjMember memberCallHandler)) interfaceImplementations
| TraitCall(sourceTypes, traitName, typeArgs, typeInstantiation, argTypes, argExprs) ->
visitExprs memberCallHandler argExprs
| ValueSet(valToSet, valueExpr) ->
visitExpr memberCallHandler valueExpr
| ValueSet(valToSet, valueExpr) -> visitExpr memberCallHandler valueExpr
| WhileLoop(guardExpr, bodyExpr, debugPointAtWhile) ->
visitExpr memberCallHandler guardExpr; visitExpr memberCallHandler bodyExpr
visitExpr memberCallHandler guardExpr
visitExpr memberCallHandler bodyExpr
| BaseValue baseType -> ()
| DefaultValue defaultType -> ()
| ThisValue thisType -> ()
| Const(constValueObj, constType) -> ()
| Value(valueToGet) -> ()
| _ -> ()

and visitExprs f exprs =
List.iter (visitExpr f) exprs
and visitExprs f exprs = List.iter (visitExpr f) exprs

and visitObjArg f objOpt =
Option.iter (visitExpr f) objOpt
and visitObjArg f objOpt = Option.iter (visitExpr f) objOpt

and visitObjMember f memb =
visitExpr f memb.Body
and visitObjMember f memb = visitExpr f memb.Body

let rec visitDeclaration f d =
match d with
| FSharpImplementationFileDeclaration.Entity (e, subDecls) ->
| FSharpImplementationFileDeclaration.Entity(e, subDecls) ->
for subDecl in subDecls do
visitDeclaration f subDecl
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue(v, vs, e) ->
visitExpr f e
| FSharpImplementationFileDeclaration.InitAction(e) ->
visitExpr f e
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue(v, vs, e) -> visitExpr f e
| FSharpImplementationFileDeclaration.InitAction(e) -> visitExpr f e

let notUsed() =
let option : Option<int> = None
let notUsed () =
let option: Option<int> = None
option.Value

[<Analyzer "OptionAnalyzer">]
let optionValueAnalyzer : Analyzer =
let optionValueAnalyzer: Analyzer =
fun ctx ->
let state = ResizeArray<range>()

let handler (range: range) (m: FSharpMemberOrFunctionOrValue) =
let name = String.Join(".", m.DeclaringEntity.Value.FullName, m.DisplayName)

if name = "Microsoft.FSharp.Core.FSharpOption`1.Value" then
state.Add range

ctx.TypedTree.Declarations |> List.iter (visitDeclaration handler)

state
|> Seq.map (fun r ->
{ Type = "Option.Value analyzer"
Message = "Option.Value shouldn't be used"
Code = "OV001"
Severity = Warning
Range = r
Fixes = []}
{
Type = "Option.Value analyzer"
Message = "Option.Value shouldn't be used"
Code = "OV001"
Severity = Warning
Range = r
Fixes = []
}
)
|> Seq.toList
|> Seq.toList
Loading