org.netbeans.modules.parsing.implspi.SourceEnvironment Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.netbeans.modules.parsing.implspi;
import java.io.IOException;
import javax.swing.event.ChangeListener;
import javax.swing.text.Document;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.impl.ParserEventForward;
import org.netbeans.modules.parsing.impl.SourceAccessor;
import org.netbeans.modules.parsing.impl.event.FileChangeSupport;
import org.netbeans.modules.parsing.impl.event.ParserChangeSupport;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Parameters;
/**
* Connects the Source instance to its environment.It is not implemented by
* Parsing API as it may introduce extra dependencies on file or object access
* libraries (e.g. Data Systems API). In exchange, the Provider gets a control
* interface, which can be used to signal source change events originating from
* the storage/file/DataObject.
*
* Instance of the SourceEnvironment is referenced from the Source object. It is
* advised not to store Source reference, but rather extract the Source instance
* from the {@link Source.EnvControl} to allow Source instances to be GCed.
*
* @author sdedic
* @since 9.2
*/
public abstract class SourceEnvironment {
/** Default reparse - sliding window for editor events*/
private static final int DEFAULT_REPARSE_DELAY = 500;
/** Default reparse - sliding window for focus events*/
private static final int IMMEDIATE_REPARSE_DELAY = 10;
private static int reparseDelay = DEFAULT_REPARSE_DELAY;
private static int immediateReparseDelay = IMMEDIATE_REPARSE_DELAY;
private final SourceControl sourceControl;
private FileChangeListener fileChangeListener;
private ChangeListener parserListener;
/**
* Initialized a new SourceEnvironment.
* @param sourceControl handle to control a Source object
*/
protected SourceEnvironment(@NonNull final SourceControl sourceControl) {
Parameters.notNull("sourceControl", sourceControl); //NOI18N
this.sourceControl = sourceControl;
}
/**
* Reads the Document based on the Source's properties
*
* @param f the FIleObject
* @param forceOpen true, if the document should be opened even though
* it does not exist yet
* @return the document, or {@code null} if the document was not opened.
*/
@CheckForNull
public abstract Document readDocument(@NonNull FileObject f, boolean forceOpen) throws IOException;
/**
* Attaches a Scheduler to the source in this environment. The implementation
* may need to listen on certain environment objects in order to schedule
* tasks at appropriate time.
*
*
* @param s the scheduler to attach or detach
* @param attach if false, the scheduler is just detached from the source.
*/
public abstract void attachScheduler(@NonNull SchedulerControl s, boolean attach);
/**
* Notifies that the source was actually used, and the parser wants to be
* notified on changes through {@link SourceControl}.
* Until this method is called, the environment implementation need not to
* listen or forward source affecting events to the parser API.
*/
public abstract void activate();
/**
* Returns true, if reparse should NOT occur immediately when source is invalidated.
* This is used when e.g. completion is active; postpones reparsing. The SourceEnvironment
* is responsible for calling {@link SourceControl#revalidate()} when the condition changes.
*
* @return true, if a reparse should not be scheduled.
*/
public abstract boolean isReparseBlocked();
/**
* Returns the {@link SourceControl}.
* @return the {@link SourceControl}
*/
protected final SourceControl getSourceControl() {
return this.sourceControl;
}
/**
* Starts listening on file changes.
* Should be called from {@link SourceEnvironment#activate}
*/
protected final void listenOnFileChanges() {
final FileObject fo = sourceControl.getSource().getFileObject();
if (fo != null) {
fileChangeListener = new FileChangeSupport(sourceControl);
fo.addFileChangeListener(FileUtil.weakFileChangeListener(this.fileChangeListener,fo));
}
}
/**
* Starts listening on {@link Source} parsers.
* Should be called from {@link SourceEnvironment#activate}
*/
protected final void listenOnParser() {
final ParserEventForward peFwd = SourceAccessor.getINSTANCE().getParserEventForward(
sourceControl.getSource());
parserListener = new ParserChangeSupport(sourceControl);
peFwd.addChangeListener(parserListener);
}
/**
* Returns a {@link SourceEnvironment} for given {@link Source}.
* @param source the {@link Source} to return {@link SourceEnvironment} for
* @return the {@link SourceEnvironment}
*/
@NonNull
protected static SourceEnvironment forSource(@NonNull final Source source) {
return SourceAccessor.getINSTANCE().getEnv(source);
}
public static int getReparseDelay(final boolean fast) {
return fast ? immediateReparseDelay : reparseDelay;
}
/**
* Sets the reparse delays.
* Used by unit tests.
*/
static void setReparseDelays(
final int standardReparseDelay,
final int fastReparseDelay) throws IllegalArgumentException {
if (standardReparseDelay < fastReparseDelay) {
throw new IllegalArgumentException(
String.format(
"Fast reparse delay %d > standatd reparse delay %d", //NOI18N
fastReparseDelay,
standardReparseDelay));
}
immediateReparseDelay = fastReparseDelay;
reparseDelay = standardReparseDelay;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy