@@ -93,39 +93,33 @@ func encloseWithQuotes(s string) string {
9393 return fmt .Sprintf (`"%v"` , s )
9494}
9595
96- func setDiagnosticData ( diagnostic * protocol. Diagnostic , instruction * parser.Node , warning lint.Warning ) {
96+ func createResolutionEdit ( instruction * parser.Node , warning lint.Warning ) * types. NamedEdit {
9797 if instruction != nil && instruction .StartLine == int (warning .Location .Ranges [0 ].Start .Line ) && instruction .Next != nil {
9898 if warning .RuleName == "MaintainerDeprecated" {
99- diagnostic .Data = []types.NamedEdit {
100- {
101- Title : "Convert MAINTAINER to a org.opencontainers.image.authors LABEL" ,
102- Edit : fmt .Sprintf (`LABEL org.opencontainers.image.authors=%v` , encloseWithQuotes (instruction .Next .Value )),
103- },
99+ return & types.NamedEdit {
100+ Title : "Convert MAINTAINER to a org.opencontainers.image.authors LABEL" ,
101+ Edit : fmt .Sprintf (`LABEL org.opencontainers.image.authors=%v` , encloseWithQuotes (instruction .Next .Value )),
104102 }
105103 } else if warning .RuleName == "StageNameCasing" {
106104 stageName := instruction .Next .Next .Next .Value
107105 lowercase := strings .ToLower (stageName )
108106 words := []string {instruction .Value , instruction .Next .Value , instruction .Next .Next .Value , lowercase }
109- diagnostic .Data = []types.NamedEdit {
110- {
111- Title : fmt .Sprintf ("Convert stage name (%v) to lowercase (%v)" , stageName , lowercase ),
112- Edit : strings .Join (words , " " ),
113- },
107+ return & types.NamedEdit {
108+ Title : fmt .Sprintf ("Convert stage name (%v) to lowercase (%v)" , stageName , lowercase ),
109+ Edit : strings .Join (words , " " ),
114110 }
115111 } else if warning .RuleName == "RedundantTargetPlatform" {
116112 words := getWords (instruction )
117113 for i := range words {
118114 if words [i ] == "--platform=$TARGETPLATFORM" {
119115 words = slices .Delete (words , i , i + 1 )
120- diagnostic .Data = []types.NamedEdit {
121- {
122- Title : "Remove unnecessary --platform flag" ,
123- Edit : strings .Join (words , " " ),
124- },
125- }
126116 break
127117 }
128118 }
119+ return & types.NamedEdit {
120+ Title : "Remove unnecessary --platform flag" ,
121+ Edit : strings .Join (words , " " ),
122+ }
129123 } else if warning .RuleName == "ConsistentInstructionCasing" {
130124 words := getWords (instruction )
131125 suggestion := strings .ToUpper (instruction .Value )
@@ -134,14 +128,13 @@ func setDiagnosticData(diagnostic *protocol.Diagnostic, instruction *parser.Node
134128 suggestion = strings .ToLower (suggestion )
135129 }
136130 words [0 ] = suggestion
137- diagnostic .Data = []types.NamedEdit {
138- {
139- Title : fmt .Sprintf ("Convert to %v" , caseSuggestion ),
140- Edit : strings .Join (words , " " ),
141- },
131+ return & types.NamedEdit {
132+ Title : fmt .Sprintf ("Convert to %v" , caseSuggestion ),
133+ Edit : strings .Join (words , " " ),
142134 }
143135 }
144136 }
137+ return nil
145138}
146139
147140func convertToDiagnostics (source string , doc document.DockerfileDocument , lines []string , warnings []lint.Warning ) []protocol.Diagnostic {
@@ -168,12 +161,71 @@ func convertToDiagnostics(source string, doc document.DockerfileDocument, lines
168161 diagnostic .Tags = []protocol.DiagnosticTag {protocol .DiagnosticTagDeprecated }
169162 }
170163 instruction := doc .Instruction (protocol.Position {Line : uint32 (warning .Location .Ranges [0 ].Start .Line ) - 1 })
171- setDiagnosticData (diagnostic , instruction , warning )
164+ ignoreEdit := createIgnoreEdit (warning .RuleName )
165+ resolutionEdit := createResolutionEdit (instruction , warning )
166+ if resolutionEdit == nil {
167+ if ignoreEdit != nil {
168+ diagnostic .Data = []types.NamedEdit {* ignoreEdit }
169+ }
170+ } else {
171+ diagnostic .Data = []types.NamedEdit {* resolutionEdit , * ignoreEdit }
172+ }
172173 diagnostics = append (diagnostics , * diagnostic )
173174 }
174175 return diagnostics
175176}
176177
178+ func createIgnoreEdit (ruleName string ) * types.NamedEdit {
179+ switch ruleName {
180+ case "ConsistentInstructionCasing" :
181+ fallthrough
182+ case "CopyIgnoredFile" :
183+ fallthrough
184+ case "DuplicateStageName" :
185+ fallthrough
186+ case "FromAsCasing" :
187+ fallthrough
188+ case "FromPlatformFlagConstDisallowed" :
189+ fallthrough
190+ case "InvalidDefaultArgInFrom" :
191+ fallthrough
192+ case "InvalidDefinitionDescription" :
193+ fallthrough
194+ case "JSONArgsRecommended" :
195+ fallthrough
196+ case "LegacyKeyValueFormat" :
197+ fallthrough
198+ case "MaintainerDeprecated" :
199+ fallthrough
200+ case "MultipleInstructionsDisallowed" :
201+ fallthrough
202+ case "NoEmptyContinuation" :
203+ fallthrough
204+ case "RedundantTargetPlatform" :
205+ fallthrough
206+ case "ReservedStageName" :
207+ fallthrough
208+ case "SecretsUsedInArgOrEnv" :
209+ fallthrough
210+ case "StageNameCasing" :
211+ fallthrough
212+ case "UndefinedArgInFrom" :
213+ fallthrough
214+ case "UndefinedVar" :
215+ fallthrough
216+ case "WorkdirRelativePath" :
217+ return & types.NamedEdit {
218+ Title : fmt .Sprintf ("Ignore this type of error with check=skip=%v" , ruleName ),
219+ Edit : fmt .Sprintf ("# check=skip=%v\n " , ruleName ),
220+ Range : & protocol.Range {
221+ Start : protocol.Position {Line : 0 , Character : 0 },
222+ End : protocol.Position {Line : 0 , Character : 0 },
223+ },
224+ }
225+ }
226+ return nil
227+ }
228+
177229func lintWithBuildKitBinary (contextPath , source string , doc document.DockerfileDocument , content string ) ([]protocol.Diagnostic , error ) {
178230 var buf bytes.Buffer
179231 cmd := exec .Command ("docker" , "buildx" , "build" , "--call=check,format=json" , "-f-" , contextPath )
0 commit comments