blob: 6c92e68094a534b39a07361c68a1901e5064135d [file] [log] [blame]
/*
* Copyright (c) 2014, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.wst.ui;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.html.ast.HtmlUnit;
import com.google.dart.engine.internal.element.angular.AngularApplication;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.utilities.general.ObjectUtilities;
import com.google.dart.tools.core.DartCoreDebug;
import com.google.dart.tools.core.analysis.model.AnalysisListener;
import com.google.dart.tools.core.analysis.model.Project;
import com.google.dart.tools.core.analysis.model.ResolvedHtmlEvent;
import com.google.dart.tools.core.internal.builder.AnalysisWorker;
import com.google.dart.tools.ui.internal.text.dart.DartUpdateSourceHelper;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.eclipse.wst.validation.internal.provisional.core.IValidator;
/**
* Bridge between WST HTML document and resolved {@link HtmlUnit}.
*/
public class HtmlReconcilerHook implements ISourceValidator, IValidator {
private IDocumentListener documentListener = new IDocumentListener() {
@Override
public void documentAboutToBeChanged(DocumentEvent event) {
}
@Override
public void documentChanged(DocumentEvent event) {
sourceChanged(document.get());
}
};
private IDocument document;
private StructuredDocumentDartInfo documentInfo;
private HtmlUnit resolvedUnit;
private AngularApplication application;
private AnalysisListener analysisListener;
public HtmlReconcilerHook() {
}
@Override
public void cleanup(IReporter reporter) {
// Not used, but WST expects IValidator
}
@Override
public void connect(IDocument document) {
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
return;
}
this.document = document;
this.documentInfo = StructuredDocumentDartInfo.create(document);
// we need it
if (documentInfo == null) {
return;
}
// track changes
document.addDocumentListener(documentListener);
HtmlReconcilerManager.getInstance().reconcileWith(document, this);
// remember resolved HtmlUnit
analysisListener = new AnalysisListener.Empty() {
@Override
public void resolvedHtml(ResolvedHtmlEvent event) {
StructuredDocumentDartInfo info = documentInfo;
if (info != null) {
AnalysisContext eventContext = event.getContext();
Source eventSource = event.getSource();
if (eventContext == info.getContext()
&& ObjectUtilities.equals(eventSource, info.getSource())) {
resolvedUnit = event.getUnit();
application = eventContext.getAngularApplicationWithHtml(eventSource);
}
}
}
};
AnalysisWorker.addListener(analysisListener);
// force reconcile
sourceChanged(document.get());
}
@Override
public void disconnect(IDocument document) {
AnalysisWorker.removeListener(analysisListener);
sourceChanged(null);
// clean up
document.removeDocumentListener(documentListener);
DartReconcilerManager.getInstance().reconcileWith(document, null);
this.document = null;
this.documentInfo = null;
this.resolvedUnit = null;
}
public AngularApplication getApplication() {
return application;
}
public AnalysisContext getContext() {
StructuredDocumentDartInfo info = documentInfo;
return info != null ? info.getContext() : null;
}
public HtmlUnit getResolvedUnit() {
return resolvedUnit;
}
public Source getSource() {
StructuredDocumentDartInfo info = documentInfo;
return info != null ? info.getSource() : null;
}
@Override
public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
// Not used, but WST expects IValidator
}
@Override
@SuppressWarnings("restriction")
public void validate(IValidationContext helper, IReporter reporter)
throws org.eclipse.wst.validation.internal.core.ValidationException {
// Not used, but WST expects IValidator
}
/**
* Notify the context that the source has changed.
* <p>
* Note, that {@link Source} is updated in {@link AnalysisContext} in the background thread, so
* there is a small probability that some operation will be initiated on not-quite-synchronized
* content. But it is better than nothing for now...
*
* @param code the new source code or {@code null} if the source should be pulled from disk
*/
private void sourceChanged(String code) {
if (documentInfo != null) {
AnalysisContext context = documentInfo.getContext();
if (context != null) {
Project project = documentInfo.getProject();
Source source = documentInfo.getSource();
DartUpdateSourceHelper.getInstance().updateWithDelay(project, context, source, code);
}
}
}
}