-
-
Notifications
You must be signed in to change notification settings - Fork 193
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 .editorconfig to define Fantomas settings #650
Comments
Hey @xperiandri , this issue came just in time ;) I'm a bit less familiar with .editorconfig so my main question would be: how does this work with custom settings? Can we just write anything we want in the file and parse it as we want? How would our current default look like in .editorconfig? {
"IndentSpaceNum":4,
"PageWidth":120,
"SemicolonAtEndOfLine":false,
"SpaceBeforeArgument":true ,
"SpaceBeforeColon":false,
"SpaceAfterComma":true ,
"SpaceAfterSemicolon":true ,
"IndentOnTryWith":false,
"ReorderOpenDeclaration":false,
"SpaceAroundDelimiter":true ,
"KeepNewlineAfter":false,
"MaxIfThenElseShortWidth":40,
"StrictMode":false
} One advantage of using a JSON file is that we have listed a JSON schema. Would there be something similar for editorconfig? |
@madskristensen could you explain what is the source of Editor Config Language autocomplete? How can Fantomas provide F# specific settings to a service? |
|
Why are you changing the names of settings?
And why not use boolean for
To be clear, the only thing I'm considering here is swapping the JSON config file to .editorconfig format. Different names for the settings might eventually be being discussed but for now, I would like to keep the same names in the CLI tool as in the configuration file. Changing names is something that I would only do in the next major version. |
@nojaf, could you show me an excerpt of the code, that matches your settings that I have changed? module Waggrx.Store.Cache
open Waggrx.Models
open System.Collections.Generic
open System.Net.Http
open FSharp.Collections.Immutable
open Blazor.Fluxor
type State =
{
Products : HashMap<ProductId, Product>
ProductTypes : HashMap<ProductTypeId, ProductType>
Dosages : HashMap<DosageId, Dosage>
Quantities : HashMap<QuantityId, Quantity>
Flavors : HashMap<FlavorId, Flavor>
}
type Action =
| LoadProducts
| LoadProductTypes of Id : ProductId
| LoadProductType of ProductId : ProductId * ProductTypeId : ProductTypeId
let inline private merge< ^K, ^E when ^E : (member Id: ^K) > existing (loaded : seq< ^E>) =
let keys = loaded |> Seq.map (fun e -> (^E: (member Id: ^K) (e)))
let cached = (keys, existing) ||> HashMap.except
let loaded = loaded |> Seq.map Catalog.toKVP
(cached, loaded) ||> HashMap.append
let loadProducts (loadFunction : HttpClient -> Async<FlatList<Product>>)
httpClient (state : State) =
async {
let! loadedProducts = loadFunction httpClient
return merge state.Products loadedProducts
}
let loadAllProducts httpClient state =
async {
let! mergedProducts = loadProducts Catalog.loadProducts httpClient state
return { state with Products = mergedProducts }
}
let loadProductTypes httpClient (state : State) id =
async {
let! loadedProductTypes = Catalog.loadProductTypes httpClient id
let keys = loadedProductTypes |> Seq.map (fun pt -> pt.Id)
let cachedProducts = (keys, state.ProductTypes) ||> HashMap.except
let loadedProductTypes = loadedProductTypes |> Seq.map Catalog.toKVP
let mergedProducts = (cachedProducts, loadedProductTypes) ||> HashMap.append
return { state with ProductTypes = mergedProducts }
}
let loadProductsPage httpClient (state : State) pageSize pageNumber =
async {
let loadFunction httpClient = Catalog.loadProductsPage httpClient pageSize pageNumber
let! mergedProducts = loadProducts loadFunction httpClient state
let! productIdsWithTypes =
async {
let! productIdsWithTypes =
query {
for productId in mergedProducts.Keys do
let productIdsWithTypes = async {
let! productTypes =
Catalog.loadProductTypes httpClient productId
return productTypes
|> Seq.map (fun productType -> KeyValuePair(productId, productType))
}
select productIdsWithTypes
} |> Async.Parallel
return productIdsWithTypes
|> Seq.collect id
|> HashMap.ofSeq
}
let! productIdsWithDosages =
async {
let! productIdsWithDosages =
query {
let idsPairs =
productIdsWithTypes
|> Seq.map (fun kvp -> struct (kvp.Key, kvp.Value.Id))
for ids in idsPairs do
let struct (productId, typeId) = ids
let productIdsWithDosages = async {
let! dosages = Catalog.loadDosages httpClient productId typeId
return dosages
|> Seq.map (fun dosage -> KeyValuePair(ids, dosage))
}
select productIdsWithDosages
} |> Async.Parallel
return productIdsWithDosages
|> Seq.collect id
|> HashMap.ofSeq
}
let! quantities =
async {
let! productIdsWithQuantities =
query {
let idsTriples =
productIdsWithDosages
|> Seq.map (fun kvp ->
let struct (productId, typeId) = kvp.Key
struct (productId, typeId, kvp.Value.Id))
for ids in idsTriples do
let struct (productId, typeId, dosageId) = ids
select (Catalog.loadQuantities httpClient productId typeId dosageId)
} |> Async.Parallel
return productIdsWithQuantities
|> Seq.collect id
}
let! productIdsWithFlavors =
async {
let! productIdsWithFlavors =
query {
let idsPairs =
productIdsWithTypes
|> Seq.where (fun kvp -> kvp.Value.HasFlavors)
|> Seq.map (fun kvp -> struct (kvp.Key, kvp.Value.Id))
for ids in idsPairs do
let struct (productId, typeId) = ids
let productIdsWithFlavors = async {
let! flavors = Catalog.loadFlavors httpClient productId typeId
return flavors
|> Seq.map (fun dosage -> KeyValuePair(ids, dosage))
}
select productIdsWithFlavors
} |> Async.Parallel
return productIdsWithFlavors
|> Seq.collect id
|> HashMap.ofSeq
}
return {
Products = mergedProducts
ProductTypes = merge state.ProductTypes productIdsWithTypes.Values
Dosages = merge state.Dosages productIdsWithDosages.Values
Quantities = merge state.Quantities quantities
Flavors = merge state.Flavors productIdsWithFlavors.Values
}
}
type Feature () =
inherit Feature<State> ()
override __.GetName () = "Cache"
override __.GetInitialState () =
{
Products = HashMap.empty
ProductTypes = HashMap.empty
Dosages = HashMap.empty
Quantities = HashMap.empty
Flavors = HashMap.empty
} Or any from here https://github.com/SfSync/Bayeux/tree/master/src/Bayeux.Client These are how I prefer to format my code. |
Because I would prefer having option to set spaces not only after colons and semicolons but before them too.
I'm OK with that. |
Please create another issue for these kinds of requests 😉, otherwise, this issue is getting a bit derailed. Check out the current options at our documentation. So to get back on track, I will see if I can come up with a PR to get the settings from an .editorconfig file instead of our JSON format. |
@xperiandri See these files: https://github.com/madskristensen/EditorConfigLanguage/tree/master/src/Schema This is where you specify the properties in the .json file and you also have to add a few things in some of the other files since you're introducing a new language. It should be simple enough when you see the code in those files |
Hello @xperiandri , I've refactored the code a bit so that the only thing remaining here is the implementation of parsing the file to settings. I won't pursuit this myself for the time being, there are other priorities and this can easily be picked up by someone else it doesn't really involve any knowledge about Fantomas. To whoever that wants to pick this up, keep the following rules in mind:
|
Why don't got want to reference Roslyn package that already has that logic? |
|
Fantomas is being used by Rider, FSAutocomplete , FSAst and maybe even other projects. I don't want to introduce an additional dependency for the consumers of Fantomas. |
I don't see any benefit copying already implemented code even as source especially if it is from official MS package used by all IDEs |
There is also: https://github.com/editorconfig/editorconfig-core-net which I maintain and is itself dependency free. Rider already uses it as well. |
Hey @Mpdreamz , thanks for the suggestion.
|
I thought about finishing the feature as prepared by @nojaf. However I found out that the code is not quite ready yet. The editorconfig format supports two features, that fantomas-config does not:
This sets indentation for Now how to implement that? The I see three possible solutions:
What do you think? Ad custom settings in editorconfig. Currently the editorconfig format defines only a limited set of universal properties (like tab settings, charset, newlines etc.). The file can contain any custom properties. There is a prefix-based convention for naming the file format specific properties. E.g. Visual Studio uses properties with This means we are free to come up with any There is a discussion (see editorconfig/editorconfig#415) in the editorconfig project itself regarding its future extensions and custom namespaces. However there is no definite conclusion yet. |
Hello @josefblaha, thanks for this thorough remark. As for the custom settings, if we can use As @Mpdreamz mentioned https://github.com/editorconfig/editorconfig-core-net also seems interesting. Perhaps we can combine this with some sort of assembly weaving. So from a Nuget point of view, we still don't have the extra dependency. Lastly, thinking out loud at this point, perhaps we should consider of having only the .editorconfig solution. |
I would definitely be in favor of standardizing on .editorconfig, personally. |
I've talked with @jindraivanek about this behind the scenes and we would move forward on this. |
Oh :-/ Have you made much progress yet? I'm working on it too. I thought this would be a good starter issue for me. |
Hey, I've trying to port https://github.com/editorconfig/editorconfig-core-net to F#. The further I get there, the more obvious it becomes that this is a bad idea so I'm abandoning that train of thought. Next attempt I had in mind was to use ILRepack and move the C# project to this repository and merge it into the Fantomas dll. How is your attempt going @josefblaha? Biggest challenge seems the glob thing. Any fork I can take a look at maybe? |
So far I've been playing with editorconfig-core-net. It provides not only parsing the Why do you think it's necessary to move the library to this repository? Wouldn't referencing it as a regular NuGet package and merging it to Fantomas DLL as part of the build process be enough? What are the cons of merging the library to Fantomas DLL? If there is a requirement for a single DLL output, it seems like a good solution. |
Yes, I experimented there a bit as well. Using that method it is rather easy indeed. Reason for going with a fork was to have an netstandard2.0 only thing. I didn't like the msbuild warnings I guess. Maybe I missed something in Paket configuration there.
Never really used any ilmerge like thing, so has that black alchemy vibe to it. |
I wouldn't worry too much about ilmerging, paket has been doing it from the beginning with several dependencies and it hasn't been an issue there. |
I released a new alpha to try this out: https://www.nuget.org/packages/fantomas-tool/4.0.0-alpha-012 For the settings names, see the docs. |
Custom settings are totally fine! Namespacing is an active discussion but given the prevalence of existing prefixes I reckon reserved prefixes will end up in the spec at some point.
Some LSP's support it and some don't. I don't think the LSP protocol exposes it explicitly although there is this: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#workspace_configuration I'm keen to get y'all of the fork, I will look at getting the compiler errors to go away when building on a non Windows machine. There is a dotnet tool I help maintain that could be run before IL merge: https://github.com/nullean/assembly-rewriter To rewrite the namespaces to Let me know how I can help further in any way. You should be able to find me on the fsharp slack too. |
.editorconfig is a common solution to define all code related rules including formatting and code analysis.
It would be the right option for Fantomas to read settings from it.
The text was updated successfully, but these errors were encountered: