/******************************************************************************* | |
* 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)); | |
} | |
} |