<commit_before>/*******************************************************************************
 * Copyright (c) 2016 Red Hat Inc. and others.
 * 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
 *******************************************************************************/
package org.jboss.tools.vscode.java.internal.handlers;

import java.util.List;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.jboss.tools.langs.DidChangeTextDocumentParams;
import org.jboss.tools.langs.DidCloseTextDocumentParams;
import org.jboss.tools.langs.DidOpenTextDocumentParams;
import org.jboss.tools.langs.DidSaveTextDocumentParams;
import org.jboss.tools.langs.Range;
import org.jboss.tools.langs.TextDocumentContentChangeEvent;
import org.jboss.tools.langs.base.LSPMethods;
import org.jboss.tools.vscode.internal.ipc.NotificationHandler;
import org.jboss.tools.vscode.java.internal.JDTUtils;
import org.jboss.tools.vscode.java.internal.JavaClientConnection;
import org.jboss.tools.vscode.java.internal.JavaLanguageServerPlugin;

public class DocumentLifeCycleHandler {

	private JavaClientConnection connection;

	public class ClosedHandler implements NotificationHandler<DidCloseTextDocumentParams, Object>{
		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_CLOSED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidCloseTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleClosed(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document close ", e);
			}
			return null;
		}

	}

	public class OpenHandler implements NotificationHandler<DidOpenTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_OPENED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidOpenTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleOpen(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document open ", e);
			}
			return null;
		}
	}

	public class ChangeHandler implements NotificationHandler<DidChangeTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_CHANGED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidChangeTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleChanged(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document open ", e);
			}
			return null;
		}
	}

	public class SaveHandler implements NotificationHandler<DidSaveTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_SAVED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidSaveTextDocumentParams param) {
			// Nothing to do just keeping the clients happy with a response
			return null;
		}
	}

	public DocumentLifeCycleHandler(JavaClientConnection connection) {
		this.connection = connection;
	}

	private void handleOpen(DidOpenTextDocumentParams params) {
		ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
		if (unit == null) {
			return;
		}
		try {
			// The open event can happen before the workspace element added event when a new file is added.
			// checks if the underlying resource exists and refreshes to sync the newly created file.
			if(unit.getResource() != null && !unit.getResource().isAccessible()){
				try {
					unit.getResource().refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
				} catch (CoreException e) {
					// ignored
				}
			}

			IBuffer buffer = unit.getBuffer();
			if(buffer != null)
				buffer.setContents(params.getTextDocument().getText());

			// TODO: wire up cancellation.
			unit.becomeWorkingCopy(new DiagnosticsHandler(connection, unit.getUnderlyingResource()), null);
			unit.reconcile();
		} catch (JavaModelException e) {
			JavaLanguageServerPlugin.logException("Creating working copy ",e);
		}
	}

	private void handleChanged(DidChangeTextDocumentParams params) {
		ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());

		if (unit == null || !unit.isWorkingCopy()) {
			return;
		}

		ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
		ITextFileBuffer buffer = manager.getTextFileBuffer(unit.getResource().getFullPath(), LocationKind.IFILE);
		IDocument document = buffer.getDocument();
		try {
			MultiTextEdit root = new MultiTextEdit();
			List<TextDocumentContentChangeEvent> contentChanges = params.getContentChanges();
			for (TextDocumentContentChangeEvent changeEvent : contentChanges) {

				Range range = changeEvent.getRange();

				int startOffset = document.getLineOffset(range.getStart().getLine().intValue()) + range.getStart().getCharacter().intValue();
				int endOffset = document.getLineOffset(range.getEnd().getLine().intValue()) + range.getEnd().getCharacter().intValue();
				int length = endOffset - startOffset;

				TextEdit edit = null;
				if (length == 0) {
					edit = new InsertEdit(startOffset, changeEvent.getText());
				} else if (changeEvent.getText().length() == 0) {
					edit = new DeleteEdit(startOffset, length);
				} else {
					edit = new ReplaceEdit(startOffset, length, changeEvent.getText());
				}
				root.addChild(edit);
			}

			if (root.hasChildren()) {
				root.apply(document);
				unit.reconcile();
			}
		} catch (JavaModelException e) {<commit_msg>small simplification of change event<commit_after>/*******************************************************************************
 * Copyright (c) 2016 Red Hat Inc. and others.
 * 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
 *******************************************************************************/
package org.jboss.tools.vscode.java.internal.handlers;

import java.util.List;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.jboss.tools.langs.DidChangeTextDocumentParams;
import org.jboss.tools.langs.DidCloseTextDocumentParams;
import org.jboss.tools.langs.DidOpenTextDocumentParams;
import org.jboss.tools.langs.DidSaveTextDocumentParams;
import org.jboss.tools.langs.Range;
import org.jboss.tools.langs.TextDocumentContentChangeEvent;
import org.jboss.tools.langs.base.LSPMethods;
import org.jboss.tools.vscode.internal.ipc.NotificationHandler;
import org.jboss.tools.vscode.java.internal.JDTUtils;
import org.jboss.tools.vscode.java.internal.JavaClientConnection;
import org.jboss.tools.vscode.java.internal.JavaLanguageServerPlugin;

public class DocumentLifeCycleHandler {

	private JavaClientConnection connection;

	public class ClosedHandler implements NotificationHandler<DidCloseTextDocumentParams, Object>{
		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_CLOSED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidCloseTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleClosed(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document close ", e);
			}
			return null;
		}

	}

	public class OpenHandler implements NotificationHandler<DidOpenTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_OPENED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidOpenTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleOpen(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document open ", e);
			}
			return null;
		}
	}

	public class ChangeHandler implements NotificationHandler<DidChangeTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_CHANGED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidChangeTextDocumentParams param) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						handleChanged(param);
					}
				}, new NullProgressMonitor());
			} catch (CoreException e) {
				JavaLanguageServerPlugin.logException("Handle document open ", e);
			}
			return null;
		}
	}

	public class SaveHandler implements NotificationHandler<DidSaveTextDocumentParams, Object>{

		@Override
		public boolean canHandle(String request) {
			return LSPMethods.DOCUMENT_SAVED.getMethod().equals(request);
		}

		@Override
		public Object handle(DidSaveTextDocumentParams param) {
			// Nothing to do just keeping the clients happy with a response
			return null;
		}
	}

	public DocumentLifeCycleHandler(JavaClientConnection connection) {
		this.connection = connection;
	}

	private void handleOpen(DidOpenTextDocumentParams params) {
		ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
		if (unit == null) {
			return;
		}
		try {
			// The open event can happen before the workspace element added event when a new file is added.
			// checks if the underlying resource exists and refreshes to sync the newly created file.
			if(unit.getResource() != null && !unit.getResource().isAccessible()){
				try {
					unit.getResource().refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
				} catch (CoreException e) {
					// ignored
				}
			}

			IBuffer buffer = unit.getBuffer();
			if(buffer != null)
				buffer.setContents(params.getTextDocument().getText());

			// TODO: wire up cancellation.
			unit.becomeWorkingCopy(new DiagnosticsHandler(connection, unit.getUnderlyingResource()), null);
			unit.reconcile();
		} catch (JavaModelException e) {
			JavaLanguageServerPlugin.logException("Creating working copy ",e);
		}
	}

	private void handleChanged(DidChangeTextDocumentParams params) {
		ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());

		if (unit == null || !unit.isWorkingCopy()) {
			return;
		}

		ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
		ITextFileBuffer buffer = manager.getTextFileBuffer(unit.getResource().getFullPath(), LocationKind.IFILE);
		IDocument document = buffer.getDocument();
		try {
			MultiTextEdit root = new MultiTextEdit();
			List<TextDocumentContentChangeEvent> contentChanges = params.getContentChanges();
			for (TextDocumentContentChangeEvent changeEvent : contentChanges) {

				Range range = changeEvent.getRange();

				int startOffset = document.getLineOffset(range.getStart().getLine().intValue()) + range.getStart().getCharacter().intValue();
				int length = changeEvent.getRangeLength().intValue();

				TextEdit edit = null;
				if (length == 0) {
					edit = new InsertEdit(startOffset, changeEvent.getText());
				} else if (changeEvent.getText().isEmpty()){
					edit = new DeleteEdit(startOffset, length);
				} else {
					edit = new ReplaceEdit(startOffset, length, changeEvent.getText());
				}
				root.addChild(edit);
			}

			if (root.hasChildren()) {
				root.apply(document);
				unit.reconcile();
			}
		} catch (JavaModelException e) {
{'fraction_non_alphanumeric': 0.12180208040483553, 'fraction_numerical': 0.0013353949957829632, 'mean_word_length': 4.874896779521057, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3962650', 'n_tokens_mistral': 4554, 'n_tokens_neox': 3921, 'n_words': 858}