From 6c38b5d3c5561e17f0c214aef36c17f3535040f3 Mon Sep 17 00:00:00 2001 From: khartlage Date: Sun, 30 May 2004 10:27:29 +0000 Subject: [PATCH] 3m9 compatible; removed xerces dependency first version for code folding (only methods;must enable preferences) --- net.sourceforge.phpeclipse/.project | 1 + net.sourceforge.phpeclipse/plugin.properties | 9 +- net.sourceforge.phpeclipse/plugin.xml | 85 ++- .../phpdt/core/dom/CompilationUnit.java | 854 ++++++++++++ .../sourceforge/phpdt/core/jdom/DOMFactory.java | 2 +- .../phpdt/internal/compiler/parser/UnitParser.java | 5 +- .../phpdt/internal/compiler/util/Util.java | 22 +- .../sourceforge/phpdt/internal/core/util/Util.java | 1365 ++++++++++++++++++++ .../internal/corext/template/TemplateSet.java | 38 +- .../phpdt/internal/ui/actions/ActionMessages.java | 10 +- .../internal/ui/actions/AddBlockCommentAction.java | 4 +- .../internal/ui/actions/FoldingActionGroup.java | 141 ++ .../ui/actions/FoldingExpandAllRulerAction.java | 39 + .../ui/actions/FoldingToggleRulerAction.java | 76 ++ .../ui/actions/RemoveBlockCommentAction.java | 4 +- .../phpdt/internal/ui/text/ITypingRunListener.java | 36 + .../ui/text/JavaPresentationReconciler.java | 48 + .../phpdt/internal/ui/text/PreferencesAdapter.java | 309 +++++ .../internal/ui/text/SmartBackspaceManager.java | 280 ++++ .../phpdt/internal/ui/text/TypingRun.java | 103 ++ .../phpdt/internal/ui/text/TypingRunDetector.java | 471 +++++++ .../ui/text/java/IJavaReconcilingListener.java | 38 + .../ui/text/java/JavaStringAutoIndentStrategy.java | 2 +- .../ui/text/java/hover/BestMatchHover.java | 9 +- .../java/hover/SourceViewerInformationControl.java | 398 ++++++ .../ui/text/link/LinkedPositionManager.java | 2 +- .../ui/viewsupport/ProblemMarkerManager.java | 4 +- .../sourceforge/phpdt/ui/text/JavaTextTools.java | 54 +- .../phpeclipse/phpeditor/html/HTMLFormatter.java | 4 +- .../phpeditor/html/HTMLFormattingStrategy.java | 4 +- 30 files changed, 4358 insertions(+), 59 deletions(-) create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java diff --git a/net.sourceforge.phpeclipse/.project b/net.sourceforge.phpeclipse/.project index 6aa6c77..f592e9e 100644 --- a/net.sourceforge.phpeclipse/.project +++ b/net.sourceforge.phpeclipse/.project @@ -28,3 +28,4 @@ org.eclipse.pde.PluginNature + diff --git a/net.sourceforge.phpeclipse/plugin.properties b/net.sourceforge.phpeclipse/plugin.properties index 3673587..e03c089 100644 --- a/net.sourceforge.phpeclipse/plugin.properties +++ b/net.sourceforge.phpeclipse/plugin.properties @@ -49,6 +49,9 @@ htmFileExtension=htm xmlFileExtension=xml tplFileExtension=tpl +javaDocumentFactory=PHP Document Factory +javaDocumentSetupParticipant=PHP Document Setup Participant + sourceHover= Source sourceHoverDescription= Shows the source of the selected element. javadocHover= PHPdoc @@ -369,6 +372,10 @@ Program.externalTools = PHP Program OccurrenceAnnotation.label= PHP Marker Occurrences - phpEditorFontDefiniton.label= Java Editor Text Font phpEditorFontDefintion.description= The Java editor text font is used by Java editors. + +#--- folding +foldingStructureProvidersExtensionPoint= Folding Structure Providers +defaultFoldingStructureProviderName= Default PHP Folding +Folding.label= F&olding \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/plugin.xml b/net.sourceforge.phpeclipse/plugin.xml index 1eb9e64..a872078 100644 --- a/net.sourceforge.phpeclipse/plugin.xml +++ b/net.sourceforge.phpeclipse/plugin.xml @@ -31,7 +31,6 @@ - @@ -89,8 +88,8 @@ - - + + + + + + + + + + + + + + + + @@ -1100,6 +1143,33 @@ + + + + + + + + + + + + + + + + + diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java new file mode 100644 index 0000000..9053d2b --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java @@ -0,0 +1,854 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package net.sourceforge.phpdt.core.dom; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import net.sourceforge.phpdt.core.compiler.IProblem; +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import org.eclipse.jface.text.IDocument; +import org.eclipse.text.edits.TextEdit; + +/** + * Java compilation unit AST node type. This is the type of the root of an AST. + *

+ * The source range for this type of node is ordinarily the entire source file, + * including leading and trailing whitespace and comments. + *

+ * For JLS2: + *
+ * CompilationUnit:
+ *    [ PackageDeclaration ]
+ *        { ImportDeclaration }
+ *        { TypeDeclaration | ; }
+ * 
+ * For JLS3, the kinds of type declarations + * grew to include enum and annotation type declarations: + *
+ * CompilationUnit:
+ *    [ PackageDeclaration ]
+ *        { ImportDeclaration }
+ *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | ; }
+ * 
+ * + * @since 2.0 + */ +public class CompilationUnit { + +// /** +// * The "package" structural property of this node type. +// * +// * @since 3.0 +// */ +// public static final ChildPropertyDescriptor PACKAGE_PROPERTY = +// new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ +// +// /** +// * The "imports" structural property of this node type. +// * +// * @since 3.0 +// */ +// public static final ChildListPropertyDescriptor IMPORTS_PROPERTY = +// new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$ +// +// /** +// * The "types" structural property of this node type. +// * +// * @since 3.0 +// */ +// public static final ChildListPropertyDescriptor TYPES_PROPERTY = +// new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$ +// +// /** +// * A list of property descriptors (element type: +// * {@link StructuralPropertyDescriptor}), +// * or null if uninitialized. +// * @since 3.0 +// */ +// private static final List PROPERTY_DESCRIPTORS; +// +// static { +// createPropertyList(CompilationUnit.class); +// addProperty(PACKAGE_PROPERTY); +// addProperty(IMPORTS_PROPERTY); +// addProperty(TYPES_PROPERTY); +// PROPERTY_DESCRIPTORS = reapPropertyList(); +// } +// +// /** +// * Returns a list of structural property descriptors for this node type. +// * Clients must not modify the result. +// * +// * @param apiLevel the API level; one of the +// * AST.JLS* constants +// +// * @return a list of property descriptors (element type: +// * {@link StructuralPropertyDescriptor}) +// * @since 3.0 +// */ +// public static List propertyDescriptors(int apiLevel) { +// return PROPERTY_DESCRIPTORS; +// } +// +// /** +// * The comment table, or null if none; initially +// * null. This array is the storage underlying +// * the optionalCommentList ArrayList. +// * @since 3.0 +// */ +// Comment[] optionalCommentTable = null; +// +// /** +// * The comment list (element type: Comment, +// * or null if none; initially null. +// * @since 3.0 +// */ +// private List optionalCommentList = null; +// +// /** +// * The package declaration, or null if none; initially +// * null. +// */ +// private PackageDeclaration optionalPackageDeclaration = null; +// +// /** +// * The list of import declarations in textual order order; +// * initially none (elementType: ImportDeclaration). +// */ +// private ASTNode.NodeList imports = +// new ASTNode.NodeList(IMPORTS_PROPERTY); +// +// /** +// * The list of type declarations in textual order order; +// * initially none (elementType: AbstractTypeDeclaration) +// */ +// private ASTNode.NodeList types = +// new ASTNode.NodeList(TYPES_PROPERTY); +// +// /** +// * Line end table. If lineEndTable[i] == p then the +// * line number i+1 ends at character position +// * p. Except for the last line, the positions are that +// * of the last character of the line delimiter. +// * For example, the source string A\nB\nC has +// * line end table {1, 3} (if \n is one character). +// */ +// private int[] lineEndTable = new int[0]; +// +// /** +// * Canonical empty list of messages. +// */ +// private static final Message[] EMPTY_MESSAGES = new Message[0]; +// +// /** +// * Canonical empty list of problems. +// */ +// private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0]; +// +// /** +// * Messages reported by the compiler during parsing or name resolution. +// */ +// private Message[] messages; +// +// /** +// * Problems reported by the compiler during parsing or name resolution. +// */ +// private IProblem[] problems = EMPTY_PROBLEMS; +// +// /** +// * The comment mapper, or null in none; +// * initially null. +// * @since 3.0 +// */ +// private DefaultCommentMapper commentMapper = null; +// +// /** +// * Sets the line end table for this compilation unit. +// * If lineEndTable[i] == p then line number i+1 +// * ends at character position p. Except for the last line, the +// * positions are that of (the last character of) the line delimiter. +// * For example, the source string A\nB\nC has +// * line end table {1, 3, 4}. +// * +// * @param lineEndtable the line end table +// */ +// void setLineEndTable(int[] lineEndTable) { +// if (lineEndTable == null) { +// throw new NullPointerException(); +// } +// // alternate root is *not* considered a structural property +// // but we protect them nevertheless +// checkModifiable(); +// this.lineEndTable = lineEndTable; +// } +// +// /** +// * Creates a new AST node for a compilation owned by the given AST. +// * The compilation unit initially has no package declaration, no +// * import declarations, and no type declarations. +// *

+// * N.B. This constructor is package-private; all subclasses must be +// * declared in the same package; clients are unable to declare +// * additional subclasses. +// *

+// * +// * @param ast the AST that is to own this node +// */ +// CompilationUnit(AST ast) { +// super(ast); +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// * @since 3.0 +// */ +// final List internalStructuralPropertiesForType(int apiLevel) { +// return propertyDescriptors(apiLevel); +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { +// if (property == PACKAGE_PROPERTY) { +// if (get) { +// return getPackage(); +// } else { +// setPackage((PackageDeclaration) child); +// return null; +// } +// } +// // allow default implementation to flag the error +// return super.internalGetSetChildProperty(property, get, child); +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// final List internalGetChildListProperty(ChildListPropertyDescriptor property) { +// if (property == IMPORTS_PROPERTY) { +// return imports(); +// } +// if (property == TYPES_PROPERTY) { +// return types(); +// } +// // allow default implementation to flag the error +// return super.internalGetChildListProperty(property); +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// final int getNodeType0() { +// return COMPILATION_UNIT; +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// ASTNode clone0(AST target) { +// CompilationUnit result = new CompilationUnit(target); +// // n.b do not copy line number table or messages +// result.setSourceRange(this.getStartPosition(), this.getLength()); +// result.setPackage( +// (PackageDeclaration) ASTNode.copySubtree(target, getPackage())); +// result.imports().addAll(ASTNode.copySubtrees(target, imports())); +// result.types().addAll(ASTNode.copySubtrees(target, types())); +// return result; +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// final boolean subtreeMatch0(ASTMatcher matcher, Object other) { +// // dispatch to correct overloaded match method +// return matcher.match(this, other); +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// void accept0(ASTVisitor visitor) { +// boolean visitChildren = visitor.visit(this); +// if (visitChildren) { +// // visit children in normal left to right reading order +// acceptChild(visitor, getPackage()); +// acceptChildren(visitor, this.imports); +// acceptChildren(visitor, this.types); +// } +// visitor.endVisit(this); +// } +// +// /** +// * Returns the node for the package declaration of this compilation +// * unit, or null if this compilation unit is in the +// * default package. +// * +// * @return the package declaration node, or null if none +// */ +// public PackageDeclaration getPackage() { +// return this.optionalPackageDeclaration; +// } +// +// /** +// * Sets or clears the package declaration of this compilation unit +// * node to the given package declaration node. +// * +// * @param pkgDecl the new package declaration node, or +// * null if this compilation unit does not have a package +// * declaration (that is in the default package) +// * @exception IllegalArgumentException if: +// *
    +// *
  • the node belongs to a different AST
  • +// *
  • the node already has a parent
  • +// *
+// */ +// public void setPackage(PackageDeclaration pkgDecl) { +// ASTNode oldChild = this.optionalPackageDeclaration; +// preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY); +// this.optionalPackageDeclaration = pkgDecl; +// postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY); +// } +// +// /** +// * Returns the live list of nodes for the import declarations of this +// * compilation unit, in order of appearance. +// * +// * @return the live list of import declaration nodes +// * (elementType: ImportDeclaration) +// */ +// public List imports() { +// return this.imports; +// } +// +// /** +// * Returns the live list of nodes for the top-level type declarations of this +// * compilation unit, in order of appearance. +// *

+// * Note that in JLS3, the types may include both enum declarations +// * and annotation type declarations introduced in J2SE 1.5. +// * For JLS2, the elements are always TypeDeclaration. +// *

+// * +// * @return the live list of top-level type declaration +// * nodes (elementType: AbstractTypeDeclaration) +// */ +// public List types() { +// return this.types; +// } +// +// /** +// * Finds the corresponding AST node in the given compilation unit from +// * which the given binding originated. Returns null if the +// * binding does not correspond to any node in this compilation unit. +// * This method always returns null if bindings were not requested +// * when this AST was built. +// *

+// * The following table indicates the expected node type for the various +// * different kinds of bindings: +// *

    +// *
  • +// *
  • package - a PackageDeclaration
  • +// *
  • class or interface - a TypeDeclaration or a +// * AnonymousClassDeclaration (for anonymous classes)
  • +// *
  • primitive type - none
  • +// *
  • array type - none
  • +// *
  • field - a VariableDeclarationFragment in a +// * FieldDeclaration
  • +// *
  • local variable - a SingleVariableDeclaration, or +// * a VariableDeclarationFragment in a +// * VariableDeclarationStatement or +// * VariableDeclarationExpression
  • +// *
  • method - a MethodDeclaration
  • +// *
  • constructor - a MethodDeclaration
  • +// *
  • annotation type - an AnnotationTypeDeclaration
  • +// *
  • annotation type member - an AnnotationTypeMemberDeclaration
  • +// *
  • enum type - an EnumDeclaration
  • +// *
  • enum constant - an EnumConstantDeclaration
  • +// *
+// *

+// *

+// * Each call to {@link ASTParser#createAST(IProgressMonitor)} with a request for bindings +// * gives rise to separate universe of binding objects. This method always returns +// * null when the binding object comes from a different AST. +// * Use findDeclaringNode(binding.getKey()) when the binding comes +// * from a different AST. +// *

+// * +// * @param binding the binding +// * @return the corresponding node where the given binding is declared, +// * or null if the binding does not correspond to a node in this +// * compilation unit or if bindings were not requested when this AST was built +// * @see #findDeclaringNode(String) +// */ +// public ASTNode findDeclaringNode(IBinding binding) { +// return this.ast.getBindingResolver().findDeclaringNode(binding); +// } +// +// /** +// * Finds the corresponding AST node in the given compilation unit from +// * which the binding with the given key originated. Returns +// * null if the corresponding node cannot be determined. +// * This method always returns null if bindings were not requested +// * when this AST was built. +// *

+// * The following table indicates the expected node type for the various +// * different kinds of binding keys: +// *

    +// *
  • +// *
  • package - a PackageDeclaration
  • +// *
  • class or interface - a TypeDeclaration or a +// * AnonymousClassDeclaration (for anonymous classes)
  • +// *
  • primitive type - none
  • +// *
  • array type - none
  • +// *
  • field - a VariableDeclarationFragment in a +// * FieldDeclaration
  • +// *
  • local variable - a SingleVariableDeclaration, or +// * a VariableDeclarationFragment in a +// * VariableDeclarationStatement or +// * VariableDeclarationExpression
  • +// *
  • method - a MethodDeclaration
  • +// *
  • constructor - a MethodDeclaration
  • +// *
  • annotation type - an AnnotationTypeDeclaration
  • +// *
  • annotation type member - an AnnotationTypeMemberDeclaration
  • +// *
  • enum type - an EnumDeclaration
  • +// *
  • enum constant - an EnumConstantDeclaration
  • +// *
+// *

+// *

+// * Note that as explained in {@link IBinding#getKey() IBinding.getkey} +// * there may be no keys for finding the declaring node for local variables, +// * local or anonymous classes, etc. +// *

+// * +// * @param key the binding key, or null +// * @return the corresponding node where a binding with the given +// * key is declared, or null if the key is null +// * or if the key does not correspond to a node in this compilation unit +// * or if bindings were not requested when this AST was built +// * @see IBinding#getKey() +// * @since 2.1 +// */ +// public ASTNode findDeclaringNode(String key) { +// return this.ast.getBindingResolver().findDeclaringNode(key); +// } +// +// /** +// * Returns the internal comment mapper. +// * +// * @return the comment mapper, or null if none. +// * @since 3.0 +// */ +// DefaultCommentMapper getCommentMapper() { +// return this.commentMapper; +// } +// +// /** +// * Initializes the internal comment mapper with the given +// * scanner. +// * +// * @param scanner the scanner +// * @since 3.0 +// */ +// void initCommentMapper(Scanner scanner) { +// this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable); +// this.commentMapper.initialize(this, scanner); +// } +// +// /** +// * Returns the extended start position of the given node. Unlike +// * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()()}, +// * the extended source range may include comments and whitespace +// * immediately before or after the normal source range for the node. +// * +// * @param node the node +// * @return the 0-based character index, or -1 +// * if no source position information is recorded for this node +// * @see #getExtendedLength(ASTNode) +// * @since 3.0 +// */ +// public int getExtendedStartPosition(ASTNode node) { +// if (this.commentMapper == null) { +// return -1; +// } else { +// return this.commentMapper.getExtendedStartPosition(node); +// } +// } +// +// /** +// * Returns the extended source length of the given node. Unlike +// * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()()}, +// * the extended source range may include comments and whitespace +// * immediately before or after the normal source range for the node. +// * +// * @param node the node +// * @return a (possibly 0) length, or 0 +// * if no source position information is recorded for this node +// * @see #getExtendedStartPosition(ASTNode) +// * @since 3.0 +// */ +// public int getExtendedLength(ASTNode node) { +// if (this.commentMapper == null) { +// return 0; +// } else { +// return this.commentMapper.getExtendedLength(node); +// } +// } +// +// /** +// * Returns the line number corresponding to the given source character +// * position in the original source string. The initial line of the +// * compilation unit is numbered 1, and each line extends through the +// * last character of the end-of-line delimiter. The very last line extends +// * through the end of the source string and has no line delimiter. +// * For example, the source string class A\n{\n} has 3 lines +// * corresponding to inclusive character ranges [0,7], [8,9], and [10,10]. +// * Returns 1 for a character position that does not correspond to any +// * source line, or if no line number information is available for this +// * compilation unit. +// * +// * @param position a 0-based character position, possibly +// * negative or out of range +// * @return the 1-based line number, or 1 if the character +// * position does not correspond to a source line in the original +// * source file or if line number information is not known for this +// * compilation unit +// * @see ASTParser +// */ +// public int lineNumber(int position) { +// int length = lineEndTable.length; +// if (length == 0) { +// // no line number info +// return 1; +// } +// int low = 0; +// if (position <= lineEndTable[low]) { +// // position illegal or before the first line delimiter +// return 1; +// } +// // assert position > lineEndTable[low+1] && low == 0 +// int hi = length - 1; +// if (position > lineEndTable[hi]) { +// // position beyond the last line separator +// if (position >= getStartPosition() + getLength()) { +// // this is beyond the end of the source length +// return 1; +// } else { +// return length + 1; +// } +// } +// // assert lineEndTable[low] < position <= lineEndTable[hi] +// // && low == 0 && hi == length - 1 && low < hi +// +// // binary search line end table +// while (true) { +// // invariant lineEndTable[low] < position <= lineEndTable[hi] +// // && 0 <= low < hi <= length - 1 +// // reducing measure hi - low +// if (low + 1 == hi) { +// // assert lineEndTable[low] < position <= lineEndTable[low+1] +// // position is on line low+1 (line number is low+2) +// return low + 2; +// } +// // assert hi - low >= 2, so average is truly in between +// int mid = (low + hi) / 2; +// // assert 0 <= low < mid < hi <= length - 1 +// if (position <= lineEndTable[mid]) { +// // assert lineEndTable[low] < position <= lineEndTable[mid] +// // && 0 <= low < mid < hi <= length - 1 +// hi = mid; +// } else { +// // position > lineEndTable[mid] +// // assert lineEndTable[mid] < position <= lineEndTable[hi] +// // && 0 <= low < mid < hi <= length - 1 +// low = mid; +// } +// // in both cases, invariant reachieved with reduced measure +// } +// } +// +// /** +// * Returns the list of messages reported by the compiler during the parsing +// * or the type checking of this compilation unit. This list might be a subset of +// * errors detected and reported by a Java compiler. +// *

+// * This list of messages is suitable for simple clients that do little +// * more than log the messages or display them to the user. Clients that +// * need further details should call getProblems to get +// * compiler problem objects. +// *

+// * +// * @return the list of messages, possibly empty +// * @see #getProblems() +// * @see ASTParser +// */ +// public Message[] getMessages() { +// if (this.messages == null) { +// int problemLength = this.problems.length; +// if (problemLength == 0) { +// this.messages = EMPTY_MESSAGES; +// } else { +// this.messages = new Message[problemLength]; +// for (int i = 0; i < problemLength; i++) { +// IProblem problem = this.problems[i]; +// int start = problem.getSourceStart(); +// int end = problem.getSourceEnd(); +// messages[i] = new Message(problem.getMessage(), start, end - start + 1); +// } +// } +// } +// return this.messages; +// } +// +// /** +// * Returns the list of detailed problem reports noted by the compiler +// * during the parsing or the type checking of this compilation unit. This +// * list might be a subset of errors detected and reported by a Java +// * compiler. +// *

+// * Simple clients that do little more than log the messages or display +// * them to the user should probably call getMessages instead. +// *

+// * +// * @return the list of detailed problem objects, possibly empty +// * @see #getMessages() +// * @see ASTParser +// * @since 2.1 +// */ +// public IProblem[] getProblems() { +// return this.problems; +// } +// +// /** +// * Sets the array of problems reported by the compiler during the parsing or +// * name resolution of this compilation unit. +// * +// * @param problems the list of problems +// */ +// void setProblems(IProblem[] problems) { +// if (problems == null) { +// throw new IllegalArgumentException(); +// } +// this.problems = problems; +// } +// +// /** +// * Returns a list of the comments encountered while parsing +// * this compilation unit. +// *

+// * Since the Java language allows comments to appear most anywhere +// * in the source text, it is problematic to locate comments in relation +// * to the structure of an AST. The one exception is doc comments +// * which, by convention, immediately precede type, field, and +// * method declarations; these comments are located in the AST +// * by {@link BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}. +// * Other comments do not show up in the AST. The table of comments +// * is provided for clients that need to find the source ranges of +// * all comments in the original source string. It includes entries +// * for comments of all kinds (line, block, and doc), arranged in order +// * of increasing source position. +// *

+// * Note on comment parenting: The {@link ASTNode#getParent() getParent()} +// * of a doc comment associated with a body declaration is the body +// * declaration node; for these comment nodes +// * {@link ASTNode#getRoot() getRoot()} will return the compilation unit +// * (assuming an unmodified AST) reflecting the fact that these nodes +// * are property located in the AST for the compilation unit. +// * However, for other comment nodes, {@link ASTNode#getParent() getParent()} +// * will return null, and {@link ASTNode#getRoot() getRoot()} +// * will return the comment node itself, indicating that these comment nodes +// * are not directly connected to the AST for the compilation unit. The +// * {@link Comment#getAlternateRoot Comment.getAlternateRoot} +// * method provides a way to navigate from a comment to its compilation +// * unit. +// *

+// *

+// * A note on visitors: The only comment nodes that will be visited when +// * visiting a compilation unit are the doc comments parented by body +// * declarations. To visit all comments in normal reading order, iterate +// * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept} +// * on each element. +// *

+// *

+// * Clients cannot modify the resulting list. +// *

+// * +// * @return an unmodifiable list of comments in increasing order of source +// * start position, or null if comment information +// * for this compilation unit is not available +// * @see ASTParser +// * @since 3.0 +// */ +// public List getCommentList() { +// return this.optionalCommentList; +// } +// +// /** +// * Sets the list of the comments encountered while parsing +// * this compilation unit. +// * +// * @param commentTable a list of comments in increasing order +// * of source start position, or null if comment +// * information for this compilation unit is not available +// * @exception IllegalArgumentException if the comment table is +// * not in increasing order of source position +// * @see #getCommentList() +// * @see ASTParser +// * @since 3.0 +// */ +// void setCommentTable(Comment[] commentTable) { +// // double check table to ensure that all comments have +// // source positions and are in strictly increasing order +// if (commentTable == null) { +// this.optionalCommentList = null; +// this.optionalCommentTable = null; +// } else { +// int nextAvailablePosition = 0; +// for (int i = 0; i < commentTable.length; i++) { +// Comment comment = commentTable[i]; +// if (comment == null) { +// throw new IllegalArgumentException(); +// } +// int start = comment.getStartPosition(); +// int length = comment.getLength(); +// if (start < 0 || length < 0 || start < nextAvailablePosition) { +// throw new IllegalArgumentException(); +// } +// nextAvailablePosition = comment.getStartPosition() + comment.getLength(); +// } +// this.optionalCommentTable = commentTable; +// List commentList = Arrays.asList(commentTable); +// // protect the list from further modification +// this.optionalCommentList = Collections.unmodifiableList(commentList); +// } +// } +// +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// void appendDebugString(StringBuffer buffer) { +// buffer.append("CompilationUnit"); //$NON-NLS-1$ +// // include the type names +// buffer.append("["); //$NON-NLS-1$ +// for (Iterator it = types().iterator(); it.hasNext(); ) { +// AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next(); +// buffer.append(d.getName().getIdentifier()); +// if (it.hasNext()) { +// buffer.append(","); //$NON-NLS-1$ +// } +// } +// buffer.append("]"); //$NON-NLS-1$ +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// int memSize() { +// int size = BASE_NODE_SIZE + 8 * 4; +// if (this.lineEndTable != null) { +// size += HEADERS + 4 * this.lineEndTable.length; +// } +// if (this.optionalCommentTable != null) { +// size += HEADERS + 4 * this.optionalCommentTable.length; +// } +// // ignore the space taken up by optionalCommentList +// return size; +// } +// +// /* (omit javadoc for this method) +// * Method declared on ASTNode. +// */ +// int treeSize() { +// int size = memSize(); +// if (this.optionalPackageDeclaration != null) { +// size += getPackage().treeSize(); +// } +// size += this.imports.listSize(); +// size += this.types.listSize(); +// // include disconnected comments +// if (this.optionalCommentList != null) { +// for (int i = 0; i < this.optionalCommentList.size(); i++) { +// Comment comment = (Comment) this.optionalCommentList.get(i); +// if (comment != null && comment.getParent() == null) { +// size += comment.treeSize(); +// } +// } +// } +// return size; +// } +// +// /** +// * Enables the recording of changes to this compilation +// * unit and its descendents. The compilation unit must have +// * been created by ASTParser and still be in +// * its original state. Once recording is on, +// * arbitrary changes to the subtree rooted at this compilation +// * unit are recorded internally. Once the modification has +// * been completed, call rewrite to get an object +// * representing the corresponding edits to the original +// * source code string. +// * +// * @exception IllegalArgumentException if this compilation unit is +// * marked as unmodifiable, or if this compilation unit has already +// * been tampered with, or recording has already been enabled +// * @since 3.0 +// */ +// public void recordModifications() { +// getAST().recordModifications(this); +// } +// +// /** +// * Converts all modifications recorded for this compilation +// * unit into an object representing the corresponding text +// * edits to the given document containing the original source +// * code for this compilation unit. +// *

+// * The compilation unit must have been created by +// * ASTParser from the source code string in the +// * given document, and recording must have been turned +// * on with a prior call to recordModifications +// * while the AST was still in its original state. +// *

+// *

+// * Calling this methods does not discard the modifications +// * on record. Subsequence modifications made to the AST +// * are added to the ones already on record. If this method +// * is called again later, the resulting text edit object will +// * accurately reflect the net cumulative affect of all those +// * changes. +// *

+// * +// * @param document original document containing source code +// * for this compilation unit +// * @param options the table of formatter options +// * (key type: String; value type: String); +// * or null to use the standard global options +// * {@link JavaCore#getOptions() JavaCore.getOptions()}. +// * @return text edit object describing the changes to the +// * document corresponding to the recorded AST modifications +// * @exception IllegalArgumentException if the document passed is +// * null or does not correspond to this AST +// * @exception IllegalStateException if recordModifications +// * was not called to enable recording +// * @see #recordModifications() +// * @since 3.0 +// */ +// public TextEdit rewrite(IDocument document, Map options) { +// return getAST().rewrite(document, options); +// } +} + diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/jdom/DOMFactory.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/jdom/DOMFactory.java index 0e61752..fdc8bbd 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/jdom/DOMFactory.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/jdom/DOMFactory.java @@ -10,9 +10,9 @@ *******************************************************************************/ package net.sourceforge.phpdt.core.jdom; -import net.sourceforge.phpdt.internal.core.Util; import net.sourceforge.phpdt.internal.core.jdom.DOMBuilder; import net.sourceforge.phpdt.internal.core.jdom.SimpleDOMBuilder; +import net.sourceforge.phpdt.internal.core.util.Util; /** diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/UnitParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/UnitParser.java index 3a40512..5ee16b9 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/UnitParser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/UnitParser.java @@ -19,8 +19,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; /** - * @author jsurfer - * + * * */ public class UnitParser extends Parser { @@ -202,7 +201,7 @@ public class UnitParser extends Parser { new Integer(problem.getSourceStart()), new Integer(problem.getSourceEnd() + 1), new Integer(problem.getSourceLineNumber()), - net.sourceforge.phpdt.internal.core.Util.getProblemArgumentsForMarker(problem.getArguments())}); + net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())}); } } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/util/Util.java index 9ece7dc..66208c0 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/util/Util.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/util/Util.java @@ -24,6 +24,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; public class Util { @@ -373,15 +374,16 @@ public class Util { * implementation is not creating extra strings. */ public final static boolean isJavaFileName(String name) { - int nameLength = name == null ? 0 : name.length(); - int suffixLength = SUFFIX_JAVA.length; - if (nameLength < suffixLength) return false; - - for (int i = 0; i < suffixLength; i++) { - char c = name.charAt(nameLength - i - 1); - int suffixIndex = suffixLength - i - 1; - if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false; - } - return true; + return PHPFileUtil.isPHPFileName(name); +// int nameLength = name == null ? 0 : name.length(); +// int suffixLength = SUFFIX_JAVA.length; +// if (nameLength < suffixLength) return false; +// +// for (int i = 0; i < suffixLength; i++) { +// char c = name.charAt(nameLength - i - 1); +// int suffixIndex = suffixLength - i - 1; +// if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false; +// } +// return true; } } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java new file mode 100644 index 0000000..ea8125b --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java @@ -0,0 +1,1365 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.core.util; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.StringTokenizer; + +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; +import net.sourceforge.phpdt.core.IPackageFragment; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.core.JavaCore; +import net.sourceforge.phpdt.core.Signature; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.core.PackageFragmentRoot; +import net.sourceforge.phpdt.internal.corext.Assert; +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Provides convenient utility methods to other types in this package. + */ +public class Util { + + private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ + private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ + private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$ + private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$ + + public interface Comparable { + /** + * Returns 0 if this and c are equal, >0 if this is greater than c, + * or <0 if this is less than c. + */ + int compareTo(Comparable c); + } + + public interface Comparer { + /** + * Returns 0 if a and b are equal, >0 if a is greater than b, + * or <0 if a is less than b. + */ + int compare(Object a, Object b); + } + + public interface Displayable { + String displayString(Object o); + } + + public static final String[] fgEmptyStringArray = new String[0]; + + /** + * Are we running JDK 1.1? + */ + private static boolean JDK1_1 = false; + + /* Bundle containing messages */ + protected static ResourceBundle bundle; + private final static String bundleName = "net.sourceforge.phpdt.internal.core.messages"; //$NON-NLS-1$ + +// public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$ + + static { + String ver = System.getProperty("java.version"); //$NON-NLS-1$ + JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$ + relocalize(); + } + + /** + * Lookup the message with the given ID in this catalog + */ + public static String bind(String id) { + return bind(id, (String[])null); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string values. + */ + public static String bind(String id, String[] bindings) { + if (id == null) + return "No message available"; //$NON-NLS-1$ + String message = null; + try { + message = bundle.getString(id); + } catch (MissingResourceException e) { + // If we got an exception looking for the message, fail gracefully by just returning + // the id we were looking for. In most cases this is semi-informative so is not too bad. + return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$ + } + // for compatibility with MessageFormat which eliminates double quotes in original message + char[] messageWithNoDoubleQuotes = + CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); + message = new String(messageWithNoDoubleQuotes); + + if (bindings == null) + return message; + + int length = message.length(); + int start = -1; + int end = length; + StringBuffer output = new StringBuffer(80); + while (true) { + if ((end = message.indexOf('{', start)) > -1) { + output.append(message.substring(start + 1, end)); + if ((start = message.indexOf('}', end)) > -1) { + int index = -1; + try { + index = Integer.parseInt(message.substring(end + 1, start)); + output.append(bindings[index]); + } catch (NumberFormatException nfe) { + output.append(message.substring(end + 1, start + 1)); + } catch (ArrayIndexOutOfBoundsException e) { + output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ + } + } else { + output.append(message.substring(end, length)); + break; + } + } else { + output.append(message.substring(start + 1, length)); + break; + } + } + return output.toString(); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + public static String bind(String id, String binding) { + return bind(id, new String[] {binding}); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given strings. + */ + public static String bind(String id, String binding1, String binding2) { + return bind(id, new String[] {binding1, binding2}); + } + + /** + * Checks the type signature in String sig, + * starting at start and ending before end (end is not included). + * Returns the index of the character immediately after the signature if valid, + * or -1 if not valid. + */ + private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) { + if (start >= end) return -1; + int i = start; + char c = sig.charAt(i++); + int nestingDepth = 0; + while (c == '[') { + ++nestingDepth; + if (i >= end) return -1; + c = sig.charAt(i++); + } + switch (c) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + break; + case 'V': + if (!allowVoid) return -1; + // array of void is not allowed + if (nestingDepth != 0) return -1; + break; + case 'L': + int semicolon = sig.indexOf(';', i); + // Must have at least one character between L and ; + if (semicolon <= i || semicolon >= end) return -1; + i = semicolon + 1; + break; + default: + return -1; + } + return i; + } + + /** + * Combines two hash codes to make a new one. + */ + public static int combineHashCodes(int hashCode1, int hashCode2) { + return hashCode1 * 17 + hashCode2; + } + + /** + * Compares two byte arrays. + * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null. + * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null. + * Returns 0 if they are equal or both null. + */ + public static int compare(byte[] a, byte[] b) { + if (a == b) + return 0; + if (a == null) + return -1; + if (b == null) + return 1; + int len = Math.min(a.length, b.length); + for (int i = 0; i < len; ++i) { + int diff = a[i] - b[i]; + if (diff != 0) + return diff; + } + if (a.length > len) + return 1; + if (b.length > len) + return -1; + return 0; + } + + /** + * Compares two char arrays lexicographically. + * The comparison is based on the Unicode value of each character in + * the char arrays. + * @return the value 0 if a is equal to + * b; a value less than 0 if a + * is lexicographically less than b; and a + * value greater than 0 if a is + * lexicographically greater than b. + */ + public static int compare(char[] v1, char[] v2) { + int len1 = v1.length; + int len2 = v2.length; + int n = Math.min(len1, len2); + int i = 0; + while (n-- != 0) { + if (v1[i] != v2[i]) { + return v1[i] - v2[i]; + } + ++i; + } + return len1 - len2; + } + + /** + * Concatenate two strings with a char in between. + * @see #concat(String, String) + */ + public static String concat(String s1, char c, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + 1 + l2]; + s1.getChars(0, l1, buf, 0); + buf[l1] = c; + s2.getChars(0, l2, buf, l1 + 1); + return new String(buf); + } + + /** + * Concatenate two strings. + * Much faster than using +, which: + * - creates a StringBuffer, + * - which is synchronized, + * - of default size, so the resulting char array is + * often larger than needed. + * This implementation creates an extra char array, since the + * String constructor copies its argument, but there's no way around this. + */ + public static String concat(String s1, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + l2]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + return new String(buf); + } + + /** + * Concatenate three strings. + * @see #concat(String, String) + */ + public static String concat(String s1, String s2, String s3) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + if (s3 == null) s3 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + int l3 = s3.length(); + char[] buf = new char[l1 + l2 + l3]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + s3.getChars(0, l3, buf, l1 + l2); + return new String(buf); + } + + /** + * Converts a type signature from the IBinaryType representation to the DC representation. + */ + public static String convertTypeSignature(char[] sig) { + return new String(sig).replace('/', '.'); + } + + /** + * Returns true iff str.toLowerCase().endsWith(end.toLowerCase()) + * implementation is not creating extra strings. + */ + public final static boolean endsWithIgnoreCase(String str, String end) { + + int strLength = str == null ? 0 : str.length(); + int endLength = end == null ? 0 : end.length(); + + // return false if the string is smaller than the end. + if(endLength > strLength) + return false; + + // return false if any character of the end are + // not the same in lower case. + for(int i = 1 ; i <= endLength; i++){ + if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i))) + return false; + } + + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * all elements are equal. + */ + public static boolean equalArraysOrNull(int[] a, int[] b) { + if (a == b) + return true; + if (a == null || b == null) + return false; + int len = a.length; + if (len != b.length) + return false; + for (int i = 0; i < len; ++i) { + if (a[i] != b[i]) + return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * all elements compare true with equals. + */ + public static boolean equalArraysOrNull(Object[] a, Object[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + + int len = a.length; + if (len != b.length) return false; + for (int i = 0; i < len; ++i) { + if (a[i] == null) { + if (b[i] != null) return false; + } else { + if (!a[i].equals(b[i])) return false; + } + } + return true; + } + + /** + * Compares two String arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two objects using equals(). + * Either or both array may be null. + * Returns true if both are null. + * Returns false if only one is null. + * Otherwise, return the result of comparing with equals(). + */ + public static boolean equalOrNull(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.equals(b); + } + + /** + * Given a qualified name, extract the last component. + * If the input is not qualified, the same string is answered. + */ + public static String extractLastName(String qualifiedName) { + int i = qualifiedName.lastIndexOf('.'); + if (i == -1) return qualifiedName; + return qualifiedName.substring(i+1); + } + + /** + * Extracts the parameter types from a method signature. + */ + public static String[] extractParameterTypes(char[] sig) { + int count = getParameterCount(sig); + String[] result = new String[count]; + if (count == 0) + return result; + int i = CharOperation.indexOf('(', sig) + 1; + count = 0; + int len = sig.length; + int start = i; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } else { + ++i; + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } + } + return result; + } + + /** + * Extracts the return type from a method signature. + */ + public static String extractReturnType(String sig) { + int i = sig.lastIndexOf(')'); + Assert.isTrue(i != -1); + return sig.substring(i+1); + } + + /** + * Finds the first line separator used by the given text. + * + * @return "\n" or "\r" or "\r\n", + * or null if none found + */ + public static String findLineSeparator(char[] text) { + // find the first line separator + int length = text.length; + if (length > 0) { + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': return "\n"; //$NON-NLS-1$ + case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + // not found + return null; + } + + /** + * Returns the line separator used by the given buffer. + * Uses the given text if none found. + * + * @return "\n" or "\r" or "\r\n" + */ + private static String getLineSeparator(char[] text, char[] buffer) { + // search in this buffer's contents first + String lineSeparator = findLineSeparator(buffer); + if (lineSeparator == null) { + // search in the given text + lineSeparator = findLineSeparator(text); + if (lineSeparator == null) { + // default to system line separator + return System.getProperty("line.separator"); + } + } + return lineSeparator; + } + + /** + * Returns the number of parameter types in a method signature. + */ + public static int getParameterCount(char[] sig) { + int i = CharOperation.indexOf('(', sig) + 1; + Assert.isTrue(i != 0); + int count = 0; + int len = sig.length; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + ++count; + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + } else { + ++count; + ++i; + } + } + return count; + } + + /** + * Returns the given file's contents as a byte array. + */ + public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException { + InputStream stream= null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new JavaModelException(e); + } + try { + return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1); + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Returns the given file's contents as a character array. + */ + public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException { + String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true); + return getResourceContentsAsCharArray(file, encoding); + } + + public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException { + InputStream stream= null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); + } + try { + return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding); + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Returns a trimmed version the simples names returned by Signature. + */ + public static String[] getTrimmedSimpleNames(String name) { + String[] result = Signature.getSimpleNames(name); + if (result == null) return null; + for (int i = 0, length = result.length; i < length; i++) { + result[i] = result[i].trim(); + } + return result; + } + + /** + * Returns true iff str.toLowerCase().endsWith(".class") + * implementation is not creating extra strings. + */ +// public final static boolean isClassFileName(String name) { +// int nameLength = name == null ? 0 : name.length(); +// int suffixLength = SUFFIX_CLASS.length; +// if (nameLength < suffixLength) return false; +// +// for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false; +// } +// return true; +// } + + /* + * Returns whether the given java element is exluded from its root's classpath. + */ + public static final boolean isExcluded(IJavaElement element) { + int elementType = element.getElementType(); + PackageFragmentRoot root = null; + IResource resource = null; + switch (elementType) { +// case IJavaElement.PACKAGE_FRAGMENT: +// PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); +// IResource resource = element.getResource(); +// return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()); + case IJavaElement.COMPILATION_UNIT: + root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + resource = element.getResource(); +// if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars())) +// return true; + return isExcluded(element.getParent()); + default: + IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT); + return cu != null && isExcluded(cu); + } + } + /* + * Returns whether the given resource path matches one of the exclusion + * patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) { + if (exclusionPatterns == null) return false; + char[] path = resourcePath.toString().toCharArray(); + for (int i = 0, length = exclusionPatterns.length; i < length; i++) + if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) + return true; + return false; + } + + /* + * Returns whether the given resource matches one of the exclusion patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) { + IPath path = resource.getFullPath(); + // ensure that folders are only excluded if all of their children are excluded + if (resource.getType() == IResource.FOLDER) + path = path.append("*"); //$NON-NLS-1$ + return isExcluded(path, exclusionPatterns); + } + + /** + * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip") + * implementation is not creating extra strings. + */ +// public final static boolean isArchiveFileName(String name) { +// int nameLength = name == null ? 0 : name.length(); +// int suffixLength = SUFFIX_JAR.length; +// if (nameLength < suffixLength) return false; +// +// int i, offset; +// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break; +// } +// if (i == suffixLength) return true; +// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false; +// } +// return true; +// } + + /** + * Validate the given compilation unit name. + * A compilation unit name must obey the following rules: + *
    + *
  • it must not be null + *
  • it must include the ".java" suffix + *
  • its prefix must be a valid identifier + *
+ *

+ * @param name the name of a compilation unit + * @return a status object with code IStatus.OK if + * the given name is valid as a compilation unit name, otherwise a status + * object indicating what is wrong with the name + */ + public static boolean isValidCompilationUnitName(String name) { + return PHPFileUtil.isPHPFileName(name); +// return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR; + } + + /** + * Validate the given .class file name. + * A .class file name must obey the following rules: + *
    + *
  • it must not be null + *
  • it must include the ".class" suffix + *
  • its prefix must be a valid identifier + *
+ *

+ * @param name the name of a .class file + * @return a status object with code IStatus.OK if + * the given name is valid as a .class file name, otherwise a status + * object indicating what is wrong with the name + */ +// public static boolean isValidClassFileName(String name) { +// return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR; +// } + + /** + * Returns true if the given method signature is valid, + * false if it is not. + */ + public static boolean isValidMethodSignature(String sig) { + int len = sig.length(); + if (len == 0) return false; + int i = 0; + char c = sig.charAt(i++); + if (c != '(') return false; + if (i >= len) return false; + while (sig.charAt(i) != ')') { + // Void is not allowed as a parameter type. + i = checkTypeSignature(sig, i, len, false); + if (i == -1) return false; + if (i >= len) return false; + } + ++i; + i = checkTypeSignature(sig, i, len, true); + return i == len; + } + + /** + * Returns true if the given type signature is valid, + * false if it is not. + */ + public static boolean isValidTypeSignature(String sig, boolean allowVoid) { + int len = sig.length(); + return checkTypeSignature(sig, 0, len, allowVoid) == len; + } + + /** + * Returns true if the given folder name is valid for a package, + * false if it is not. + */ + public static boolean isValidFolderNameForPackage(String folderName) { +// return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR; + return true; + } + + /* + * Add a log entry + */ + public static void log(Throwable e, String message) { + Throwable nestedException; + if (e instanceof JavaModelException + && (nestedException = ((JavaModelException)e).getException()) != null) { + e = nestedException; + } + IStatus status= new Status( + IStatus.ERROR, + JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), + IStatus.ERROR, + message, + e); + JavaCore.getPlugin().getLog().log(status); + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use the given buffer's line separator. + */ + public static char[] normalizeCRs(char[] text, char[] buffer) { + CharArrayBuffer result = new CharArrayBuffer(); + int lineStart = 0; + int length = text.length; + if (length == 0) return text; + String lineSeparator = getLineSeparator(text, buffer); + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': + int lineLength = i-lineStart; + char[] line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + lineStart = i+1; + break; + case '\r': + lineLength = i-lineStart; + if (lineLength >= 0) { + line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + if (nextChar == '\n') { + nextChar = ' '; + lineStart = i+2; + } else { + // when line separator are mixed in the same file + // \r might not be followed by a \n. If not, we should increment + // lineStart by one and not by two. + lineStart = i+1; + } + } else { + // when line separator are mixed in the same file + // we need to prevent NegativeArraySizeException + lineStart = i+1; + } + break; + } + } + char[] lastLine; + if (lineStart > 0) { + int lastLineLength = length-lineStart; + if (lastLineLength > 0) { + lastLine = new char[lastLineLength]; + System.arraycopy(text, lineStart, lastLine, 0, lastLineLength); + result.append(lastLine); + } + return result.getContents(); + } else { + return text; + } + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use given buffer's line sepatator. + */ + public static String normalizeCRs(String text, String buffer) { + return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray())); + } + + /** + * Sort the objects in the given collection using the given sort order. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) { + int original_left = left; + int original_right = right; + int mid = sortOrder[ (left + right) / 2]; + do { + while (sortOrder[left] < mid) { + left++; + } + while (mid < sortOrder[right]) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + int tmp2 = sortOrder[left]; + sortOrder[left] = sortOrder[right]; + sortOrder[right] = tmp2; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, sortOrder); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, sortOrder); + } + } + + /** + * Sort the objects in the given collection using the given comparer. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) { + int original_left = left; + int original_right = right; + Object mid = sortedCollection[ (left + right) / 2]; + do { + while (comparer.compare(sortedCollection[left], mid) < 0) { + left++; + } + while (comparer.compare(mid, sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, comparer); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, comparer); + } + } + + /** + * Sort the strings in the given collection. + */ + private static void quickSort(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Converts the given relative path into a package name. + * Returns null if the path is not a valid package name. + */ + public static String packageName(IPath pkgPath) { + StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME); + for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) { + String segment = pkgPath.segment(j); + if (!isValidFolderNameForPackage(segment)) { + return null; + } + pkgName.append(segment); + if (j < pkgPath.segmentCount() - 1) { + pkgName.append("." ); //$NON-NLS-1$ + } + } + return pkgName.toString(); + } + + /** + * Sort the comparable objects in the given collection. + */ + private static void quickSort(Comparable[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + Comparable mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Comparable tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Sort the strings in the given collection in reverse alphabetical order. + */ + private static void quickSortReverse(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) > 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) > 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSortReverse(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSortReverse(sortedCollection, left, original_right); + } + } + + /** + * Sorts an array of objects in place, using the sort order given for each item. + */ + public static void sort(Object[] objects, int[] sortOrder) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, sortOrder); + } + + /** + * Sorts an array of objects in place. + * The given comparer compares pairs of items. + */ + public static void sort(Object[] objects, Comparer comparer) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, comparer); + } + + /** + * Sorts an array of strings in place using quicksort. + */ + public static void sort(String[] strings) { + if (strings.length > 1) + quickSort(strings, 0, strings.length - 1); + } + + /** + * Sorts an array of Comparable objects in place. + */ + public static void sort(Comparable[] objects) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1); + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Object[] sortCopy(Object[] objects, Comparer comparer) { + int len = objects.length; + Object[] copy = new Object[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy, comparer); + return copy; + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static String[] sortCopy(String[] objects) { + int len = objects.length; + String[] copy = new String[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of Comparable objects, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Comparable[] sortCopy(Comparable[] objects) { + int len = objects.length; + Comparable[] copy = new Comparable[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of strings in place using quicksort + * in reverse alphabetical order. + */ + public static void sortReverseOrder(String[] strings) { + if (strings.length > 1) + quickSortReverse(strings, 0, strings.length - 1); + } + + /** + * Converts a String[] to char[][]. + */ + public static char[][] toCharArrays(String[] a) { + int len = a.length; + char[][] result = new char[len][]; + for (int i = 0; i < len; ++i) { + result[i] = toChars(a[i]); + } + return result; + } + + /** + * Converts a String to char[]. + */ + public static char[] toChars(String s) { + int len = s.length(); + char[] chars = new char[len]; + s.getChars(0, len, chars, 0); + return chars; + } + + /** + * Converts a String to char[][], where segments are separate by '.'. + */ + public static char[][] toCompoundChars(String s) { + int len = s.length(); + if (len == 0) { + return CharOperation.NO_CHAR_CHAR; + } + int segCount = 1; + for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) { + ++segCount; + } + char[][] segs = new char[segCount][]; + int start = 0; + for (int i = 0; i < segCount; ++i) { + int dot = s.indexOf('.', start); + int end = (dot == -1 ? s.length() : dot); + segs[i] = new char[end - start]; + s.getChars(start, end, segs[i], 0); + start = end + 1; + } + return segs; + } + + /** + * Converts a char[][] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + if (i != 0) sb.append('.'); + sb.append(c[i]); + } + return sb.toString(); + } + + /** + * Converts a char[][] and a char[] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c, char[] d) { + if (c == null) return new String(d); + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + sb.append(c[i]); + sb.append('.'); + } + sb.append(d); + return sb.toString(); + } + + /** + * Converts a char[] to String. + */ + public static String toString(char[] c) { + return new String(c); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects) { + return toString(objects, + new Displayable(){ + public String displayString(Object o) { + if (o == null) return "null"; //$NON-NLS-1$ + return o.toString(); + } + }); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects, Displayable renderer) { + if (objects == null) return ""; //$NON-NLS-1$ + StringBuffer buffer = new StringBuffer(10); + for (int i = 0; i < objects.length; i++){ + if (i > 0) buffer.append(", "); //$NON-NLS-1$ + buffer.append(renderer.displayString(objects[i])); + } + return buffer.toString(); + } + + /** + * Asserts that the given method signature is valid. + */ + public static void validateMethodSignature(String sig) { + Assert.isTrue(isValidMethodSignature(sig)); + } + + /** + * Asserts that the given type signature is valid. + */ + public static void validateTypeSignature(String sig, boolean allowVoid) { + Assert.isTrue(isValidTypeSignature(sig, allowVoid)); + } + public static void verbose(String log) { + verbose(log, System.out); + } + public static synchronized void verbose(String log, PrintStream printStream) { + int start = 0; + do { + int end = log.indexOf('\n', start); + printStream.print(Thread.currentThread()); + printStream.print(" "); //$NON-NLS-1$ + printStream.print(log.substring(start, end == -1 ? log.length() : end+1)); + start = end+1; + } while (start != 0); + printStream.println(); + } + /** + * Creates a NLS catalog for the given locale. + */ + public static void relocalize() { + try { + bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + /** + * Put all the arguments in one String. + */ + public static String getProblemArgumentsForMarker(String[] arguments){ + StringBuffer args = new StringBuffer(10); + + args.append(arguments.length); + args.append(':'); + + + for (int j = 0; j < arguments.length; j++) { + if(j != 0) + args.append(ARGUMENTS_DELIMITER); + + if(arguments[j].length() == 0) { + args.append(EMPTY_ARGUMENT); + } else { + args.append(arguments[j]); + } + } + + return args.toString(); + } + + /** + * Separate all the arguments of a String made by getProblemArgumentsForMarker + */ + public static String[] getProblemArgumentsFromMarker(String argumentsString){ + if (argumentsString == null) return null; + int index = argumentsString.indexOf(':'); + if(index == -1) + return null; + + int length = argumentsString.length(); + int numberOfArg; + try{ + numberOfArg = Integer.parseInt(argumentsString.substring(0 , index)); + } catch (NumberFormatException e) { + return null; + } + argumentsString = argumentsString.substring(index + 1, length); + + String[] args = new String[length]; + int count = 0; + + StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER); + while(tokenizer.hasMoreTokens()) { + String argument = tokenizer.nextToken(); + if(argument.equals(EMPTY_ARGUMENT)) + argument = ""; //$NON-NLS-1$ + args[count++] = argument; + } + + if(count != numberOfArg) + return null; + + System.arraycopy(args, 0, args = new String[count], 0, count); + return args; + } + +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/template/TemplateSet.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/template/TemplateSet.java index ab30dd3..3ddf18f 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/template/TemplateSet.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/template/TemplateSet.java @@ -22,11 +22,16 @@ import javax.xml.parsers.ParserConfigurationException; import net.sourceforge.phpeclipse.PHPeclipsePlugin; -import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.Serializer; -import org.apache.xml.serialize.SerializerFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; @@ -218,16 +223,27 @@ public class TemplateSet { node.appendChild(pattern); } - OutputFormat format = new OutputFormat(); - format.setPreserveSpace(true); - Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format); //$NON-NLS-1$ - serializer.asDOMSerializer().serialize(document); + Transformer transformer=TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(stream); + + transformer.transform(source, result); + +// OutputFormat format = new OutputFormat(); +// format.setPreserveSpace(true); +// Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format); //$NON-NLS-1$ +// serializer.asDOMSerializer().serialize(document); } catch (ParserConfigurationException e) { throwWriteException(e); - } catch (IOException e) { - throwWriteException(e); - } + } catch (TransformerException e) { + throwWriteException(e); + } +// } catch (IOException e) { +// throwWriteException(e); +// } } private static void throwReadException(Throwable t) throws CoreException { diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.java index 120b578..3a0465f 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.java @@ -41,7 +41,15 @@ public class ActionMessages { return '!' + key + '!'; } } - + /** + * Returns the resource bundle managed by the receiver. + * + * @return the resource bundle + * @since 3.0 + */ + public static ResourceBundle getResourceBundle() { + return RESOURCE_BUNDLE; + } /** * Returns the formatted resource string associated with the given key in the resource bundle. * MessageFormat is used to format the message. If there isn't any value diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java index 1567bca..2da463d 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java @@ -53,7 +53,7 @@ public class AddBlockCommentAction extends BlockCommentAction { int selectionOffset= selection.getOffset(); int selectionEndOffset= selectionOffset + selection.getLength(); List edits= new LinkedList(); - ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, selectionOffset); + ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, selectionOffset, false); handleFirstPartition(partition, edits, factory, selectionOffset); @@ -124,7 +124,7 @@ public class AddBlockCommentAction extends BlockCommentAction { } // advance to next partition - partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset); + partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset, false); partType= partition.getType(); // start of next partition diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java new file mode 100644 index 0000000..e40f478 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.actions; + +import org.eclipse.jface.action.IMenuManager; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.source.projection.IProjectionListener; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.editors.text.IFoldingCommandIds; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextOperationAction; + + +/** + * Groups the JDT folding actions. + * + * @since 3.0 + */ +public class FoldingActionGroup extends ActionGroup { + private ProjectionViewer fViewer; + + private TextOperationAction fToggle; + private TextOperationAction fExpand; + private TextOperationAction fCollapse; + private TextOperationAction fExpandAll; + + private IProjectionListener fProjectionListener; + + /** + * Creates a new projection action group for editor. If the + * supplied viewer is not an instance of ProjectionViewer, the + * action group is disabled. + * + * @param editor the text editor to operate on + * @param viewer the viewer of the editor + */ + public FoldingActionGroup(ITextEditor editor, ITextViewer viewer) { + if (viewer instanceof ProjectionViewer) { + fViewer= (ProjectionViewer) viewer; + + fProjectionListener= new IProjectionListener() { + + public void projectionEnabled() { + update(); + } + + public void projectionDisabled() { + update(); + } + }; + + fViewer.addProjectionListener(fProjectionListener); + + fToggle= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$ + fToggle.setChecked(true); + fToggle.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE); + editor.setAction("FoldingToggle", fToggle); //$NON-NLS-1$ + + fExpandAll= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$ + fExpandAll.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL); + editor.setAction("FoldingExpandAll", fExpandAll); //$NON-NLS-1$ + + fExpand= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Expand.", editor, ProjectionViewer.EXPAND, true); //$NON-NLS-1$ + fExpand.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND); + editor.setAction("FoldingExpand", fExpand); //$NON-NLS-1$ + + fCollapse= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Collapse.", editor, ProjectionViewer.COLLAPSE, true); //$NON-NLS-1$ + fCollapse.setActionDefinitionId(IFoldingCommandIds.FOLDING_COLLAPSE); + editor.setAction("FoldingCollapse", fCollapse); //$NON-NLS-1$ + } + } + + /** + * Returns true if the group is enabled. + *
+	 * Invariant: isEnabled() <=> fViewer and all actions are != null.
+	 * 
+ * + * @return true if the group is enabled + */ + protected boolean isEnabled() { + return fViewer != null; + } + + /* + * @see org.eclipse.ui.actions.ActionGroup#dispose() + */ + public void dispose() { + if (isEnabled()) { + fViewer.removeProjectionListener(fProjectionListener); + fViewer= null; + } + super.dispose(); + } + + /** + * Updates the actions. + */ + protected void update() { + if (isEnabled()) { + fToggle.update(); + fToggle.setChecked(fViewer.getProjectionAnnotationModel() != null); + fExpand.update(); + fExpandAll.update(); + fCollapse.update(); + } + } + + /** + * Fills the menu with all folding actions. + * + * @param manager the menu manager for the folding submenu + */ + public void fillMenu(IMenuManager manager) { + if (isEnabled()) { + update(); + manager.add(fToggle); + manager.add(fExpandAll); + manager.add(fExpand); + manager.add(fCollapse); + } + } + + /* + * @see org.eclipse.ui.actions.ActionGroup#updateActionBars() + */ + public void updateActionBars() { + update(); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java new file mode 100644 index 0000000..7619360 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.actions; + +import org.eclipse.jface.action.IAction; + +import org.eclipse.jface.text.source.IVerticalRulerInfo; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +import org.eclipse.ui.editors.text.IFoldingCommandIds; +import org.eclipse.ui.texteditor.AbstractRulerActionDelegate; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextOperationAction; + + +/** + * Groups the JDT folding actions. + * + * @since 3.0 + */ +public class FoldingExpandAllRulerAction extends AbstractRulerActionDelegate { + + /* + * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.IVerticalRulerInfo) + */ + protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) { + TextOperationAction action= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$ + action.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL); + return action; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java new file mode 100644 index 0000000..d22d55f --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; + +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRulerInfo; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.editors.text.IFoldingCommandIds; +import org.eclipse.ui.texteditor.AbstractRulerActionDelegate; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextOperationAction; + +import net.sourceforge.phpeclipse.phpeditor.PHPEditor; + + +/** + * Groups the JDT folding actions. + * + * @since 3.0 + */ +public class FoldingToggleRulerAction extends AbstractRulerActionDelegate { + + private IAction fUIAction; + private TextOperationAction fAction; + private ITextEditor fTextEditor; + + /* + * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.IVerticalRulerInfo) + */ + protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) { + fTextEditor= editor; + fAction= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$ + fAction.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE); + + return fAction; + } + + /* + * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart) + */ + public void setActiveEditor(IAction callerAction, IEditorPart targetEditor) { + fUIAction= callerAction; + super.setActiveEditor(callerAction, targetEditor); + } + + /* + * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#menuAboutToShow(org.eclipse.jface.action.IMenuManager) + */ + public void menuAboutToShow(IMenuManager manager) { + update(); + super.menuAboutToShow(manager); + } + + private void update() { + if (fTextEditor instanceof PHPEditor) { + ISourceViewer viewer= ((PHPEditor) fTextEditor).getViewer(); + if (viewer instanceof ProjectionViewer) { + boolean enabled= ((ProjectionViewer) viewer).getProjectionAnnotationModel() != null; + fUIAction.setChecked(enabled); + } + } + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java index 60eadc2..2af8550 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java @@ -54,7 +54,7 @@ public class RemoveBlockCommentAction extends BlockCommentAction { int offset= selection.getOffset(); int endOffset= offset + selection.getLength(); - ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, offset); + ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, offset, false); int partOffset= partition.getOffset(); int partEndOffset= partOffset + partition.getLength(); @@ -65,7 +65,7 @@ public class RemoveBlockCommentAction extends BlockCommentAction { edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$ } - partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset); + partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset, false); partOffset= partition.getOffset(); partEndOffset= partOffset + partition.getLength(); } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java new file mode 100644 index 0000000..0d79e10 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text; + +import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType; + + +/** + * Listener for TypingRun events. + * + * @since 3.0 + */ +public interface ITypingRunListener { + /** + * Called when a new TypingRun is started. + * + * @param run the newly started run + */ + void typingRunStarted(TypingRun run); + + /** + * Called whenever a TypingRun is ended. + * + * @param run the ended run + * @param reason the type of change that caused the end of the run + */ + void typingRunEnded(TypingRun run, ChangeType reason); +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java new file mode 100644 index 0000000..67b0c5e --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package net.sourceforge.phpdt.internal.ui.text; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.presentation.PresentationReconciler; + + +/** + * Presentation reconciler, adding functionality for operation without a viewer. + * + * @since 3.0 + */ +public class JavaPresentationReconciler extends PresentationReconciler { + + /** Last used document */ + private IDocument fLastDocument; + + /** + * Constructs a "repair description" for the given damage and returns + * this description as a text presentation. + *

+ * NOTE: Should not be used if this reconciler is installed on a viewer. + *

+ * + * @param damage the damage to be repaired + * @param document the document whose presentation must be repaired + * @return the presentation repair description as text presentation + */ + public TextPresentation createRepairDescription(IRegion damage, IDocument document) { + if (document != fLastDocument) { + setDocumentToDamagers(document); + setDocumentToRepairers(document); + } + return createPresentation(damage, document); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java new file mode 100644 index 0000000..0302dc9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java @@ -0,0 +1,309 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package net.sourceforge.phpdt.internal.ui.text; + +import org.eclipse.core.runtime.Preferences; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.ListenerList; +import org.eclipse.jface.util.PropertyChangeEvent; + +/** + * Adapts {@link org.eclipse.core.runtime.Preferences} to + * {@link org.eclipse.jface.preference.IPreferenceStore} + * + * @since 3.0 + */ +public class PreferencesAdapter implements IPreferenceStore { + + /** + * Property change listener. Listens for events of type + * {@link org.eclipse.core.runtime.Preferences.PropertyChangeEvent} and fires + * a {@link org.eclipse.jface.util.PropertyChangeEvent} on the + * adapter with arguments from the received event. + */ + private class PropertyChangeListener implements Preferences.IPropertyChangeListener { + + /* + * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent) + */ + public void propertyChange(Preferences.PropertyChangeEvent event) { + firePropertyChangeEvent(event.getProperty(), event.getOldValue(), event.getNewValue()); + } + } + + /** Listeners on the adapter */ + private ListenerList fListeners= new ListenerList(); + + /** Listener on the adapted Preferences */ + private PropertyChangeListener fListener= new PropertyChangeListener(); + + /** Adapted Preferences */ + private Preferences fPreferences; + + /** True iff no events should be forwarded */ + private boolean fSilent; + + /** + * Initialize with empty Preferences. + */ + public PreferencesAdapter() { + this(new Preferences()); + } + /** + * Initialize with the given Preferences. + * + * @param preferences The preferences to wrap. + */ + public PreferencesAdapter(Preferences preferences) { + fPreferences= preferences; + } + + /** + * {@inheritDoc} + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + if (fListeners.size() == 0) + fPreferences.addPropertyChangeListener(fListener); + fListeners.add(listener); + } + + /** + * {@inheritDoc} + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + fListeners.remove(listener); + if (fListeners.size() == 0) + fPreferences.removePropertyChangeListener(fListener); + } + + /** + * {@inheritDoc} + */ + public boolean contains(String name) { + return fPreferences.contains(name); + } + + /** + * {@inheritDoc} + */ + public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { + if (!fSilent) { + PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue); + Object[] listeners= fListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) + ((IPropertyChangeListener) listeners[i]).propertyChange(event); + } + } + + /** + * {@inheritDoc} + */ + public boolean getBoolean(String name) { + return fPreferences.getBoolean(name); + } + + /** + * {@inheritDoc} + */ + public boolean getDefaultBoolean(String name) { + return fPreferences.getDefaultBoolean(name); + } + + /** + * {@inheritDoc} + */ + public double getDefaultDouble(String name) { + return fPreferences.getDefaultDouble(name); + } + + /** + * {@inheritDoc} + */ + public float getDefaultFloat(String name) { + return fPreferences.getDefaultFloat(name); + } + + /** + * {@inheritDoc} + */ + public int getDefaultInt(String name) { + return fPreferences.getDefaultInt(name); + } + + /** + * {@inheritDoc} + */ + public long getDefaultLong(String name) { + return fPreferences.getDefaultLong(name); + } + + /** + * {@inheritDoc} + */ + public String getDefaultString(String name) { + return fPreferences.getDefaultString(name); + } + + /** + * {@inheritDoc} + */ + public double getDouble(String name) { + return fPreferences.getDouble(name); + } + + /** + * {@inheritDoc} + */ + public float getFloat(String name) { + return fPreferences.getFloat(name); + } + + /** + * {@inheritDoc} + */ + public int getInt(String name) { + return fPreferences.getInt(name); + } + + /** + * {@inheritDoc} + */ + public long getLong(String name) { + return fPreferences.getLong(name); + } + + /** + * {@inheritDoc} + */ + public String getString(String name) { + return fPreferences.getString(name); + } + + /** + * {@inheritDoc} + */ + public boolean isDefault(String name) { + return fPreferences.isDefault(name); + } + + /** + * {@inheritDoc} + */ + public boolean needsSaving() { + return fPreferences.needsSaving(); + } + + /** + * {@inheritDoc} + */ + public void putValue(String name, String value) { + try { + fSilent= true; + fPreferences.setValue(name, value); + } finally { + fSilent= false; + } + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, double value) { + fPreferences.setDefault(name, value); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, float value) { + fPreferences.setDefault(name, value); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, int value) { + fPreferences.setDefault(name, value); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, long value) { + fPreferences.setDefault(name, value); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, String defaultObject) { + fPreferences.setDefault(name, defaultObject); + } + + /** + * {@inheritDoc} + */ + public void setDefault(String name, boolean value) { + fPreferences.setDefault(name, value); + } + + /** + * {@inheritDoc} + */ + public void setToDefault(String name) { + fPreferences.setToDefault(name); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, double value) { + fPreferences.setValue(name, value); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, float value) { + fPreferences.setValue(name, value); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, int value) { + fPreferences.setValue(name, value); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, long value) { + fPreferences.setValue(name, value); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, String value) { + fPreferences.setValue(name, value); + } + + /** + * {@inheritDoc} + */ + public void setValue(String name, boolean value) { + fPreferences.setValue(name, value); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java new file mode 100644 index 0000000..99484ea --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.TextEdit; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension; +import org.eclipse.jface.text.TextViewer; + +import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType; + + + +/** + * Installs as a verify key listener on a viewer and overwrites the behaviour + * of the backspace key. Clients may register undo specifications for certain + * offsets in a document. The SmartBackspaceManager will manage the + * specfications and execute the contained TextEdits when backspace + * is pressed at the given offset and the specification is still valid. + *

+ * Undo specifications are removed after a number of typing runs. + *

+ * + * @since 3.0 + */ +public class SmartBackspaceManager { + /* independent of JDT - may be moved to jface.text */ + + /** + * An undo specification describes the change that should be executed if + * backspace is pressed at its trigger offset. + * + * @since 3.0 + */ + public static final class UndoSpec { + private final int triggerOffset; + private final IRegion selection; + private final TextEdit[] undoEdits; + private final UndoSpec child; + int lives; + + /** + * Creates a new spec. A specification consists of a number of + * TextEdit s that will be executed when backspace is + * pressed at triggerOffset. The spec will be removed + * when it is executed, or if more than lives + * TypingRuns have ended after registering the spec. + *

+ * Optionally, a child specification can be registered. After executing + * the spec, the child spec will be registered with the manager. This allows + * to create chains of UndoSpecs that will be executed upon + * repeated pressing of backspace. + *

+ * + * @param triggerOffset the offset where this spec is active + * @param selection the selection after executing the undo spec + * @param edits the TextEdit s to perform when executing + * the spec + * @param lives the number of TypingRun s before removing + * the spec + * @param child a child specification that will be registered after + * executing this spec, or null + */ + public UndoSpec(int triggerOffset, IRegion selection, TextEdit[] edits, int lives, UndoSpec child) { + Assert.isLegal(triggerOffset >= 0); + Assert.isLegal(selection != null); + Assert.isLegal(lives >= 0); + Assert.isLegal(edits != null); + Assert.isLegal(edits.length > 0); + for (int i= 0; i < edits.length; i++) { + Assert.isLegal(edits[i] != null); + } + + this.triggerOffset= triggerOffset; + this.selection= selection; + this.undoEdits= edits; + this.lives= lives; + this.child= child; + } + } + + + private class BackspaceListener implements VerifyKeyListener { + + /* + * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent) + */ + public void verifyKey(VerifyEvent event) { + if (fViewer != null && isBackspace(event)) { + int offset= getCaretOffset(); + UndoSpec spec= removeEdit(offset); + if (spec != null) { + try { + beginChange(); + for (int i= 0; i < spec.undoEdits.length; i++) { + spec.undoEdits[i].apply(getDocument(), TextEdit.UPDATE_REGIONS); + } + fViewer.setSelectedRange(spec.selection.getOffset(), spec.selection.getLength()); + if (spec.child != null) + register(spec.child); + } catch (MalformedTreeException e) { + // fall back to standard bs + return; + } catch (BadLocationException e) { + // fall back to standard bs + return; + } finally { + endChange(); + } + event.doit= false; + } + + } + } + + private void beginChange() { + ITextViewer viewer= fViewer; + if (viewer instanceof TextViewer) { + TextViewer v= (TextViewer) viewer; + v.getRewriteTarget().beginCompoundChange(); + v.setRedraw(false); + } + } + + private void endChange() { + ITextViewer viewer= fViewer; + if (viewer instanceof TextViewer) { + TextViewer v= (TextViewer) viewer; + v.getRewriteTarget().endCompoundChange(); + v.setRedraw(true); + } + } + + private boolean isBackspace(VerifyEvent event) { + return event.doit == true && event.character == SWT.BS && event.stateMask == 0; + } + + private int getCaretOffset() { + ITextViewer viewer= fViewer; + Point point= viewer.getSelectedRange(); + return point.x; + } + + } + + private ITextViewer fViewer; + private BackspaceListener fBackspaceListener; + private Map fSpecs; + private TypingRunDetector fRunDetector; + private ITypingRunListener fRunListener; + + /** + * Registers an undo specification with this manager. + * + * @param spec the specification to register + * @throws IllegalStateException if the manager is not installed + */ + public void register(UndoSpec spec) { + if (fViewer == null) + throw new IllegalStateException(); + + ensureListenerInstalled(); + addEdit(spec); + } + + private void addEdit(UndoSpec spec) { + Integer i= new Integer(spec.triggerOffset); + fSpecs.put(i, spec); + } + + private UndoSpec removeEdit(int offset) { + Integer i= new Integer(offset); + UndoSpec spec= (UndoSpec) fSpecs.remove(i); + return spec; + } + + private void ensureListenerInstalled() { + if (fBackspaceListener == null) { + fBackspaceListener= new BackspaceListener(); + ITextViewer viewer= fViewer; + if (viewer instanceof ITextViewerExtension) + ((ITextViewerExtension) viewer).prependVerifyKeyListener(fBackspaceListener); + else + viewer.getTextWidget().addVerifyKeyListener(fBackspaceListener); + } + } + + private void ensureListenerRemoved() { + if (fBackspaceListener != null) { + ITextViewer viewer= fViewer; + if (viewer instanceof ITextViewerExtension) + ((ITextViewerExtension) viewer).removeVerifyKeyListener(fBackspaceListener); + else + viewer.getTextWidget().removeVerifyKeyListener(fBackspaceListener); + fBackspaceListener= null; + } + } + + private IDocument getDocument() { + return fViewer.getDocument(); + } + + /** + * Installs the receiver on a text viewer. + * + * @param viewer + */ + public void install(ITextViewer viewer) { + Assert.isLegal(viewer != null); + + fViewer= viewer; + fSpecs= new HashMap(); + fRunDetector= new TypingRunDetector(); + fRunDetector.install(viewer); + fRunListener= new ITypingRunListener() { + + /* + * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunStarted(org.eclipse.jface.text.TypingRunDetector.TypingRun) + */ + public void typingRunStarted(TypingRun run) { + } + + /* + * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunEnded(org.eclipse.jface.text.TypingRunDetector.TypingRun) + */ + public void typingRunEnded(TypingRun run, ChangeType reason) { + if (reason == TypingRun.SELECTION) + fSpecs.clear(); + else + prune(); + } + }; + fRunDetector.addTypingRunListener(fRunListener); + } + + private void prune() { + for (Iterator it= fSpecs.values().iterator(); it.hasNext();) { + UndoSpec spec= (UndoSpec) it.next(); + if (--spec.lives < 0) + it.remove(); + } + } + + /** + * Uninstalls the receiver. No undo specifications may be registered on an + * uninstalled manager. + */ + public void uninstall() { + if (fViewer != null) { + fRunDetector.removeTypingRunListener(fRunListener); + fRunDetector.uninstall(); + fRunDetector= null; + ensureListenerRemoved(); + fViewer= null; + } + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java new file mode 100644 index 0000000..350672a --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text; + + + +/** + * Describes a run of similar typing changes. + *

+ * XXX to be extended with further information, e.g. offset, length, and + * content of the run. + *

+ * + * @since 3.0 + */ +public final class TypingRun { + /** + * A change of type DELETE deletes one single character (through delete or + * backspace or empty paste). + */ + public static final ChangeType DELETE= new ChangeType(true, "DELETE"); //$NON-NLS-1$ + /** + * A change of type INSERT inserts one single character + * (normal typing). + */ + public static final ChangeType INSERT= new ChangeType(true, "INSERT"); //$NON-NLS-1$ + /** + * A change of type NO_CHANGE does not change anything. + */ + public static final ChangeType NO_CHANGE= new ChangeType(false, "NO_CHANGE"); //$NON-NLS-1$ + /** + * A change of type OVERTYPE replaces one single character + * (overwrite mode, pasting a single character). + */ + public static final ChangeType OVERTYPE= new ChangeType(true, "OVERTYPE"); //$NON-NLS-1$ + /** + * A change of type SELECTION does not change text, but + * changes the focus, or selection. Such a change ends all typing runs. + */ + public static final ChangeType SELECTION= new ChangeType(false, "SELECTION"); //$NON-NLS-1$ + /** + * A change of type UNKNOWN modifies text in an + * unspecified way. An example is pasting more than one character, or + * deleting an entire selection, or reverting a file. Such a change ends + * all typing runs and cannot form a typing run with any other change, + * including a change of type UNKNOWN. + */ + public static final ChangeType UNKNOWN= new ChangeType(true, "UNKNOWN"); //$NON-NLS-1$ + + + /** + * Enumeration of change types. + * + * @since 3.0 + */ + public static final class ChangeType { + private final boolean fIsModification; + private final String fName; + + /** Private ctor for type safe enumeration. */ + private ChangeType(boolean isRunPart, String name) { + fIsModification= isRunPart; + fName= name; + } + + /** + * Returns true if changes of this type modify text. + * + * @return true if changes of this type modify text, + * false otherwise + */ + boolean isModification() { + return fIsModification; + } + + /* + * @see java.lang.Object#toString() + */ + public String toString() { + return fName; + } + } + + /** + * Creates a new run. + * + * @param type the type of the run + */ + TypingRun(ChangeType type) { + this.type= type; + } + + /** The change type of this run. */ + public final ChangeType type; +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java new file mode 100644 index 0000000..61d59e1 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java @@ -0,0 +1,471 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextEvent; + +import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType; + + +/** + * When connected to a text viewer, a TypingRunDetector observes + * TypingRun events. A typing run is a sequence of similar text + * modifications, such as inserting or deleting single characters. + *

+ * Listeners are informed about the start and end of a TypingRun. + *

+ * + * @since 3.0 + */ +public class TypingRunDetector { + /* + * Implementation note: This class is independent of JDT and may be pulled + * up to jface.text if needed. + */ + + /** Debug flag. */ + private static final boolean DEBUG= false; + + /** + * Instances of this class abstract a text modification into a simple + * description. Typing runs consists of a sequence of one or more modifying + * changes of the same type. Every change records the type of change + * described by a text modification, and an offset it can be followed by + * another change of the same run. + */ + private static final class Change { + private ChangeType fType; + private int fNextOffset; + + /** + * Creates a new change of type type. + * + * @param type the ChangeType of the new change + * @param nextOffset the offset of the next change in a typing run + */ + public Change(ChangeType type, int nextOffset) { + fType= type; + fNextOffset= nextOffset; + } + + /** + * Returns true if the receiver can extend the typing + * range the last change of which is described by change. + * + * @param change the last change in a typing run + * @return true if the receiver is a valid extension to + * change,false otherwise + */ + public boolean canFollow(Change change) { + if (fType == TypingRun.NO_CHANGE) + return true; + else if (fType.equals(TypingRun.UNKNOWN)) + return false; + if (fType.equals(change.fType)) { + if (fType == TypingRun.DELETE) + return fNextOffset == change.fNextOffset - 1; + else if (fType == TypingRun.INSERT) + return fNextOffset == change.fNextOffset + 1; + else if (fType == TypingRun.OVERTYPE) + return fNextOffset == change.fNextOffset + 1; + else if (fType == TypingRun.SELECTION) + return true; + } + return false; + } + + /** + * Returns true if the receiver describes a text + * modification, false if it describes a focus / + * selection change. + * + * @return true if the receiver is a text modification + */ + public boolean isModification() { + return fType.isModification(); + } + + /* + * @see java.lang.Object#toString() + */ + public String toString() { + return fType.toString() + "@" + fNextOffset; //$NON-NLS-1$ + } + + /** + * Returns the change type of this change. + * + * @return the change type of this change + */ + public ChangeType getType() { + return fType; + } + } + + /** + * Observes any events that modify the content of the document displayed in + * the editor. Since text events may start a new run, this listener is + * always registered if the detector is connected. + */ + private class TextListener implements ITextListener { + + /* + * @see org.eclipse.jface.text.ITextListener#textChanged(org.eclipse.jface.text.TextEvent) + */ + public void textChanged(TextEvent event) { + handleTextChanged(event); + } + } + + /** + * Observes non-modifying events that will end a run, such as clicking into + * the editor, moving the caret, and the editor losing focus. These events + * can never start a run, therefore this listener is only registered if + * there is an ongoing run. + */ + private class SelectionListener implements MouseListener, KeyListener, FocusListener { + + /* + * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent) + */ + public void focusGained(FocusEvent e) { + handleSelectionChanged(); + } + + /* + * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) + */ + public void focusLost(FocusEvent e) { + } + + /* + * @see MouseListener#mouseDoubleClick + */ + public void mouseDoubleClick(MouseEvent e) { + } + + /* + * If the right mouse button is pressed, the current editing command is closed + * @see MouseListener#mouseDown + */ + public void mouseDown(MouseEvent e) { + if (e.button == 1) + handleSelectionChanged(); + } + + /* + * @see MouseListener#mouseUp + */ + public void mouseUp(MouseEvent e) { + } + + /* + * @see KeyListener#keyPressed + */ + public void keyReleased(KeyEvent e) { + } + + /* + * On cursor keys, the current editing command is closed + * @see KeyListener#keyPressed + */ + public void keyPressed(KeyEvent e) { + switch (e.keyCode) { + case SWT.ARROW_UP: + case SWT.ARROW_DOWN: + case SWT.ARROW_LEFT: + case SWT.ARROW_RIGHT: + case SWT.END: + case SWT.HOME: + case SWT.PAGE_DOWN: + case SWT.PAGE_UP: + handleSelectionChanged(); + break; + } + } + } + + /** The listeners. */ + private final Set fListeners= new HashSet(); + /** + * The viewer we work upon. Set to null in + * uninstall. + */ + private ITextViewer fViewer; + /** The text event listener. */ + private final TextListener fTextListener= new TextListener(); + /** + * The selection listener. Set to null when no run is active. + */ + private SelectionListener fSelectionListener; + + /* state variables */ + + /** The most recently observed change. Never null. */ + private Change fLastChange; + /** The current run, or null if there is none. */ + private TypingRun fRun; + + /** + * Installs the receiver with a text viewer. + * + * @param viewer the viewer to install on + */ + public void install(ITextViewer viewer) { + Assert.isLegal(viewer != null); + fViewer= viewer; + connect(); + } + + /** + * Initializes the state variables and registers any permanent listeners. + */ + private void connect() { + if (fViewer != null) { + fLastChange= new Change(TypingRun.UNKNOWN, -1); + fRun= null; + fSelectionListener= null; + fViewer.addTextListener(fTextListener); + } + } + + /** + * Uninstalls the receiver and removes all listeners. install() + * must be called for events to be generated. + */ + public void uninstall() { + if (fViewer != null) { + fListeners.clear(); + disconnect(); + fViewer= null; + } + } + + /** + * Disconnects any registered listeners. + */ + private void disconnect() { + fViewer.removeTextListener(fTextListener); + ensureSelectionListenerRemoved(); + } + + /** + * Adds a listener for TypingRun events. Repeatedly adding + * the same listener instance has no effect. Listeners may be added even + * if the receiver is neither connected nor installed. + * + * @param listener the listener add + */ + public void addTypingRunListener(ITypingRunListener listener) { + Assert.isLegal(listener != null); + fListeners.add(listener); + if (fListeners.size() == 1) + connect(); + } + + /** + * Removes the listener from this manager. If listener is not + * registered with the receiver, nothing happens. + * + * @param listener the listener to remove, or null + */ + public void removeTypingRunListener(ITypingRunListener listener) { + fListeners.remove(listener); + if (fListeners.size() == 0) + disconnect(); + } + + /** + * Handles an incoming text event. + * + * @param event the text event that describes the text modification + */ + void handleTextChanged(TextEvent event) { + Change type= computeChange(event); + handleChange(type); + } + + /** + * Computes the change abstraction given a text event. + * + * @param event the text event to analyze + * @return a change object describing the event + */ + private Change computeChange(TextEvent event) { + DocumentEvent e= event.getDocumentEvent(); + if (e == null) + return new Change(TypingRun.NO_CHANGE, -1); + + int start= e.getOffset(); + int end= e.getOffset() + e.getLength(); + String newText= e.getText(); + if (newText == null) + newText= new String(); + + if (start == end) { + // no replace / delete / overwrite + if (newText.length() == 1) + return new Change(TypingRun.INSERT, end + 1); + } else if (start == end - 1) { + if (newText.length() == 1) + return new Change(TypingRun.OVERTYPE, end); + if (newText.length() == 0) + return new Change(TypingRun.DELETE, start); + } + + return new Change(TypingRun.UNKNOWN, -1); + } + + /** + * Handles an incoming selection event. + */ + void handleSelectionChanged() { + handleChange(new Change(TypingRun.SELECTION, -1)); + } + + /** + * State machine. Changes state given the current state and the incoming + * change. + * + * @param change the incoming change + */ + private void handleChange(Change change) { + if (change.getType() == TypingRun.NO_CHANGE) + return; + + if (DEBUG) + System.err.println("Last change: " + fLastChange); //$NON-NLS-1$ + + if (!change.canFollow(fLastChange)) + endIfStarted(change); + fLastChange= change; + if (change.isModification()) + startOrContinue(); + + if (DEBUG) + System.err.println("New change: " + change); //$NON-NLS-1$ + } + + /** + * Starts a new run if there is none and informs all listeners. If there + * already is a run, nothing happens. + */ + private void startOrContinue() { + if (!hasRun()) { + if (DEBUG) + System.err.println("+Start run"); //$NON-NLS-1$ + fRun= new TypingRun(fLastChange.getType()); + ensureSelectionListenerAdded(); + fireRunBegun(fRun); + } + } + + /** + * Returns true if there is an active run, false + * otherwise. + * + * @return true if there is an active run, false + * otherwise + */ + private boolean hasRun() { + return fRun != null; + } + + /** + * Ends any active run and informs all listeners. If there is none, nothing + * happens. + * + * @param change the change that triggered ending the active run + */ + private void endIfStarted(Change change) { + if (hasRun()) { + ensureSelectionListenerRemoved(); + if (DEBUG) + System.err.println("-End run"); //$NON-NLS-1$ + fireRunEnded(fRun, change.getType()); + fRun= null; + } + } + + /** + * Adds the selection listener to the text widget underlying the viewer, if + * not already done. + */ + private void ensureSelectionListenerAdded() { + if (fSelectionListener == null) { + fSelectionListener= new SelectionListener(); + StyledText textWidget= fViewer.getTextWidget(); + textWidget.addFocusListener(fSelectionListener); + textWidget.addKeyListener(fSelectionListener); + textWidget.addMouseListener(fSelectionListener); + } + } + + /** + * If there is a selection listener, it is removed from the text widget + * underlying the viewer. + */ + private void ensureSelectionListenerRemoved() { + if (fSelectionListener != null) { + StyledText textWidget= fViewer.getTextWidget(); + textWidget.removeFocusListener(fSelectionListener); + textWidget.removeKeyListener(fSelectionListener); + textWidget.removeMouseListener(fSelectionListener); + fSelectionListener= null; + } + } + + /** + * Informs all listeners about a newly started TypingRun. + * + * @param run the new run + */ + private void fireRunBegun(TypingRun run) { + List listeners= new ArrayList(fListeners); + for (Iterator it= listeners.iterator(); it.hasNext();) { + ITypingRunListener listener= (ITypingRunListener) it.next(); + listener.typingRunStarted(fRun); + } + } + + /** + * Informs all listeners about an ended TypingRun. + * + * @param run the previously active run + * @param reason the type of change that caused the run to be ended + */ + private void fireRunEnded(TypingRun run, ChangeType reason) { + List listeners= new ArrayList(fListeners); + for (Iterator it= listeners.iterator(); it.hasNext();) { + ITypingRunListener listener= (ITypingRunListener) it.next(); + listener.typingRunEnded(fRun, reason); + } + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java new file mode 100644 index 0000000..6fc5499 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text.java; + +import org.eclipse.core.runtime.IProgressMonitor; + +import net.sourceforge.phpdt.core.dom.CompilationUnit; + + +/** + * Interface of an object listening to Java reconciling. + * + * @since 3.0 + */ +public interface IJavaReconcilingListener { + + /** + * Called before reconciling is started. + */ + void aboutToBeReconciled(); + + /** + * Called after reconciling has been finished. + * @param ast the compilation unit AST or null if + * the working copy was consistent or reconciliation has been cancelled + * @param forced true iff this reconciliation was forced + * @param progressMonitor the progress monitor + */ + void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor progressMonitor); +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategy.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategy.java index 319980b..56d3d75 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategy.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategy.java @@ -147,7 +147,7 @@ public class JavaStringAutoIndentStrategy extends DefaultAutoIndentStrategy { private void javaStringIndentAfterNewLine(IDocument document, DocumentCommand command) throws BadLocationException { - ITypedRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset); + ITypedRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset, false); int offset= partition.getOffset(); int length= partition.getLength(); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java index cb927fb..5b5e1cf 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java @@ -9,7 +9,6 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.ui.text.java.hover; - import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -109,12 +108,12 @@ public class BestMatchHover extends AbstractJavaEditorTextHover implements IText } /* - * @see org.eclipse.jface.text.ITextHoverExtension#getInformationControlCreator() + * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator() * @since 3.0 */ - public IInformationControlCreator getInformationControlCreator() { + public IInformationControlCreator getHoverControlCreator() { if (fBestHover instanceof ITextHoverExtension) - return ((ITextHoverExtension)fBestHover).getInformationControlCreator(); + return ((ITextHoverExtension)fBestHover).getHoverControlCreator(); return null; } @@ -129,4 +128,4 @@ public class BestMatchHover extends AbstractJavaEditorTextHover implements IText return null; } -} +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java new file mode 100644 index 0000000..2936e54 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java @@ -0,0 +1,398 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.text.java.hover; + +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer; +import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlExtension; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * Source viewer based implementation of IInformationControl. + * Displays information in a source viewer. + * + * @since 3.0 + */ +public class SourceViewerInformationControl implements IInformationControl, IInformationControlExtension, DisposeListener { + + /** Border thickness in pixels. */ + private static final int BORDER= 1; + /** The control's shell */ + private Shell fShell; + /** The control's text widget */ + private StyledText fText; + /** The control's source viewer */ + private SourceViewer fViewer; + /** + * The optional status field. + * + * @since 3.0 + */ + private Label fStatusField; + /** + * The separator for the optional status field. + * + * @since 3.0 + */ + private Label fSeparator; + /** + * The font of the optional status text label. + * + * @since 3.0 + */ + private Font fStatusTextFont; + + /** + * Creates a default information control with the given shell as parent. The given + * information presenter is used to process the information to be displayed. The given + * styles are applied to the created styled text widget. + * + * @param parent the parent shell + * @param shellStyle the additional styles for the shell + * @param style the additional styles for the styled text widget + */ + public SourceViewerInformationControl(Shell parent, int shellStyle, int style) { + this(parent, shellStyle, style, null); + } + + /** + * Creates a default information control with the given shell as parent. The given + * information presenter is used to process the information to be displayed. The given + * styles are applied to the created styled text widget. + * + * @param parent the parent shell + * @param shellStyle the additional styles for the shell + * @param style the additional styles for the styled text widget + * @param statusFieldText the text to be used in the optional status field + * or null if the status field should be hidden + * @since 3.0 + */ + public SourceViewerInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) { + GridLayout layout; + GridData gd; + + fShell= new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); + Display display= fShell.getDisplay(); + fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + + Composite composite= fShell; + layout= new GridLayout(1, false); + int border= ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; + layout.marginHeight= border; + layout.marginWidth= border; + composite.setLayout(layout); + gd= new GridData(GridData.FILL_HORIZONTAL); + composite.setLayoutData(gd); + + if (statusFieldText != null) { + composite= new Composite(composite, SWT.NONE); + layout= new GridLayout(1, false); + layout.marginHeight= 0; + layout.marginWidth= 0; + composite.setLayout(layout); + gd= new GridData(GridData.FILL_BOTH); + composite.setLayoutData(gd); + composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + } + + // Source viewer + IPreferenceStore store= PHPeclipsePlugin.getDefault().getCombinedPreferenceStore(); + fViewer= new JavaSourceViewer(composite, null, null, false, style, store); + fViewer.configure(new PHPSourceViewerConfiguration(PHPeclipsePlugin.getDefault().getJavaTextTools().getColorManager(), store, null, null)); + fViewer.setEditable(false); + + fText= fViewer.getTextWidget(); + gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH); + fText.setLayoutData(gd); + fText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + fText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + + fText.addKeyListener(new KeyListener() { + + public void keyPressed(KeyEvent e) { + if (e.character == 0x1B) // ESC + fShell.dispose(); + } + + public void keyReleased(KeyEvent e) {} + }); + + // Status field + if (statusFieldText != null) { + + // Horizontal separator line + fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); + fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Status field label + fStatusField= new Label(composite, SWT.RIGHT); + fStatusField.setText(statusFieldText); + Font font= fStatusField.getFont(); + FontData[] fontDatas= font.getFontData(); + for (int i= 0; i < fontDatas.length; i++) + fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); + fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas); + fStatusField.setFont(fStatusTextFont); + GridData gd2= new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); + fStatusField.setLayoutData(gd2); + + // Regarding the color see bug 41128 + fStatusField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); + + fStatusField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + } + + addDisposeListener(this); + } + + /** + * Creates a default information control with the given shell as parent. The given + * information presenter is used to process the information to be displayed. The given + * styles are applied to the created styled text widget. + * + * @param parent the parent shell + * @param style the additional styles for the styled text widget + */ + public SourceViewerInformationControl(Shell parent,int style) { + this(parent, SWT.NO_TRIM, style); + } + + /** + * Creates a default information control with the given shell as parent. The given + * information presenter is used to process the information to be displayed. The given + * styles are applied to the created styled text widget. + * + * @param parent the parent shell + * @param style the additional styles for the styled text widget + * @param statusFieldText the text to be used in the optional status field + * or null if the status field should be hidden + * @since 3.0 + */ + public SourceViewerInformationControl(Shell parent,int style, String statusFieldText) { + this(parent, SWT.NO_TRIM, style, statusFieldText); + } + + /** + * Creates a default information control with the given shell as parent. + * No information presenter is used to process the information + * to be displayed. No additional styles are applied to the styled text widget. + * + * @param parent the parent shell + */ + public SourceViewerInformationControl(Shell parent) { + this(parent, SWT.NONE); + } + + /** + * Creates a default information control with the given shell as parent. + * No information presenter is used to process the information + * to be displayed. No additional styles are applied to the styled text widget. + * + * @param parent the parent shell + * @param statusFieldText the text to be used in the optional status field + * or null if the status field should be hidden + * @since 3.0 + */ + public SourceViewerInformationControl(Shell parent, String statusFieldText) { + this(parent, SWT.NONE, statusFieldText); + } + + /* + * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object) + */ + public void setInput(Object input) { + if (input instanceof String) + setInformation((String)input); + else + setInformation(null); + } + + /* + * @see IInformationControl#setInformation(String) + */ + public void setInformation(String content) { + if (content == null) { + fViewer.setInput(null); + return; + } + + IDocument doc= new Document(content); + PHPeclipsePlugin.getDefault().getJavaTextTools().setupJavaDocumentPartitioner(doc); + + fViewer.setInput(doc); + } + + /* + * @see IInformationControl#setVisible(boolean) + */ + public void setVisible(boolean visible) { + fShell.setVisible(visible); + } + + /** + * {@inheritDoc} + * @since 3.0 + */ + public void widgetDisposed(DisposeEvent event) { + if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) + fStatusTextFont.dispose(); + + fStatusTextFont= null; + fShell= null; + fText= null; + } + + /** + * {@inheritDoc} + */ + public final void dispose() { + if (fShell != null && !fShell.isDisposed()) + fShell.dispose(); + else + widgetDisposed(null); + } + + /* + * @see IInformationControl#setSize(int, int) + */ + public void setSize(int width, int height) { + + if (fStatusField != null) { + GridData gd= (GridData)fViewer.getTextWidget().getLayoutData(); + Point statusSize= fStatusField.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + Point separatorSize= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + gd.heightHint= height - statusSize.y - separatorSize.y; + } + fShell.setSize(width, height); + + if (fStatusField != null) + fShell.pack(true); + } + + /* + * @see IInformationControl#setLocation(Point) + */ + public void setLocation(Point location) { + Rectangle trim= fShell.computeTrim(0, 0, 0, 0); + Point textLocation= fText.getLocation(); + location.x += trim.x - textLocation.x; + location.y += trim.y - textLocation.y; + fShell.setLocation(location); + } + + /* + * @see IInformationControl#setSizeConstraints(int, int) + */ + public void setSizeConstraints(int maxWidth, int maxHeight) { + maxWidth= maxHeight; + } + + /* + * @see IInformationControl#computeSizeHint() + */ + public Point computeSizeHint() { + return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT); + } + + /* + * @see IInformationControl#addDisposeListener(DisposeListener) + */ + public void addDisposeListener(DisposeListener listener) { + fShell.addDisposeListener(listener); + } + + /* + * @see IInformationControl#removeDisposeListener(DisposeListener) + */ + public void removeDisposeListener(DisposeListener listener) { + fShell.removeDisposeListener(listener); + } + + /* + * @see IInformationControl#setForegroundColor(Color) + */ + public void setForegroundColor(Color foreground) { + fText.setForeground(foreground); + } + + /* + * @see IInformationControl#setBackgroundColor(Color) + */ + public void setBackgroundColor(Color background) { + fText.setBackground(background); + } + + /* + * @see IInformationControl#isFocusControl() + */ + public boolean isFocusControl() { + return fText.isFocusControl(); + } + + /* + * @see IInformationControl#setFocus() + */ + public void setFocus() { + fShell.forceFocus(); + fText.setFocus(); + } + + /* + * @see IInformationControl#addFocusListener(FocusListener) + */ + public void addFocusListener(FocusListener listener) { + fText.addFocusListener(listener); + } + + /* + * @see IInformationControl#removeFocusListener(FocusListener) + */ + public void removeFocusListener(FocusListener listener) { + fText.removeFocusListener(listener); + } + + /* + * @see IInformationControlExtension#hasContents() + */ + public boolean hasContents() { + return fText.getCharCount() > 0; + } + + protected ISourceViewer getViewer() { + return fViewer; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java index 11403b2..4fb0216 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java @@ -722,7 +722,7 @@ public class LinkedPositionManager implements IDocumentListener, IPositionUpdate try { if (position.getType().equals(currentPosition.getType()) && !position.equals(currentPosition)) - command.addCommand(position.getOffset() + deltaOffset, command.length, command.text, true, this); + command.addCommand(position.getOffset() + deltaOffset, command.length, command.text, this); } catch (BadLocationException e) { PHPeclipsePlugin.log(e); } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java index 3be74d5..69bbfb9 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java @@ -127,7 +127,6 @@ public class ProblemMarkerManager implements IResourceChangeListener, IAnnotatio fireChanges(changes, true); } } - /* (non-Javadoc) * @see IAnnotationModelListener#modelChanged(IAnnotationModel) */ @@ -141,14 +140,13 @@ public class ProblemMarkerManager implements IResourceChangeListener, IAnnotatio public void modelChanged(AnnotationModelEvent event) { if (event instanceof CompilationUnitAnnotationModelEvent) { CompilationUnitAnnotationModelEvent cuEvent= (CompilationUnitAnnotationModelEvent) event; - if (cuEvent.includesMarkerAnnotationChanges()) { + if (cuEvent.includesProblemMarkerAnnotationChanges()) { IResource[] changes= new IResource[] { cuEvent.getUnderlyingResource() }; fireChanges(changes, false); } } } - /** * Adds a listener for problem marker changes. */ diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java index 946e308..5c025c8 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java @@ -5,7 +5,6 @@ package net.sourceforge.phpdt.ui.text; * All Rights Reserved. */ -import net.sourceforge.phpdt.internal.ui.text.FastJavaPartitionScanner; import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions; import net.sourceforge.phpdt.internal.ui.text.JavaColorManager; import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCodeScanner; @@ -16,6 +15,7 @@ import net.sourceforge.phpeclipse.phpeditor.php.PHPPartitionScanner; import net.sourceforge.phpeclipse.phpeditor.php.SmartyCodeScanner; import net.sourceforge.phpeclipse.phpeditor.php.SmartyDocCodeScanner; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; @@ -26,6 +26,7 @@ import org.eclipse.jface.text.rules.IPartitionTokenScanner; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.ui.part.FileEditorInput; // //import org.phpeclipse.phpdt.internal.ui.text.FastJavaPartitionScanner; //import org.phpeclipse.phpdt.internal.ui.text.JavaColorManager; @@ -364,25 +365,56 @@ public class JavaTextTools { return partitioner; } - /** - * Sets up the Java document partitioner for the given document for the given partitioning. + * Sets up the Java document partitioner for the given document for the default partitioning. * * @param document the document to be set up + * @since 3.0 + */ + public void setupJavaDocumentPartitioner(IDocument document) { + setupJavaDocumentPartitioner(document, IDocumentExtension3.DEFAULT_PARTITIONING,null); + } + /** + * Sets up the Java document partitioner for the given document for the given partitioning. + * @param document the document to be set up * @param partitioning the document partitioning + * @param element TODO + * * @since 3.0 */ - public void setupJavaDocumentPartitioner(IDocument document, String partitioning) { - IDocumentPartitioner partitioner= createDocumentPartitioner(); - if (document instanceof IDocumentExtension3) { - IDocumentExtension3 extension3= (IDocumentExtension3) document; - extension3.setDocumentPartitioner(partitioning, partitioner); - } else { + public void setupJavaDocumentPartitioner(IDocument document, String partitioning, Object element) { + IDocumentPartitioner partitioner = createDocumentPartitioner(".php"); + +// if (document instanceof IDocumentExtension3) { +// IDocumentExtension3 extension3= (IDocumentExtension3) document; +// extension3.setDocumentPartitioner(partitioning, partitioner); +// } else { + document.setDocumentPartitioner(partitioner); +// } + partitioner.connect(document); + } + public void setupHTMLDocumentPartitioner(IDocument document, String partitioning, Object element) { + IDocumentPartitioner partitioner = createDocumentPartitioner(".html"); + +// if (document instanceof IDocumentExtension3) { +// IDocumentExtension3 extension3= (IDocumentExtension3) document; +// extension3.setDocumentPartitioner(partitioning, partitioner); +// } else { + document.setDocumentPartitioner(partitioner); +// } + partitioner.connect(document); + } + public void setupSmartyDocumentPartitioner(IDocument document, String partitioning, Object element) { + IDocumentPartitioner partitioner = createDocumentPartitioner(".tpl"); + +// if (document instanceof IDocumentExtension3) { +// IDocumentExtension3 extension3= (IDocumentExtension3) document; +// extension3.setDocumentPartitioner(partitioning, partitioner); +// } else { document.setDocumentPartitioner(partitioner); - } +// } partitioner.connect(document); } - /** * Returns the names of the document position categories used by the document * partitioners created by this object to manage their partition information. diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormatter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormatter.java index 30ed71c..7e4c33c 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormatter.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormatter.java @@ -5,11 +5,11 @@ import java.util.HashSet; import java.util.Set; import net.sourceforge.phpeclipse.PHPeclipsePlugin; -import net.sourceforge.phpeclipse.phpeditor.PHPEditor; import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.ui.texteditor.ITextEditor; /** * Modified from the XMLFormatter. Some tags in HTML do not indent. @@ -43,7 +43,7 @@ public class HTMLFormatter implements IHTMLConstants { private PHPSourceViewerConfiguration fConfig; private SourceViewer fViewer; // - private PHPEditor fEditor; + private ITextEditor fEditor; private String fFilename; //////////////////////////////////////////////////////////////////////// diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormattingStrategy.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormattingStrategy.java index e3d00d4..2781272 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormattingStrategy.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormattingStrategy.java @@ -1,6 +1,5 @@ package net.sourceforge.phpeclipse.phpeditor.html; -import net.sourceforge.phpeclipse.phpeditor.PHPEditor; import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration; import org.eclipse.jface.text.BadLocationException; @@ -8,6 +7,7 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.formatter.IFormattingStrategy; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.ui.texteditor.ITextEditor; /** * @author chrisl @@ -24,7 +24,7 @@ public class HTMLFormattingStrategy implements IFormattingStrategy, IHTMLConstan private PHPSourceViewerConfiguration fConfig; private ISourceViewer fViewer; // - private PHPEditor fEditor; + private ITextEditor fEditor; private int fTabWidth; //////////////////////////////////////////////////////////////////////// -- 1.7.1