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

Extract shared logic between json config and editorconfig. #663

Merged
merged 4 commits into from
Feb 3, 2020
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
5 changes: 3 additions & 2 deletions src/Fantomas.Tests/Fantomas.Tests.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\netfx.props" />
<PropertyGroup>
<Version>3.2.0-beta-002</Version>
Expand Down Expand Up @@ -57,7 +57,8 @@
<Compile Include="ElmishTests.fs" />
<Compile Include="LambdaTests.fs" />
<Compile Include="IfThenElseTests.fs" />
<Compile Include="FormatConfigConfigurationFileTests.fs" />
<Compile Include="FormatConfigJsonConfigurationFileTests.fs" />
<Compile Include="FormatConfigEditorConfigurationFileTests.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fantomas\Fantomas.fsproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module Fantomas.Tests.FormatConfigEditorConfigurationFileTests

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Fantomas.Tests.FormatConfigConfigurationFileTests
module Fantomas.Tests.FormatConfigJsonConfigurationFileTests

open System
open Fantomas
Expand All @@ -7,7 +7,8 @@ open NUnit.Framework
open System.IO
open Fantomas.Tests.TestHelper

let private getTempFolder () = Path.GetTempPath()
[<Literal>]
let private configFileName ="fantomas-config.json"

let private configToJson config =
Reflection.getRecordFields config
Expand All @@ -24,24 +25,12 @@ let private configToJson config =
|> String.concat ",\n "
|> sprintf "{ %s }"

let private mkConfigPath folder =
match folder with
| Some folder ->
let folderPath = Path.Combine(getTempFolder(), folder)
Directory.CreateDirectory(folderPath) |> ignore
Path.Combine(folderPath, "fantomas-config.json")
| None ->
Path.Combine(getTempFolder(), "fantomas-config.json")
let private mkConfig folder fantomasConfig =
let file = mkConfigPath folder
let content = configToJson fantomasConfig
File.WriteAllText(file, content)
file

let private mkConfigFromJson folder json =
let file = mkConfigPath folder
File.WriteAllText(file, json)
file
let private mkConfig subFolder config =
let json = configToJson config
mkConfigFromContent configFileName subFolder json

let private mkConfigFromJson subFolder json =
mkConfigFromContent configFileName subFolder json

let rec private delete fileOrFolder =
if File.Exists(fileOrFolder) then
Expand All @@ -54,6 +43,10 @@ let rec private delete fileOrFolder =
()
let private uniqueString () = System.Guid.NewGuid().ToString("N")

let private applyOptionsToConfig config path =
let json = File.ReadAllText path
let options, warnings = JsonConfig.parseOptionsFromJson json
FormatConfig.applyOptions(config, options),warnings

[<Test>]
let ``single configuration file`` () =
Expand Down Expand Up @@ -101,24 +94,24 @@ let ``pointing to config in a subfolder should return parent config file as well
[<Test>]
let ``simple config file parses valid option`` () =
let path = mkConfigFromJson None "{\"KeepNewlineAfter\":true}"
let config, warnings = ConfigFile.applyOptionsToConfig FormatConfig.Default path
let config, warnings = applyOptionsToConfig FormatConfig.Default path
true == config.KeepNewlineAfter
[] == warnings

[<Test>]
let ``keys should not necessarily have quotes to be parsed`` () =
let path = mkConfigFromJson None "{KeepNewlineAfter:true}"
let config, warnings = ConfigFile.applyOptionsToConfig FormatConfig.Default path
let config, warnings = applyOptionsToConfig FormatConfig.Default path
true == config.KeepNewlineAfter
[] == warnings

[<Test>]
let ``invalid option returns a warning`` () =
let path = mkConfigFromJson None "{ \"Foo\": true }"
let config, warnings = ConfigFile.applyOptionsToConfig FormatConfig.Default path
let config, warnings = applyOptionsToConfig FormatConfig.Default path
config == FormatConfig.Default
match warnings with
| [ error ] ->
| [| error |] ->
StringAssert.IsMatch("\"Foo\":true is no valid setting for Fantomas v(.*)", error)
| _ -> fail()

Expand Down Expand Up @@ -176,20 +169,7 @@ let ``$schema key should not return warning`` () =
"IndentOnTryWith": true
}
"""
let _, warnings = ConfigFile.applyOptionsToConfig FormatConfig.Default path
[] == warnings

/// Ok to remove test once ReorderOpenDeclaration is removed from the code-base

[<Test>]
let ``configuration with ReorderOpenDeclaration should return a warning`` () =
let path = mkConfigFromJson None """
{
"ReorderOpenDeclaration": true
}
"""
let _, warnings = ConfigFile.applyOptionsToConfig FormatConfig.Default path
match warnings with
| [ reorderWarning ] ->
StringAssert.IsMatch("ReorderOpenDeclaration will be deprecated in the next major version. Using this feature can lead to compilation errors after formatting.", reorderWarning)
| _ -> fail()
let _, warnings =
File.ReadAllText path
|> JsonConfig.parseOptionsFromJson
[] == warnings
17 changes: 17 additions & 0 deletions src/Fantomas.Tests/TestHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ open FSharp.Compiler.Ast
open FSharp.Compiler.Range
open NUnit.Framework
open FsCheck
open System.IO

let config = FormatConfig.Default
let newline = "\n"
Expand Down Expand Up @@ -180,3 +181,19 @@ type NUnitRunner () =
// TODO : Log more information about the test failure.
Runner.onFinishedToString name result
|> Assert.Fail

let private getTempFolder () = Path.GetTempPath()

let private mkConfigPath fileName folder =
match folder with
| Some folder ->
let folderPath = Path.Combine(getTempFolder(), folder)
Directory.CreateDirectory(folderPath) |> ignore
Path.Combine(folderPath, fileName)
| None ->
Path.Combine(getTempFolder(), fileName)

let mkConfigFromContent fileName folder content =
let file = mkConfigPath fileName folder
File.WriteAllText(file, content)
file
24 changes: 2 additions & 22 deletions src/Fantomas/CodeFormatter.fs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
namespace Fantomas

open Fantomas
open FormatConfig

[<Sealed>]
type CodeFormatter =
static member ParseAsync(fileName, source, parsingOptions, checker) =
Expand Down Expand Up @@ -35,23 +32,6 @@ type CodeFormatter =
static member MakeRange(fileName, startLine, startCol, endLine, endCol) =
CodeFormatterImpl.makeRange fileName startLine startCol endLine endCol

static member GetVersion() = Fantomas.Version.fantomasVersion.Value

static member ReadConfiguration(fileOrFolder) =
try
let configurationFiles =
ConfigFile.findConfigurationFiles fileOrFolder

if List.isEmpty configurationFiles then failwithf "No configuration files were found for %s" fileOrFolder

let (config,warnings) =
List.fold (fun (currentConfig, warnings) configPath ->
let updatedConfig, warningsForPath = ConfigFile.applyOptionsToConfig currentConfig configPath
(updatedConfig, warnings @ warningsForPath)
) (FormatConfig.Default, []) configurationFiles
static member GetVersion() = Version.fantomasVersion.Value

match warnings with
| [] -> FormatConfigFileParseResult.Success config
| w -> FormatConfigFileParseResult.PartialSuccess (config, w)
with
| exn -> FormatConfigFileParseResult.Failure exn
static member ReadConfiguration(fileOrFolder) = CodeFormatterImpl.readConfiguration fileOrFolder
34 changes: 33 additions & 1 deletion src/Fantomas/CodeFormatterImpl.fs
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,36 @@ type internal BlockType =
| Tuple

/// Make a position at (line, col) to denote cursor position
let makePos line col = mkPos line col
let makePos line col = mkPos line col

let readConfiguration fileOrFolder =
try
let configurationFiles =
ConfigFile.findConfigurationFiles fileOrFolder

if List.isEmpty configurationFiles then failwithf "No configuration files were found for %s" fileOrFolder

let (config,warnings) =
List.fold (fun (currentConfig, warnings) configPath ->
let configContent = System.IO.File.ReadAllText(configPath)
let options, warningFromConfigPath =
match System.IO.Path.GetFileName(configPath) with
| json when (json = ConfigFile.jsonConfigFileName) ->
JsonConfig.parseOptionsFromJson configContent
| editorconfig when (editorconfig = ConfigFile.editorConfigFileName) ->
EditorConfig.parseOptionsFromEditorConfig configContent
| _ ->
failwithf "Filename is not supported!"
let updatedConfig = FormatConfig.applyOptions(currentConfig, options)
let locationAwareWarnings =
List.ofArray warningFromConfigPath
|> List.map (ConfigFile.makeWarningLocationAware configPath)

(updatedConfig, warnings @ locationAwareWarnings)
) (FormatConfig.Default, []) configurationFiles

match warnings with
| [] -> FormatConfigFileParseResult.Success config
| w -> FormatConfigFileParseResult.PartialSuccess (config, w)
with
| exn -> FormatConfigFileParseResult.Failure exn
62 changes: 62 additions & 0 deletions src/Fantomas/ConfigFile.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module internal Fantomas.ConfigFile

open System.IO
open Fantomas.FormatConfig
open Fantomas.Version

let jsonConfigFileName = "fantomas-config.json"
let editorConfigFileName = ".editor-config"

let private allowedFileNames = [jsonConfigFileName; editorConfigFileName]

let rec private getParentFolders acc current =
let parent = Directory.GetParent(current) |> Option.ofObj
match parent with
| Some p -> getParentFolders (current::acc) p.FullName
| None -> current::acc

/// Returns all the found configuration files for the given path
/// fileOrFolder can be a concrete json file or a directory path
let rec findConfigurationFiles fileOrFolder : string list =
let findConfigInFolder folderPath =
allowedFileNames
|> List.map (fun fn -> Path.Combine(folderPath, fn))
|> List.filter (File.Exists)

if Path.GetExtension(fileOrFolder) = "" && Directory.Exists fileOrFolder then
getParentFolders [] fileOrFolder
|> List.collect findConfigInFolder
elif File.Exists(fileOrFolder) then
let parentFolder =
Directory.GetParent(Path.GetDirectoryName(fileOrFolder))
|> Option.ofObj
match parentFolder with
| Some pf -> findConfigurationFiles pf.FullName @ [fileOrFolder]
| None -> [fileOrFolder]
else
[]

let makeWarningLocationAware configPath warning =
sprintf "%s, in %s" warning configPath

let private fantomasFields = Reflection.getRecordFields FormatConfig.Default |> Array.map fst
let private (|FantomasSetting|_|) (s:string) =
let s = s.Trim('\"')
Array.tryFind ((=) s) fantomasFields

let private (|Number|_|) d =
match System.Int32.TryParse(d) with
| true, d -> Some (box d)
| _ -> None
let private (|Boolean|_|) b =
if b = "true" then Some (box true)
elif b = "false" then Some (box false)
else None

let processSetting originalLine key value =
match (key, value) with
| (FantomasSetting(fs), Number(v))
| (FantomasSetting(fs), Boolean(v)) -> Ok (fs, v)
| _ ->
let warning = sprintf "%s is no valid setting for Fantomas v%s" originalLine (fantomasVersion.Value)
Error warning
7 changes: 7 additions & 0 deletions src/Fantomas/EditorConfig.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module internal Fantomas.EditorConfig

/// Similar to how to processing of the JSON file happens, this function should the options found in the editor config.
/// The first argument in the return tuple are the options. Listed as (key,value) where key is a member name of the FormatConfig record. Value is either a boolean or an int boxed as object.
/// The second argument in the return tuple are warnings. F.ex. invalid settings
let parseOptionsFromEditorConfig editorConfig : (string * obj) array * string array =
Array.empty, Array.empty
3 changes: 3 additions & 0 deletions src/Fantomas/Fantomas.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<Compile Include="Dbg.fs" />
<Compile Include="Utils.fs" />
<Compile Include="FormatConfig.fs" />
<Compile Include="ConfigFile.fs" />
<Compile Include="JsonConfig.fs" />
<Compile Include="EditorConfig.fs" />
<Compile Include="TriviaTypes.fs" />
<Compile Include="TokenParserBoolExpr.fs" />
<Compile Include="TriviaHelpers.fs" />
Expand Down
Loading