/******************************************************************************* * Copyright (c) 2012-2015 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.worker; import org.eclipse.che.ide.collections.Jso; import org.eclipse.che.ide.collections.StringMap; import org.eclipse.che.ide.collections.js.JsoArray; import org.eclipse.che.ide.collections.js.JsoStringMap; import org.eclipse.che.ide.ext.java.jdt.CUVariables; import org.eclipse.che.ide.ext.java.jdt.codeassistant.ContentAssistHistory; import org.eclipse.che.ide.ext.java.jdt.codeassistant.TemplateCompletionProposalComputer; import org.eclipse.che.ide.ext.java.jdt.core.JavaCore; import org.eclipse.che.ide.ext.java.jdt.core.compiler.IProblem; import org.eclipse.che.ide.ext.java.jdt.core.dom.AST; import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTNode; import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTParser; import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit; import org.eclipse.che.ide.ext.java.jdt.core.formatter.CodeFormatter; import org.eclipse.che.ide.ext.java.jdt.internal.codeassist.impl.AssistOptions; import org.eclipse.che.ide.ext.java.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.che.ide.ext.java.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.che.ide.ext.java.jdt.internal.compiler.problem.DefaultProblem; import org.eclipse.che.ide.ext.java.jdt.internal.corext.util.CodeFormatterUtil; import org.eclipse.che.ide.ext.java.jdt.templates.CodeTemplateContextType; import org.eclipse.che.ide.ext.java.jdt.templates.ContextTypeRegistry; import org.eclipse.che.ide.ext.java.jdt.templates.ElementTypeResolver; import org.eclipse.che.ide.ext.java.jdt.templates.ExceptionVariableNameResolver; import org.eclipse.che.ide.ext.java.jdt.templates.FieldResolver; import org.eclipse.che.ide.ext.java.jdt.templates.ImportsResolver; import org.eclipse.che.ide.ext.java.jdt.templates.JavaContextType; import org.eclipse.che.ide.ext.java.jdt.templates.JavaDocContextType; import org.eclipse.che.ide.ext.java.jdt.templates.LinkResolver; import org.eclipse.che.ide.ext.java.jdt.templates.LocalVarResolver; import org.eclipse.che.ide.ext.java.jdt.templates.NameResolver; import org.eclipse.che.ide.ext.java.jdt.templates.StaticImportResolver; import org.eclipse.che.ide.ext.java.jdt.templates.TemplateStore; import org.eclipse.che.ide.ext.java.jdt.templates.TypeResolver; import org.eclipse.che.ide.ext.java.jdt.templates.TypeVariableResolver; import org.eclipse.che.ide.ext.java.jdt.templates.VarResolver; import org.eclipse.che.ide.ext.java.messages.ConfigMessage; import org.eclipse.che.ide.ext.java.messages.DependenciesUpdatedMessage; import org.eclipse.che.ide.ext.java.messages.FileClosedMessage; import org.eclipse.che.ide.ext.java.messages.FormatMessage; import org.eclipse.che.ide.ext.java.messages.ParseMessage; import org.eclipse.che.ide.ext.java.messages.PreferenceFormatSetMessage; import org.eclipse.che.ide.ext.java.messages.Problem; import org.eclipse.che.ide.ext.java.messages.RemoveFqnMessage; import org.eclipse.che.ide.ext.java.messages.RoutingTypes; import org.eclipse.che.ide.ext.java.messages.impl.MessagesImpls; import org.eclipse.che.ide.ext.java.jdt.text.edits.CopySourceEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.CopyTargetEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.CopyingRangeMarker; import org.eclipse.che.ide.ext.java.jdt.text.edits.DeleteEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.InsertEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.MoveSourceEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.MoveTargetEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.MultiTextEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.RangeMarker; import org.eclipse.che.ide.ext.java.jdt.text.edits.ReplaceEdit; import org.eclipse.che.ide.ext.java.jdt.text.edits.TextEdit; import com.google.gwt.webworker.client.MessageEvent; import com.google.gwt.webworker.client.MessageHandler; import com.google.gwt.webworker.client.messages.MessageFilter; import com.google.gwt.webworker.client.messages.MessageImpl; import java.util.HashMap; import java.util.Map; /** * @author Evgen Vidolob */ public class WorkerMessageHandler implements MessageHandler, MessageFilter.MessageRecipient<ParseMessage> { private static WorkerMessageHandler instance; private final WorkerOutlineModelUpdater outlineModelUpdater; private final WorkerJavadocHandleComputer javadocHandleComputer; private final WorkerCuCache cuCache; private WorkerCorrectionProcessor correctionProcessor; private INameEnvironment nameEnvironment; private HashMap<String, String> options = new HashMap<String, String>(); private Map<String, String> preferenceFormatSettings = new HashMap<String, String>(); private MessageFilter messageFilter; private JavaParserWorker worker; private ContentAssistHistory contentAssistHistory; private ContextTypeRegistry fCodeTemplateContextTypeRegistry; private TemplateStore templateStore; private String projectName; private CUVariables cuVar; private TemplateCompletionProposalComputer templateCompletionProposalComputer; private WorkerCodeAssist workerCodeAssist; public WorkerMessageHandler(final JavaParserWorker worker) { this.worker = worker; instance = this; initOptions(); messageFilter = new MessageFilter(); cuCache = new WorkerCuCache(); javadocHandleComputer = new WorkerJavadocHandleComputer(worker, cuCache); MessageFilter.MessageRecipient<ConfigMessage> configMessageRecipient = new MessageFilter.MessageRecipient<ConfigMessage>() { @Override public void onMessageReceived(ConfigMessage config) { nameEnvironment = new WorkerNameEnvironment(config.caPath(), config.restContext(), config.wsId()); projectName = config.projectName(); WorkerProposalApplier applier = new WorkerProposalApplier(WorkerMessageHandler.this.worker, messageFilter); workerCodeAssist = new WorkerCodeAssist(WorkerMessageHandler.this.worker, messageFilter, applier, nameEnvironment, templateCompletionProposalComputer, config.javaDocContext(), cuCache); correctionProcessor = new WorkerCorrectionProcessor(WorkerMessageHandler.this.worker, messageFilter, applier, cuCache); } }; messageFilter.registerMessageRecipient(RoutingTypes.CONFIG, configMessageRecipient); messageFilter.registerMessageRecipient(RoutingTypes.PARSE, this); templateCompletionProposalComputer = new TemplateCompletionProposalComputer(getTemplateContextRegistry()); outlineModelUpdater = new WorkerOutlineModelUpdater(worker); messageFilter.registerMessageRecipient(RoutingTypes.REMOVE_FQN, new MessageFilter.MessageRecipient<RemoveFqnMessage>() { @Override public void onMessageReceived(RemoveFqnMessage message) { WorkerTypeInfoStorage.get().removeFqn(message.fqn()); } }); messageFilter.registerMessageRecipient(RoutingTypes.FORMAT, new MessageFilter.MessageRecipient<FormatMessage>() { @Override public void onMessageReceived(FormatMessage message) { if (preferenceFormatSettings != null) { TextEdit edit; if (message.offset() == 0) { edit = CodeFormatterUtil.format2(CodeFormatter.K_COMPILATION_UNIT, message.content(), 0, null, preferenceFormatSettings); } else { edit = CodeFormatterUtil.format2(CodeFormatter.K_COMPILATION_UNIT, message.content(), message.offset(), message.length(), 0, null, preferenceFormatSettings); } Jso textEditJso = convertTextEditToJso(edit); MessagesImpls.FormatResultMessageImpl formatResultMes = MessagesImpls.FormatResultMessageImpl.make(); formatResultMes.setTextEdit(textEditJso); formatResultMes.setId(message.id()); worker.sendMessage(formatResultMes.serialize()); } } }); messageFilter.registerMessageRecipient(RoutingTypes.PREFERENCE_FORMAT_SETTINGS, new MessageFilter.MessageRecipient<PreferenceFormatSetMessage>() { @Override public void onMessageReceived(PreferenceFormatSetMessage message) { JsoStringMap<String> settingsJso = message.settings(); settingsJso.iterate(new StringMap.IterationCallback<String>() { @Override public void onIteration(String key, String value) { preferenceFormatSettings.put(key, value); } }); } }); messageFilter.registerMessageRecipient(RoutingTypes.DEPENDENCIES_UPDATED, new MessageFilter.MessageRecipient<DependenciesUpdatedMessage>() { @Override public void onMessageReceived(DependenciesUpdatedMessage message) { if(nameEnvironment != null) { nameEnvironment.clearBlackList(); } WorkerTypeInfoStorage.get().clear(); } }); messageFilter.registerMessageRecipient(RoutingTypes.FILE_CLOSED, new MessageFilter.MessageRecipient<FileClosedMessage>() { @Override public void onMessageReceived(FileClosedMessage message) { cuCache.removeCompilationUnit(message.getFilePath()); } }); messageFilter.registerMessageRecipient(RoutingTypes.COMPUTE_JAVADOC_HANDE, javadocHandleComputer); } public static WorkerMessageHandler get() { return instance; } /** Creates a JsoArray from a Java array. */ public static <M> JsoArray<M> from(M... array) { JsoArray<M> result = JsoArray.create(); for (M s : array) { if(s != null) result.add(s); } return result; } private Jso convertTextEditToJso(TextEdit edit) { Jso textEdit = Jso.create(); textEdit.addField("offSet", edit.getOffset()); if (edit.hasChildren()) { textEdit.addField("children", convertChildrenTextEditToJso(edit.getChildren())); } if (!(edit instanceof InsertEdit || edit instanceof MoveTargetEdit || edit instanceof CopyTargetEdit)) { textEdit.addField("length", edit.getLength()); } if (edit instanceof ReplaceEdit) { textEdit.addField("text", ((ReplaceEdit)edit).getText()); textEdit.addField("type", "ReplaceEdit"); } else if (edit instanceof DeleteEdit) { textEdit.addField("type", "DeleteEdit"); } else if (edit instanceof InsertEdit) { textEdit.addField("text", ((InsertEdit)edit).getText()); textEdit.addField("type", "InsertEdit"); } else if (edit instanceof CopyingRangeMarker) { textEdit.addField("type", "CopyingRangeMarker"); } else if (edit instanceof CopySourceEdit) { if (((CopySourceEdit)edit).getTargetEdit() != null) { Jso copyTargetEdit = Jso.create(); copyTargetEdit.addField("offSet", ((CopySourceEdit)edit).getTargetEdit().getOffset()); textEdit.addField("CopyTargetEdit", copyTargetEdit); } textEdit.addField("type", "CopySourceEdit"); } else if (edit instanceof MoveSourceEdit) { if (((MoveSourceEdit)edit).getTargetEdit() != null) { Jso moveTargetEdit = Jso.create(); moveTargetEdit.addField("offSet", ((MoveSourceEdit)edit).getTargetEdit().getOffset()); textEdit.addField("MoveTargetEdit", moveTargetEdit); } textEdit.addField("type", "MoveSourceEdit"); } else if (edit instanceof MoveTargetEdit) { if (((MoveTargetEdit)edit).getSourceEdit() != null) { Jso moveSourceEdit = Jso.create(); moveSourceEdit.addField("offSet", ((MoveTargetEdit)edit).getSourceEdit().getOffset()); moveSourceEdit.addField("length", ((MoveTargetEdit)edit).getSourceEdit().getLength()); textEdit.addField("MoveSourceEdit", moveSourceEdit); } textEdit.addField("type", "MoveTargetEdit"); } else if (edit instanceof MultiTextEdit) { textEdit.addField("type", "MultiTextEdit"); } else if (edit instanceof RangeMarker) { textEdit.addField("type", "RangeMarker"); } else if (edit instanceof CopyTargetEdit) { Jso copySourceEdit = Jso.create(); copySourceEdit.addField("offSet", ((CopyTargetEdit)edit).getSourceEdit().getOffset()); copySourceEdit.addField("length", ((CopyTargetEdit)edit).getSourceEdit().getLength()); textEdit.addField("CopySourceEdit", copySourceEdit); textEdit.addField("type", "CopyTargetEdit"); } return textEdit; } private JsoArray<Jso> convertChildrenTextEditToJso(TextEdit[] childrensEdit) { JsoArray<Jso> edits = JsoArray.create(); for (TextEdit chEdit : childrensEdit) { Jso child = convertTextEditToJso(chEdit); edits.add(child); } return edits; } private void initOptions() { options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7); options.put(JavaCore.CORE_ENCODING, "UTF-8"); options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7); options.put(CompilerOptions.OPTION_TargetPlatform, JavaCore.VERSION_1_7); options.put(AssistOptions.OPTION_PerformVisibilityCheck, AssistOptions.ENABLED); options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING); options.put(CompilerOptions.OPTION_TaskTags, CompilerOptions.WARNING); options.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.WARNING); options.put(CompilerOptions.OPTION_SuppressWarnings, CompilerOptions.DISABLED); options.put(JavaCore.COMPILER_TASK_TAGS, "TODO,FIXME,XXX"); options.put(JavaCore.COMPILER_PB_UNUSED_PARAMETER_INCLUDE_DOC_COMMENT_REFERENCE, JavaCore.ENABLED); options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); options.put(CompilerOptions.OPTION_Process_Annotations, JavaCore.DISABLED); options.put(AssistOptions.OPTION_PerformForbiddenReferenceCheck, AssistOptions.ENABLED); options.put(AssistOptions.OPTION_PerformVisibilityCheck, AssistOptions.ENABLED); options.put(AssistOptions.OPTION_PerformDeprecationCheck, AssistOptions.DISABLED); options.put(AssistOptions.OPTION_PerformDiscouragedReferenceCheck, AssistOptions.ENABLED); } /** {@inheritDoc} */ @Override public void onMessage(MessageEvent event) { MessageImpl message = event.getDataAsJSO().cast(); messageFilter.dispatchMessage(message); } public HashMap<String, String> getOptions() { return options; } @Override public void onMessageReceived(final ParseMessage message) { nameEnvironment.setProjectPath(message.projectPath()); cuVar = new CUVariables(message.fileName(), message.packageName(), projectName); ASTParser parser = ASTParser.newParser(AST.JLS4); parser.setSource(message.source()); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setUnitName(message.fileName().substring(0, message.fileName().lastIndexOf('.'))); parser.setResolveBindings(true); parser.setIgnoreMethodBodies(message.ignoreMethodBodies()); parser.setNameEnvironment(nameEnvironment); ASTNode ast = parser.createAST(); CompilationUnit unit = (CompilationUnit)ast; cuCache.putCompilationUnit(message.filePath(), unit, message.source()); IProblem[] problems = unit.getProblems(); MessagesImpls.ProblemsMessageImpl problemsMessage = MessagesImpls.ProblemsMessageImpl.make(); JsoArray<Problem> problemsArray = JsoArray.create(); for (IProblem p : problems) { problemsArray.add(convertProblem(p)); } IProblem[] tasks = (IProblem[])unit.getProperty("tasks"); if (tasks != null) { for (IProblem p : tasks) { problemsArray.add(convertProblem(p)); } } problemsMessage.setProblems(problemsArray); problemsMessage.setId(message.id()); worker.sendMessage(problemsMessage.serialize()); outlineModelUpdater.onCompilationUnitChanged(unit, message.filePath()); } private MessagesImpls.ProblemImpl convertProblem(IProblem p) { MessagesImpls.ProblemImpl problem = MessagesImpls.ProblemImpl.make(); DefaultProblem prop = (DefaultProblem)p; problem.setOriginatingFileName(new String(prop.getOriginatingFileName())); problem.setMessage(prop.getMessage()); problem.setId(prop.getID()); problem.setStringArguments(from(prop.getArguments())); problem.setSeverity(prop.getSeverity()); problem.setStartPosition(prop.getSourceStart()); problem.setEndPosition(prop.getSourceEnd()); problem.setLine(prop.getSourceLineNumber()); problem.setColumn(prop.getSourceColumnNumber()); return problem; } public ContentAssistHistory getContentAssistHistory() { if (contentAssistHistory == null) { Preferences preferences = new Preferences(); // TODO use user name contentAssistHistory = ContentAssistHistory.load(preferences, Preferences.CODEASSIST_LRU_HISTORY +"change me" /*userInfo.getName()*/); if (contentAssistHistory == null) contentAssistHistory = new ContentAssistHistory(); } return contentAssistHistory; } /** @return */ public ContextTypeRegistry getTemplateContextRegistry() { if (fCodeTemplateContextTypeRegistry == null) { fCodeTemplateContextTypeRegistry = new ContextTypeRegistry(); CodeTemplateContextType.registerContextTypes(fCodeTemplateContextTypeRegistry); JavaContextType contextTypeAll = new JavaContextType(JavaContextType.ID_ALL); contextTypeAll.initializeContextTypeResolvers(); FieldResolver fieldResolver = new FieldResolver(); fieldResolver.setType("field"); contextTypeAll.addResolver(fieldResolver); LocalVarResolver localVarResolver = new LocalVarResolver(); localVarResolver.setType("localVar"); contextTypeAll.addResolver(localVarResolver); VarResolver varResolver = new VarResolver(); varResolver.setType("var"); contextTypeAll.addResolver(varResolver); NameResolver nameResolver = new NameResolver(); nameResolver.setType("newName"); contextTypeAll.addResolver(nameResolver); TypeResolver typeResolver = new TypeResolver(); typeResolver.setType("newType"); contextTypeAll.addResolver(typeResolver); ElementTypeResolver elementTypeResolver = new ElementTypeResolver(); elementTypeResolver.setType("elemType"); contextTypeAll.addResolver(elementTypeResolver); TypeVariableResolver typeVariableResolver = new TypeVariableResolver(); typeVariableResolver.setType("argType"); contextTypeAll.addResolver(typeVariableResolver); LinkResolver linkResolver = new LinkResolver(); linkResolver.setType("link"); contextTypeAll.addResolver(linkResolver); ImportsResolver importsResolver = new ImportsResolver(); importsResolver.setType("import"); StaticImportResolver staticImportResolver = new StaticImportResolver(); staticImportResolver.setType("importStatic"); contextTypeAll.addResolver(staticImportResolver); ExceptionVariableNameResolver exceptionVariableNameResolver = new ExceptionVariableNameResolver(); exceptionVariableNameResolver.setType("exception_variable_name"); contextTypeAll.addResolver(exceptionVariableNameResolver); fCodeTemplateContextTypeRegistry.addContextType(contextTypeAll); fCodeTemplateContextTypeRegistry.addContextType(new JavaDocContextType()); JavaContextType contextTypeMembers = new JavaContextType(JavaContextType.ID_MEMBERS); JavaContextType contextTypeStatements = new JavaContextType(JavaContextType.ID_STATEMENTS); contextTypeMembers.initializeResolvers(contextTypeAll); contextTypeStatements.initializeResolvers(contextTypeAll); fCodeTemplateContextTypeRegistry.addContextType(contextTypeMembers); fCodeTemplateContextTypeRegistry.addContextType(contextTypeStatements); } return fCodeTemplateContextTypeRegistry; } /** @return */ public TemplateStore getTemplateStore() { if (templateStore == null) templateStore = new TemplateStore(); return templateStore; } public INameEnvironment getNameEnvironment() { return nameEnvironment; } public CUVariables getCUVariables() { return cuVar; } }