Skip to content

Commit 1f06368

Browse files
committed
Use SubMonitor + Open TypeScript file if needed when compilation is
done. See #142 (comment)
1 parent 093beff commit 1f06368

File tree

4 files changed

+113
-44
lines changed

4 files changed

+113
-44
lines changed

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/builder/TypeScriptBuilder.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.eclipse.core.runtime.CoreException;
2626
import org.eclipse.core.runtime.IProgressMonitor;
2727
import org.eclipse.core.runtime.IStatus;
28+
import org.eclipse.core.runtime.ProgressMonitorWrapper;
2829
import org.eclipse.core.runtime.Status;
2930

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

262263
try {
263-
tsProject.compileWithTsserver(updatedTsFiles, removedTsFiles, monitor);
264+
if (updatedTsFiles.size() > 0 || removedTsFiles.size() > 0) {
265+
tsProject.compileWithTsserver(updatedTsFiles, removedTsFiles, getSubMonitor(monitor));
266+
}
264267
} catch (TypeScriptException e) {
265268
throw new CoreException(new Status(IStatus.ERROR, TypeScriptCorePlugin.PLUGIN_ID,
266269
"Error while compiling with tsserver", e));
267270
}
268271
}
272+
273+
private IProgressMonitor getSubMonitor(IProgressMonitor monitor) {
274+
// we need to use the parent SubMonitor otherwise SubMonitor#worked, etc doesn't work?
275+
// See article
276+
// https://medium.com/@jgwest/debugging-eclipse-subprogressmonitor-and-submonitor-0-work-completed-or-work-not-reported-f482c71cc85c
277+
if (monitor instanceof ProgressMonitorWrapper) {
278+
return getSubMonitor(((ProgressMonitorWrapper) monitor).getWrappedProgressMonitor());
279+
}
280+
return monitor;
281+
}
269282
}

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/internal/core/TypeScriptCoreMessages.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public class TypeScriptCoreMessages extends NLS {
3737

3838
// Launch
3939
public static String TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath;
40+
41+
// TypeScript Compiler builder
42+
public static String IDETypeScriptProject_compile_task;
43+
public static String IDETypeScriptProject_compile_collecting_step;
44+
public static String IDETypeScriptProject_compile_collecting_file;
45+
public static String IDETypeScriptProject_compile_compiling_step;
46+
public static String IDETypeScriptProject_compile_compiling_file;
4047

4148
public static ResourceBundle getResourceBundle() {
4249
try {

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/internal/core/TypeScriptCoreMessages.properties

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,11 @@ tsconfig_cannot_use_compileOnSave_with_outFile_error=TypeScript file cannot be c
2020
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.
2121

2222
# Launch
23-
TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath=The tsconfig file {0} does not exist for the compiler launch named {1}.
23+
TypeScriptCompilerLaunchConfigurationDelegate_invalidBuildPath=The tsconfig file {0} does not exist for the compiler launch named {1}.
24+
25+
# TypeScript Compiler builder
26+
IDETypeScriptProject_compile_task=TypeScript compilation
27+
IDETypeScriptProject_compile_collecting_step=Collecting TypeScript files to compile...
28+
IDETypeScriptProject_compile_collecting_file=Collect files for ''{0}''
29+
IDETypeScriptProject_compile_compiling_step=Compiling collected TypeScript files...
30+
IDETypeScriptProject_compile_compiling_file=Compile file ''{0}''...

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/internal/core/resources/IDETypeScriptProject.java

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@
1616
import java.util.HashMap;
1717
import java.util.List;
1818
import java.util.Map;
19+
import java.util.concurrent.CancellationException;
1920
import java.util.concurrent.ExecutionException;
2021
import java.util.concurrent.TimeUnit;
22+
import java.util.concurrent.TimeoutException;
2123

2224
import org.eclipse.core.resources.IFile;
2325
import org.eclipse.core.resources.IMarker;
2426
import org.eclipse.core.resources.IProject;
2527
import org.eclipse.core.resources.IResource;
2628
import org.eclipse.core.runtime.CoreException;
2729
import org.eclipse.core.runtime.IProgressMonitor;
30+
import org.eclipse.core.runtime.OperationCanceledException;
31+
import org.eclipse.core.runtime.SubMonitor;
2832
import org.eclipse.jface.text.IDocument;
33+
import org.eclipse.osgi.util.NLS;
2934

3035
import ts.TypeScriptException;
3136
import ts.TypeScriptNoContentAvailableException;
@@ -51,6 +56,7 @@
5156
import ts.eclipse.ide.core.utils.TypeScriptResourceUtil;
5257
import ts.eclipse.ide.core.utils.WorkbenchResourceUtil;
5358
import ts.eclipse.ide.internal.core.Trace;
59+
import ts.eclipse.ide.internal.core.TypeScriptCoreMessages;
5460
import ts.eclipse.ide.internal.core.compiler.IDETypeScriptCompiler;
5561
import ts.eclipse.ide.internal.core.console.TypeScriptConsoleConnectorManager;
5662
import ts.eclipse.ide.internal.core.resources.jsonconfig.JsonConfigResourcesManager;
@@ -376,19 +382,19 @@ protected ITypeScriptLint createTslint(File tslintFile, File tslintJsonFile, Fil
376382
@Override
377383
public void compileWithTsserver(List<IFile> updatedTsFiles, List<IFile> removedTsFiles, IProgressMonitor monitor)
378384
throws TypeScriptException {
385+
SubMonitor subMonitor = SubMonitor.convert(monitor, TypeScriptCoreMessages.IDETypeScriptProject_compile_task,
386+
100);
387+
List<IFile> tsFilesToClose = new ArrayList<>();
379388
try {
380389
List<String> tsFilesToCompile = new ArrayList<>();
381390
// Collect ts files to compile by using tsserver to retrieve
382391
// dependencies files.
383392
// It works only if tsconfig.json declares "compileOnSave: true".
384-
if (collectTsFilesToCompile(updatedTsFiles, getClient(), tsFilesToCompile, false, monitor)) {
385-
return;
386-
}
393+
collectTsFilesToCompile(updatedTsFiles, tsFilesToCompile, tsFilesToClose, getClient(), subMonitor);
387394

388395
// Compile ts files with tsserver.
389-
if (compileTsFiles(tsFilesToCompile, getClient(), monitor)) {
390-
return;
391-
}
396+
compileTsFiles(tsFilesToCompile, getClient(), subMonitor);
397+
392398
if (removedTsFiles.size() > 0) {
393399
// ts files was removed, how to get referenced files which must
394400
// be recompiled (with errors)?
@@ -397,54 +403,86 @@ public void compileWithTsserver(List<IFile> updatedTsFiles, List<IFile> removedT
397403
throw e;
398404
} catch (Exception e) {
399405
throw new TypeScriptException(e);
406+
} finally {
407+
for (IFile tsFile : tsFilesToClose) {
408+
closeFile(tsFile);
409+
}
410+
subMonitor.done();
400411
}
401412
}
402413

403414
/**
404415
* Collect ts files to compile from the given ts files list.
405416
*
406-
* @param tsFiles
407-
* @param client
417+
* @param updatedTsFiles
418+
* list of TypeScript files which have changed.
408419
* @param tsFilesToCompile
409-
* @param exclude
410-
* @param monitor
420+
* list of collected ts files to compile.
421+
* @param tsFilesToClose
422+
* list of ts files to close.
423+
* @param client
424+
* @param subMonitor
411425
* @throws Exception
412426
*/
413-
private boolean collectTsFilesToCompile(List<IFile> tsFiles, ITypeScriptServiceClient client,
414-
List<String> tsFilesToCompile, boolean exclude, IProgressMonitor monitor) throws Exception {
415-
for (IFile tsFile : tsFiles) {
416-
if (monitor.isCanceled()) {
417-
return true;
427+
private void collectTsFilesToCompile(List<IFile> updatedTsFiles, List<String> tsFilesToCompile,
428+
List<IFile> tsFilesToClose, ITypeScriptServiceClient client, SubMonitor subMonitor) throws Exception {
429+
SubMonitor loopMonitor = subMonitor.split(50).setWorkRemaining(updatedTsFiles.size());
430+
loopMonitor.subTask(TypeScriptCoreMessages.IDETypeScriptProject_compile_collecting_step);
431+
for (IFile tsFile : updatedTsFiles) {
432+
if (loopMonitor.isCanceled()) {
433+
throw new OperationCanceledException();
418434
}
419435
String filename = WorkbenchResourceUtil.getFileName(tsFile);
436+
loopMonitor
437+
.subTask(NLS.bind(TypeScriptCoreMessages.IDETypeScriptProject_compile_collecting_file, filename));
420438
if (!tsFilesToCompile.contains(filename)) {
421-
collectTsFilesToCompile(filename, client, tsFilesToCompile, exclude);
439+
collectTsFilesToCompile(filename, client, tsFilesToCompile, tsFilesToClose, loopMonitor);
422440
}
441+
loopMonitor.worked(1);
442+
// loopMonitor.split(1);
423443
}
424-
return false;
444+
// subMonitor.setWorkRemaining(50);
425445
}
426446

427447
/**
428-
* Collect ts files to compile from the given ts file name.
448+
* Collect ts files to compile from the given TypeScript file.
429449
*
430450
* @param filename
431451
* @param client
432452
* @param tsFilesToCompile
433-
* @param exclude
453+
* @param tsFilesToClose
454+
* @param monitor
434455
* @throws Exception
435456
*/
436457
private void collectTsFilesToCompile(String filename, ITypeScriptServiceClient client,
437-
List<String> tsFilesToCompile, boolean exclude) throws Exception {
438-
// call tsserver compileOnSaveAffectedFileList to retrieve file
439-
// dependencies of the given filename
440-
List<CompileOnSaveAffectedFileListSingleProject> affectedProjects = client
441-
.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
442-
for (CompileOnSaveAffectedFileListSingleProject affectedProject : affectedProjects) {
443-
List<String> affectedTsFilenames = affectedProject.getFileNames();
444-
for (String affectedFilename : affectedTsFilenames) {
445-
if (!tsFilesToCompile.contains(affectedFilename) && !(exclude && filename.equals(affectedFilename))) {
446-
tsFilesToCompile.add(affectedFilename);
458+
List<String> tsFilesToCompile, List<IFile> tsFilesToClose, IProgressMonitor monitor) throws Exception {
459+
while (!monitor.isCanceled()) {
460+
try {
461+
// When tsserver is not started, it takes time, we try to collect TypeScript
462+
// files every time and stop the search if user stops the builder.
463+
List<CompileOnSaveAffectedFileListSingleProject> affectedProjects = client
464+
.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
465+
if (affectedProjects.size() == 0 && getOpenedFile(filename) == null) {
466+
// Case when none TypeScript files are opened.
467+
// In this case, compileOnSaveAffectedFileList returns null, the tsserver needs
468+
// having just one opened TypeScript file
469+
// in order to compileOnSaveAffectedFileList returns the well list.
470+
IFile tsFile = WorkbenchResourceUtil.findFileFromWorkspace(filename);
471+
openFile(tsFile, null);
472+
tsFilesToClose.add(tsFile);
473+
affectedProjects = client.compileOnSaveAffectedFileList(filename).get(5000, TimeUnit.MILLISECONDS);
447474
}
475+
for (CompileOnSaveAffectedFileListSingleProject affectedProject : affectedProjects) {
476+
List<String> affectedTsFilenames = affectedProject.getFileNames();
477+
for (String affectedFilename : affectedTsFilenames) {
478+
if (!tsFilesToCompile.contains(affectedFilename)) {
479+
tsFilesToCompile.add(affectedFilename);
480+
}
481+
}
482+
}
483+
return;
484+
} catch (TimeoutException e) {
485+
// tsserver is not initialized, retry again...
448486
}
449487
}
450488
}
@@ -454,28 +492,32 @@ private void collectTsFilesToCompile(String filename, ITypeScriptServiceClient c
454492
*
455493
* @param tsFilesToCompile
456494
* @param client
457-
* @param monitor
458-
* @return true if process must be stopped and false otherwise.
495+
* @param subMonitor
459496
* @throws Exception
460497
*/
461-
private boolean compileTsFiles(List<String> tsFilesToCompile, ITypeScriptServiceClient client,
462-
IProgressMonitor monitor) throws Exception {
498+
private void compileTsFiles(List<String> tsFilesToCompile, ITypeScriptServiceClient client, SubMonitor subMonitor)
499+
throws Exception {
500+
SubMonitor loopMonitor = subMonitor.newChild(50).setWorkRemaining(tsFilesToCompile.size());// subMonitor.split(50).setWorkRemaining(tsFilesToCompile.size());
501+
loopMonitor.subTask(TypeScriptCoreMessages.IDETypeScriptProject_compile_compiling_step);
463502
for (String filename : tsFilesToCompile) {
464-
if (monitor.isCanceled()) {
465-
return true;
466-
}
467503
try {
504+
if (loopMonitor.isCanceled()) {
505+
throw new OperationCanceledException();
506+
}
507+
loopMonitor.subTask(
508+
NLS.bind(TypeScriptCoreMessages.IDETypeScriptProject_compile_compiling_file, filename));
468509
compileTsFile(filename, client);
510+
loopMonitor.worked(1);
511+
// loopMonitor.split(1);
469512
} catch (ExecutionException e) {
470513
if (e.getCause() instanceof TypeScriptNoContentAvailableException) {
471514
// Ignore "No content available" error.
472-
}
473-
else {
515+
} else {
474516
throw e;
475517
}
476518
}
477519
}
478-
return false;
520+
// subMonitor.setWorkRemaining(100);
479521
}
480522

481523
/**
@@ -493,7 +535,7 @@ private void compileTsFile(String filename, ITypeScriptServiceClient client) thr
493535
if (tsFile != null) {
494536
// Delete TypeScript error marker
495537
TypeScriptResourceUtil.deleteTscMarker(tsFile);
496-
// Add TypeScript error marker if there error errors.
538+
// Add TypeScript error marker if there are errors.
497539
DiagnosticEventBody event = client.syntacticDiagnosticsSync(filename, true).get(5000,
498540
TimeUnit.MILLISECONDS);
499541
addMarker(tsFile, event);

0 commit comments

Comments
 (0)