public IVariableStatement Build() { if (m_expression == null) { throw new InvalidOperationException(FormattableStringEx.I($"The initializer expression was not specified. Did you forget to call Initializer method?")); } if (m_name == null) { throw new InvalidOperationException(FormattableStringEx.I($"The name was not specified. Did you forget to call Initializer method?")); } var nodeFlags = m_isConst ? NodeFlags.Const : NodeFlags.None; if (m_visibility == DScript.Visibility.Export || m_visibility == DScript.Visibility.Public) { nodeFlags |= NodeFlags.Export; } var result = new VariableStatement( m_name, m_expression, type: m_type, flags: nodeFlags); if (m_visibility == DScript.Visibility.Public) { result.WithPublicDecorator(); } return(result); }
/// <summary> /// Returns a properly formatted/sorted list of directory dependencies. /// </summary> private List <string> GetDirectoryDependencies(ReadOnlyArray <DirectoryArtifact> dependencies) { var result = new List <string>(); var directories = new Stack <(DirectoryArtifact artifact, string path, int tabCount)>( dependencies .Select(d => (artifact: d, path: d.Path.ToString(PathTable), 0)) .OrderByDescending(tupple => tupple.path)); while (directories.Count > 0) { var directory = directories.Pop(); result.Add(directory.tabCount == 0 ? FormattableStringEx.I($"{directory.path} (PartialSealId: {directory.artifact.PartialSealId}, IsSharedOpaque: {directory.artifact.IsSharedOpaque})") : FormattableStringEx.I($"|{string.Concat(Enumerable.Repeat("---", directory.tabCount))}{directory.path} (PartialSealId: {directory.artifact.PartialSealId}, IsSharedOpaque: {directory.artifact.IsSharedOpaque})")); var sealPipId = CachedGraph.PipGraph.GetSealedDirectoryNode(directory.artifact).ToPipId(); if (PipTable.IsSealDirectoryComposite(sealPipId)) { var sealPip = (SealDirectory)CachedGraph.PipGraph.GetSealedDirectoryPip(directory.artifact, PipQueryContext.SchedulerExecuteSealDirectoryPip); foreach (var nestedDirectory in sealPip.ComposedDirectories.Select(d => (artifact: d, path: d.Path.ToString(PathTable))).OrderByDescending(tupple => tupple.path)) { directories.Push((nestedDirectory.artifact, nestedDirectory.path, directory.tabCount + 1)); } } } return(result); }
/// <summary> /// Extracts the qualifier type from the given node and returns a corresponding qualifier space for it /// </summary> public QualifierSpaceId ConvertQualifierType(INode node) { var qualifierType = m_semanticModel.GetCurrentQualifierType(node); if (qualifierType == null || qualifierType.Flags == TypeFlags.Any) { // TODO: this needs to be removed once semantic evaluation will work only with new qualifiers. // With V1 qualifiers the condition in the if statement can be true. return(m_qualifierTable.EmptyQualifierSpaceId); } var resolvedType = qualifierType as IResolvedType; if (resolvedType == null) { // This method is on a hot path, and string computation is not cheap. // Moving this assertion inside the loop saves reasonable amount of time for large builds. Contract.Assert(false, FormattableStringEx.I($"Qualifier type should be of 'IResolvedType' but got '{qualifierType.GetType()}'")); } using (var closure = s_convertQualifierClosures.GetInstance()) { var func = closure.Instance.CreateClosure(resolvedType, m_qualifierTable, m_semanticModel); return(m_qualifierSpaceDeclarationCache.GetOrAdd(resolvedType.Id, func)); } }
/// <summary> /// Tries to read a package's hash file from disk. /// </summary> /// <remarks> /// The <see cref="Failure"/> returned from this method is recoverable. /// </remarks> public static Possible <PackageHashFile> TryReadFrom(string path) { string[] content; try { content = ExceptionUtilities.HandleRecoverableIOException( () => { if (!File.Exists(path)) { return(null); } return(File.ReadAllLines(path)); }, e => throw new BuildXLException(FormattableStringEx.I($"Failed to parse package hash file."), e)); } catch (BuildXLException e) { return(new PackageHashFileFailure(e.LogEventMessage)); } if (content == null) { return(new PackageHashFileFailure(FormattableStringEx.I($"Package hash file is missing."))); } if (content.Length < MinNumberOfLines) { // The version field potentially can be used for invalidating generated packages as well. // The new file format is: // Version // Specs format version // SHA // Fingerprint // List of files return(new PackageHashFileFailure(FormattableStringEx.I($"Package hash file has an invalid content. Expected at least {MinNumberOfLines} lines but got {content.Length} lines."))); } var version = content[0]; if (version != HashFileFormatVersion) { return(new PackageHashFileFailure(FormattableStringEx.I($"Package hash file has different version. Expected version: {HashFileFormatVersion}, actual version: {version}."))); } var specsFileVersion = content[1]; var fingerprintHash = content[2]; var fingerprintText = content[3]; var files = content.Skip(MinNumberOfLines).Where(s => !string.IsNullOrEmpty(s)).ToArray(); if (files.Length == 0) { return(new PackageHashFileFailure(FormattableStringEx.I($"Package hash file does not have package content files."))); } return(new PackageHashFile(fingerprintHash, fingerprintText, files, specsFormatIsUpToDate: specsFileVersion == GeneratedSpecsVersion)); }
private CodeLens GetModuleReference(ParsedModule module, ISourceFile spec) { var moduleVersion = string.IsNullOrEmpty(module.Descriptor.Version) ? null : $" (version: {module.Descriptor.Version})"; // Ideally we want to navigate to the module declaration, but unfortunately we don't keep proper track of that. // Therefore we do a quick file existence check, try to find the common name and then fall back to the current spec file. var moduleConfigFile = module.Definition.ModuleConfigFile.ToString(PathTable); if (!File.Exists(moduleConfigFile)) { moduleConfigFile = Path.Combine(Path.GetDirectoryName(moduleConfigFile), "module.config.dsc"); } else if (!File.Exists(moduleConfigFile)) { // Fall back to the current spec.... moduleConfigFile = spec.FileName; } return (new CodeLens { Range = spec.ToRange(), Command = new Command { Title = FormattableStringEx.I($"Module: {module.Descriptor.Name}{moduleVersion} - {module.Definition.Root.ToString(PathTable)}"), CommandIdentifier = "DScript.openDocument", Arguments = new object[] { UriExtensions.GetUriFromPath(moduleConfigFile) }, }, }); }
private void Log(FormattableString message) { var pid = -1; #pragma warning disable ERP022 // Unobserved exception in generic exception handler try { pid = ProcessId; } catch {} #pragma warning restore ERP022 // Unobserved exception in generic exception handler m_logger?.Invoke(FormattableStringEx.I($"Process({pid}) - {message}")); }
private static string GetIdentifierForNode(INode node) { var asDeclaration = node.As <IDeclaration>(); if (asDeclaration != null) { return(asDeclaration.Name.Text); } var asVariableStatement = node.As <IVariableStatement>(); if (asVariableStatement != null) { return(asVariableStatement.DeclarationList.Declarations[0].Name.GetText()); } return(FormattableStringEx.I($"Unknown({node.Kind})")); }
private List <string> GetDirectoryOutputsWithContent(Process pip) { var outputs = new List <string>(); var rootExpander = new RootExpander(PathTable); foreach (var directoryOutput in pip.DirectoryOutputs) { outputs.Add(FormattableStringEx.I($"{directoryOutput.Path.ToString(PathTable)} (PartialSealId: {directoryOutput.PartialSealId}, IsSharedOpaque: {directoryOutput.IsSharedOpaque})")); if (m_directoryContents.TryGetValue(directoryOutput, out var directoryContent)) { foreach (var file in directoryContent) { outputs.Add(FormattableStringEx.I($"|--- {file.Path.ToString(PathTable, rootExpander)}")); } } } return(outputs); }
private bool GetQualifierAsCodeLens(INode node, out CodeLens codeLens) { codeLens = default(CodeLens); // If the current module is V1 the qualifier types would be unavailable var qualifierType = SemanticModel.GetCurrentQualifierType(node); if (qualifierType == null) { return(false); } var qualifierDeclaration = SemanticModel.GetCurrentQualifierDeclaration(node); if (qualifierDeclaration == null) { return(false); } var formattedQualifier = TypeChecker.TypeToString(qualifierType); var fileUri = qualifierDeclaration.GetSourceFile().ToUri().AbsoluteUri; var range = qualifierDeclaration.ToRange(); codeLens = new CodeLens { Range = node.ToRange(), Command = new Command { Title = FormattableStringEx.I($"Qualifier type: {formattedQualifier}"), CommandIdentifier = "DScript.openDocument", Arguments = new object[] { fileUri, range, }, }, }; return(true); }
/// <summary> /// Returns a friendly name for a current package. /// </summary> public string GetFriendlyName() => FormattableStringEx.I($"{Protocol}://{Id}/{Version}");
/// <nodoc/> public Result <SignatureHelp, ResponseError> SignatureHelp(TextDocumentPositionParams positionParams, CancellationToken token) { // TODO: support cancellation if (!TryFindNode(positionParams, out var nodeAtPosition)) { return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } ICallExpression callExpression = GetContainingCallExpression(nodeAtPosition); if (callExpression == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var callSymbol = TypeChecker.GetSymbolAtLocation(callExpression.Expression); // If the user has typed a call expresion to a symbol (function) that doesn't exist (i.e. "foo.bar()") // Then just issue a debug writeline and a success instead of crashing. // There is going to be a red-line squiggle under it anyway. if (callSymbol == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find symbol for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var signature = TypeChecker.GetSignaturesOfType(TypeChecker.GetTypeAtLocation(callExpression.Expression), SignatureKind.Call).FirstOrDefault(); if (signature == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call signature for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var functionDeclaration = DScriptFunctionSignature.FromSignature(callSymbol.Name, signature); var parameterInformations = functionDeclaration.FormattedParameterNames.Select(formattedParameterName => new ParameterInformation() { Label = formattedParameterName, }); int activeParameterIndex = DScriptFunctionSignature.GetActiveParameterIndex(callExpression, nodeAtPosition); var signatureHelp = new SignatureHelp() { Signatures = new SignatureInformation[] { new SignatureInformation() { Label = functionDeclaration.FormattedFullFunctionSignature, Parameters = parameterInformations.ToArray(), Documentation = DocumentationUtilities.GetDocumentationForSymbolAsString(callSymbol), }, }, ActiveParameter = activeParameterIndex, ActiveSignature = 0, }; return(Result <SignatureHelp, ResponseError> .Success(signatureHelp)); }
private static bool TryCreateImportStatementCommand( Workspace workspace, PathTable pathTable, CodeActionParams actionParams, out dynamic[] commandArguments) { commandArguments = default(dynamic[]); var typeChecker = workspace.GetSemanticModel().TypeChecker; if (!actionParams.TextDocument.Uri.TryGetSourceFile(workspace, pathTable, out var sourceUri)) { return(false); } Contract.Assert(actionParams.Range?.Start != null); if (!DScriptNodeUtilities.TryGetNodeAtPosition(sourceUri, actionParams.Range.Start.ToLineAndColumn(), out var node)) { return(false); } var nodeFlags = NodeUtilities.GetCombinedNodeFlags(node); if ((nodeFlags & NodeFlags.ScriptPublic) == NodeFlags.None) { return(false); } var symbol = typeChecker.GetSymbolAtLocation(node) ?? node.Symbol ?? node.ResolvedSymbol; if (symbol == null) { return(false); } var symbolFullName = typeChecker.GetFullyQualifiedName(symbol); // The import statement can only contain a single identifier, so if the symbol's full name // is Namespace.Subnamespace.value, we care about just 'Namespace' var identifier = GetFirstIdentifier(symbolFullName); var module = workspace.TryGetModuleBySpecFileName(sourceUri.GetAbsolutePath(pathTable)); if (module == null) { return(false); } var importString = string.Format( CultureInfo.InvariantCulture, "import {{{0}}} from \"{1}\";", identifier, module.Definition.Descriptor.Name); var bannerString = FormattableStringEx.I($"Import string for '{symbolFullName}' placed on clipboard"); commandArguments = new dynamic[] { importString, bannerString, }; return(true); }
/// <inheritdoc /> public override string ToString() { return(FormattableStringEx.I($"WF:{WeakFingerprint}, PS#:{PathSetHash}, SF:{StrongFingerprint}, MD#:{CacheEntry.MetadataHash}")); }