blob: d3df3748c8b4b089034a34add2bf8733e2c9bb5e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.compiler.closure;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.compiler.IProblem;
import org.eclipse.wst.jsdt.core.dom.AST;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.BlockComment;
import org.eclipse.wst.jsdt.core.dom.ClosureCompilerASTConverter;
import org.eclipse.wst.jsdt.core.dom.JSdoc;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.LineComment;
import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
import com.google.javascript.jscomp.parsing.parser.Parser;
import com.google.javascript.jscomp.parsing.parser.Parser.Config;
import com.google.javascript.jscomp.parsing.parser.SourceFile;
import com.google.javascript.jscomp.parsing.parser.trees.Comment;
import com.google.javascript.jscomp.parsing.parser.trees.ProgramTree;
import com.google.javascript.jscomp.parsing.parser.util.SourcePosition;
/**
* @author Gorkem Ercan
*
*/
public class ClosureCompiler {
private static class ErrorCollector extends com.google.javascript.jscomp.parsing.parser.util.ErrorReporter {
private final String fileName;
private final List<IProblem> problems = new ArrayList<IProblem>();
public ErrorCollector(String file) {
this.fileName = file;
}
@Override
protected void reportError(SourcePosition location, String message) {
addProblem(message,location,ProblemSeverities.Error);
}
protected void reportWarning(SourcePosition location, String message) {
addProblem(message,location,ProblemSeverities.Warning);
}
IProblem[] problems(){
return problems.toArray(new DefaultProblem[problems.size()]);
}
private void addProblem(String description, SourcePosition location, int severity){
DefaultProblem result = new DefaultProblem(fileName.toCharArray(),
description,
0,
null,
severity,
location.offset,
-1,
location.line,
location.column);
problems.add(result);
}
}
private String rawContent;
private IJavaScriptUnit unit;
private boolean commentsEnabled;
private ClosureCompiler(){
super();
}
public static ClosureCompiler newInstance(){
return new ClosureCompiler();
}
public ClosureCompiler setSource(String content){
this.unit = null;
this.rawContent = content;
return this;
}
public ClosureCompiler setSource(IJavaScriptUnit content){
this.rawContent = null;
this.unit = content;
return this;
}
public ClosureCompiler toggleComments( boolean enabled){
this.commentsEnabled = enabled;
return this;
}
public JavaScriptUnit parse() {
Config config = new Config(com.google.javascript.jscomp.parsing.parser.Parser.Config.Mode.ES6);
SourceFile source = getSourceFile();
ErrorCollector errorCollector = new ErrorCollector(source.name);
Parser parser = new Parser(config, errorCollector, source);
ProgramTree tree = parser.parseProgram();
AST ast = AST.newAST(AST.JLS3);
ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
ClosureCompilerASTConverter transformer = new ClosureCompilerASTConverter(ast, parser.getComments());
JavaScriptUnit $ = (JavaScriptUnit) transformer.transform(null,tree);
$.setLineEndTable(LineNumberComputer.computeLineTable(source.contents));
$.setProblems(errorCollector.problems());
if(commentsEnabled){
$.setCommentTable(buildComments(parser.getComments(), ast));
}
ast.setDefaultNodeFlag(0);
return $;
}
/**
* @param comments
*/
private org.eclipse.wst.jsdt.core.dom.Comment[] buildComments(List<Comment> comments, AST ast) {
ArrayList<org.eclipse.wst.jsdt.core.dom.Comment> domComments = new ArrayList<org.eclipse.wst.jsdt.core.dom.Comment>();
for (Comment comment : comments) {
switch (comment.type) {
case BLOCK :
BlockComment bc = ast.newBlockComment();
setSourceRange(bc,comment);
domComments.add(bc);
break;
case SHEBANG:
case LINE:
LineComment lc = ast.newLineComment();
setSourceRange(lc,comment);
domComments.add(lc);
break;
case JSDOC:
JSdoc jd = ast.newJSdoc();
jd.setComment(comment.value);
setSourceRange(jd,comment);
domComments.add(jd);
break;
}
}
return domComments.toArray(new org.eclipse.wst.jsdt.core.dom.Comment[domComments.size()]);
}
private void setSourceRange(ASTNode node, Comment comment) {
node.setSourceRange(comment.location.start.offset, comment.location.end.offset - comment.location.start.offset);
}
private SourceFile getSourceFile(){
String content = rawContent;
String filename = ""; //$NON-NLS-1$
if(unit != null )
try {
content = unit.getSource();
filename= unit.getDisplayName();
}
catch (JavaScriptModelException e) {
e.printStackTrace();
}
return(new SourceFile(filename,content));
}
}