public string GetSdkPath(MSBuildDocument doc, string sdk, TextSpan loc) { if (!SdkReference.TryParse(sdk, out SdkReference sdkRef)) { string parseErrorMsg = $"Could not parse SDK '{sdk}'"; LoggingService.LogError(parseErrorMsg); if (doc.IsToplevel) { doc.Diagnostics.Add(CoreDiagnostics.InvalidSdkAttribute, loc, sdk); } return(null); } try { var sdkPath = RuntimeInformation.GetSdkPath( (sdkRef.Name, sdkRef.Version, sdkRef.MinimumVersion), ProjectPath, null); if (sdk != null) { return(sdkPath); } } catch (Exception ex) when(IsNotCancellation(ex)) { LoggingService.LogError("Error in SDK resolver", ex); return(null); } string notFoundMsg = $"Did not find SDK '{sdk}'"; LoggingService.LogError(notFoundMsg); if (doc.IsToplevel) { doc.Diagnostics.Add(CoreDiagnostics.SdkNotFound, loc, sdk); } return(null); }
public void Run( XDocument xDocument, ITextSource textSource, MSBuildDocument doc, int offset = 0, int length = 0, CancellationToken token = default ) { Run(xDocument.RootElement, null, textSource, doc, offset, length, token); }
public string GetSdkPath(MSBuildDocument doc, string sdk, TextSpan loc) { if (!SdkReference.TryParse(sdk, out SdkReference sdkRef)) { string parseErrorMsg = $"Could not parse SDK '{sdk}'"; LoggingService.LogError(parseErrorMsg); if (doc.IsToplevel) { AddError(parseErrorMsg); } return(null); } try { var sdkPath = RuntimeInformation.GetSdkPath(sdkRef, ProjectPath, null); if (sdk != null) { return(sdkPath); } } catch (Exception ex) { LoggingService.LogError("Error in SDK resolver", ex); return(null); } string notFoundMsg = $"Did not find SDK '{sdk}'"; LoggingService.LogError(notFoundMsg); if (doc.IsToplevel) { AddError(notFoundMsg); } return(null); void AddError(string msg) => doc.Errors.Add(new XmlDiagnosticInfo(DiagnosticSeverity.Error, msg, loc)); }
public void Run(XElement element, MSBuildLanguageElement resolvedElement, ITextSource textSource, MSBuildDocument document, int offset = 0, int length = 0) { Filename = textSource.FileName; Document = document; Extension = Filename == null ? ".props" : System.IO.Path.GetExtension(Filename); TextSource = textSource; range = new TextSpan(offset, length > 0 ? length + offset : int.MaxValue); if (resolvedElement != null) { VisitResolvedElement(element, resolvedElement); } else if (element != null) { ResolveAndVisit(element, null); } }
public void Run( XElement element, MSBuildElementSyntax resolvedElement, ITextSource textSource, MSBuildDocument document, int offset = 0, int length = 0, CancellationToken token = default) { Document = document; Extension = Filename == null ? ".props" : System.IO.Path.GetExtension(Filename); TextSource = textSource; CancellationToken = token; range = new TextSpan(offset, length > 0 ? length + offset : int.MaxValue); if (resolvedElement != null) { VisitResolvedElement(element, resolvedElement); } else if (element != null) { ResolveAndVisit(element, null); } }
public static MSBuildResolveResult Resolve( XmlSpineParser spineParser, ITextSource textSource, MSBuildDocument context, IFunctionTypeProvider functionTypeProvider, CancellationToken cancellationToken = default) { int offset = spineParser.Position; var nodePath = spineParser.AdvanceToNodeEndAndGetNodePath(textSource); nodePath.ConnectParents(); //need to look up element by walking how the path, since at each level, if the parent has special children, //then that gives us information to identify the type of its children MSBuildElementSyntax languageElement = null; MSBuildAttributeSyntax languageAttribute = null; XElement el = null; XAttribute att = null; foreach (var node in nodePath) { if (node is XAttribute xatt && xatt.Name.Prefix == null) { att = xatt; languageAttribute = languageElement?.GetAttribute(att.Name.Name); break; } //if children of parent is known to be arbitrary data, don't go into it if (languageElement != null && languageElement.ValueKind == MSBuildValueKind.Data) { break; } //code completion is forgiving, all we care about best guess resolve for deepest child if (node is XElement xel && xel.Name.Prefix == null) { el = xel; languageElement = MSBuildElementSyntax.Get(el.Name.Name, languageElement); if (languageElement != null) { continue; } } if (node is XText) { continue; } if (node is XClosingTag ct && ct == el.ClosingTag) { continue; } languageElement = null; } if (languageElement == null) { return(null); } var rr = new MSBuildResolveResult { ElementSyntax = languageElement, AttributeSyntax = languageAttribute, Element = el, Attribute = att }; var rv = new MSBuildResolveVisitor(offset, rr, functionTypeProvider); try { rv.Run(el, languageElement, textSource, context, token: cancellationToken); } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { // callers always have to handle the possibility this returns null // so this means callers don't need to handle cancellation exceptions explciitly return(null); } return(rr); }
public void Run(XDocument xDocument, ITextSource textSource, MSBuildDocument doc, int offset = 0, int length = 0) { Run(xDocument.RootElement, null, textSource, doc, offset, length); }
public static MSBuildResolveResult Resolve( XmlParser parser, ITextSource textSource, MSBuildDocument context, IFunctionTypeProvider functionTypeProvider) { int offset = parser.Position; //clones and connects nodes to their parents parser = parser.GetTreeParser(); var nodePath = parser.Nodes.ToList(); nodePath.Reverse(); //capture incomplete names, attributes and element values int i = offset; if (parser.CurrentState is XmlRootState && parser.Nodes.Peek() is XElement unclosedEl) { while (i < textSource.Length && InRootOrClosingTagState() && !unclosedEl.IsClosed) { parser.Push(textSource.GetCharAt(i++)); } } else { while (i < textSource.Length && InNameOrAttributeState()) { parser.Push(textSource.GetCharAt(i++)); } } //if nodes are incomplete, they won't get connected //HACK: the only way to reconnect them is reflection if (nodePath.Count > 1) { for (int idx = 1; idx < nodePath.Count; idx++) { var node = nodePath[idx]; if (node.Parent == null) { var parent = nodePath[idx - 1]; ParentProp.SetValue(node, parent); } } } //need to look up element by walking how the path, since at each level, if the parent has special children, //then that gives us information to identify the type of its children MSBuildLanguageElement languageElement = null; MSBuildLanguageAttribute languageAttribute = null; XElement el = null; XAttribute att = null; foreach (var node in nodePath) { if (node is XAttribute xatt && xatt.Name.Prefix == null) { att = xatt; languageAttribute = languageElement?.GetAttribute(att.Name.Name); break; } //if children of parent is known to be arbitrary data, don't go into it if (languageElement != null && languageElement.ValueKind == MSBuildValueKind.Data) { break; } //code completion is forgiving, all we care about best guess resolve for deepest child if (node is XElement xel && xel.Name.Prefix == null) { el = xel; languageElement = MSBuildLanguageElement.Get(el.Name.Name, languageElement); if (languageElement != null) { continue; } } languageElement = null; } if (languageElement == null) { return(null); } var rr = new MSBuildResolveResult { LanguageElement = languageElement, LanguageAttribute = languageAttribute, XElement = el, XAttribute = att }; var rv = new MSBuildResolveVisitor(offset, rr, functionTypeProvider); rv.Run(el, languageElement, textSource, context); return(rr); bool InNameOrAttributeState() => parser.CurrentState is XmlNameState || parser.CurrentState is XmlAttributeState || parser.CurrentState is XmlAttributeValueState; bool InRootOrClosingTagState() => parser.CurrentState is XmlRootState || parser.CurrentState is XmlNameState || parser.CurrentState is XmlClosingTagState; }