1 module served.linters.dub; 2 3 import core.thread; 4 5 import painlessjson; 6 7 import served.extension; 8 import served.linters.diagnosticmanager; 9 import served.types; 10 11 import std.algorithm; 12 import std.array; 13 import std.file; 14 import std.json; 15 import std.path; 16 import std.process; 17 import std.stdio; 18 import std.string; 19 20 import workspaced.api; 21 import workspaced.coms; 22 23 import workspaced.com.dub : ErrorType; 24 25 enum DiagnosticSlot = 1; 26 27 enum DubDiagnosticSource = "DUB"; 28 29 string fixPath(string workspaceRoot, string path, string[] stringImportPaths) 30 { 31 auto mixinIndex = path.indexOf("-mixin-"); 32 if (mixinIndex != -1) 33 path = path[0 .. mixinIndex]; 34 auto absPath = isAbsolute(path) ? path : buildNormalizedPath(workspaceRoot, path); 35 if (path.endsWith(".d")) 36 path = absPath; 37 else if (!isAbsolute(path)) 38 { 39 bool found; 40 foreach (imp; stringImportPaths) 41 { 42 if (!isAbsolute(imp)) 43 imp = buildNormalizedPath(workspaceRoot, imp); 44 auto modPath = buildNormalizedPath(imp, path); 45 if (exists(modPath)) 46 { 47 path = modPath; 48 found = true; 49 break; 50 } 51 } 52 if (!found) 53 path = absPath; 54 } 55 else 56 path = absPath; 57 return path; 58 } 59 60 DiagnosticSeverity mapDubLintType(ErrorType type) 61 { 62 final switch (type) 63 { 64 case ErrorType.Deprecation: 65 return DiagnosticSeverity.information; 66 case ErrorType.Warning: 67 return DiagnosticSeverity.warning; 68 case ErrorType.Error: 69 return DiagnosticSeverity.error; 70 } 71 } 72 73 void lint(Document document) 74 { 75 auto workspaceRoot = workspaceRootFor(document.uri); 76 77 stderr.writeln("Running dub build"); 78 auto imports = backend.get!DubComponent(workspaceRoot).stringImports; 79 auto issues = backend.get!DubComponent(workspaceRoot).build.getYield; 80 PublishDiagnosticsParams[] result; 81 foreach (issue; issues) 82 { 83 auto uri = uriFromFile(fixPath(workspaceRoot, issue.file, imports)); 84 Diagnostic error; 85 error.range = TextRange(Position(issue.line - 1, issue.column - 1)); 86 error.severity = mapDubLintType(issue.type); 87 error.source = DubDiagnosticSource; 88 error.message = issue.text; 89 bool found; 90 foreach (ref elem; result) 91 if (elem.uri == uri) 92 { 93 found = true; 94 elem.diagnostics ~= error; 95 } 96 if (!found) 97 result ~= PublishDiagnosticsParams(uri, [error]); 98 } 99 100 diagnostics[DiagnosticSlot] = result; 101 updateDiagnostics(document.uri); 102 }