@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
334 lines • 13 kB
JavaScript
// *****************************************************************************
// Copyright (C) 2017 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createUntitledURI = exports.UntitledResource = exports.UntitledResourceResolver = exports.UNTITLED_SCHEME = exports.InMemoryTextResourceResolver = exports.InMemoryTextResource = exports.MEMORY_TEXT = exports.InMemoryResources = exports.ReferenceMutableResource = exports.MutableResource = exports.DefaultResourceProvider = exports.ResourceProvider = exports.ResourceResolver = exports.ResourceError = exports.Resource = void 0;
const inversify_1 = require("inversify");
const uri_1 = require("../common/uri");
const contribution_provider_1 = require("./contribution-provider");
const event_1 = require("./event");
const application_error_1 = require("./application-error");
const stream_1 = require("./stream");
const reference_1 = require("./reference");
var Resource;
(function (Resource) {
async function save(resource, context, token) {
if (!resource.saveContents) {
return;
}
if (await trySaveContentChanges(resource, context)) {
return;
}
if (token && token.isCancellationRequested) {
return;
}
if (typeof context.content !== 'string' && resource.saveStream) {
await resource.saveStream(context.content, context.options);
}
else {
const content = typeof context.content === 'string' ? context.content : stream_1.Readable.toString(context.content);
await resource.saveContents(content, context.options);
}
}
Resource.save = save;
async function trySaveContentChanges(resource, context) {
if (!context.changes || !resource.saveContentChanges || shouldSaveContent(resource, context)) {
return false;
}
try {
await resource.saveContentChanges(context.changes, context.options);
return true;
}
catch (e) {
if (!ResourceError.NotFound.is(e) && !ResourceError.OutOfSync.is(e)) {
console.error(`Failed to apply incremental changes to '${resource.uri.toString()}':`, e);
}
return false;
}
}
Resource.trySaveContentChanges = trySaveContentChanges;
function shouldSaveContent(resource, { contentLength, changes }) {
if (!changes || (resource.saveStream && contentLength > 32 * 1024 * 1024)) {
return true;
}
let contentChangesLength = 0;
for (const change of changes) {
contentChangesLength += JSON.stringify(change).length;
if (contentChangesLength > contentLength) {
return true;
}
}
return contentChangesLength > contentLength;
}
Resource.shouldSaveContent = shouldSaveContent;
})(Resource = exports.Resource || (exports.Resource = {}));
var ResourceError;
(function (ResourceError) {
ResourceError.NotFound = application_error_1.ApplicationError.declare(-40000, (raw) => raw);
ResourceError.OutOfSync = application_error_1.ApplicationError.declare(-40001, (raw) => raw);
})(ResourceError = exports.ResourceError || (exports.ResourceError = {}));
exports.ResourceResolver = Symbol('ResourceResolver');
exports.ResourceProvider = Symbol('ResourceProvider');
let DefaultResourceProvider = class DefaultResourceProvider {
constructor(resolversProvider) {
this.resolversProvider = resolversProvider;
}
/**
* Reject if a resource cannot be provided.
*/
async get(uri) {
const resolvers = this.resolversProvider.getContributions();
for (const resolver of resolvers) {
try {
return await resolver.resolve(uri);
}
catch (err) {
// no-op
}
}
return Promise.reject(new Error(`A resource provider for '${uri.toString()}' is not registered.`));
}
};
DefaultResourceProvider = __decorate([
(0, inversify_1.injectable)(),
__param(0, (0, inversify_1.inject)(contribution_provider_1.ContributionProvider)),
__param(0, (0, inversify_1.named)(exports.ResourceResolver)),
__metadata("design:paramtypes", [Object])
], DefaultResourceProvider);
exports.DefaultResourceProvider = DefaultResourceProvider;
class MutableResource {
constructor(uri) {
this.uri = uri;
this.contents = '';
this.onDidChangeContentsEmitter = new event_1.Emitter();
this.onDidChangeContents = this.onDidChangeContentsEmitter.event;
}
dispose() { }
async readContents() {
return this.contents;
}
async saveContents(contents) {
this.contents = contents;
this.fireDidChangeContents();
}
fireDidChangeContents() {
this.onDidChangeContentsEmitter.fire(undefined);
}
}
exports.MutableResource = MutableResource;
class ReferenceMutableResource {
constructor(reference) {
this.reference = reference;
}
get uri() {
return this.reference.object.uri;
}
get onDidChangeContents() {
return this.reference.object.onDidChangeContents;
}
dispose() {
this.reference.dispose();
}
readContents() {
return this.reference.object.readContents();
}
saveContents(contents) {
return this.reference.object.saveContents(contents);
}
}
exports.ReferenceMutableResource = ReferenceMutableResource;
let InMemoryResources = class InMemoryResources {
constructor() {
this.resources = new reference_1.SyncReferenceCollection(uri => new MutableResource(new uri_1.default(uri)));
}
add(uri, contents) {
const resourceUri = uri.toString();
if (this.resources.has(resourceUri)) {
throw new Error(`Cannot add already existing in-memory resource '${resourceUri}'`);
}
const resource = this.acquire(resourceUri);
resource.saveContents(contents);
return resource;
}
update(uri, contents) {
const resourceUri = uri.toString();
const resource = this.resources.get(resourceUri);
if (!resource) {
throw new Error(`Cannot update non-existed in-memory resource '${resourceUri}'`);
}
resource.saveContents(contents);
return resource;
}
resolve(uri) {
const uriString = uri.toString();
if (!this.resources.has(uriString)) {
throw new Error(`In memory '${uriString}' resource does not exist.`);
}
return this.acquire(uriString);
}
acquire(uri) {
const reference = this.resources.acquire(uri);
return new ReferenceMutableResource(reference);
}
};
InMemoryResources = __decorate([
(0, inversify_1.injectable)()
], InMemoryResources);
exports.InMemoryResources = InMemoryResources;
exports.MEMORY_TEXT = 'mem-txt';
/**
* Resource implementation for 'mem-txt' URI scheme where content is saved in URI query.
*/
class InMemoryTextResource {
constructor(uri) {
this.uri = uri;
}
async readContents(options) {
return this.uri.query;
}
dispose() { }
}
exports.InMemoryTextResource = InMemoryTextResource;
/**
* ResourceResolver implementation for 'mem-txt' URI scheme.
*/
let InMemoryTextResourceResolver = class InMemoryTextResourceResolver {
resolve(uri) {
if (uri.scheme !== exports.MEMORY_TEXT) {
throw new Error(`Expected a URI with ${exports.MEMORY_TEXT} scheme. Was: ${uri}.`);
}
return new InMemoryTextResource(uri);
}
};
InMemoryTextResourceResolver = __decorate([
(0, inversify_1.injectable)()
], InMemoryTextResourceResolver);
exports.InMemoryTextResourceResolver = InMemoryTextResourceResolver;
exports.UNTITLED_SCHEME = 'untitled';
let untitledResourceSequenceIndex = 0;
let UntitledResourceResolver = class UntitledResourceResolver {
constructor() {
this.resources = new Map();
}
has(uri) {
if (uri.scheme !== exports.UNTITLED_SCHEME) {
throw new Error('The given uri is not untitled file uri: ' + uri);
}
else {
return this.resources.has(uri.toString());
}
}
async resolve(uri) {
if (uri.scheme !== exports.UNTITLED_SCHEME) {
throw new Error('The given uri is not untitled file uri: ' + uri);
}
else {
const untitledResource = this.resources.get(uri.toString());
if (!untitledResource) {
return this.createUntitledResource('', '', uri);
}
else {
return untitledResource;
}
}
}
async createUntitledResource(content, extension, uri) {
if (!uri) {
uri = this.createUntitledURI(extension);
}
return new UntitledResource(this.resources, uri, content);
}
createUntitledURI(extension, parent) {
let counter = 1; // vscode starts at 1
let untitledUri;
do {
const name = `Untitled-${counter}${extension !== null && extension !== void 0 ? extension : ''}`;
if (parent) {
untitledUri = parent.resolve(name).withScheme(exports.UNTITLED_SCHEME);
}
untitledUri = new uri_1.default().resolve(name).withScheme(exports.UNTITLED_SCHEME);
counter++;
} while (this.has(untitledUri));
return untitledUri;
}
};
UntitledResourceResolver = __decorate([
(0, inversify_1.injectable)()
], UntitledResourceResolver);
exports.UntitledResourceResolver = UntitledResourceResolver;
class UntitledResource {
constructor(resources, uri, content) {
this.resources = resources;
this.uri = uri;
this.content = content;
this.onDidChangeContentsEmitter = new event_1.Emitter();
this.resources.set(this.uri.toString(), this);
}
get onDidChangeContents() {
return this.onDidChangeContentsEmitter.event;
}
dispose() {
this.resources.delete(this.uri.toString());
this.onDidChangeContentsEmitter.dispose();
}
async readContents(options) {
if (this.content) {
return this.content;
}
else {
return '';
}
}
async saveContents(content, options) {
// This function must exist to ensure readOnly is false for the Monaco editor.
// However it should not be called because saving 'untitled' is always processed as 'Save As'.
throw Error('Untitled resources cannot be saved.');
}
fireDidChangeContents() {
this.onDidChangeContentsEmitter.fire(undefined);
}
get version() {
return undefined;
}
get encoding() {
return undefined;
}
}
exports.UntitledResource = UntitledResource;
/**
* @deprecated Since 1.27.0. Please use `UntitledResourceResolver.createUntitledURI` instead.
*/
function createUntitledURI(extension, parent) {
const name = `Untitled-${untitledResourceSequenceIndex++}${extension !== null && extension !== void 0 ? extension : ''}`;
if (parent) {
return parent.resolve(name).withScheme(exports.UNTITLED_SCHEME);
}
return new uri_1.default().resolve(name).withScheme(exports.UNTITLED_SCHEME);
}
exports.createUntitledURI = createUntitledURI;
//# sourceMappingURL=resource.js.map
;