Skip to content

Commit

Permalink
Use SubMonitor + Open TypeScript file if needed when compilation is
Browse files Browse the repository at this point in the history
done. See
#142 (comment)
  • Loading branch information
angelozerr committed Jul 27, 2017
1 parent 093beff commit 1f06368
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ProgressMonitorWrapper;
import org.eclipse.core.runtime.Status;

import ts.TypeScriptException;
Expand Down Expand Up @@ -74,8 +75,8 @@ private void fullBuild(IIDETypeScriptProject tsProject, IProgressMonitor monitor
for (int i = 0; i < tsContainers.length; i++) {
ITsconfigBuildPath tsContainer = tsContainers[i];
/*
* try { IDETsconfigJson tsconfig = tsContainer.getTsconfig(); if
* (tsconfig == null || tsconfig.isCompileOnSave()) {
* try { IDETsconfigJson tsconfig = tsContainer.getTsconfig(); if (tsconfig ==
* null || tsconfig.isCompileOnSave()) {
* tsProject.getCompiler().compile(tsconfig, null); } } catch
* (TypeScriptException e) { Trace.trace(Trace.SEVERE,
* "Error while tsc compilation", e); }
Expand Down Expand Up @@ -260,10 +261,22 @@ public boolean visit(IResourceDelta delta) throws CoreException {
});

try {
tsProject.compileWithTsserver(updatedTsFiles, removedTsFiles, monitor);
if (updatedTsFiles.size() > 0 || removedTsFiles.size() > 0) {
tsProject.compileWithTsserver(updatedTsFiles, removedTsFiles, getSubMonitor(monitor));
}
} catch (TypeScriptException e) {
throw new CoreException(new Status(IStatus.ERROR, TypeScriptCorePlugin.PLUGIN_ID,
"Error while compiling with tsserver", e));
}
}

private IProgressMonitor getSubMonitor(IProgressMonitor monitor) {
// we need to use the parent SubMonitor otherwise SubMonitor#worked, etc doesn't work?
// See article
// https://medium.com/@jgwest/debugging-eclipse-subprogressmonitor-and-submonitor-0-work-completed-or-work-not-reported-f482c71cc85c
if (monitor instanceof ProgressMonitorWrapper) {
return getSubMonitor(((ProgressMonitorWrapper) monitor).getWrappedProgressMonitor());
}
return monitor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public class TypeScriptCoreMessages extends NLS {

// Launch
public static String TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath;

// TypeScript Compiler builder
public static String IDETypeScriptProject_compile_task;
public static String IDETypeScriptProject_compile_collecting_step;
public static String IDETypeScriptProject_compile_collecting_file;
public static String IDETypeScriptProject_compile_compiling_step;
public static String IDETypeScriptProject_compile_compiling_file;

public static ResourceBundle getResourceBundle() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ tsconfig_cannot_use_compileOnSave_with_outFile_error=TypeScript file cannot be c
tsconfig_cannot_use_compileOnSave_with_path_mapping_error=TypeScript file cannot be compiled on save because tsconfig.json uses path mapping features ("paths", "rootDirs"). If this is not intended, please set "buildOnSave" to "true" of your "{0}" file.

# Launch
TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath=The tsconfig file {0} does not exist for the compiler launch named {1}.
TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath=The tsconfig file {0} does not exist for the compiler launch named {1}.

# TypeScript Compiler builder
IDETypeScriptProject_compile_task=TypeScript compilation
IDETypeScriptProject_compile_collecting_step=Collecting TypeScript files to compile...
IDETypeScriptProject_compile_collecting_file=Collect files for ''{0}''
IDETypeScriptProject_compile_compiling_step=Compiling collected TypeScript files...
IDETypeScriptProject_compile_compiling_file=Compile file ''{0}''...
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,21 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.osgi.util.NLS;

import ts.TypeScriptException;
import ts.TypeScriptNoContentAvailableException;
Expand All @@ -51,6 +56,7 @@
import ts.eclipse.ide.core.utils.TypeScriptResourceUtil;
import ts.eclipse.ide.core.utils.WorkbenchResourceUtil;
import ts.eclipse.ide.internal.core.Trace;
import ts.eclipse.ide.internal.core.TypeScriptCoreMessages;
import ts.eclipse.ide.internal.core.compiler.IDETypeScriptCompiler;
import ts.eclipse.ide.internal.core.console.TypeScriptConsoleConnectorManager;
import ts.eclipse.ide.internal.core.resources.jsonconfig.JsonConfigResourcesManager;
Expand Down Expand Up @@ -376,19 +382,19 @@ protected ITypeScriptLint createTslint(File tslintFile, File tslintJsonFile, Fil
@Override
public void compileWithTsserver(List<IFile> updatedTsFiles, List<IFile> removedTsFiles, IProgressMonitor monitor)
throws TypeScriptException {
SubMonitor subMonitor = SubMonitor.convert(monitor, TypeScriptCoreMessages.IDETypeScriptProject_compile_task,
100);
List<IFile> tsFilesToClose = new ArrayList<>();
try {
List<String> tsFilesToCompile = new ArrayList<>();
// Collect ts files to compile by using tsserver to retrieve
// dependencies files.
// It works only if tsconfig.json declares "compileOnSave: true".
if (collectTsFilesToCompile(updatedTsFiles, getClient(), tsFilesToCompile, false, monitor)) {
return;
}
collectTsFilesToCompile(updatedTsFiles, tsFilesToCompile, tsFilesToClose, getClient(), subMonitor);

// Compile ts files with tsserver.
if (compileTsFiles(tsFilesToCompile, getClient(), monitor)) {
return;
}
compileTsFiles(tsFilesToCompile, getClient(), subMonitor);

if (removedTsFiles.size() > 0) {
// ts files was removed, how to get referenced files which must
// be recompiled (with errors)?
Expand All @@ -397,54 +403,86 @@ public void compileWithTsserver(List<IFile> updatedTsFiles, List<IFile> removedT
throw e;
} catch (Exception e) {
throw new TypeScriptException(e);
} finally {
for (IFile tsFile : tsFilesToClose) {
closeFile(tsFile);
}
subMonitor.done();
}
}

/**
* Collect ts files to compile from the given ts files list.
*
* @param tsFiles
* @param client
* @param updatedTsFiles
* list of TypeScript files which have changed.
* @param tsFilesToCompile
* @param exclude
* @param monitor
* list of collected ts files to compile.
* @param tsFilesToClose
* list of ts files to close.
* @param client
* @param subMonitor
* @throws Exception
*/
private boolean collectTsFilesToCompile(List<IFile> tsFiles, ITypeScriptServiceClient client,
List<String> tsFilesToCompile, boolean exclude, IProgressMonitor monitor) throws Exception {
for (IFile tsFile : tsFiles) {
if (monitor.isCanceled()) {
return true;
private void collectTsFilesToCompile(List<IFile> updatedTsFiles, List<String> tsFilesToCompile,
List<IFile> tsFilesToClose, ITypeScriptServiceClient client, SubMonitor subMonitor) throws Exception {
SubMonitor loopMonitor = subMonitor.split(50).setWorkRemaining(updatedTsFiles.size());
loopMonitor.subTask(TypeScriptCoreMessages.IDETypeScriptProject_compile_collecting_step);
for (IFile tsFile : updatedTsFiles) {
if (loopMonitor.isCanceled()) {
throw new OperationCanceledException();
}
String filename = WorkbenchResourceUtil.getFileName(tsFile);
loopMonitor
.subTask(NLS.bind(TypeScriptCoreMessages.IDETypeScriptProject_compile_collecting_file, filename));
if (!tsFilesToCompile.contains(filename)) {
collectTsFilesToCompile(filename, client, tsFilesToCompile, exclude);
collectTsFilesToCompile(filename, client, tsFilesToCompile, tsFilesToClose, loopMonitor);
}
loopMonitor.worked(1);
// loopMonitor.split(1);
}
return false;
// subMonitor.setWorkRemaining(50);
}

/**
* Collect ts files to compile from the given ts file name.
* Collect ts files to compile from the given TypeScript file.
*
* @param filename
* @param client
* @param tsFilesToCompile
* @param exclude
* @param tsFilesToClose
* @param monitor
* @throws Exception
*/
private void collectTsFilesToCompile(String filename, ITypeScriptServiceClient client,
List<String> tsFilesToCompile, boolean exclude) throws Exception {
// call tsserver compileOnSaveAffectedFileList to retrieve file
// dependencies of the given filename
List<CompileOnSaveAffectedFileListSingleProject> affectedProjects = client
.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
for (CompileOnSaveAffectedFileListSingleProject affectedProject : affectedProjects) {
List<String> affectedTsFilenames = affectedProject.getFileNames();
for (String affectedFilename : affectedTsFilenames) {
if (!tsFilesToCompile.contains(affectedFilename) && !(exclude && filename.equals(affectedFilename))) {
tsFilesToCompile.add(affectedFilename);
List<String> tsFilesToCompile, List<IFile> tsFilesToClose, IProgressMonitor monitor) throws Exception {
while (!monitor.isCanceled()) {
try {
// When tsserver is not started, it takes time, we try to collect TypeScript
// files every time and stop the search if user stops the builder.
List<CompileOnSaveAffectedFileListSingleProject> affectedProjects = client
.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
if (affectedProjects.size() == 0 && getOpenedFile(filename) == null) {
// Case when none TypeScript files are opened.
// In this case, compileOnSaveAffectedFileList returns null, the tsserver needs
// having just one opened TypeScript file
// in order to compileOnSaveAffectedFileList returns the well list.
IFile tsFile = WorkbenchResourceUtil.findFileFromWorkspace(filename);
openFile(tsFile, null);
tsFilesToClose.add(tsFile);
affectedProjects = client.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
}
for (CompileOnSaveAffectedFileListSingleProject affectedProject : affectedProjects) {
List<String> affectedTsFilenames = affectedProject.getFileNames();
for (String affectedFilename : affectedTsFilenames) {
if (!tsFilesToCompile.contains(affectedFilename)) {
tsFilesToCompile.add(affectedFilename);
}
}
}
return;
} catch (TimeoutException e) {
// tsserver is not initialized, retry again...
}
}
}
Expand All @@ -454,28 +492,32 @@ private void collectTsFilesToCompile(String filename, ITypeScriptServiceClient c
*
* @param tsFilesToCompile
* @param client
* @param monitor
* @return true if process must be stopped and false otherwise.
* @param subMonitor
* @throws Exception
*/
private boolean compileTsFiles(List<String> tsFilesToCompile, ITypeScriptServiceClient client,
IProgressMonitor monitor) throws Exception {
private void compileTsFiles(List<String> tsFilesToCompile, ITypeScriptServiceClient client, SubMonitor subMonitor)
throws Exception {
SubMonitor loopMonitor = subMonitor.newChild(50).setWorkRemaining(tsFilesToCompile.size());// subMonitor.split(50).setWorkRemaining(tsFilesToCompile.size());
loopMonitor.subTask(TypeScriptCoreMessages.IDETypeScriptProject_compile_compiling_step);
for (String filename : tsFilesToCompile) {
if (monitor.isCanceled()) {
return true;
}
try {
if (loopMonitor.isCanceled()) {
throw new OperationCanceledException();
}
loopMonitor.subTask(
NLS.bind(TypeScriptCoreMessages.IDETypeScriptProject_compile_compiling_file, filename));
compileTsFile(filename, client);
loopMonitor.worked(1);
// loopMonitor.split(1);
} catch (ExecutionException e) {
if (e.getCause() instanceof TypeScriptNoContentAvailableException) {
// Ignore "No content available" error.
}
else {
} else {
throw e;
}
}
}
return false;
// subMonitor.setWorkRemaining(100);
}

/**
Expand All @@ -493,7 +535,7 @@ private void compileTsFile(String filename, ITypeScriptServiceClient client) thr
if (tsFile != null) {
// Delete TypeScript error marker
TypeScriptResourceUtil.deleteTscMarker(tsFile);
// Add TypeScript error marker if there error errors.
// Add TypeScript error marker if there are errors.
DiagnosticEventBody event = client.syntacticDiagnosticsSync(filename, true).get(5000,
TimeUnit.MILLISECONDS);
addMarker(tsFile, event);
Expand Down

0 comments on commit 1f06368

Please sign in to comment.