public static bool CanNavigate(MSBuildRootDocument doc, int offset, MSBuildResolveResult rr) { if (rr == null) { return(false); } var annotations = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset); if (annotations != null && annotations.Any()) { return(true); } if (rr.ReferenceKind == MSBuildReferenceKind.Target) { return(true); } if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder) { return(true); } return(false); }
public static List <MSBuildNavigationResult> ResolveAll(MSBuildRootDocument doc, int offset, int length) { var visitor = new MSBuildNavigationVisitor(); visitor.Run(doc, offset, length); return(visitor.Navigations); }
public static IEnumerable <ISymbol> GetComparandCompletions(MSBuildRootDocument doc, IReadOnlyList <ExpressionNode> variables) { var names = new HashSet <string> (); foreach (var variable in variables) { VariableInfo info; switch (variable) { case ExpressionProperty ep: if (ep.IsSimpleProperty) { info = doc.GetProperty(ep.Name, true) ?? new PropertyInfo(ep.Name, null, false); break; } continue; case ExpressionMetadata em: info = doc.GetMetadata(em.ItemName, em.MetadataName, true) ?? new MetadataInfo(em.MetadataName, null, false); break; default: continue; } if (info == null) { continue; } IEnumerable <ISymbol> cinfos; if (info.CustomType != null && info.CustomType.Values.Count > 0) { cinfos = info.CustomType.Values; } else { var kind = info.InferValueKindIfUnknown(); cinfos = MSBuildCompletionExtensions.GetValueCompletions(kind, doc); } if (cinfos != null) { foreach (var ci in cinfos) { if (names.Add(ci.Name)) { yield return(ci); } } } } }
public static IEnumerable <T> GetAnnotationsAtOffset <T> (MSBuildRootDocument doc, int offset) { var xobj = doc.XDocument.FindNodeAtOffset(offset); if (xobj == null) { return(null); } return(doc.Annotations .GetMany <T> (xobj) .Where(a => !(a is IRegionAnnotation ra) || ra.Span.Contains(offset))); }
public static MSBuildNavigationResult GetPathFromNode(ExpressionNode node, MSBuildRootDocument document) { try { var path = MSBuildCompletionExtensions.EvaluateExpressionAsPaths(node, document).FirstOrDefault(); if (path != null && File.Exists(path)) { return(new MSBuildNavigationResult( new[] { path }, node.Offset, node.Length )); } } catch (Exception ex) { LoggingService.LogError($"Error checking path for file '{node}'", ex); } return(null); }
public static IEnumerable <ISymbol> GetCompletionInfos( MSBuildResolveResult rr, TriggerState trigger, MSBuildValueKind kind, ExpressionNode triggerExpression, int triggerLength, MSBuildRootDocument doc, IFunctionTypeProvider functionTypeProvider) { switch (trigger) { case TriggerState.Value: return(MSBuildCompletionExtensions.GetValueCompletions(kind, doc, rr, triggerExpression)); case TriggerState.ItemName: return(doc.GetItems()); case TriggerState.MetadataName: return(doc.GetMetadata(null, true)); case TriggerState.PropertyName: return(doc.GetProperties(true)); case TriggerState.MetadataOrItemName: return(((IEnumerable <ISymbol>)doc.GetItems()).Concat(doc.GetMetadata(null, true))); case TriggerState.DirectorySeparator: return(MSBuildCompletionExtensions.GetFilenameCompletions(kind, doc, triggerExpression, triggerLength, rr)); case TriggerState.PropertyFunctionName: return(functionTypeProvider.GetPropertyFunctionNameCompletions(triggerExpression)); case TriggerState.ItemFunctionName: return(functionTypeProvider.GetItemFunctionNameCompletions()); case TriggerState.PropertyFunctionClassName: return(functionTypeProvider.GetClassNameCompletions()); case TriggerState.None: break; case TriggerState.BareFunctionArgumentValue: //FIXME: enum completion etc return(MSBuildValueKind.Bool.GetSimpleValues(true)); case TriggerState.ConditionFunctionName: return(Builtins.ConditionFunctions.Values); } throw new InvalidOperationException($"Unhandled trigger type {trigger}"); }
public static MSBuildNavigationResult GetNavigation( MSBuildRootDocument doc, int offset, MSBuildResolveResult rr) { if (rr == null) { return(null); } var annotations = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset); var firstAnnotation = annotations.FirstOrDefault(); if (firstAnnotation != null) { return(new MSBuildNavigationResult( annotations.Select(a => a.Path).ToArray(), firstAnnotation.Span.Start, firstAnnotation.Span.Length )); } if (rr.ReferenceKind == MSBuildReferenceKind.Target) { return(new MSBuildNavigationResult( MSBuildReferenceKind.Target, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength )); } if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder) { return(new MSBuildNavigationResult( (string[])rr.Reference, rr.ReferenceOffset, rr.ReferenceLength )); } if (rr.ReferenceKind == MSBuildReferenceKind.Task) { var task = doc.GetTask((string)rr.Reference); if (task.DeclaredInFile != null) { return(new MSBuildNavigationResult( MSBuildReferenceKind.Task, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength, task.DeclaredInFile, task.DeclaredAtOffset )); } } return(null); }
public MSBuildParserContext( IRuntimeInformation runtimeInformation, MSBuildRootDocument doc, MSBuildRootDocument previous, HashSet <string> importedFiles, string projectPath, PropertyValueCollector propVals, ITaskMetadataBuilder taskBuilder, MSBuildSchemaProvider schemaProvider, CancellationToken token) { RuntimeInformation = runtimeInformation; RootDocument = doc; PreviousRootDocument = previous; ImportedFiles = importedFiles; ProjectPath = projectPath; PropertyCollector = propVals; TaskBuilder = taskBuilder; SchemaProvider = schemaProvider; Token = token; RuntimeEvaluationContext = new MSBuildRuntimeEvaluationContext(runtimeInformation); }
public static MSBuildRootDocument Parse( ITextSource textSource, string filePath, MSBuildRootDocument previous, MSBuildSchemaProvider schemaProvider, IRuntimeInformation runtimeInfo, ITaskMetadataBuilder taskBuilder, CancellationToken token) { var xmlParser = new XmlTreeParser(new XmlRootState()); var(xdocument, _) = xmlParser.Parse(textSource.CreateReader()); var propVals = new PropertyValueCollector(true); var doc = new MSBuildRootDocument(filePath) { XDocument = xdocument, Text = textSource, RuntimeInformation = runtimeInfo }; var importedFiles = new HashSet <string> (StringComparer.OrdinalIgnoreCase); if (filePath != null) { try { doc.Schema = previous?.Schema ?? schemaProvider.GetSchema(filePath, null); } catch (Exception ex) { LoggingService.LogError("Error loading schema", ex); } importedFiles.Add(filePath); } var parseContext = new MSBuildParserContext( runtimeInfo, doc, previous, importedFiles, filePath, propVals, taskBuilder, schemaProvider, token); if (filePath != null) { doc.FileEvaluationContext = new MSBuildFileEvaluationContext(parseContext.RuntimeEvaluationContext, filePath, filePath); } else { doc.FileEvaluationContext = parseContext.RuntimeEvaluationContext; } string MakeRelativeMSBuildPathAbsolute(string path) { var dir = Path.GetDirectoryName(doc.Filename); path = path.Replace('\\', Path.DirectorySeparatorChar); return(Path.GetFullPath(Path.Combine(dir, path))); } Import TryImportFile(string label, string possibleFile) { try { var fi = new FileInfo(possibleFile); if (fi.Exists) { var imp = parseContext.GetCachedOrParse(label, possibleFile, null, fi.LastWriteTimeUtc); doc.AddImport(imp); return(imp); } } catch (Exception ex) when(parseContext.IsNotCancellation(ex)) { LoggingService.LogError($"Error importing '{possibleFile}'", ex); } return(null); } Import TryImportSibling(string ifHasThisExtension, string thenTryThisExtension) { if (filePath == null) { return(null); } var extension = Path.GetExtension(filePath); if (string.Equals(ifHasThisExtension, extension, StringComparison.OrdinalIgnoreCase)) { var siblingFilename = Path.ChangeExtension(filePath, thenTryThisExtension); return(TryImportFile("(implicit)", siblingFilename)); } return(null); } void TryImportIntellisenseImports(MSBuildSchema schema) { foreach (var intellisenseImport in schema.IntelliSenseImports) { TryImportFile("(from schema)", MakeRelativeMSBuildPathAbsolute(intellisenseImport)); } } try { //if this is a targets file, try to import the props _at the top_ var propsImport = TryImportSibling(".targets", ".props"); // this currently only happens in the root file // it's a quick hack to allow files to get some basic intellisense by // importing the files _that they themselves expect to be imported from_. // we also try to load them from the sibling props, as a paired targets/props // will likely share a schema file. var schema = doc.Schema ?? propsImport?.Document?.Schema; if (schema != null) { TryImportIntellisenseImports(doc.Schema); } doc.Build(xdocument, textSource, parseContext); //if this is a props file, try to import the targets _at the bottom_ var targetsImport = TryImportSibling(".props", ".targets"); //and if we didn't load intellisense import already, try to load them from the sibling targets if (schema == null && targetsImport?.Document?.Schema != null) { TryImportIntellisenseImports(targetsImport.Document.Schema); } } catch (Exception ex) when(parseContext.IsNotCancellation(ex)) { LoggingService.LogError($"Error building document '{filePath ?? "[unnamed]"}'", ex); } try { var binpath = parseContext.RuntimeInformation.BinPath; foreach (var t in Directory.GetFiles(binpath, "*.tasks")) { doc.LoadTasks(parseContext, "(core tasks)", t); } foreach (var t in Directory.GetFiles(binpath, "*.overridetasks")) { doc.LoadTasks(parseContext, "(core overridetasks)", t); } } catch (Exception ex) when(parseContext.IsNotCancellation(ex)) { LoggingService.LogError("Error resolving tasks", ex); } try { if (previous != null) { // try to recover some values that may have been collected from the imports, as they // will not have been re-evaluated var fx = previous.Frameworks.FirstOrDefault(); if (fx != null) { propVals.Collect("TargetFramework", fx.GetShortFolderName()); propVals.Collect("TargetFrameworkVersion", FrameworkInfoProvider.FormatDisplayVersion(fx.Version)); propVals.Collect("TargetFrameworkIdentifier", fx.Framework); } } doc.Frameworks = propVals.GetFrameworks(); } catch (Exception ex) { LoggingService.LogError("Error determining project framework", ex); doc.Frameworks = new List <NuGetFramework> (); } try { //this has to run in a second pass so that it runs after all the schemas are loaded var validator = new MSBuildDocumentValidator(); validator.Run(doc.XDocument, textSource, doc); } catch (Exception ex) when(parseContext.IsNotCancellation(ex)) { LoggingService.LogError("Error in validation", ex); } return(doc); }
public void Run(MSBuildRootDocument doc, int offset = 0, int length = 0, CancellationToken token = default) { Run(doc.XDocument, doc.Text, doc, offset, length, token); }
public void Run(MSBuildRootDocument doc, int offset = 0, int length = 0) { Run(doc.XDocument, doc.Text, doc, offset, length); }
public static MSBuildNavigationResult GetNavigation( MSBuildRootDocument doc, int offset, MSBuildResolveResult rr) { if (rr == null) { return(null); } var annotations = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset); var firstAnnotation = annotations.FirstOrDefault(); if (firstAnnotation != null) { var arr = GetAnnotatedPaths().ToArray(); if (arr.Length == 0) { return(null); } return(new MSBuildNavigationResult(arr, firstAnnotation.Span.Start, firstAnnotation.Span.Length)); } IEnumerable <string> GetAnnotatedPaths() { foreach (var a in annotations) { if (a.IsSdk) { yield return(Path.Combine(a.Path, "Sdk.props")); yield return(Path.Combine(a.Path, "Sdk.targets")); } else { yield return(a.Path); } } } if (rr.ReferenceKind == MSBuildReferenceKind.Target) { return(new MSBuildNavigationResult(MSBuildReferenceKind.Target, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength)); } if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder) { return(new MSBuildNavigationResult( (string[])rr.Reference, rr.ReferenceOffset, rr.ReferenceLength )); } if (rr.ReferenceKind == MSBuildReferenceKind.Task) { var task = doc.GetTask((string)rr.Reference); if (task.DeclaredInFile != null) { return(new MSBuildNavigationResult( MSBuildReferenceKind.Task, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength, task.DeclaredInFile, task.DeclaredAtOffset )); } } if (rr.ReferenceKind == MSBuildReferenceKind.NuGetID) { return(new MSBuildNavigationResult(MSBuildReferenceKind.NuGetID, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength)); } return(null); }