-
Notifications
You must be signed in to change notification settings - Fork 155
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
Workspace peek #191
Workspace peek #191
Changes from all commits
64faba4
409e405
52b68ac
c60f1f1
20c3cf0
2e72200
d6875e5
d7ef790
b70eaa4
376767b
4a36a0f
3be572c
25683c6
c9ebb7a
0658f21
1bf46ee
09b90de
13903d4
696bc29
534684d
4e50b73
60479d2
935f562
8aebbb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
module FsAutoComplete.WorkspacePeek | ||
|
||
open System | ||
open System.IO | ||
|
||
type SolutionData = { | ||
Items: SolutionItem list | ||
Configurations: SolutionConfiguration list | ||
} | ||
and SolutionConfiguration = { | ||
Id: string | ||
ConfigurationName: string | ||
PlatformName: string | ||
IncludeInBuild: bool | ||
} | ||
and SolutionItem = { | ||
Guid: Guid | ||
Name: string | ||
Kind: SolutionItemKind | ||
} | ||
and SolutionItemKind = | ||
| MsbuildFormat of SolutionItemMsbuildConfiguration list | ||
| Folder of (SolutionItem list) * (string list) | ||
| Unsupported | ||
| Unknown | ||
and SolutionItemMsbuildConfiguration = { | ||
Id: string | ||
ConfigurationName: string | ||
PlatformName: string | ||
} | ||
|
||
[<RequireQualifiedAccess>] | ||
type Interesting = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestions? cannot think anything else atm. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Content or Contents? |
||
| Solution of string * SolutionData | ||
| Directory of string * string list | ||
|
||
let tryParseSln slnFilePath = | ||
let parseSln (sln: Microsoft.Build.Construction.SolutionFile) = | ||
let slnDir = Path.GetDirectoryName slnFilePath | ||
let makeAbsoluteFromSlnDir = | ||
let makeAbs path = | ||
if Path.IsPathRooted path then | ||
path | ||
else | ||
Path.Combine(slnDir, path) | ||
|> Path.GetFullPath | ||
Utils.normalizeDirSeparators >> makeAbs | ||
let rec parseItem (item: Microsoft.Build.Construction.ProjectInSolution) = | ||
let parseKind (item: Microsoft.Build.Construction.ProjectInSolution) = | ||
match item.ProjectType with | ||
| Microsoft.Build.Construction.SolutionProjectType.KnownToBeMSBuildFormat -> | ||
(item.RelativePath |> makeAbsoluteFromSlnDir), SolutionItemKind.MsbuildFormat [] | ||
| Microsoft.Build.Construction.SolutionProjectType.SolutionFolder -> | ||
let children = | ||
sln.ProjectsInOrder | ||
|> Seq.filter (fun x -> x.ParentProjectGuid = item.ProjectGuid) | ||
|> Seq.map parseItem | ||
|> List.ofSeq | ||
let files = | ||
item.FolderFiles | ||
|> Seq.map makeAbsoluteFromSlnDir | ||
|> List.ofSeq | ||
item.ProjectName, SolutionItemKind.Folder (children, files) | ||
| Microsoft.Build.Construction.SolutionProjectType.EtpSubProject | ||
| Microsoft.Build.Construction.SolutionProjectType.WebDeploymentProject | ||
| Microsoft.Build.Construction.SolutionProjectType.WebProject -> | ||
(item.ProjectName |> makeAbsoluteFromSlnDir), SolutionItemKind.Unsupported | ||
| Microsoft.Build.Construction.SolutionProjectType.Unknown | ||
| _ -> | ||
(item.ProjectName |> makeAbsoluteFromSlnDir), SolutionItemKind.Unknown | ||
|
||
let name, itemKind = parseKind item | ||
{ Guid = item.ProjectGuid |> Guid.Parse | ||
Name = name | ||
Kind = itemKind } | ||
|
||
let items = | ||
sln.ProjectsInOrder | ||
|> Seq.filter (fun x -> isNull x.ParentProjectGuid) | ||
|> Seq.map parseItem | ||
let data = { | ||
Items = items |> List.ofSeq | ||
Configurations = [] | ||
} | ||
(slnFilePath, data) | ||
|
||
let slnFile = | ||
try | ||
Microsoft.Build.Construction.SolutionFile.Parse(slnFilePath) | ||
|> Some | ||
with _ -> | ||
None | ||
|
||
slnFile | ||
|> Option.map parseSln | ||
|
||
open System.IO | ||
|
||
type private UsefulFile = | ||
| FsProj | ||
| Sln | ||
| Fsx | ||
|
||
let private partitionByChoice3 = | ||
let foldBy (a, b, c) t = | ||
match t with | ||
| Choice1Of3 x -> (x :: a, b, c) | ||
| Choice2Of3 x -> (a, x :: b, c) | ||
| Choice3Of3 x -> (a, b, x :: c) | ||
Array.fold foldBy ([],[],[]) | ||
|
||
let peek (rootDir: string) deep (excludedDirs: string list) = | ||
let dirInfo = DirectoryInfo(rootDir) | ||
|
||
//TODO accept glob list to ignore | ||
let ignored = | ||
let normalizedDirs = excludedDirs |> List.map (fun s -> s.ToUpperInvariant()) |> Array.ofList | ||
(fun (s: string) -> normalizedDirs |> Array.contains (s.ToUpperInvariant())) | ||
|
||
let scanDir (dirInfo: DirectoryInfo) = | ||
let hasExt ext (s: FileInfo) = s.FullName.EndsWith(ext) | ||
dirInfo.EnumerateFiles("*.*", SearchOption.TopDirectoryOnly) | ||
|> Seq.choose (fun s -> | ||
match s with | ||
| x when x |> hasExt ".sln" -> Some (UsefulFile.Sln, x) | ||
| x when x |> hasExt ".fsx" -> Some (UsefulFile.Fsx, x) | ||
| x when x |> hasExt ".fsproj" -> Some (UsefulFile.FsProj, x) | ||
| _ -> None) | ||
|> Seq.toArray | ||
|
||
let dirs = | ||
let rec scanDirs (dirInfo: DirectoryInfo) lvl = | ||
seq { | ||
if lvl <= deep then | ||
yield dirInfo | ||
for s in dirInfo.GetDirectories() do | ||
if not(ignored s.Name) then | ||
yield! scanDirs s (lvl + 1) | ||
} | ||
|
||
scanDirs dirInfo 0 | ||
|> Array.ofSeq | ||
|
||
let getInfo (t, (f: FileInfo)) = | ||
match t with | ||
| UsefulFile.Sln -> | ||
tryParseSln f.FullName | ||
|> Option.map Choice1Of3 | ||
| UsefulFile.Fsx -> | ||
Some (Choice2Of3 (f.FullName)) | ||
| UsefulFile.FsProj -> | ||
Some (Choice3Of3 (f.FullName)) | ||
|
||
let found = | ||
dirs | ||
|> Array.Parallel.collect scanDir | ||
|> Array.Parallel.choose getInfo | ||
|
||
let slns, _fsxs, fsprojs = | ||
found |> partitionByChoice3 | ||
|
||
//TODO weight order of fsprojs from sln | ||
let dir = rootDir, (fsprojs |> List.sort) | ||
|
||
[ yield! slns |> List.map Interesting.Solution | ||
yield dir |> Interesting.Directory ] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
FSharp.Compiler.Service.ProjectCracker | ||
FSharp.Compiler.Service | ||
FSharpLint.Core | ||
Sln | ||
Dotnet.ProjInfo | ||
Newtonsoft.Json | ||
Newtonsoft.Json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to pin version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is not 1.0 yet, so i can publish new version and i dont guarantee the api compatibility between minor.
just to avoid issues for others, while updating deps.