public override bool IsCodeFile(string fileName) { var ext = Path.GetExtension(fileName); return StringComparer.OrdinalIgnoreCase.Equals(ext, NodejsConstants.JavaScriptExtension) || StringComparer.OrdinalIgnoreCase.Equals(ext, NodejsConstants.JavaScriptJsxExtension) || TypeScriptHelpers.IsTypeScriptFile(fileName); }
internal bool IsTestFile(string pathToFile) { var testCaseFile = pathToFile; var project = GetTestProjectFromFile(pathToFile); if (project == null) { //The file is not included in the project. //Don't look for tests in it. return(false); } // //Check to see if we are dealing with a TypeScript file // If we are then switch the test container to the underlying js file // if (TypeScriptHelpers.IsTypeScriptFile(pathToFile)) { var jsFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(project, pathToFile); if (!File.Exists(jsFile)) { //Ignore the file for now. On the next build event the typescript compiler will generate the file // at that point this function gets invoked again on the .ts file and we'll see the newly created .js file return(false); } } else if (!StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(pathToFile), NodejsConstants.JavaScriptExtension)) { return(false); } ErrorHandler.Succeeded(((IVsHierarchy)project).ParseCanonicalName(pathToFile, out var itemId)); return(IsTestFile(itemId, project)); }
private bool ShouldDiscover(string pathToItem) { if (string.IsNullOrEmpty(pathToItem)) { return(false); } if (pathToItem.IndexOf("\\node_modules\\", StringComparison.OrdinalIgnoreCase) >= 0) { return(false); } //Setting/updating "TestFramework" property on a file item will cause metedata change in the project file, //so we need to re-discover when file change happens. if (TypeScriptHelpers.IsSupportedTestProjectFile(pathToItem)) { return(true); } if (this.IsTestFile(pathToItem)) { if (EqtTrace.IsVerboseEnabled) { EqtTrace.Verbose("TestContainerDiscoverer: Found a test {0}.", pathToItem); } return(true); } return(false); }
public override CommonFileNode CreateCodeFileNode(ProjectElement item) { var fileName = item.Url; if (!string.IsNullOrWhiteSpace(fileName) && TypeScriptHelpers.IsTypeScriptFile(fileName)) { return new NodejsTypeScriptFileNode(this, item); } return new NodejsFileNode(this, item); }
private string ResolveStartupFile() { string startupFile = _project.GetStartupFile(); if (string.IsNullOrEmpty(startupFile)) { throw new ApplicationException("Please select a startup file to launch by right-clicking the file in Solution Explorer and selecting 'Set as Node.js Startup File' or by modifying your configuration in project properties."); } if (TypeScriptHelpers.IsTypeScriptFile(startupFile)) { startupFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(_project, startupFile); } return startupFile; }
public static bool TryGetProjectDirectory(this IVsProject project, out string path) { var succeeded = TryGetProjectPath(project, out path); if (succeeded && TypeScriptHelpers.IsSupportedTestProjectFile(path)) { // remove project name from the path. path = Path.GetDirectoryName(path); } return(succeeded); }
internal bool IsTestFile(string pathToFile) { var project = this.GetTestProjectFromFile(pathToFile); if (project == null) { //The file is not included in the project. //Don't look for tests in it. return(false); } // //Check to see if we are dealing with a TypeScript file // If we are then switch the test container to the underlying js file // if (TypeScriptHelpers.IsTypeScriptFile(pathToFile)) { var jsFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(project, pathToFile); if (!File.Exists(jsFile)) { //Ignore the file for now. On the next build event the typescript compiler will generate the file // at that point this function gets invoked again on the .ts file and we'll see the newly created .js file return(false); } } else if (!StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(pathToFile), NodejsConstants.JavaScriptExtension)) { return(false); } if (!(project is IVsBuildPropertyStorage propStore)) { Debug.Fail($"Why is {nameof(project)} not of type {nameof(IVsBuildPropertyStorage)}?"); return(false); } var hr = propStore.GetPropertyValue(NodeProjectProperty.TestRoot, /*configuration*/ "", (uint)_PersistStorageType.PST_PROJECT_FILE, out var testRoot); // if test root is specified check if the file is contained, otherwise fall back to old logic if (ErrorHandler.Succeeded(hr) && !string.IsNullOrEmpty(testRoot)) { project.TryGetProjectPath(out var root); var testRootPath = Path.Combine(root, testRoot); return(CommonUtils.IsSubpathOf(root, pathToFile)); } ErrorHandler.Succeeded(((IVsHierarchy)project).ParseCanonicalName(pathToFile, out var itemId)); return(IsTestFile(itemId, project)); }
protected override async Task <bool> IsValidFileAsync(string filePath) { // Only use the tsconfig.json determine the debug target when there is an outfile specified, // otherwise each .ts file can (in theory) be the entry point. if (TypeScriptHelpers.IsTsJsConfigJsonFile(filePath)) { var tsconfig = await TsConfigJsonFactory.CreateAsync(filePath); return(!string.IsNullOrEmpty(tsconfig?.OutFile)); } return(false); }
private static (string, string)? GetTestFrameworkAndFilePath(Project project, ProjectItem projectItem, string projectRoot) { var testRoot = project.GetProperty(NodeProjectProperty.TestRoot)?.EvaluatedValue; var testFrameworkName = project.GetProperty(NodeProjectProperty.TestFramework)?.EvaluatedValue; string fileAbsolutePath; if (!string.IsNullOrEmpty(testRoot) && !string.IsNullOrEmpty(testFrameworkName)) // If the test root and framework have been configured on the project. { var testRootPath = Path.GetFullPath(Path.Combine(project.DirectoryPath, testRoot)); try { fileAbsolutePath = CommonUtils.GetAbsoluteFilePath(projectRoot, projectItem.EvaluatedInclude); } catch (ArgumentException) { // .Net core projects include invalid paths, ignore them and continue checking the items. return(null); } if (!fileAbsolutePath.StartsWith(testRootPath, StringComparison.OrdinalIgnoreCase)) { return(null); } } else // If the file has been configured individually. { testFrameworkName = projectItem.GetMetadataValue("TestFramework"); if (!TestFramework.IsValidTestFramework(testFrameworkName)) { return(null); } fileAbsolutePath = CommonUtils.GetAbsoluteFilePath(projectRoot, projectItem.EvaluatedInclude); } // Check if file is a typecript file. If so, get the javascript file. The javascript file needs to be in the same path and name. // It doesn't work with bundlers or minimizers. Also, project needs to be build in order to have the js file created. var typeScriptTest = TypeScriptHelpers.IsTypeScriptFile(fileAbsolutePath); if (typeScriptTest) { fileAbsolutePath = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(project, fileAbsolutePath); } else if (!StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(fileAbsolutePath), ".js")) { return(null); } return(testFrameworkName, fileAbsolutePath); }
private string ResolveStartupFile() { var startupFile = this._project.GetStartupFile(); if (string.IsNullOrEmpty(startupFile)) { throw new ApplicationException(Resources.DebugCouldNotResolveStartupFileErrorMessage); } if (TypeScriptHelpers.IsTypeScriptFile(startupFile)) { startupFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(this._project, startupFile); } return(startupFile); }
private string ResolveStartupFile() { string startupFile = _project.GetStartupFile(); if (string.IsNullOrEmpty(startupFile)) { throw new ApplicationException("No startup file is defined for the startup project."); } if (TypeScriptHelpers.IsTypeScriptFile(startupFile)) { startupFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(_project, startupFile); } return(startupFile); }
private IEnumerable <string> GetTestItems(string projectRoot, string outDir) { // TODO: Do our own directory traversal. It's better for performance. // If we find ts or tsx files, get the JS file and return. var files = Directory.EnumerateFiles(projectRoot, "*.ts?", SearchOption.AllDirectories) .Where(x => !x.Contains("\\node_modules\\")); if (files.Any()) { return(files .Where(p => TypeScriptHelpers.IsTypeScriptFile(p)) .Select(p => TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(p, outDir, projectRoot))); } return(Directory.EnumerateFiles(projectRoot, "*.js", SearchOption.AllDirectories) .Where(p => !p.Contains("\\node_modules\\"))); }
private async Task <bool> IsSupportedFileAsync(string filePath) { // config files are always good if (TypeScriptHelpers.IsTsJsConfigJsonFile(filePath)) { return(true); } // TypeScript files should only build when there is no containing config file if (TypeScriptHelpers.IsTypeScriptFile(filePath)) { if (await this.workspace.IsContainedByTsConfig(filePath) == null) { return(true); } } return(false); }
internal bool IsTestFile(string pathToFile) { var project = this.GetTestProjectFromFile(pathToFile); if (project == null) { //The file is not included in the project. //Don't look for tests in it. return(false); } // //Check to see if we are dealing with a TypeScript file // If we are then switch the test container to the underlying js file // if (TypeScriptHelpers.IsTypeScriptFile(pathToFile)) { var jsFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(project, pathToFile); if (jsFile == null || !File.Exists(jsFile)) { //Ignore the file for now. On the next build event the typescript compiler will generate the file // at that point this function gets invoked again on the .ts file and we'll see the newly created .js file return(false); } } else if (!TypeScriptHelpers.IsJavaScriptFile(pathToFile)) { return(false); } if (TryGetProjectUnitTestProperties(project, out var testRoot, out _) && !string.IsNullOrEmpty(testRoot) && project.TryGetProjectDirectory(out var root)) { var testRootPath = Path.Combine(root, testRoot); return(CommonUtils.IsSubpathOf(testRootPath, pathToFile)); } ErrorHandler.Succeeded(((IVsHierarchy)project).ParseCanonicalName(pathToFile, out var itemId)); return(IsTestFile(itemId, project)); }
internal override string GetItemType(string filename) { var absFileName = Path.IsPathRooted(filename) ? filename : Path.Combine(this.ProjectHome, filename); var node = this.FindNodeByFullPath(absFileName) as NodejsFileNode; if (node?.ItemNode?.ItemTypeName != null) { return node.ItemNode.ItemTypeName; } if (TypeScriptHelpers.IsTypeScriptFile(filename)) { return NodejsConstants.TypeScriptCompileItemType; } return base.GetItemType(filename); }
public IEnumerable <ITestContainer> GetTestContainers(IVsProject project) { if (!project.TryGetProjectPath(out var path)) { yield break; } // No need to search for tests in not supported projects. if (!TypeScriptHelpers.IsSupportedTestProjectFile(path)) { yield break; } if (this.detectingChanges) { this.SaveModifiedFiles(project); } if (!this.knownProjects.TryGetValue(path, out var projectInfo) || !TryGetProjectUnitTestProperties(projectInfo.Project, out _, out _)) { // Don't return any containers for projects we don't know about or that we know that they are not configured for JavaScript unit tests. yield break; } projectInfo.HasRequestedContainers = true; var latestWrite = project.GetProjectItemPaths().Aggregate( this.lastWrite, (latest, filePath) => { try { var ft = File.GetLastWriteTimeUtc(filePath); return((ft > latest) ? ft : latest); } catch (Exception exc) when(exc is UnauthorizedAccessException || exc is ArgumentException || exc is IOException) { } return(latest); }); yield return(new TestContainer(this, path, latestWrite)); }
public static async Task <TsConfigJson> IsContainedByTsConfig(this IWorkspace workspace, string filePath) { var fileService = workspace.GetFindFilesService(); var collector = new FileCollector(); await fileService.FindFilesAsync("sconfig.json", collector); foreach (var configFile in collector.FoundFiles) { if (TypeScriptHelpers.IsTsJsConfigJsonFile(configFile)) { var directory = Path.GetDirectoryName(configFile); if (filePath.StartsWith(directory, StringComparison.OrdinalIgnoreCase)) { return(await TsConfigJsonFactory.CreateAsync(configFile)); } } } return(null); }
internal override string GetItemType(string filename) { var absFileName = Path.IsPathRooted(filename) ? filename : Path.Combine(this.ProjectHome, filename); var node = this.FindNodeByFullPath(absFileName) as NodejsFileNode; if (node?.ItemNode?.ItemTypeName != null) { return(node.ItemNode.ItemTypeName); } // We need to return TypeScriptCompile for now to maintain backwards compatibility. In the future we will return "None" once the TypeScript SDK has been removed. if (TypeScriptHelpers.IsTypeScriptFile(filename)) { return(NodejsConstants.TypeScriptCompileItemType); } return(base.GetItemType(filename)); }
public async Task <IReadOnlyList <IFileContextAction> > GetActionsAsync(string filePath, FileContext fileContext, CancellationToken cancellationToken) { await this.workspaceContext.JTF.SwitchToMainThreadAsync(); this.outputPane.InitializeOutputPanes(); var actions = new List <IFileContextAction>(); if (TypeScriptHelpers.IsTsJsConfigJsonFile(filePath)) { actions.Add(new BuildTsConfigContextAction(filePath, fileContext, this.outputPane)); } else if (TypeScriptHelpers.IsTypeScriptFile(filePath)) { var tsconfig = await this.workspaceContext.IsContainedByTsConfig(filePath); if (tsconfig == null) { actions.Add(new BuildTsFileContextAction(filePath, fileContext, this.outputPane)); } } return(actions); }
private static bool IsProjectTypeScriptSourceFile(string path) { return(TypeScriptHelpers.IsTypeScriptFile(path) && !StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(path), NodejsConstants.TypeScriptDeclarationExtension) && !NodejsConstants.ContainsNodeModulesOrBowerComponentsFolder(path)); }
private static bool IsSupportedFile(string filePath) { return(TypeScriptHelpers.IsTypeScriptFile(filePath) || TypeScriptHelpers.IsTsJsConfigJsonFile(filePath)); }
protected override Task <bool> IsValidFileAsync(string filePath) { var isValidFile = TypeScriptHelpers.IsTypeScriptFile(filePath); return(Task.FromResult(isValidFile)); }
internal static void WriteProjectXml( XmlWriter writer, string projectPath, string sourcePath, string filters, string startupFile, string typeScriptVersion, ProjectLanguage projectLanguage ) { var projectHome = CommonUtils.GetRelativeDirectoryPath(Path.GetDirectoryName(projectPath), sourcePath); var projectGuid = Guid.NewGuid(); writer.WriteStartDocument(); writer.WriteStartElement("Project", "http://schemas.microsoft.com/developer/msbuild/2003"); writer.WriteAttributeString("DefaultTargets", "Build"); writer.WriteStartElement("PropertyGroup"); writer.WriteStartElement("Configuration"); writer.WriteAttributeString("Condition", " '$(Configuration)' == '' "); writer.WriteString("Debug"); writer.WriteEndElement(); writer.WriteElementString("SchemaVersion", "2.0"); writer.WriteElementString("ProjectGuid", projectGuid.ToString("B")); writer.WriteElementString("ProjectHome", string.IsNullOrWhiteSpace(projectHome) ? "." : projectHome); writer.WriteElementString("ProjectView", "ShowAllFiles"); if (CommonUtils.IsValidPath(startupFile)) { writer.WriteElementString("StartupFile", Path.GetFileName(startupFile)); } else { writer.WriteElementString("StartupFile", string.Empty); } writer.WriteElementString("WorkingDirectory", "."); writer.WriteElementString("OutputPath", "."); writer.WriteElementString("ProjectTypeGuids", "{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}"); var typeScriptSupport = projectLanguage == ProjectLanguage.TypeScript || filters.IndexOf("*.ts", StringComparison.OrdinalIgnoreCase) > -1; if (typeScriptSupport) { writer.WriteElementString("TypeScriptSourceMap", "true"); writer.WriteElementString("TypeScriptModuleKind", "CommonJS"); writer.WriteElementString("EnableTypeScript", "true"); if (typeScriptVersion != null) { writer.WriteElementString("TypeScriptToolsVersion", typeScriptVersion); } } writer.WriteStartElement("VisualStudioVersion"); writer.WriteAttributeString("Condition", "'$(VisualStudioVersion)' == ''"); writer.WriteString("14.0"); writer.WriteEndElement(); writer.WriteStartElement("VSToolsPath"); writer.WriteAttributeString("Condition", "'$(VSToolsPath)' == ''"); writer.WriteString(@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)"); writer.WriteEndElement(); writer.WriteEndElement(); // </PropertyGroup> // VS requires property groups with conditions for Debug // and Release configurations or many COMExceptions are // thrown. writer.WriteStartElement("PropertyGroup"); writer.WriteAttributeString("Condition", "'$(Configuration)' == 'Debug'"); writer.WriteEndElement(); writer.WriteStartElement("PropertyGroup"); writer.WriteAttributeString("Condition", "'$(Configuration)' == 'Release'"); writer.WriteEndElement(); var folders = new HashSet <string>( Directory.EnumerateDirectories(sourcePath, "*", SearchOption.AllDirectories) .Select(dirName => CommonUtils.TrimEndSeparator( CommonUtils.GetRelativeDirectoryPath(sourcePath, dirName) ) ) .Where(ShouldIncludeDirectory) ); // Exclude node_modules and bower_components folders. folders.RemoveWhere(NodejsConstants.ContainsNodeModulesOrBowerComponentsFolder); writer.WriteStartElement("ItemGroup"); var projectFileFilters = ""; switch (projectLanguage) { case ProjectLanguage.TypeScript: projectFileFilters = filters + TypeScriptFilters; break; case ProjectLanguage.JavaScript: default: projectFileFilters = filters + JavaScriptFilters; break; } foreach (var file in EnumerateAllFiles(sourcePath, projectFileFilters, projectLanguage)) { if (TypeScriptHelpers.IsTypeScriptFile(file)) { writer.WriteStartElement("TypeScriptCompile"); } else { writer.WriteStartElement("Content"); } writer.WriteAttributeString("Include", file); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("ItemGroup"); foreach (var folder in folders.Where(s => !string.IsNullOrWhiteSpace(s)).OrderBy(s => s)) { writer.WriteStartElement("Folder"); writer.WriteAttributeString("Include", folder); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("Import"); writer.WriteAttributeString("Project", @"$(MSBuildToolsPath)\Microsoft.Common.targets"); writer.WriteAttributeString("Condition", @"Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"); writer.WriteEndElement(); writer.WriteComment("Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them."); writer.WriteStartElement("Import"); writer.WriteAttributeString("Project", @"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets"); writer.WriteAttributeString("Condition", @"False"); writer.WriteEndElement(); writer.WriteStartElement("Import"); writer.WriteAttributeString("Project", @"$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets"); writer.WriteEndElement(); writer.WriteRaw(@" <ProjectExtensions> <VisualStudio> <FlavorProperties GUID=""{349c5851-65df-11da-9384-00065b846f21}""> <WebProjectProperties> <UseIIS>False</UseIIS> <AutoAssignPort>True</AutoAssignPort> <DevelopmentServerPort>0</DevelopmentServerPort> <DevelopmentServerVPath>/</DevelopmentServerVPath> <IISUrl>http://localhost:48022/</IISUrl> <NTLMAuthentication>False</NTLMAuthentication> <UseCustomServer>True</UseCustomServer> <CustomServerUrl>http://localhost:1337</CustomServerUrl> <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> </WebProjectProperties> </FlavorProperties> <FlavorProperties GUID=""{349c5851-65df-11da-9384-00065b846f21}"" User=""""> <WebProjectProperties> <StartPageUrl> </StartPageUrl> <StartAction>CurrentPage</StartAction> <AspNetDebugging>True</AspNetDebugging> <SilverlightDebugging>False</SilverlightDebugging> <NativeDebugging>False</NativeDebugging> <SQLDebugging>False</SQLDebugging> <ExternalProgram> </ExternalProgram> <StartExternalURL> </StartExternalURL> <StartCmdLineArguments> </StartCmdLineArguments> <StartWorkingDirectory> </StartWorkingDirectory> <EnableENC>False</EnableENC> <AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug> </WebProjectProperties> </FlavorProperties> </VisualStudio> </ProjectExtensions> "); writer.WriteEndElement(); // </Project> writer.WriteEndDocument(); }
protected override Task <bool> IsValidFileAsync(string filePath) { return(Task.FromResult(TypeScriptHelpers.IsTsJsConfigJsonFile(filePath))); }