<commit_before>/*******************************************************************************
 * Copyright (c) 2016-2017 Pivotal, 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:
 *     Pivotal, Inc. - initial API and implementation
 *******************************************************************************/

package org.springframework.ide.vscode.commons.util.text;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.linetracker.DefaultLineTracker;
import org.springframework.ide.vscode.commons.util.text.linetracker.ILineTracker;

import javolution.text.Text;

public class TextDocument implements IDocument {

	ILineTracker lineTracker = new DefaultLineTracker();
	private static final Pattern NEWLINE = Pattern.compile("\\r|\\n|\\r\\n|\\n\\r");

	private final LanguageId languageId;
	private final String uri;
	private Text text = new Text("");
	private int version;

	public TextDocument(String uri, LanguageId languageId) {
		this(uri, languageId, 0, "");
	}

	private TextDocument(TextDocument other) {
		this.uri = other.uri;
		this.languageId = other.getLanguageId();
		this.text = other.text;
		this.lineTracker.set(text.toString());
		this.version = other.version;
	}

	public TextDocument(String uri, LanguageId languageId, int version, String text) {
		this.uri = uri;
		this.languageId = languageId;
		this.version = version;
		setText(text);
	}

	@Override
	public String getUri() {
		return uri;
	}

	@Override
	public String get() {
		return getText().toString();
	}

	private synchronized Text getText() {
		return text;
	}

	public synchronized void setText(String text) {
		this.text = new Text(text);
		this.lineTracker.set(text);
	}

	private void apply(TextDocumentContentChangeEvent change) throws BadLocationException {
		Range rng = change.getRange();
		if (rng==null) {
			//full sync mode
			setText(change.getText());
		} else {
			int start = toOffset(rng.getStart());
			int end = toOffset(rng.getEnd());
			replace(start, end-start, change.getText());
		}
	}

	public synchronized void apply(DidChangeTextDocumentParams params) throws BadLocationException {
		int newVersion = params.getTextDocument().getVersion();
		Assert.isLegal(version<newVersion);
		for (TextDocumentContentChangeEvent change : params.getContentChanges()) {
			apply(change);
		}
		this.version = newVersion;
	}

	/**
	 * Convert a simple offset+length pair into a vscode range. This is a method on
	 * TextDocument because it requires splitting document into lines to determine
	 * line numbers from offsets.
	 */
	public Range toRange(int offset, int length) throws BadLocationException {
		int end = Math.min(offset + length, getLength());
		Range range = new Range();
		range.setStart(toPosition(offset));
		range.setEnd(toPosition(end));
		return range;
	}

	/**
	 * Determine the line-number a given offset (i.e. what line is the offset inside of?)
	 */<commit_msg>Supress error which is logged on each save (vscode sending a duplicate edit?)<commit_after>/*******************************************************************************
 * Copyright (c) 2016-2017 Pivotal, 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:
 *     <NAME>. - initial API and implementation
 *******************************************************************************/

package org.springframework.ide.vscode.commons.util.text;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.linetracker.DefaultLineTracker;
import org.springframework.ide.vscode.commons.util.text.linetracker.ILineTracker;

import javolution.text.Text;

public class TextDocument implements IDocument {

	ILineTracker lineTracker = new DefaultLineTracker();
	private static final Pattern NEWLINE = Pattern.compile("\\r|\\n|\\r\\n|\\n\\r");

	private final LanguageId languageId;
	private final String uri;
	private Text text = new Text("");
	private int version;

	public TextDocument(String uri, LanguageId languageId) {
		this(uri, languageId, 0, "");
	}

	private TextDocument(TextDocument other) {
		this.uri = other.uri;
		this.languageId = other.getLanguageId();
		this.text = other.text;
		this.lineTracker.set(text.toString());
		this.version = other.version;
	}

	public TextDocument(String uri, LanguageId languageId, int version, String text) {
		this.uri = uri;
		this.languageId = languageId;
		this.version = version;
		setText(text);
	}

	@Override
	public String getUri() {
		return uri;
	}

	@Override
	public String get() {
		return getText().toString();
	}

	private synchronized Text getText() {
		return text;
	}

	public synchronized void setText(String text) {
		this.text = new Text(text);
		this.lineTracker.set(text);
	}

	private void apply(TextDocumentContentChangeEvent change) throws BadLocationException {
		Range rng = change.getRange();
		if (rng==null) {
			//full sync mode
			setText(change.getText());
		} else {
			int start = toOffset(rng.getStart());
			int end = toOffset(rng.getEnd());
			replace(start, end-start, change.getText());
		}
	}

	public synchronized void apply(DidChangeTextDocumentParams params) throws BadLocationException {
		int newVersion = params.getTextDocument().getVersion();
		if (version<newVersion) {
			for (TextDocumentContentChangeEvent change : params.getContentChanges()) {
				apply(change);
			}
			this.version = newVersion;
		} else {
			Log.warn("Change event with bad version ignored: "+params);
		}
	}

	/**
	 * Convert a simple offset+length pair into a vscode range. This is a method on
	 * TextDocument because it requires splitting document into lines to determine
	 * line numbers from offsets.
	 */
	public Range toRange(int offset, int length) throws BadLocationException {
		int end = Math.min(offset + length, getLength());
		Range range = new Range();
		range.setStart(toPosition(offset));
		range.setEnd(toPosition(end));
		return range;
	}

	/**
	 * Determine the line-number a given offset (i.e. what line is the offset inside of?)
	 */
{'fraction_non_alphanumeric': 0.14858165794546957, 'fraction_numerical': 0.004957312035251997, 'mean_word_length': 4.727917981072555, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 4, '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': '5331596', 'n_tokens_mistral': 2224, 'n_tokens_neox': 2056, 'n_words': 560}