Skip to content
Open
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
70 changes: 67 additions & 3 deletions src/CSharpLanguageServer/Program.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module CSharpLanguageServer.Program

open System
open System.IO
open System.Reflection

open Argu
Expand Down Expand Up @@ -38,6 +39,66 @@ let parseLogLevel (debugMode: bool) (logLevelArg: string option) =
| Some "trace" -> LogLevel.Trace
| _ -> if debugMode then LogLevel.Debug else LogLevel.Information

let getTopLevelFiles (dir: string) (patterns: string list) =
patterns
|> List.collect (fun pattern ->
Directory.GetFiles(dir, pattern, SearchOption.TopDirectoryOnly)
|> Array.toList)

let validateSolutionsOrTopLevelProjects
(solutionPath: string option) : string option =
match solutionPath with
| Some solution ->
let fullPath = Path.GetFullPath solution
if not (File.Exists fullPath) then
invalidArg "Solution" $"Solution file not found: %s{fullPath}"

match Path.GetExtension(fullPath).ToLowerInvariant() with
| ".sln" | ".slnx" -> Some fullPath
| _ ->
invalidArg "Solution" $"Invalid solution file extension (expected .sln or .slnx): %s{fullPath}"

| None ->
let dir = Directory.GetCurrentDirectory()

let slnxFiles = getTopLevelFiles dir [ "*.slnx" ]
let slnFiles = getTopLevelFiles dir [ "*.sln" ]
let projFiles = getTopLevelFiles dir [ "*.csproj"; ]

match slnxFiles, slnFiles with
// Prefer .slnx if exactly one
| [ single ], _ ->
Some single

// Multiple .slnx → must choose
| xs, _ when List.length xs > 1 ->
invalidArg "Solution"
(sprintf
"Multiple .slnx files found in '%s'. Please specify one with -s/--solution.\n%s"
dir
(String.concat "\n" xs))

// No .slnx, but exactly one .sln
| [], [ single ] ->
Some single

// Multiple .sln → must choose
| [], xs when List.length xs > 1 ->
invalidArg "Solution"
(sprintf
"Multiple .sln files found in '%s'. Please specify one with -s/--solution.\n%s"
dir
(String.concat "\n" xs))

// No solutions at all
| [], [] ->
if List.isEmpty projFiles then
invalidArg "Solution"
$"No -s/--solution argument provided, and no .sln/.slnx or project files were found in '%s{dir}' (top-level)."
else
None
| _ -> invalidArg "Solution" "Unable to process target directory"

[<EntryPoint>]
let entry args =
try
Expand All @@ -63,15 +124,18 @@ let entry args =
|> Seq.filter (String.IsNullOrWhiteSpace >> not)
|> Set.ofSeq

let settings =
let solutionsProvided = serverArgs.TryGetResult <@ Solution @>
let solutionOrValidCurrentDir = validateSolutionsOrTopLevelProjects solutionsProvided

let settings: ServerSettings =
{ ServerSettings.Default with
DebugMode = debugMode
SolutionPath = serverArgs.TryGetResult <@ Solution @>
SolutionPath = solutionOrValidCurrentDir
UseMetadataUris = features.Contains "metadata-uris"
RazorSupport = features.Contains "razor-support"
LogLevel = logLevel }

let exitCode =
let exitCode: int =
match serverArgs.TryGetResult <@ Diagnose @> with
| Some _ ->
Logging.setupLogging LogLevel.Trace
Expand Down
Loading